Shader Subroutine
Core in version | 4.6 | |
---|---|---|
Core since version | 4.0 | |
Core ARB extension | ARB_shader_subroutine |
Shader Subroutines are special GLSL functions which can have variations. The specific variation that will be called is selected by the OpenGL code.
The general idea is as follows. The shader defines some number of special functions, each of which uses the same function signature. Each such function is called a "subroutine". Each subroutine is associated with one or more "subroutine types". The type represents a specific aggregation of subroutines that could be called, a specific list of variations.
Once a subroutine type is defined, the shader can declare one or more global "variables" of that type. Each variable represents . Because these are set from OpenGL code before rendering type, these are called "uniform"s (though they do not work like regular uniforms in almost any way). Each variable represents a specific, user-defined selection from among the possible subroutines in a subroutine type. The shader code can call these subroutine uniforms as though they were functions.
The user can query indices and locations for subroutines, types, and subroutine uniforms. These queries allow the user to specify which subroutines are used in which subroutine uniforms.
This article is a stub. You can help the OpenGL Wiki by expanding it. |
Definition
The first step in defining shader subroutines is to define a subroutine type. A subroutine type consists of a named function signature. It represents a specific set of subroutines that can be called.
A subroutine type is declared as follows:
subroutine FuncReturnType SubroutineTypeName(Type0 param0, Type1 param1, ...);
The SubroutineTypeName is the name of the subroutine type defined by this statement. Multiple different named types can use the same function signature.
A specific function definition (and only a function definition. If you use this syntax, the function must have a body) can be associated with one or more subroutine types as follows:
subroutine(SubroutineTypeName) FuncReturnType FunctionName(Type0 param0, Type1 param1, ...);
FunctionName's function signature must exactly match the subroutine type's signature.
GLSL normally allows function overloading. However, subroutine functions cannot be overloaded; you cannot declare a second FunctionName with a different set of parameters. Even if the second function is not a subroutine.
A function can be associated with multiple subroutine types by listing multiple SubroutineTypeNames, separated by commas. Obviously, all of those subroutine types must use the same signature.
The user can call FunctionName exactly as it used to, and it will have the usual behavior. To use it as a subroutine requires calling it in a different way.
Subroutine uniforms
Calling
Subroutine resources
In-shader specification
Core in version | 4.6 | |
---|---|---|
Core since version | 4.3 | |
Core ARB extension | ARB_explicit_uniform_location |
Shader Subroutines use a number of resources that can be automatically assigned to each shader stage at link time. However, the user can explicitly define them within the shader text as well, to avoid having to query them.
Subroutine functions each have a specific index that identifies that particular subroutine among all subroutines in a shader stage. This subroutine can be set from within a shader using the index layout qualifier:
layout(index = 2) subroutine(SubroutineTypeName, ...) ...;
This sets the particular subroutine function definition to index 2. No two subroutine functions may have the same index. Also, this index is subject to the limitations on the number of subroutines in a shader stage.
Each subroutine uniform variable within a shader stage has a particular position in that stage's list of subroutine uniforms. This location in the array can be set using the location layout qualifer:
layout(location = 1) subroutine uniform SubroutineTypeName subroutineVariableName;
This means that array index 1 in the call to glUniformSubroutines refers to the variable subroutineVariableName.
The number of active subroutine uniforms for this shader stage will be the largest location + 1. This means that some "active" uniform locations may be unused. If the above example were the only subroutine uniform, then the number of active subroutine uniforms will be considered to be 2, with location 0 going unusued.
Arrays of subroutine uniforms are always assigned consecutive uniform locations.
If some uniforms are user-assigned and some are linker-assigned, the linker will fill in the unused indices first, before increasing the number of active uniforms. So the number of active subroutine uniforms can be larger than this. The linker will never assign a subroutine uniform to a user-assigned subroutine uniform, even if the user-assigned one is not active.
The linking can fail if user-defined subroutine uniform assignments do not leave enough room for linker-assigned ones. Linker-assigned subroutine uniform locations for arrays must also be consecutively assigned, so if there is insufficient space to assign that many uniform locations, the linking will fail.