Standard Portable Intermediate Representation ( SPIR ) es un lenguaje intermedio para computación paralela y gráficos de Khronos Group . Se utiliza en múltiples entornos de ejecución, incluida la API de gráficos Vulkan y la API de cómputo OpenCL , para representar un sombreador o un núcleo . También se utiliza como lenguaje de intercambio para compilación cruzada. [1] [2]
SPIR-V es una nueva versión de SPIR que fue presentada en 2015 por Khronos Group y desde entonces ha reemplazado al SPIR original, que se presentó en 2012.
El 19 de septiembre de 2024, Microsoft anunció planes para adoptar SPIR-V como formato de intercambio Direct3D en lugar de DXIL, comenzando el soporte a partir de Shader Model 7. [3]
Los objetivos de SPIR-V son representar de forma nativa los primitivos necesarios para el cálculo y los gráficos; separar el lenguaje de alto nivel de la interfaz con los controladores de cálculo y gráficos; ser la forma de distribución o distribuir binarios completamente compilados; ser una especificación completamente autónoma; y admitir múltiples API. También se utiliza como un objetivo intermedio para herramientas de compilación cruzada.
Por ejemplo, SPIR-V permite que la API de Vulkan utilice cualquier lenguaje de sombreado , incluidos GLSL y HLSL . [4] [5] SPIR-V se puede descompilar en varios lenguajes de sombreado ( GLSL , GLSL ES , MSL , HLSL ) utilizando SPIRV-Cross, de modo que estos lenguajes se puedan interconvertir. [6] También tiene rutas hacia y/o desde WebGPU , OpenCL , SYCL , C++ y Rust .
En las plataformas de destino, la ingesta de SPIR-V elimina la necesidad de crear un compilador de código fuente de lenguaje de alto nivel en los controladores de dispositivos, lo que reduce la complejidad del controlador. [2]
SPIR se introdujo originalmente en 2011 y SPIR-V se introdujo en 2015.
SPIR antes del lanzamiento de SPIR-V en 2015 se basaba en la representación intermedia LLVM . En 2012 se anunció una especificación provisional para SPIR 1.0. [7] El 22 de julio de 2013, se anunció una especificación provisional SPIR 1.2 en SIGGRAPH 2013. [ 8] La especificación final de SPIR 1.2 se publicó en HiPEAC 2014 el 21 de enero de 2014. [9] El 11 de agosto de 2014, se publicó una especificación provisional para SPIR 2.0 en SIGGRAPH 2014. [ 10] SPIR-V no utiliza LLVM. [2]
SPIR-V 1.0 es una nueva versión de SPIR anunciada en marzo de 2015, [11] y lanzada el 16 de noviembre de 2015. [12] La familia SPIR ahora incluye un verdadero estándar de API cruzada completamente definido por Khronos con soporte nativo para funciones de sombreado y kernel.
Un programa independiente del Grupo Khronos permite la interconversión con LLVM IR. [13]
El soporte para la ingestión de SPIR-V está incorporado en la especificación principal de OpenCL 2.1, la API de Vulkan y OpenGL versión 4.6.
SPIR-V es un lenguaje intermedio de alto nivel que se intercambia en forma binaria. Las funciones se representan mediante un gráfico de flujo de control de bloques básicos, utilizando el formato de asignación única estática (SSA). Las estructuras de datos conservan una representación jerárquica de alto nivel. No presenta pérdidas como las representaciones intermedias anteriores de código de bytes o similares a las de máquinas virtuales que se utilizaban para los sombreadores gráficos. Esto permite un rendimiento más cercano al óptimo en los dispositivos de destino. [17]
SPIR-V se puede ampliar escribiendo extensiones para añadir semántica o reservando rangos de valores de token para el uso de la otra parte. Los proveedores pueden añadir de forma independiente la semántica deseada a SPIR-V. [18] Se pueden proporcionar conjuntos adicionales de conjuntos de instrucciones extendidas en especificaciones independientes. Se pueden importar varios conjuntos sin problemas, ya que las instrucciones extendidas se utilizan especificando el ID del conjunto y de la instrucción dentro del conjunto. [18]
Los depuradores incluyen RenderDoc , SwiftShader y Amber. [19]
Los sombreadores gráficos utilizan un flujo de control estructurado en SPIR-V para indicar cómo se anida el flujo de control. Esto ayuda a definir la divergencia y la reconvergencia del flujo de control en entornos de ejecución paralela. [20] La especialización reduce la cantidad de variantes de un sombreador que deben distribuirse. [21]
La especificación SPIR-V establece las reglas que se deben seguir para tener un módulo SPIR-V válido. Esto permite la validación fuera de línea. Los controladores no están obligados a manejar módulos SPIR-V no válidos. En las pruebas, las pruebas de conformidad verifican que los controladores se comporten correctamente al consumir SPIR-V válido, mientras que los validadores verifican que los front-ends generen SPIR-V correctamente. [22]
SPIR-V puede expresar llamadas a funciones en una unidad de compilación diferente. La versión estándar de SPIR-V utiliza esta característica para los núcleos de cómputo OpenCL, pero no para las etapas de sombreado, que las API gráficas quieren que estén completamente vinculadas en un único módulo SPIR-V. [23] Hay extensiones disponibles para permitir que las herramientas utilicen temporalmente sombreadores parcialmente vinculados y también núcleos. [24]
Un módulo SPIR-V es utilizado por una API de cliente para respaldar las características de ese módulo, que se clasifican por capacidades y se declaran al principio del módulo. Un validador puede confirmar que el módulo utiliza solo sus capacidades declaradas, y una API de cliente puede rechazar módulos que declaren capacidades no admitidas. [25]
SPIR-V se ha utilizado para ayudar a manejar múltiples versiones de lenguajes de nivel fuente. Por ejemplo, las múltiples versiones de OpenGL Shading Language (GLSL) requieren la distribución de múltiples versiones de shaders, debido a las implementaciones que están vinculadas a una versión anterior específica de GLSL, como WebGL 1.0 y la implementación OpenGL de Apple. Uno de los casos de uso notables de SPIR-V es su capacidad de ser utilizado como un formato de intercambio entre versiones GLSL, utilizando herramientas mantenidas por el Grupo Khronos para compilar GLSL a SPIR-V glslangValidator
, [26] optimizar SPIR-V spirv-opt
, [22] y realizar una compilación cruzada a SPIR-V para diferentes destinos GLSL spirv-cross
. [27]
Sin embargo, como formato, SPIR-V tiene algunas limitaciones para la compilación cruzada, incluido el requisito de que cada módulo SPIR-V tenga al menos un símbolo de punto de entrada. Esto evita que el formato se use fácilmente para la compilación separada, donde los sombreadores complejos podrían ensamblarse mediante una serie de pasos de compilación parcial seguidos de un paso de enlace. Esto va en contra de los objetivos establecidos de algunas herramientas SPIR-V como spirv-link
[ 22], que apunta a proporcionar una funcionalidad de enlace completa para el código binario SPIR-V.