Standard Portable Intermediate Representation ( SPIR ) — промежуточный язык для параллельных вычислений и графики от Khronos Group . Он используется в нескольких средах выполнения, включая графический API Vulkan и API вычислений OpenCL , для представления шейдера или ядра . Он также используется как язык обмена для кросс-компиляции. [1] [2]
SPIR-V — это новая версия SPIR, представленная в 2015 году компанией Khronos Group и заменившая оригинальный SPIR, представленный в 2012 году.
19 сентября 2024 года Microsoft объявила о планах принять SPIR-V в качестве формата Direct3D Interchange вместо DXIL, начав поддержку с Shader Model 7. [3]
Цели SPIR-V — изначально представлять примитивы, необходимые для вычислений и графики; отделять высокоуровневый язык от интерфейса для вычислений и графических драйверов; быть формой распространения или распространять полностью скомпилированные двоичные файлы; быть полностью самодостаточной спецификацией; и поддерживать несколько API. Он также используется в качестве промежуточной цели для инструментов кросс-компиляции.
Например, SPIR-V позволяет API Vulkan использовать любой язык шейдеров , включая GLSL и HLSL . [4] [5] SPIR-V можно декомпилировать в несколько языков шейдеров ( GLSL , GLSL ES , MSL , HLSL ) с помощью SPIRV-Cross, так что эти языки можно будет преобразовывать друг в друга. [6] Он также имеет пути к и/или из WebGPU , OpenCL , SYCL , C++ и Rust .
На целевых платформах внедрение SPIR-V устраняет необходимость встраивать компилятор исходного кода на языке высокого уровня в драйверы устройств, что снижает сложность драйвера. [2]
SPIR был первоначально представлен в 2011 году, а SPIR-V — в 2015 году.
SPIR до выпуска SPIR-V в 2015 году основывался на промежуточном представлении LLVM . Предварительная спецификация для SPIR 1.0 была анонсирована в 2012 году. [7] 22 июля 2013 года предварительная спецификация SPIR 1.2 была анонсирована на SIGGRAPH 2013. [8] Окончательная спецификация SPIR 1.2 была выпущена на HiPEAC 2014 21 января 2014 года . [9] 11 августа 2014 года предварительная спецификация для SPIR 2.0 была выпущена на SIGGRAPH 2014. [ 10] SPIR-V не использует LLVM. [2]
SPIR-V 1.0 — это новая версия SPIR, анонсированная в марте 2015 года [11] и выпущенная 16 ноября 2015 года [12]. Семейство SPIR теперь включает в себя настоящий кросс-API-стандарт, который полностью определен Khronos с собственной поддержкой функций шейдеров и ядра.
Отдельная программа от Khronos Group позволяет осуществлять взаимопреобразование с LLVM IR. [13]
Поддержка приема SPIR-V включена в базовую спецификацию OpenCL 2.1, API Vulkan и OpenGL версии 4.6.
SPIR-V — это промежуточный язык высокого уровня, обмен которым осуществляется в двоичной форме. Функции представлены графом потока управления базовых блоков с использованием формы статического одиночного присваивания (SSA). Структуры данных сохраняют иерархическое представление высокого уровня. Это не приводит к потерям, как предыдущие байт-кодовые или виртуальные машиноподобные промежуточные представления, используемые для графических шейдеров. Это позволяет приблизиться к оптимальной производительности на целевых устройствах. [17]
SPIR-V может быть расширен путем написания расширений для добавления семантики или резервирования диапазонов значений токенов для использования стороной. Поставщики могут независимо добавлять желаемую семантику в SPIR-V. [18] Дополнительные наборы расширенных наборов инструкций могут быть предоставлены в отдельных спецификациях. Несколько наборов могут быть импортированы без проблем, поскольку расширенные инструкции используются путем указания идентификатора набора и инструкции внутри набора. [18]
Отладчики включают RenderDoc , SwiftShader и Amber. [19]
Графические шейдеры используют структурированный поток управления в SPIR-V для указания того, как вложен поток управления. Это помогает определить расхождение и повторную сходимость потока управления в параллельных средах выполнения. [20] Специализация уменьшает количество вариантов шейдера, которые необходимо распределить. [21]
Спецификация SPIR-V устанавливает правила, которым необходимо следовать, чтобы иметь действительный модуль SPIR-V. Это позволяет проводить офлайн-проверку. Драйверы не обязаны обрабатывать недействительные модули SPIR-V. При тестировании тестирование соответствия проверяет, что драйверы ведут себя правильно при использовании действительного SPIR-V, в то время как валидаторы проверяют, что внешние интерфейсы правильно генерируют SPIR-V. [22]
SPIR-V может выражать вызовы функций в другом модуле компиляции. Стандартная версия SPIR-V использует эту функцию для вычислительных ядер OpenCL, но не для стадий шейдеров, которые графические API хотят полностью связать в один модуль SPIR-V. [23] Существуют расширения, позволяющие инструментам временно использовать частично связанные шейдеры и ядра. [24]
Модуль SPIR-V используется клиентским API для поддержки функций этого модуля, которые классифицируются по возможностям и объявляются в начале модуля. Валидатор может подтвердить, что модуль использует только свои объявленные возможности, а клиентский API может отклонить модули, которые объявляют неподдерживаемые возможности. [25]
SPIR-V использовался для помощи в работе с несколькими версиями языков исходного уровня. Например, несколько версий OpenGL Shading Language (GLSL) требуют распространения нескольких версий шейдеров из-за реализаций, которые привязаны к определенной старой версии GLSL, например, для WebGL 1.0 и реализации OpenGL от Apple. Одним из примечательных вариантов использования SPIR-V является его способность использоваться в качестве формата обмена между версиями GLSL с использованием инструментов, поддерживаемых Khronos Group , для компиляции GLSL в SPIR-V glslangValidator
[ 26], оптимизации SPIR-V spirv-opt
[ 22] и кросс-компиляции в SPIR-V для различных целевых GLSL [27]spirv-cross
.
Однако как формат SPIR-V имеет некоторые ограничения для кросс-компиляции, включая требование, чтобы каждый модуль SPIR-V имел по крайней мере один символ точки входа. Это не позволяет легко использовать формат для отдельной компиляции, где сложные шейдеры могут быть собраны серией частичных шагов компиляции, за которыми следует шаг компоновки. Это противоречит заявленным целям некоторых инструментов SPIR-V, таких как spirv-link
, [22] , который направлен на обеспечение полной функциональности компоновки для двоичного кода SPIR-V.