Program Introspection is a mechanism for taking a program object and querying information about it, so as to be able to interface and interact with it. For example, if there is a uniform, you may need to query its location so that you can set its value.
The APIs in this section represent an older interface to this information. If GL 4.3 or ARB_program_interface_query are not available, you should use these. Be advised that the new APIs provide access to more information than can be queried here.
If a program has a Vertex Shader, vertex shader inputs, aka Vertex Attributes, can be queried. Vertex attributes can be active or inactive. Attributes that are unused are inactive; they do not have a binding. The number of active attributes in a program can be retrieved with glGetProgramiv with GL_ACTIVE_ATTRIBUTES.
To retrieve information about an attribute, call this function:
void glGetActiveAttrib( GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, char *name );
The index is a number on the half-open range [0, GL_ACTIVE_ATTRIBUTES); it represents a particular active attribute. name will be filled in with the name of the attribute; bufSize is the size of this character array. If length is not NULL, it will be filled in with the number of characters written to name. The size will be filled with the number of elements in the attribute array, if the attribute is an array type. Otherwise, it will be set to 1. The type will be set to the OpenGL enumeration for the GLSL type of the attribute.
To get the attribute location (the one used by glVertexAttribPointer, not the index field used above), we use this function:
GLint glGetAttribLocation( GLuint program, const char *name );
If name is not an active attribute in program, the function will return -1.
GLint glGetFragDataLocation(GLuint program, const char * name); GLint glGetFragDataIndex(GLuint program, const char * name);
Note that you must provide a name for these functions. Unlike with attributes, the old-style query mechanism cannot be used to enumerate the names and properties of fragment shader outputs.
Uniforms and blocks
Active uniforms are uniforms that the shader compiler/linker has determined are in active use by the executable code. Uniforms that are not active cannot be queried.
All uniforms, whether uniform block names or just uniform names, are assigned an index when the program is linked. This index is not the same as a uniform location or a uniform block index.
You can enumerate all of the active uniforms by using glGet with GL_ACTIVE_UNIFORMS. Thus, all active uniform indices will have indices less than this value. You can then loop over this range.
However, you can also get uniform indices from string names of the uniforms. This is done with this function:
void glGetUniformIndices(GLuint program, GLsizei uniformCount, const char ** uniformNames, GLuint *uniformIndices);
This will cause the array uniformIndices, which is of size uniformCount to be filled with the indices for the strings in the uniformNames list (also of size uniformCount); If a uniform name in the string list doesn't correspond to the name of an active uniform, then the corresponding index in uniformIndices will be GL_INVALID_INDEX.
Once you have an index, you can query the name of the uniform with this function:
void glGetActiveUniformName( GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei *length, char *uniformName);
This function stores the name in the uniformName buffer, which is of size bufSize bytes. The actual length of uniformName is stored in length (unless length is NULL, which is allowed).
General information about uniforms can be queried with this function, which can retrieve information for multiple uniforms at once:
void glGetActiveUniformsiv( GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params );
The uniformIndices array is a list of uniform indices uniformCount in length. These are the uniforms that the user is asking to acquire. pname is an enum that determines what information to query for the uniforms. params are the values that get returned; it is an array uniformCount in length. One value for each uniform index is generated.
The possibilities for pname are:
- GL_UNIFORM_TYPE: Retrieves the GLenum for the uniform's type.
- GL_UNIFORM_SIZE: Retrieves the size of the uniform. For arrays, this is the length of the array1. For non-arrays, this is 1.
- GL_UNIFORM_NAME_LENGTH: The length of that uniform's name.
- GL_UNIFORM_BLOCK_INDEX: The uniform block index for this uniform. If this uniform is not in a block, the value will be -1.
- GL_UNIFORM_OFFSET: The byte offset into the beginning of the uniform block for this uniform. If the uniform is not in a block, the value will be -1.
- GL_UNIFORM_ARRAY_STRIDE: The byte stride for elements of the array, for uniforms in a uniform block. For non-array uniforms in a block, this value is 0. For uniforms not in a block, the value will be -1.
- GL_UNIFORM_MATRIX_STRIDE: The byte stride for columns of a column-major matrix or rows for a row-major matrix, for uniforms in a uniform block. For non-matrix uniforms in a block, this value is 0. For uniforms not in a block, the value will be -1.
- GL_UNIFORM_IS_ROW_MAJOR: GL_TRUE if the matrix is row-major and the uniform is in a block. If the uniform is not in a block, the uniform is column-major, or simply not a matrix type, GL_FALSE is returned.
void glGetActiveUniform( GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, char *name );
This retrieves the name as in glGetActiveUniformName, but it also retrieves GL_UNIFORM_TYPE in type, GL_UNIFORM_SIZE in size, and GL_UNIFORM_NAME_LENGTH in length.
The length of the longest uniform name in a program can be queried with GL_ACTIVE_UNIFORM_MAX_LENGTH through glGetProgramiv. You can use this along with GL_ACTIVE_UNIFORMS to allocate an array of strings that will be sufficiently large enough to hold the string names for a program's uniforms.
The above APIs can query information about uniforms outside of a block, but getting information about the uniform block itself, or uniforms within the block, requires a different set of APIs.
Each active uniform block has an index. As with the uniform API, you can query this in two ways. You can iterate over the active uniform blocks by calling glGetIntegerv(GL_ACTIVE_UNIFORM_BLOCKS) to get the limit to iterate over. Or you can get the index for a uniform block by name with this function:
void glGetUniformBlockIndex( GLuint program, const char *name );
With the index, properties about the block as a while can be queried. The numerical properties can be queried with this function:
void glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
pname must be one of these:
- GL_UNIFORM_BLOCK_BINDING: The current block binding, as set either within the shader or from glUniformBlockBinding.
- GL_UNIFORM_BLOCK_DATA_SIZE: The buffer object storage size needed for this block.
- GL_UNIFORM_BLOCK_NAME_LENGTH: The length of this block's name.
- GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: The number of active uniforms within this block.
- GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: params will be filled in with the uniform indices of all uniforms that are stored in this block. It will receive GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS number of uniforms.
- GL_UNIFORM_BLOCK_REFERENCED_BY_*: GL_FALSE if the uniform block is not referenced by an active * shader, where * is the particular shader stage in question. It can be VERTEX_SHADER, FRAGMENT_SHADER, or GEOMETRY_SHADER. If GL 4.0/ARB_tessellation_shader, then it can also be TESS_CONTROL_SHADER or TESS_EVALUATION_SHADER. If GL 4.3/ARB_compute_shader, then COMPUTE_SHADER is also possible.
The name of a block can be queried with this function:
void glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
You can use the GL_UNIFORM_BLOCK_NAME_LENGTH query to get how much space you should reserve.
|Core in version||4.5|
|Core since version||4.3|
|Core ARB extension||ARB_program_interface_query|
This new interface provides a uniform mechanism for querying just about everything from a program. At least, you can query everything that external OpenGL code can interface with. You can't query information about number of functions (unless they're subroutines) or global variables or things like that. But uniforms, inputs/outputs, etc? All of those are made available through this consistent interface.
|This article is a stub. You can help the OpenGL Wiki by expanding it.|