As with GLSL, SPIR-V makes use of shader and program objects. Because SPIR-V is a binary format, SPIR-V shaders are loaded into shader objects via the use of the shader binary API:
shaders is an array of count length of previously created shader objects that the SPIR-V data will be loaded into. So this function can load the same SPIR-V source code into multiple shader objects.
SPIR-V has a specific binaryFormat: the enumerator SHADER_BINARY_FORMAT_SPIR_V. The binary is the loaded SPIR-V itself, with a byte length of length. This must include the entire SPIR-V, as defined by the specification, including header information.
The use of this function will replace the shaders specified by previous calls to glShaderSource or glShaderBinary. Loading a non-SPIR-V binary or loading GLSL source strings into the program will make it no longer contain SPIR-V code.
While a shader object has a SPIR-V binary loaded into it, the object becomes slightly different. glGetShaderiv(shader, GL_SPIR_V_BINARY) will return GL_TRUE.
Entry points and specialization
SPIR-V is similar to GLSL, but it has some differences. Two differences are particularly relevant.
- A single SPIR-V file can have function entry-points for multiple shader stages, even of different types.
- SPIR-V has the concept of "specialization constants": numbers which the user can provide before compilation to specialize a particular use of a shader.
Before a SPIR-V shader object can be used, you must specify which entry-point to use and provide values for any specialization constants. This is done through a single function:
pEntryPoint is the string name of the entry-point that this SPIR-V shader object will use. pConstantIndex and pConstantValue are arrays containing the index of each specialization constant and the corresponding values that will be used. These arrays are numSpecializationConstants in length. Specialization constants not referenced by pConstantIndex.
Specializing a SPIR-V shader is analogous to compiling a GLSL shader. So if this function completes successfully, the shader object's compile status is GL_TRUE. If specialization fails, then the shader infolog has information explaining why and an OpenGL Error is generated.
Specialization can fail due to pEntryPoint not referencing a valid entry point in the SPIR-V. It can also fail if pConstantIndex references a specialization constant index that the SPIR-V binary does not use.
Once specialized, SPIR-V shaders cannot be re-specialized. However, you can reload the SPIR-V binary data into them, which will allow them to be specialized.
SPIR-V shader objects that have been specialized can be used to link programs (separable or otherwise). If you link multiple shader objects in the same program, then either all of them must be SPIR-V shaders or none of them may be SPIR-V shaders. You cannot link SPIR-V to non-SPIR-V shaders in a program.
Also, note that SPIR-V shaders must have an entry-point. So SPIR-V modules for the same stage cannot be linked together. Each SPIR-V shader object must provide all of the code for its module.
You can use separable programs built from SPIR-V shaders in the same pipeline object as non-SPIR-V shaders.