|Core in version||4.6|
|Core since version||4.6|
|Core ARB extension||ARB_spirv_extensions|
The Standard, Portable Intermediate Representation - V (SPIR-V) is an intermediate language for defining shaders. It is intended to be a compiler target from a number of different languages, which allows users the freedom to write shader languages however they want, while allowing implementations to not have to deal with the parsing of more complex languages like GLSL.
The SPIR-V registry contains the current SPIR-V specification, along with its extensions.
|This article is a stub. You can help the OpenGL Wiki by expanding it.|
Mapping to GLSL
SPIR-V defines many concepts that directly match equivalents in GLSL. And the OpenGL specification still considers GLSL to be the primary OpenGL shading language. So SPIR-V concepts map to GLSL concepts. The mapping in most cases is obvious, so we will discuss the non-obvious cases here.
GLSL provides a comprehensive API for querying resource interfaces that are part of a linked program. These APIs are allowed for parts of a program that comes from SPIR-V, within one restriction.
Because SPIR-V is an intermediate language, things like names are unnecessary. As such, while SPIR-V does permit you to assign a name to a particular construct, it does not require you to do so. Therefore, any OpenGL introspection query that involves the name of a SPIR-V variable or other construct may not produce reasonable results.
If you have the index of a SPIR-V-defined resource, and you query the name, you may get an empty string (NUL-terminated). But you may also get the name assigned to it in the SPIR-V shader. Which you get is implementation-dependent.
What is not implementation-dependent is the ability to query aspects of a resource from its name. Even if the SPIR-V shader assigns the resource a name, any query by name will produce either -1 or GL_INVALID_INDEX, whichever is appropriate for the value being queried.
All other forms of introspection are perfectly valid. For example, you can query the number of default block uniforms, then iterate over each one, reliably fetching all of the usual information (type, location, etc). Except for the name, of course.
Input/output interface matching for user-defined variables in SPIR-V works by matching explicit Locations. As such, all variables that are used for input/output interfaces must have a location assigned. Even members of blocks (via structs) must have locations assigned.
An output variable for a particular Location and Component must have a corresponding input variable with the same Location and Component values.
If the type of an output variable is a built-in scalar or vector type, then the type of the corresponding input does not have to match exactly. The output must have the same basic type as the input, and it must provide at least as many components as the input receives.
If the type of the output is a struct, then the input struct must match in the types, numbers, and declaration order of their members. Output arrays match input arrays if they have the same number of array elements and the same type.
Decorations must match between corresponding variables, except for interpolation decorations.
For built-in interface variables, things are a bit more complex. In SPIR-V, you can only have one built-in input block and one built-in output block. Each such block must have all of its members decorated with BuiltIn, and the block cannot have any members decorated with Location. Lastly, the top-level members of the block must be built-in types.
Interface matching for built-in blocks requires an exact match, except for the fragment shader input block. That one (which contains all of the built-in variables) does not need to match the previous Vertex Processing stage's built-in variables. But the built-in blocks between vertex processing stages do need to match exactly.
Any shader stage entry-point that will output feedback information must explicitly use the Xfb execution mode.
SPIR-V does not support subroutines at all, so you may not use them.
SPIR-V is extensible. And working with all of OpenGL's features requires some SPIR-V extensions.
SPIR-V has the concept of specialization constants. These are values provided after a module is loaded but before it is linked. They are considered constant expressions in most cases, and they allow you
To support this in OpenGL, a shader object populated with a SPIR-V module can be specialized with constants. This function must be called before linking with a SPIR-V shader object, even if your shader does not use specialization constants.