Shader Subroutine/Introspection

From OpenGL Wiki
Jump to navigation Jump to search

Because the list of subroutine resources (of all kinds) are broken down by shader stage, all functions that query information about them take a shadertype​ parameter in addition to the program​ object to query from. The shadertype​ is the shader stage enumerator name for the stage to query information about.

Each active subroutine (a subroutine function which can be used with a subroutine uniform that itself is active) has an index. There are two ways to get the index for a particular subroutine function. If you have the name of a subroutine, you can query the index with this function:

GLuint glGetSubroutineIndex(GLuint program​, GLenum shadertype​, const GLchar *name​);

If name​ does not name an active subroutine function, then GL_INVALID_INDEX will be returned. Otherwise, it will be the index of the subroutine function.

To iterate through the list of all subroutine functions, you can query the total number of subroutines. This is done via this function:

void glGetProgramStageiv(GLuint program​, GLenum shadertype​, GLenum pname​, GLint *values​);

To query the number of active subroutine functions, pname​ must be GL_ACTIVE_SUBROUTINES. This stores the number of active subroutine functions as a single integer in values​.

To get the name of a subroutine function from an index, pass the index​ to this function:

void glGetActiveSubroutineName(GLuint program​, GLenum shadertype​, GLuint index​, GLsizei bufsize​, GLsizei *length​, GLchar *name​);

bufsize​ is the total number of bytes that name​ points to; OpenGL will not write more than this number of bytes. If length​ is not NULL, the function will write the number of characters written into name​.

There is no way to query the length of the name for a specific subroutine function (at least, not with this API. You must use the query API for that). However, you can query the largest subroutine function name used by a shader stage. This is done with glGetProgramStage, using the GL_ACTIVE_SUBROUTINE_MAX_LENGTH enumerator.

The name is the only information that can be queried about a subroutine function directly.

Like regular uniforms, subroutine uniforms have both a location and an index. The location is used when actually selecting which subroutine to use for that uniform, while the index is only used to query information about that uniform.

To iterate through the number of subroutine uniforms for a stage and query information about them, you must first get the number of subroutine uniform indices. This uses glGetProgramStage with GL_ACTIVE_SUBROUTINE_UNIFORMS​. The valid indices range from 0 to that value minus one.

Armed with a subroutine uniform index​, one can query general information about the subroutine uniform with this function:

void glGetActiveSubroutineUniformiv(GLuint program​, GLenum shadertype​, GLuint index​, GLenum pname​, GLint *values​);

pname​ defines what information is to be set into values​:

  • GL_NUM_COMPATIBLE_SUBROUTINES: The number of subroutine functions that can be used with this uniform.
  • GL_COMPATIBLE_SUBROUTINES: This returns an array of indices for each of the subroutine functions that can be used with this uniform. values​ must be at least GL_NUM_COMPATIBLE_SUBROUTINES entries in size.
  • GL_UNIFORM_SIZE: The number of entries in the subroutine uniform. Subroutine uniforms can be in arrays, so this is the count of array elements. If the subroutine uniform is not an array,
  • GL_UNIFORM_NAME_LENGTH: The length of the uniform's name.

To get the subroutine uniform's name, call this function:

void glGetActiveSubroutineUniformName(GLuint program​, GLenum shadertype​, GLuint index​, GLsizei bufsize​, GLsizei *length​, GLchar *name​);

The subroutine uniform location is used to know how to assign a subroutine function index to the subroutine uniform when it comes time to render with the shader.

Regular uniform variables are assigned locations arbitrarily. Subroutine uniforms are a bit different. The number of subroutine uniform locations assigned to a particular shader stage can be determined by calling glGetProgramStage with GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS. All subroutine uniform locations less than that number (and >= 0) are active subroutine uniform locations. This is required by the specification.

Because subroutine uniforms can be arrays, there can be more subroutine uniform locations than there are subroutine uniform indices. Each subroutine uniform only counts as one for the index list, but arrayed subroutine uniforms take up multiple locations.

To get a subroutine uniform's location given the name, use this function:

GLint glGetSubroutineUniformLocation(GLuint program​, GLenum shadertype​, const GLchar *name​);

If name​ names an arrayed subroutine uniform, then the location refers to X consecutive locations starting from the returned location, where X is the array size declared in the shader. If the subroutine uniform is not active, this function will return -1.