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 GL_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": parameters which the user can provide before the SPIR-V is compiled into its final form.
Before a SPIR-V shader object can be used, you must specify which entry-point to use and provide values for any specialization constants used by that entry-point. 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 use the default values specified in the SPIR-V shader.
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.
pEntryPoint must name a valid entry point. Also, the entry point's "execution model" (SPIR-V speak for "Shader Stage") must match the stage the shader object was created with. Specialization can also fail if pConstantIndex references a specialization constant index that the SPIR-V binary does not use. If specialization fails, the shader's info log is updated appropriately.
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 again.
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.