Name ARB_uniform_buffer_object Name Strings GL_ARB_uniform_buffer_object Contact Benj Lipchak, APPLE (lipchak 'at' apple.com) John Rosasco, APPLE (jdr 'at' apple.com) Jeremy Sandmel, APPLE (jsandmel 'at' apple.com) Pat Brown, NVIDIA (pbrown 'at' nvidia.com) Contributors Rob Barris Keith Bauer Bob Beretta Pat Brown Nick Burns Matt Collins Michael Gold John Kessenich Jon Leech Barthold Lichtenbelt Benj Lipchak Bruce Merry John Rosasco Jeremy Sandmel Geoff Stahl Notice Copyright (c) 2009-2013 The Khronos Group Inc. Copyright terms at http://www.khronos.org/registry/speccopyright.html Specification Update Policy Khronos-approved extension specifications are updated in response to issues and bugs prioritized by the Khronos OpenGL Working Group. For extensions which have been promoted to a core Specification, fixes will first appear in the latest version of that core Specification, and will eventually be backported to the extension document. This policy is described in more detail at https://www.khronos.org/registry/OpenGL/docs/update_policy.php Status Complete. Approved by the ARB on February 17, 2009. Version Last Modified Date: 2015/06/23 Author revision: 68 Number ARB Extension #57 Dependencies The OpenGL Shading Language (GLSL) is required. OpenGL 2.0 or the ARB_shader_objects extension is required. OpenGL 1.5 or ARB_vertex_buffer_object is required. This extension is written against the OpenGL 2.1 specification and version 1.20-8 of the OpenGL Shading Language specification. This extension interacts with OpenGL 3.0, ARB_geometry_shader4, ARB_texture_rectangle, EXT_gpu_shader4, EXT_texture_array, EXT_texture_integer, and EXT_texture_buffer_object. Overview This extension introduces the concept of a group of GLSL uniforms known as a "uniform block", and the API mechanisms to store "uniform blocks" in GL buffer objects. The extension also defines both a standard cross-platform layout in memory for uniform block data, as well as mechanisms to allow the GL to optimize the data layout in an implementation-defined manner. Prior to this extension, the existing interface for modification of uniform values allowed modification of large numbers of values using glUniform* calls, but only for a single uniform name (or a uniform array) at a time. However, updating uniforms in this manner may not map well to heterogenous uniform data structures defined for a GL application and in these cases, the application is forced to either: A) restructure their uniform data definitions into arrays or B) make an excessive number of calls through the GL interface to one of the Uniform* variants. These solutions have their disadvantages. Solution A imposes considerable development overhead on the application developer. Solution B may impose considerable run-time overhead on the application if the number of uniforms modified in a given frame of rendering is sufficiently large. This extension provides a better alternative to either (A) or (B) by allowing buffer object backing for the storage associated with all uniforms of a given GLSL program. Storing uniform blocks in buffer objects enables several key use cases: - sharing of uniform data storage between program objects and between program stages - rapid swapping of sets of previously defined uniforms by storing sets of uniform data on the GL server - rapid updates of uniform data from both the client and the server The data storage for a uniform block can be declared to use one of three layouts in memory: packed, shared, or std140. - "packed" uniform blocks have an implementation-dependent data layout for efficiency, and unused uniforms may be eliminated by the compiler to save space. - "shared" uniform blocks, the default layout, have an implementation- dependent data layout for efficiency, but the layout will be uniquely determined by the structure of the block, allowing data storage to be shared across programs. - "std140" uniform blocks have a standard cross-platform cross-vendor layout (see below). Unused uniforms will not be eliminated. Any uniforms not declared in a named uniform block are said to be part of the "default uniform block". While uniforms in the default uniform block are updated with glUniform* entry points and can have static initializers, uniforms in named uniform blocks are not. Instead, uniform block data is updated using the routines that update buffer objects and can not use static initializers. Rules and Concepts Guiding this Specification: For reference, a uniform has a "uniform index" (subsequently referred to as "u_index) and also a "uniform location" to efficiently identify it in the uniform data store of the implementation. We subsequently refer to this uniform data store of the implementation as the "uniform database". A "uniform block" only has a "uniform block index" used for queries and connecting the "uniform block" to a buffer object. A "uniform block" has no "location" because "uniform blocks" are not updated directly. The buffer object APIs are used instead. Properties of Uniforms and uniform blocks: a) A uniform is "active" if it exists in the database and has a valid u_index. b) A "uniform block" is "active" if it exists in the database and has a valid ub_index. c) Uniforms and "uniform blocks" can be inactive because they don't exist in the source, or because they have been removed by dead code elimination. d) An inactive uniform has u_index == INVALID_INDEX. e) An inactive uniform block has ub_index == INVALID_INDEX. f) A u_index or ub_index of INVALID_INDEX generates the INVALID_VALUE error if given as a function argument. g) The default uniform block, which is not assigned any ub_index, uses a private, internal data storage, and does not have any buffer object associated with it. h) An active uniform that is a member of the default uniform block has location >= 0 and it has offset == stride == -1. i) An active uniform that is a member of a named uniform block has location == -1. j) A uniform location of -1 is silently ignored if given as a function argument. k) Uniform block declarations may not be nested IP Status No known IP claims. New Procedures and Functions void GetUniformIndices(uint program, sizei uniformCount, const char* const * uniformNames, uint* uniformIndices); void GetActiveUniformsiv(uint program, sizei uniformCount, const uint* uniformIndices, enum pname, int* params); void GetActiveUniformName(uint program, uint uniformIndex, sizei bufSize, sizei* length, char* uniformName); uint GetUniformBlockIndex(uint program, const char* uniformBlockName); void GetActiveUniformBlockiv(uint program, uint uniformBlockIndex, enum pname, int* params); void GetActiveUniformBlockName(uint program, uint uniformBlockIndex, sizei bufSize, sizei* length, char* uniformBlockName); void BindBufferRange(enum target, uint index, uint buffer, intptr offset, sizeiptr size); void BindBufferBase(enum target, uint index, uint buffer); void GetIntegeri_v(enum target, uint index, int* data); void UniformBlockBinding(uint program, uint uniformBlockIndex, uint uniformBlockBinding); New Types None. New Tokens Accepted by the parameters of BindBuffer, BufferData, BufferSubData, MapBuffer, UnmapBuffer, GetBufferSubData, and GetBufferPointerv: UNIFORM_BUFFER 0x8A11 Accepted by the parameter of GetIntegeri_v, GetBooleanv, GetIntegerv, GetFloatv, and GetDoublev: UNIFORM_BUFFER_BINDING 0x8A28 Accepted by the parameter of GetIntegeri_v: UNIFORM_BUFFER_START 0x8A29 UNIFORM_BUFFER_SIZE 0x8A2A Accepted by the parameter of GetBooleanv, GetIntegerv, GetFloatv, and GetDoublev: MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F MAX_UNIFORM_BLOCK_SIZE 0x8A30 MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31 MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32 MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33 UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34 Accepted by the parameter of GetProgramiv: ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35 ACTIVE_UNIFORM_BLOCKS 0x8A36 Accepted by the parameter of GetActiveUniformsiv: UNIFORM_TYPE 0x8A37 UNIFORM_SIZE 0x8A38 UNIFORM_NAME_LENGTH 0x8A39 UNIFORM_BLOCK_INDEX 0x8A3A UNIFORM_OFFSET 0x8A3B UNIFORM_ARRAY_STRIDE 0x8A3C UNIFORM_MATRIX_STRIDE 0x8A3D UNIFORM_IS_ROW_MAJOR 0x8A3E Accepted by the parameter of GetActiveUniformBlockiv: UNIFORM_BLOCK_BINDING 0x8A3F UNIFORM_BLOCK_DATA_SIZE 0x8A40 UNIFORM_BLOCK_NAME_LENGTH 0x8A41 UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42 UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43 UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44 UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45 UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46 Returned by GetActiveUniformsiv and GetUniformBlockIndex INVALID_INDEX 0xFFFFFFFFu 2.1 Specification Updates Additions to Chapter 2 - OpenGL Operation Section 2.9 - Buffer Objects Add UNIFORM_BUFFER to list of buffer object targets on: Pg 35, 2nd pgph Pg 37, top of page Pg 38, top of page Section 2.15 - Vertex Shaders Pg 79, bump Uniform Variables up to a numbered section since there will now be hierarchy under it; replace all but first paragraph of Uniform Variables section on this page, through to the start of the first full paragraph on p. 80 (beginning "A valid ...") under the description of GetUniformLocation: Sets of uniforms can be grouped into "uniform blocks". The values of each uniform in such a set are extracted from the data store of a buffer object corresponding to the uniform block. OpenGL Shading Language syntax serves to delimit named blocks of uniforms that can be backed by a buffer object. These are referred to as "named uniform blocks," and are assigned a uniform block index. Uniforms that are declared outside of a named uniform block are said to be part of the "default uniform block." Default uniform blocks have no name or uniform block index. Like uniforms, uniform blocks can be active or inactive. Active uniform blocks are those that contain active uniforms after a program has been compiled and linked. The amount of storage available for uniform variables in the default uniform block accessed by a vertex shader is specified by the value of the implementation-dependent constant MAX_VERTEX_UNIFORM_COMPONENTS. The total amount of combined storage available for uniform variables in all uniform blocks accessed by a vertex shader (including the default uniform block) is specified by the value of the implementation-dependent constant MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS. These values represent the numbers of individual floating-point, integer, or boolean values that can be held in uniform variable storage for a vertex shader. A link error is generated if an attempt is made to utilize more than the space available for vertex shader uniform variables. When a program is successfully linked, all active uniforms belonging to the program object's default uniform block are initialized to zero (FALSE for booleans). A successful link will also generate a location for each active uniform in the default uniform block. The values of active uniforms in the default uniform block can be changed using this location and the appropriate Uniform* command (see below). These locations are invalidated and new ones assigned after each successful re-link. Similarly, when a program is successfully linked, all active uniforms belonging to the program's named uniform blocks are assigned offsets (and strides for array and matrix type uniforms) within the uniform block according to layout rules described below. Uniform buffer objects provide the storage for named uniform blocks, so the values of active uniforms in named uniform blocks may be changed by modifying the contents of the buffer object using commands such as BufferData, BufferSubData, MapBuffer, and UnmapBuffer. Uniforms in a named uniform block are not assigned a location and may not be modified using the Uniform* commands. The offsets and strides of all active uniforms belonging to named uniform blocks of a program object are invalidated and new ones assigned after each successful re-link. To find the location within a program object of an active uniform variable associated with the default uniform block, use the command int GetUniformLocation(uint program, const char *name); This command will return the location of uniform variable if it is associated with the default uniform block. must be a null-terminated string, without white space. The value -1 will be returned if does not correspond to an active uniform variable name in , if is associated with a named uniform block, or if starts with the reserved prefix "gl_". If has not been successfully linked, the error INVALID_OPERATION is generated. After a program is linked, the location of a uniform variable will not change, unless the program is re-linked. A valid ... Pg 80, insert before the description of GetActiveUniform: Named uniform blocks, like uniforms, are identified by name strings. Uniform block indices corresponding to uniform block names can be queried by calling uint GetUniformBlockIndex(uint program, const char* uniformBlockName); is the name of a program object for which the command LinkProgram has been issued in the past. It is not necessary for to have been linked successfully. The link could have failed because the number of active uniforms exceeded the limit. must contain a null-terminated string specifying the name of a uniform block. GetUniformBlockIndex returns the uniform block index for the uniform block named of . If does not identify an active uniform block of , or an error occurred, then INVALID_INDEX is returned. The indices of the active uniform blocks of a program are assigned in consecutive order, beginning with zero. An active uniform block's name string can be queried from its uniform block index by calling void GetActiveUniformBlockName(uint program, uint uniformBlockIndex, sizei bufSize, sizei* length, char* uniformBlockName); is the name of a program object for which the command LinkProgram has been issued in the past. It is not necessary for to have been linked successfully. The link could have failed because the number of active uniforms exceeded the limit. must be an active uniform block index of , in the range zero to the value of ACTIVE_UNIFORM_BLOCKS - 1. The value of ACTIVE_UNIFORM_BLOCKS can be queried with GetProgramiv (see section 6.1.14). If is greater than or equal to the value of ACTIVE_UNIFORM_BLOCKS, the error INVALID_VALUE is generated. The string name of the uniform block identified by is returned into . The name is null-terminated. The actual number of characters written into , excluding the null terminator, is returned in . If is NULL, no length is returned. contains the maximum number of characters (including the null terminator) that will be written back to . If an error occurs, nothing will be written to or . Information about an active uniform block can be queried by calling void GetActiveUniformBlockiv(uint program, uint uniformBlockIndex, enum pname, int* params); is the name of a program object for which the command LinkProgram has been issued in the past. It is not necessary for to have been linked successfully. The link could have failed because the number of active uniforms exceeded the limit. is an active uniform block index of . If is greater than or equal to the value of ACTIVE_UNIFORM_BLOCKS, or is not the index of an active uniform block in , the error INVALID_VALUE is generated. If no error occurs, the uniform block parameter(s) specified by are returned in . Otherwise, nothing will be written to . If is UNIFORM_BLOCK_BINDING, then the index of the uniform buffer binding point last selected by the uniform block specified by for is returned. If no uniform block has been previously specified, zero is returned. If is UNIFORM_BLOCK_DATA_SIZE, the value returned is the implementation-dependent minimum total buffer object size, in basic machine units, required to hold all active uniforms in the uniform block identified by . It is neither guaranteed nor expected that a given implementation will arrange uniform values as tightly packed in a buffer object. The exception to this is the "std140" uniform block layout, which guarantees specific packing behavior and does not require the application to query for offsets and strides. In this case, the minimum size may still be queried, even though it is determined in advance based only on the uniform block declaration (see "Standard Uniform Block Layout" in section 2.15.3.1.2). The total amount of buffer object storage available for any given uniform block is subject to an implementation-dependent limit; the maximum amount of available space, in basic machine units, can be queried by calling GetIntegerv with the constant MAX_UNIFORM_BLOCK_SIZE. If the amount of storage required for a uniform block exceeds this limit, a program may fail to link. If is UNIFORM_BLOCK_NAME_LENGTH, then the total length (including the null terminator) of the name of the uniform block identified by is returned. If is UNIFORM_BLOCK_ACTIVE_UNIFORMS, then the number of active uniforms in the uniform block identified by is returned. If is UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, then a list of the active uniform indices for the uniform block identified by is returned. The number of elements that will be written to is the value of UNIFORM_BLOCK_ACTIVE_UNIFORMS for . If is UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER, UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER, or UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER, then a boolean value indicating whether the uniform block identified by is referenced by the vertex, geometry, or fragment programming stage of , respectively, is returned. Each active uniform, whether in a named uniform block or in the default block, is assigned an index when a program is linked. These indices are assigned in consecutive order, beginning with zero. The indices assigned to a set of uniforms in a program may be queried by calling void GetUniformIndices(uint program, sizei uniformCount, const char* const * uniformNames, uint* uniformIndices); is the name of a program object for which the command LinkProgram has been issued in the past. It is not necessary for to have been linked successfully. The link could have failed because the number of active uniforms exceeded the limit. indicates both the number of elements in the array of names and the number of indices that may be written to . contains a list of name strings identifying the uniform names to be queried for indices. For each name string in , the index assigned to the active uniform of that name will be written to the corresponding element of . If a string in is not the name of an active uniform, the value INVALID_INDEX will be written to the corresponding element of . If an error occurs, nothing is written to . The name of an active uniform may be queried from the corresponding uniform index by calling void GetActiveUniformName(uint program, uint uniformIndex, sizei bufSize, sizei* length, char* uniformName); is the name of a program object for which the command LinkProgram has been issued in the past. It is not necessary for to have been linked successfully. The link could have failed because the number of active uniforms exceeded the limit. must be an active uniform index of the program , in the range zero to the value of ACTIVE_UNIFORMS - 1. The value of ACTIVE_UNIFORMS can be queried with GetProgramiv. If is greater than or equal to the value of ACTIVE_UNIFORMS, the error INVALID_VALUE is generated. The name of the uniform identified by is returned as a null-terminated string in . The actual number of characters written into , excluding the null terminator, is returned in . If is NULL, no length is returned. The maximum number of characters that may be written into , including the null terminator, is specified by . The returned uniform name can be the name of built-in uniform state as well. The complete list of built-in uniform state is described in section 7.5 of the OpenGL Shading Language specification. The length of the longest uniform name in is given by the value of ACTIVE_UNIFORM_MAX_LENGTH, which can be queried with GetProgramiv. If GetActiveUniformName is not successful, nothing is written to or . Each uniform variable, declared in a shader, is broken down into one or more strings using the "." (dot) and "[]" operators, if necessary, to the point that it is legal to pass each string back into GetUniformLocation, for default uniform block uniform names, or GetUniformIndices, for named uniform block uniform names. Pg 80, replace description of GetActiveUniform Information about active uniforms can be obtained by calling either void GetActiveUniform(uint program, uint index, sizei bufSize, sizei* length, int* size, enum* type, char* name); or void GetActiveUniformsiv(uint program, sizei uniformCount, const uint* uniformIndices, enum pname, int* params); is the name of a program object for which the command LinkProgram has been issued in the past. It is not necessary for to have been linked successfully. The link could have failed because the number of active uniforms exceeded the limit. These commands provide information about the uniform or uniforms selected by or , respectively. In GetActiveUniform, an of 0 selects the first active uniform, and an of the value of ACTIVE_UNIFORMS - 1 selects the last active uniform. In GetActiveUniformsiv, is an array of such active uniform indices. If any index is greater than or equal to the value of ACTIVE_UNIFORMS, the error INVALID_VALUE is generated. For the selected uniform, GetActiveUniform returns the uniform name as a null-terminated string in . The actual number of characters written into , excluding the null terminator, is returned in . If is NULL, no length is returned. The maximum number of characters that may be written into , including the null terminator, is specified by . The returned uniform name can be the name of built-in uniform state as well. The complete list of built-in uniform state is described in section 7.5 of the OpenGL Shading Language specification. The length of the longest uniform name in is given by ACTIVE_UNIFORM_MAX_LENGTH. Each uniform variable, declared in a shader, is broken down into one or more strings using the "." (dot) and "[]" operators, if necessary, to the point that it is legal to pass each string back into GetUniformLocation, for default uniform block uniform names, or GetUniformIndices, for named uniform block uniform names. For the selected uniform, GetActiveUniform returns the type of the uniform into and the size of the uniform is into . The value in is in units of the uniform type, which can be any of the values in Table 2.utype. If one or more elements of an array are active, GetActiveUniform will return the name of the array in , subject to the restrictions listed above. The type of the array is returned in . The parameter contains the highest array element index used, plus one. The compiler or linker determines the highest index used. There will be only one active uniform reported by the GL per uniform array. GetActiveUniform will return as much information about active uniforms as possible. If no information is available, will be set to zero and will be an empty string. This situation could arise if GetActiveUniform is issued after a failed link. If an error occurs, nothing is written to , , , or . Type Name Token Keyword Type Name Token Keyword --------------- ------- --------------- ------- FLOAT float SAMPLER_1D sampler1D FLOAT_VEC2 vec2 SAMPLER_2D sampler2D FLOAT_VEC3 vec3 SAMPLER_3D sampler3D FLOAT_VEC4 vec4 SAMPLER_CUBE samplerCube INT int SAMPLER_1D_SHADOW sampler1DShadow INT_VEC2 ivec2 SAMPLER_2D_SHADOW sampler2DShadow INT_VEC3 ivec3 SAMPLER_1D_ARRAY_EXT sampler1DArray INT_VEC4 ivec4 SAMPLER_2D_ARRAY_EXT sampler2DArray UNSIGNED_INT unsigned int SAMPLER_1D_ARRAY_SHADOW_EXT sampler1DArrayShadow UNSIGNED_INT_VEC2_EXT uvec2 SAMPLER_2D_ARRAY_SHADOW_EXT sampler2DArrayShadow UNSIGNED_INT_VEC3_EXT uvec3 SAMPLER_CUBE_SHADOW_EXT samplerCubeShadow UNSIGNED_INT_VEC4_EXT uvec4 SAMPLER_2D_RECT_ARB sampler2DRect BOOL bool SAMPLER_2D_RECT_SHADOW_ARB sampler2DRectShadow BOOL_VEC2 bvec2 INT_SAMPLER_1D_EXT isampler1D BOOL_VEC3 bvec3 INT_SAMPLER_2D_EXT isampler2D BOOL_VEC4 bvec4 INT_SAMPLER_3D_EXT isampler3D FLOAT_MAT2 mat2 INT_SAMPLER_CUBE_EXT isamplerCube FLOAT_MAT3 mat3 INT_SAMPLER_1D_ARRAY_EXT isampler1DArray FLOAT_MAT4 mat4 INT_SAMPLER_2D_ARRAY_EXT isampler2DArray FLOAT_MAT2x3 mat2x3 UNSIGNED_INT_SAMPLER_1D_EXT usampler1D FLOAT_MAT2x4 mat2x4 UNSIGNED_INT_SAMPLER_2D_EXT usampler2D FLOAT_MAT3x2 mat3x2 UNSIGNED_INT_SAMPLER_3D_EXT usampler3D FLOAT_MAT3x4 mat3x4 UNSIGNED_INT_SAMPLER_CUBE_EXT usamplerCube FLOAT_MAT4x2 mat4x2 UNSIGNED_INT_SAMPLER_1D_ARRAY_EXT usampler1DArray FLOAT_MAT4x3 mat4x3 UNSIGNED_INT_SAMPLER_2D_ARRAY_EXT usampler2DArray SAMPLER_BUFFER_EXT samplerBuffer INT_SAMPLER_BUFFER_EXT isamplerBuffer UNSIGNED_INT_SAMPLER_BUFFER_EXT usamplerBuffer INT_SAMPLER_2D_RECT_EXT isampler2DRect UNSIGNED_INT_SAMPLER_2D_RECT_EXT usampler2DRect ----------------------------------------------------------------------- Table 2.utype: OpenGL Shading Language type tokens returned by GetActiveUniform and GetActiveUniformsiv, and corresponding shading language keywords declaring each such type. For GetActiveUniformsiv, indicates both the number of elements in the array of indices and the number of parameters written to upon successful return. identifies a property of each uniform in that should be written into the corresponding element of . If an error occurs, nothing will be written to . If is UNIFORM_TYPE, then an array identifying the types of the uniforms specified by the corresponding array of is returned. The returned types can be any of the values in Table 2.utype. If is UNIFORM_SIZE, then an array identifying the size of the uniforms specified by the corresponding array of is returned. The sizes returned are in units of the type returned by a query of UNIFORM_TYPE. For active uniforms that are arrays, the size is the number of active elements in the array; for all other uniforms, the size is one. If is UNIFORM_NAME_LENGTH, then an array identifying the length, including the terminating null character, of the uniform name strings specified by the corresponding array of is returned. If is UNIFORM_BLOCK_INDEX, then an array identifying the uniform block index of each of the uniforms specified by the corresponding array of is returned. The index of a uniform associated with the default uniform block is -1. If is UNIFORM_OFFSET, then an array of uniform buffer offsets is returned. For uniforms in a named uniform block, the returned value will be its offset, in basic machine units, relative to the beginning of the uniform block in the buffer object data store. For uniforms in the default uniform block, -1 will be returned. If is UNIFORM_ARRAY_STRIDE, then an array identifying the stride between elements, in basic machine units, of each of the uniforms specified by the corresponding array of is returned. The stride of a uniform associated with the default uniform block is -1. Note that this information only makes sense for uniforms that are arrays. For uniforms that are not arrays, but are declared in a named uniform block, an array stride of zero is returned. If is UNIFORM_MATRIX_STRIDE, then an array identifying the stride between columns of a column-major matrix or rows of a row-major matrix, in basic machine units, of each of the uniforms specified by the corresponding array of is returned. The matrix stride of a uniform associated with the default uniform block is -1. Note that this information only makes sense for uniforms that are matrices. For uniforms that are not matrices, but are declared in a named uniform block, a matrix stride of zero is returned. If is UNIFORM_IS_ROW_MAJOR, then an array identifying whether each of the uniforms specified by the corresponding array of is a row-major matrix or not is returned. A value of one indicates a row-major matrix, and a value of zero indicates a column-major matrix, a matrix in the default uniform block, or a non-matrix. Pg 81, replace Uniform* description with: To load values into the uniform variables of the default uniform block of the program object that is currently in use, use the commands ... The given values are loaded into the default uniform block uniform variable location identified by . Sub-section 2.15.3.1 - Uniform Blocks The values of uniforms arranged in named uniform blocks are extracted from buffer object storage. The mechanisms for placing individual uniforms in a buffer object and connecting a uniform block to an individual buffer object are described below. There is a set of implementation-dependent maximums for the number of active uniform blocks used by each shader (vertex, fragment, geometry). If the number of uniform blocks used by any shader in the program exceeds its corresponding limit, the program will fail to link. The limits for vertex, fragment, and geometry shaders can be obtained by calling GetIntegerv with values of MAX_VERTEX_UNIFORM_BLOCKS, MAX_FRAGMENT_UNIFORM_BLOCKS, and MAX_GEOMETRY_UNIFORM_BLOCKS, respectively. Additionally, there is an implementation-dependent limit on the sum of the number of active uniform blocks used by each shader of a program. If a uniform block is used by multiple shaders, each such use counts separately against this combined limit. The combined uniform block use limit can be obtained by calling GetIntegerv with a of MAX_COMBINED_UNIFORM_BLOCKS. When a named uniform block is declared by multiple shaders in a program, it must be declared identically in each shader. The uniforms within the block must be declared with the same names and types, and in the same order. If a program contains multiple shaders with different declarations for the same named uniform block differs between shader, the program will fail to link. Sub-section 2.15.3.1.1 - Uniform Buffer Object Storage When stored in buffer objects associated with uniform blocks, uniforms are represented in memory as follows: - Members of type "bool" are extracted from a buffer object by reading a single uint-typed value at the specified offset. All non-zero values correspond to true, and zero corresponds to false. - Members of type "int" are extracted from a buffer object by reading a single int-typed value at the specified offset. - Members of type "uint" are extracted from a buffer object by reading a single uint-typed value at the specified offset. - Members of type "float" are extracted from a buffer object by reading a single float-typed value at the specified offset. - Vectors with elements with basic data types of "bool", "int", "uint", or "float" are extracted as values in consecutive memory locations beginning at the specified offset, with components stored in order with the first (X) component at the lowest offset. The GL data type used for component extraction is derived according to the rules for scalar members above. - Column-major matrices with columns and rows (using the type "matx", or simply "mat" if ==) are treated as an array of floating-point column vectors, each consisting of components. The column vectors will be stored in order, with column zero at the lowest offset. The difference in offsets between consecutive columns of the matrix will be referred to as the column stride, and is constant across the matrix. The column stride, UNIFORM_MATRIX_STRIDE, is an implementation-dependent value and may be queried after a program is linked. - Row-major matrices with columns and rows (using the type "matx", or simply "mat" if ==) are treated as an array of floating-point row vectors, each consisting of components. The row vectors will be stored in order, with row zero at the lowest offset. The difference in offsets between consecutive rows of the matrix will be referred to as the row stride, and is constant across the matrix. The row stride, UNIFORM_MATRIX_STRIDE, is an implementation-dependent value and may be queried after a program is linked. - Arrays of scalars, vectors, and matrices are stored in memory by element order, with array member zero at the lowest offset. The difference in offsets between each pair of elements in the array in basic machine units is referred to as the array stride, and is constant across the entire array. The array stride, UNIFORM_ARRAY_STRIDE, is an implementation-dependent value and may be queried after a program is linked. Sub-section 2.15.3.1.2 - Standard Uniform Block Layout By default, uniforms contained within a uniform block are extracted from buffer storage in an implementation-dependent manner. Applications may query the offsets assigned to uniforms inside uniform blocks with query functions provided by the GL. The "layout" qualifier provides shaders with control of the layout of uniforms within a uniform block. When the "std140" layout is specified, the offset of each uniform in a uniform block can be derived from the definition of the uniform block by applying the set of rules described below. If a uniform block is declared in multiple shaders linked together into a single program, the link will fail unless the uniform block declaration, including layout qualifier, are identical in all such shaders. When using the "std140" storage layout, structures will be laid out in buffer storage with its members stored in monotonically increasing order based on their location in the declaration. A structure and each structure member have a base offset and a base alignment, from which an aligned offset is computed by rounding the base offset up to a multiple of the base alignment. The base offset of the first member of a structure is taken from the aligned offset of the structure itself. The base offset of all other structure members is derived by taking the offset of the last basic machine unit consumed by the previous member and adding one. Each structure member is stored in memory at its aligned offset. The members of a top-level uniform block are laid out in buffer storage by treating the uniform block as a structure with a base offset of zero. (1) If the member is a scalar consuming basic machine units, the base alignment is . (2) If the member is a two- or four-component vector with components consuming basic machine units, the base alignment is 2 or 4, respectively. (3) If the member is a three-component vector with components consuming basic machine units, the base alignment is 4. (4) If the member is an array of scalars or vectors, the base alignment and array stride are set to match the base alignment of a single array element, according to rules (1), (2), and (3), and rounded up to the base alignment of a vec4. The array may have padding at the end; the base offset of the member following the array is rounded up to the next multiple of the base alignment. (5) If the member is a column-major matrix with columns and rows, the matrix is stored identically to an array of column vectors with components each, according to rule (4). (6) If the member is an array of column-major matrices with columns and rows, the matrix is stored identically to a row of * column vectors with components each, according to rule (4). (7) If the member is a row-major matrix with columns and rows, the matrix is stored identically to an array of row vectors with components each, according to rule (4). (8) If the member is an array of row-major matrices with columns and rows, the matrix is stored identically to a row of * row vectors with components each, according to rule (4). (9) If the member is a structure, the base alignment of the structure is , where is the largest base alignment value of any of its members, and rounded up to the base alignment of a vec4. The individual members of this sub-structure are then assigned offsets by applying this set of rules recursively, where the base offset of the first member of the sub-structure is equal to the aligned offset of the structure. The structure may have padding at the end; the base offset of the member following the sub-structure is rounded up to the next multiple of the base alignment of the structure. (10) If the member is an array of structures, the elements of the array are laid out in order, according to rule (9). For uniform blocks laid out according to these rules, the minimum buffer object size returned by the UNIFORM_BLOCK_DATA_SIZE query is derived by taking the offset of the last basic machine unit consumed by the last uniform of the uniform block (including any end-of-array or end-of-structure padding), adding one, and rounding up to the next multiple of the base alignment required for a vec4. Sub-section 2.15.3.2 - Uniform Buffer Object Bindings The value an active uniform inside a named uniform block is extracted from the data store of a buffer object bound to one of an array of uniform buffer binding points. The number of binding points can be queried using GetIntegerv with the constant MAX_UNIFORM_BUFFER_BINDINGS. Buffer objects are bound to uniform block binding points by calling one of the commands void BindBufferRange(enum target, uint index, uint buffer, intptr offset, sizeiptr size); void BindBufferBase(enum target, uint index, uint buffer); with set to UNIFORM_BUFFER. There is an array of buffer object binding points with which uniform blocks can be associated via UniformBlockBinding, plus a single general binding point that can be used by other buffer object manipulation functions (e.g. BindBuffer, MapBuffer). Both commands bind the buffer object named by to the general binding point, and additionally bind the buffer object to the binding point in the array given by . The error INVALID_VALUE is generated if is greater than or equal to the value of MAX_UNIFORM_BUFFER_BINDINGS. For BindBufferRange, specifies a starting offset into the buffer object , and specifies the amount of data that can be read from the buffer object while used as the storage for a uniform block. Both and are in basic machine units. An INVALID_VALUE error is generated if is less than or equal to zero or if is not a multiple of the implementation-dependent required alignment (the value of UNIFORM_BUFFER_OFFSET_ALIGNMENT). BindBufferBase binds the entire buffer, even when the size of the buffer is changed after the binding is established. It is equivalent to calling BindBufferRange with zero, while is determined by the size of the bound buffer at the time the binding is used. Regardless of the size specified with BindBufferRange, or indirectly with BindBufferBase, the GL will never read or write beyond the end of a bound buffer. This may result in visibly different behavior when a buffer overflow would otherwise result. Each of a program's active uniform blocks has a corresponding uniform buffer object binding point. This binding point can be assigned by calling: void UniformBlockBinding(uint program, uint uniformBlockIndex, uint uniformBlockBinding); is a name of a program object for which the command LinkProgram has been issued in the past. must be an active uniform block index of the program . Otherwise, INVALID_VALUE is generated. must be less than MAX_UNIFORM_BUFFER_BINDINGS. Otherwise, INVALID_VALUE is generated. If successful, UniformBlockBinding specifies that will use the data store of the buffer object bound to the binding point to extract the values of the uniforms in the uniform block identified by . The results of Begin or commands that perform an implicit Begin are undefined when an active uniform block of the active program is assigned a uniform buffer binding point where the parameter to BindBufferRange is less than the value of UNIFORM_BLOCK_DATA_SIZE for that uniform block, or when no buffer object is bound to that binding point, and may result in GL interruption or termination. When executing shaders that access uniform blocks, the binding point corresponding to each active uniform block must be populated with a buffer object with a size no smaller than the minimum required size of the uniform block (UNIFORM_BLOCK_DATA_SIZE). For binding points populated by BindBufferRange, the size in question is the value of the parameter. If any active uniform block is not backed by a sufficiently large buffer object, the results of shader execution are undefined, and may result in GL interruption or termination. Shaders may be executed to process the primitives and vertices specified between Begin and End commands or by Draw* or MultiDraw* commands (see section 2.8). Shaders may also be executed as a result of DrawPixels, Bitmap, or RasterPos* commands. When a program object is linked or re-linked, the uniform buffer object binding point assigned to each of its active uniform blocks is reset to zero. Additions to Chapter 3 - Rasterization 3.11.1 Shader Variables, p. 196 Replace the second two sentences with: The amount of storage available for fragment shader uniform variables in the default uniform block is specified by the value of the implementation- dependent constant MAX_FRAGMENT_UNIFORM_COMPONENTS. The total amount of combined storage available for fragment shader uniform variables in all uniform blocks (including the default uniform block) is specified by the value of the implementation-dependent constant MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS. These values represent the numbers of individual floating-point, integer, or boolean values that can be held in uniform variable storage for a fragment shader. Additions to Chapter 4 - Per-Fragment Operations and the Framebuffer None Additions to Chapter 5 - State and State Requests 5.4 Display Lists, p. 244 Add the following language to the list of commands excluded from display list compilation: "Buffer objects: BindBufferRange, BindBufferBase" Additions to Chapter 6 - State and State Requests 6.1.1 Simple Queries, p. 247 Add the following paragraph: Indexed simple state variables are queried with the command void GetIntegeri_v(enum target, uint index, int* data); is the name of the indexed state and is the index of the particular element being queried. is a pointer to a scalar or array of the indicated type in which to place the returned data. An INVALID_VALUE error is generated if is outside the valid range for the indexed state . 6.1.13 Buffer Object Queries, p. 260 Add after description of GetBufferPointerv: To query which buffer objects are bound to the array of uniform buffer binding points and will be used as the storage for active uniform blocks, call GetIntegeri_v with set to UNIFORM_BUFFER_BINDING. must be in the range zero to the value of MAX_UNIFORM_BUFFER_BINDINGS - 1. The name of the buffer object bound to is returned in . If no buffer object is bound for , zero is returned in . To query the starting offset or size of the range of each buffer object binding used for uniform buffers, call GetIntegeri_v with set to UNIFORM_BUFFER_START or UNIFORM_BUFFER_SIZE respectively. must be in the range zero to the value of MAX_UNIFORM_BUFFER_BINDINGS - 1. If the parameter (starting offset or size) was not specified when the buffer object was bound (e.g. if bound with BindBufferBase), or if no buffer object is bound to , zero is returned. 6.1.14 Shader and Program Queries Pg 261, continuation of paragraph defining "GetProgramiv" If is ACTIVE_UNIFORM_BLOCKS the number of uniform blocks for containing active uniforms is returned. If is ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, the length of the longest active uniform block name, including the null terminator, is returned. Pg 263, replace GetUniform{f|i}v description with: ... return the value or values of the uniform at location of the default uniform block for program object ... GLX Protocol GLX protocol for BindBufferRange, BindBufferBase and GetIntegeri_v was added through NV_transform_feedback and EXT_draw_buffers2 protocol specs. The following rendering commands are sent to the server as part of a glXRender request: UniformBlockBinding 2 16 rendering command length 2 366 rendering command opcode 4 CARD32 program 4 CARD32 uniformBlockIndex 4 CARD32 uniformBlockBinding The following non-rendering commands are added: GetUniformIndices 1 CARD8 opcode(X assigned) 1 215 GLX opcode 2 4+n+(s+p)/4 request length 4 GLX_CONTEXT_TAG context tag 4 CARD32 program 4 CARD32 uniformCount n LISTofINT32 lengths[n], n = uniformCount, lengths[i] = strlen(uniformNames[i]) + 1, 0 <= i < n. s LISTofCHAR uniformNames, s = length[0]+...+length[n-1]. array p unused, p = pad(s) => 1 1 reply 1 unused 2 CARD16 sequence number 4 n reply length 4 unused 4 CARD32 n (number of uniform Indices) if (n == 1) this follows: 4 CARD32 uniformIndices 12 unused otherwise this follows: 16 unused 4*n LISTofCARD32 uniformIndices GetActiveUniformsiv 1 CARD8 opcode(X assigned) 1 216 GLX opcode 2 5+n request length 4 GLX_CONTEXT_TAG context tag 4 CARD32 program 4 INT32 uniformCount(n) 4 ENUM pname n LISTofCARD32 uniformIndices => 1 1 reply 1 unused 2 CARD16 sequence number 4 n reply length 4 unused if (n == 1) this follows: 4 INT32 params 12 unused otherwise this follows: 16 unused 4*n LISTofINT32 params GetActiveUniformName 1 CARD8 opcode(X assigned) 1 217 GLX opcode 2 5 request length 4 GLX_CONTEXT_TAG context tag 4 CARD32 program 4 CARD32 uniformIndex 4 INT32 bufsize => 1 1 reply 1 unused 2 CARD16 sequence number 4 m reply length, m = (n+p)/4 4 unused 4 INT32 n 16 unused n LISTofCHAR uniformName, n = strlen(uniformName)+1 p unused, p=pad(n) GetUniformBlockIndex 1 CARD8 opcode(X assigned) 1 218 GLX opcode 2 3+(n+p)/4 request length 4 GLX_CONTEXT_TAG context tag 4 CARD32 program n LISTofCHAR uniformBlockName, n = strlen(uniformBlockName)+1 p unused, p=pad(n) => 1 1 reply 1 unused 2 CARD16 sequence number 4 0 reply length 4 CARD32 return value 20 unused GetActiveUniformBlockiv 1 CARD8 opcode(X assigned) 1 219 GLX opcode 2 5 request length 4 GLX_CONTEXT_TAG context tag 4 CARD32 program 4 CARD32 uniformBlockIndex 4 ENUM pname => 1 1 reply 1 unused 2 CARD16 sequence number 4 n reply length 4 unused if (n == 1) this follows: 4 INT32 params 12 unused otherwise this follows: 16 unused 4*n LISTofINT32 params GetActiveUniformBlockName 1 CARD8 opcode(X assigned) 1 220 GLX opcode 2 5 request length 4 GLX_CONTEXT_TAG context tag 4 CARD32 program 4 CARD32 uniformBlockIndex 4 INT32 bufsize => 1 1 reply 1 unused 2 CARD16 sequence number 4 m reply length, m = (n+p)/4 4 unused 4 INT32 n 16 unused n LISTofCHAR uniformBlockName, n = strlen(uniformBlockName)+1 p unused, p=pad(n) OpenGL Shading Language Spec v1.20.8 Updates Including the following line in a shader can be used to control the language features described in this extension: #extension GL_ARB_uniform_buffer_object : where is as specified in section 3.3. A new preprocessor #define is added to the OpenGL Shading Language: #define GL_ARB_uniform_buffer_object 1 Add two new sections: 4.3.5.1 Uniform Blocks Variable declarations at global scope can be grouped into a named block to provide coarser granularity for manipulation, sharing, or backing than is achievable with individual declarations. This is currently only allowed for uniform variables grouped into uniform blocks. All other uses are reserved. The application backs a uniform block with a buffer. This allows application access to a set of uniform variables through a single buffer. The application will need to query the offsets of the variables within the block or follow standard rules for block layout in order to know how to layout the contents of a buffer used to back the block. A uniform block (rather than a uniform variable) is created by the uniform keyword, followed by a block name, followed by an open curly brace ( { ) as follows: uniform-block : layout-qualifieropt uniform block-name { member-list } ; layout-qualifier : layout ( layout-qualifier-id-list ) member-list : member-declaration member-declaration member-list member-declaration : layout-qualifieropt uniformopt basic-type declarators ; Where declarators are the same as for other uniform variable declarations, except initializers are not allowed. Layout qualifiers are defined in the next section. For example, uniform Transform { mat4 ModelViewMatrix; mat4 ModelViewProjectionMatrix; uniform mat3 NormalMatrix; // reuse of uniform is optional float Deformation; }; The above establishes a uniform block named "Transform" with four uniforms grouped inside it. The names declared inside the block are accessed as if they were declared outside the block. In no way does the shader ever access block members through any use of block-name. Uniform block names and variable names declared within uniform blocks are scoped at the program level. Matching block names from multiple compilation units in the same program must match in terms of having the same number of declarations with the same sequence of types and the same sequence of member names, as well as having the same member-wise layout qualification (see next section). Any mismatch will generate a link error. Sampler types are not allowed inside of uniform blocks. All other types, arrays, and structures allowed for uniforms are allowed within a uniform block. There is an implementation-dependent limit on the number of uniform blocks that can be used per stage. If this limit is exceeded, it will cause a link error. 4.3.5.2 Uniform Block Layout Qualifiers The layout-qualifier-id-list for uniform blocks is a comma separated list of the following qualifiers: shared (default) packed std140 row_major column_major (default) These qualifiers are identifiers, not keywords. None of these have any semantic affect at all on the usage of the variables being declared; they only describe how data is laid out in memory. For example, matrix semantics are always column-based, as described in the rest of this specification, no matter what layout qualifiers are being used. Uniform block layout qualifiers can be declared at global scope, on a single uniform block, or on a single block member. At global scope, it is an error to use layout qualifiers to declare a variable. Instead, at global scope, layout qualifiers apply just to the keyword uniform and establish default qualification for subsequent blocks: layout-defaults : layout-qualifier uniform ; When this is done, the previous default qualification is first inherited and then overridden as per the override rules listed below for each qualifier listed in the declaration. The result becomes the new default qualification scoped to subsequent uniform block definitions. Layout defaults can only be specified at global scope. The initial state of compilation is as if the following were declared: layout(shared, column_major) uniform; Explicitly declaring this in a shader will return defaults back to their initial state. Uniform blocks can be declared with optional layout qualifiers, and so can their individual member declarations. Such block layout qualification is scoped only to the content of the block. As with global layout declarations, block layout qualification first inherits from the current default qualification and then overrides it. Similarly, individual member layout qualification is scoped just to the member declaration, and inherits from and overrides the block's qualification. The shared qualifier overrides only the std140 and packed qualifiers; other qualifiers are inherited. The compiler/linker will ensure that multiple programs and programmable stages containing this definition will share the same memory layout for this block, as long as they also matched in their row_major and/or column_major qualifications. This allows use of the same buffer to back the same block definition across different programs. The packed qualifier overrides only std140 and shared; other qualifiers are inherited. When packed is used, no shareable layout is guaranteed. The compiler and linker can optimize memory use based on what variables actively get used and on other criteria. Offsets must be queried, as there is no other way of guaranteeing where (and which) variables reside within the block. Attempts to share a packed uniform block across programs or stages will generally fail. However, implementations may aid application management of packed blocks by using canonical layouts for packed blocks. The std140 qualifier overrides only the packed and shared qualifiers; other qualifiers are inherited. The layout is explicitly determined by this, as described in the API specification section 2.15.3.1.2. Hence, as in shared above, the resulting layout is shareable across programs. Layout qualifiers on member declarations cannot use the shared, packed, or std140 qualifiers. These can only be used at global scope or on a block declaration. The row_major qualifier overrides only the column_major qualifier; other qualifiers are inherited. It only affects the layout of matrices. Elements within a matrix row will be contiguous in memory. The column_major qualifier overrides only the row_major qualifier; other qualifiers are inherited. It only affects the layout of matrices. Elements within a matrix column will be contiguous in memory. When multiple arguments are listed in a layout declaration, the affect will be the same as if they were declared one at a time, in order from left to right, each in turn inheriting from and overriding the result from the previous qualification. For example layout(row_major, column_major) results in the qualification being column_major. Other examples: layout(shared, row_major) uniform; // default is now shared & row_major layout(std140) uniform Transform { // layout of this block is std140 mat4 M1; // row_major layout(column_major) mat4 M2; // column major mat3 N1; // row_major }; uniform T2 { // layout of this block is shared ... }; layout(column_major) uniform T3 { // shared and column_major mat4 M3; // column_major layout(row_major) mat4 m4; // row major mat3 N2; // column_major }; Interactions with OpenGL 3.0 If OpenGL 3.0 is supported, the introduction of BindBufferBase and BindBufferRange can be ignored, though the uniform buffer object language herein will need to be merged with the transform feedback language in GL 3.0. If OpenGL 3.0 is supported, the introduction of GetIntegeri_v can be ignored. If OpenGL 3.0 is supported, change: "When a program is successfully linked, all active uniforms belonging to the program object's default uniform block are initialized to zero (FALSE for booleans). A successful link will also generate a location for each active uniform in the default uniform block. The values of active uniforms in the default uniform block can be changed using this location and the appropriate Uniform* command (see below)." to "When a program is successfully linked, all active uniforms belonging to the program object's default uniform block are initialized as defined by the version of the OpenGL Shading Language used to compile the program. A successful link will also generate a location for each active uniform in the default uniform block. The values of active uniforms in the default uniform block can be changed using this location and the appropriate Uniform* command (see below)." If OpenGL 3.0 is supported, replace "Begin or commands that perform an implicit Begin" with "Draw* commands." If OpenGL 3.0 is supported, UNIFORM_BUFFER is a valid target for new buffer-related API, e.g. MapBufferRange. Interactions with EXT_gpu_shader4 If EXT_gpu_shader4 is not supported, then all of the types in table 2.utype with extension suffixes should be omitted. Interactions with ARB_texture_rectangle If ARB_texture_rectangle is not available, then all of the types in table 2.utype with RECT in their names should be omitted. Interactions with EXT_texture_array If EXT_texture_array is not available, then all of the types in table 2.utype with ARRAY in their names should be omitted. Interactions with EXT_texture_buffer_object If EXT_texture_buffer_object is not available, then all of the types in table 2.utype with BUFFER in their names should be omitted. Interactions with EXT_texture_integer If EXT_texture_integer is not available, then all of the types in table 2.utype with UNSIGNED_INT or INT_SAMPLER in their names should be omitted. Interactions with ARB_geometry_shader4 If ARB_geometry_shader4 is not supported, omit all mentions of the geometry shader stage, including MAX_GEOMETRY_UNIFORM_BUFFERS and UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER. The minimum value of MAX_COMBINED_UNIFORM_BLOCKS and MAX_UNIFORM_BUFFER_BINDINGS changes from 36 to 24. Language describing MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS can be found in the ARB_geometry_shader4 specification. Errors The error INVALID_OPERATION is generated by BindBufferRange and BindBufferBase if is not the name of a valid buffer object. The error INVALID_VALUE is generated by GetUniformIndices, GetActiveUniformsiv, GetActiveUniformName, GetUniformBlockIndex, GetActiveUniformBlockiv, GetActiveUniformBlockName, and UniformBlockBinding if is not a value generated by GL. The error INVALID_VALUE is generated by GetUniformIndices and GetActiveUniformsiv if is less than zero. The error INVALID_VALUE is generated by GetActiveUniformName and GetActiveUniformBlockName if is less than zero. The error INVALID_VALUE is generated by BindBufferRange if is less than zero. The error INVALID_VALUE is generated by GetActiveUniformName if is greater than or equal to ACTIVE_UNIFORMS. The error INVALID_VALUE is generated by GetActiveUniformsiv if any of the indices in is greater than or equal to ACTIVE_UNIFORMS. The error INVALID_VALUE is generated by GetActiveUniformBlockiv, GetActiveUniformBlockName, and UniformBlockBinding if is greater than or equal to ACTIVE_UNIFORM_BLOCKS. The error INVALID_VALUE is generated by UniformBlockBinding if is greater than or equal to MAX_UNIFORM_BUFFER_BINDINGS. The error INVALID_VALUE is generated by BindBufferRange and BindBufferBase if is greater than or equal to MAX_UNIFORM_BUFFER_BINDINGS. The error INVALID_VALUE is generated by BindBufferRange if is not a multiple of UNIFORM_BUFFER_OFFSET_ALIGNMENT basic machine units. The error INVALID_ENUM is generated by GetActiveUniformsiv and GetActiveUniformBlockiv if is not one of the accepted values. The error INVALID_ENUM is generated by BindBufferRange and BindBufferBase if is not an accepted indexable buffer object target. New State Initial Get Value Type Get Command Value Description Sec Attribute -------------------------- ---- ----------- ----- ------------------------- ----- --------- UNIFORM_BUFFER_BINDING Z+ GetIntegerv 0 Uniform buffer object 2.15.3 - bound to the context for buffer object manipulation. UNIFORM_BUFFER_BINDING nxZ+ GetIntegeri_v 0 Uniform buffer object 2.15.3 - bound to the specified context binding point ACTIVE_UNIFORM_BLOCKS Z+ GetProgramiv 0 Number of active 2.15.3 - uniform blocks in a program ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH Z+ GetProgramiv 0 Length of longest active 2.15.3 - uniform block name UNIFORM_TYPE 0*xZ_27 GetActiveUniformsiv - Type of active uniform 2.15.3 - UNIFORM_SIZE 0*xZ+ GetActiveUniformsiv - Size of active uniform 2.15.3 - UNIFORM_NAME_LENGTH 0*xZ+ GetActiveUniformsiv - Uniform name length 2.15.3 - UNIFORM_BLOCK_INDEX 0*xZ GetActiveUniformsiv - Uniform block index 2.15.3 - UNIFORM_OFFSET 0*xZ GetActiveUniformsiv - Uniform buffer offset 2.15.3 - UNIFORM_ARRAY_STRIDE 0*xZ GetActiveUniformsiv - Uniform buffer array 2.15.3 - stride UNIFORM_MATRIX_STRIDE 0*xZ GetActiveUniformsiv - Uniform buffer intra- 2.15.3 - matrix stride UNIFORM_IS_ROW_MAJOR 0*xZ+ GetActiveUniformsiv - Whether uniform is a 2.15.3 - row-major matrix UNIFORM_BLOCK_BINDING 0*xZ+ GetActiveUniformBlockiv 0 Uniform buffer binding 2.15.3 - points associated with the specified uniform block UNIFORM_BLOCK_DATA_SIZE 0*xZ+ GetActiveUniformBlockiv - Size of the storage 2.15.3 - needed to hold this uniform block's data UNIFORM_BLOCK_ACTIVE_UNIFORMS 0*xZ+ GetActiveUniformBlockiv - Count of active 2.15.3 - uniforms in the specified uniform block UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0*xnxZ+ GetActiveUniformBlockiv - Array of active 2.15.3 - uniform indices of the specified uniform block UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0*xB GetActiveUniformBlockiv 0 TRUE if uniform block 2.15.3 - is actively referenced by the vertex shader UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0*xB GetActiveUniformBlockiv 0 TRUE if uniform block 2.15.3 - is actively referenced by the geometry shader UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0*xB GetActiveUniformBlockiv 0 TRUE if uniform block 2.15.3 - is actively referenced by the fragment shader New Implementation Dependent State Minimum Get Value Type Get Command Value Description Sec Attribute -------------------------------- -- ----------- ----- ------------------------- ----- ---------- MAX_VERTEX_UNIFORM_BLOCKS Z+ GetIntegerv 12 Maximum number of vertex 2.15.3 - uniform buffers per program MAX_FRAGMENT_UNIFORM_BLOCKS Z+ GetIntegerv 12 Maximum number of fragment 2.15.3 - uniform buffers per program MAX_GEOMETRY_UNIFORM_BLOCKS Z+ GetIntegerv 12 Maximum number of geometry 2.15.3 - uniform buffers per program MAX_COMBINED_UNIFORM_BLOCKS Z+ GetIntegerv 36 Maximum number of uniform 2.15.3 - buffers per program MAX_UNIFORM_BUFFER_BINDINGS Z+ GetIntegerv 36 Maximum number of uniform 2.15.3 - buffer binding points on the context MAX_UNIFORM_BLOCK_SIZE Z+ GetIntegerv 16384 Max size in basic machine 2.15.3 - units of a uniform block MAX_VERTEX_UNIFORM_COMPONENTS Z+ GetIntegerv * Number of words for vertex 2.15.3 - shader uniform variables in default uniform block MAX_FRAGMENT_UNIFORM_COMPONENTS Z+ GetIntegerv * Number of words for fragment 2.15.3 - shader uniform variables in default uniform block MAX_GEOMETRY_UNIFORM_COMPONENTS Z+ GetIntegerv * Number of words for geometry 2.15.3 - shader uniform variables in default uniform block MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS Z+ GetIntegerv * Number of words for vertex 2.15.3 - shader uniform variables in all uniform blocks (including default) MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS Z+ GetIntegerv * Number of words for fragment 2.15.3 - shader uniform variables in all uniform blocks (including default) MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS Z+ GetIntegerv * Number of words for geometry 2.15.3 - shader uniform variables in all uniform blocks (including default) UNIFORM_BUFFER_OFFSET_ALIGNMENT Z+ GetIntegerv 1 Minimum required alignment 2.15.3 - for uniform buffer sizes and offsets * Minimum value for OpenGL 3.1 is (MAX__UNIFORM_BLOCKS * MAX_UNIFORM_BLOCK_SIZE) + MAX__UNIFORM_COMPONENTS. Minimum value prior to OpenGL 3.1 is MAX__UNIFORM_COMPONENTS. Sample Code //////////////////////////////////////////////////////////////////////////// Example: Full code of a simple use case: updating a group of variables in a real shader. //////////////////////////////////////////////////////////////////////////// //Platform-specific includes go here #define glError() { \ GLenum err = glGetError(); \ while (err != GL_NO_ERROR) { \ printf("glError: %s caught at %s:%u", \ (char*)gluErrorString(err), __FILE__, __LINE__); \ err = glGetError(); \ exit(-1); \ } \ } // globals int initialized = 0; int width=640; int height=480; GLfloat wf,hf; //uniform names GLchar* names[] = { "SurfaceColor", "WarmColor", "CoolColor", "DiffuseWarm", "DiffuseCool" }; GLuint buffer_id, uniformBlockIndex, index, vshad_id, fshad_id, prog_id; GLsizei uniformBlockSize; GLint singleSize, offset; GLfloat colors[] = { 0.45,0.45,1,1, 0.45,0.45,1,1, 0.75,0.75,0.75,1, 0.0,0.0,1.0,1, 0.0,1.0,0.0,1, }; void reshape(int w, int h) { width = w; height = h; wf = (GLfloat) width; hf = (GLfloat) height; glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0, wf/hf, 0.1, 100.0); } void init_opengl() { reshape(width, height); //load_shader and link_program are utility functions omitted here vshad_id = load_shader(GL_VERTEX_SHADER, "gooch.vs"); fshad_id = load_shader(GL_FRAGMENT_SHADER, "gooch.fs"); prog_id = glCreateProgram(); glAttachShader(prog_id, vshad_id); glAttachShader(prog_id, fshad_id); link_program(prog_id); //Update the uniforms using ARB_uniform_buffer_object glGenBuffers(1, &buffer_id); //There's only one uniform block here, the 'colors0' uniform block. //It contains the color info for the gooch shader. uniformBlockIndex = glGetUniformBlockIndex(prog_id, "colors0"); //We need to get the uniform block's size in order to back it with the //appropriate buffer glGetActiveUniformBlockiv(prog_id, uniformBlockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &uniformBlockSize); glError(); //Create UBO. glBindBuffer(GL_UNIFORM_BUFFER, buffer_id); glBufferData(GL_UNIFORM_BUFFER, uniformBlockSize, NULL, GL_DYNAMIC_DRAW); //Now we attach the buffer to UBO binding point 0... glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer_id); //And associate the uniform block to this binding point. glUniformBlockBinding(prog_id, uniformBlockIndex, 0); glError(); //To update a single uniform in a uniform block, we need to get its //offset into the buffer. glGetUniformIndices(prog_id, 1, &names[2], &index); glGetActiveUniformsiv(prog_id, 1, &index, GL_UNIFORM_OFFSET, &offset); glGetActiveUniformsiv(prog_id, 1, &index, GL_UNIFORM_SIZE, &singleSize); glError(); glViewport(0, 0, width, height); } void render() { glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT); glUseProgram(prog_id); glEnable(GL_DEPTH_TEST); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0, 0, -4); glColor3f(1.0, 1.0, 1.0); glBindBuffer(GL_UNIFORM_BUFFER, buffer_id); //We can use BufferData to upload our data to the shader, //since we know it's in the std140 layout glBufferData(GL_UNIFORM_BUFFER, 80, colors, GL_DYNAMIC_DRAW); //With a non-standard layout, we'd use BufferSubData for each uniform. glBufferSubData(GL_UNIFORM_BUFFER, offset, singleSize, &colors[8]); //the teapot winds backwards glFrontFace(GL_CW); glutSolidTeapot(1.33); glFrontFace(GL_CCW); glutSwapBuffers(); } void display() { if(!initialized) { init_opengl(); initialized = 1; } render(); } int main (int argc, const char** argv) { //GLUT initialization goes here } // Vertex shader for Gooch shading // Author: Randi Rost // Copyright (c) 2002-2006 3Dlabs Inc. Ltd. // See 3Dlabs-License.txt for license information vec3 LightPosition = vec3(0.0, 10.0, 4.0); varying float NdotL; varying vec3 ReflectVec; varying vec3 ViewVec; void main(void) { vec3 ecPos = vec3 (gl_ModelViewMatrix * gl_Vertex); vec3 tnorm = normalize(gl_NormalMatrix * gl_Normal); vec3 lightVec = normalize(LightPosition - ecPos); ReflectVec = normalize(reflect(-lightVec, tnorm)); ViewVec = normalize(-ecPos); NdotL = (dot(lightVec, tnorm) + 1.0) * 0.5; gl_Position = ftransform(); } // Fragment shader for Gooch shading, adapted for ARB_uniform_buffer_object #extension GL_ARB_uniform_buffer_object : enable layout(std140) uniform colors0 { float DiffuseCool; float DiffuseWarm; vec3 SurfaceColor; vec3 WarmColor; vec3 CoolColor; }; varying float NdotL; varying vec3 ReflectVec; varying vec3 ViewVec; void main (void) { vec3 kcool = min(CoolColor + DiffuseCool * SurfaceColor, 1.0); vec3 kwarm = min(WarmColor + DiffuseWarm * SurfaceColor, 1.0); vec3 kfinal = mix(kcool, kwarm, NdotL); vec3 nreflect = normalize(ReflectVec); vec3 nview = normalize(ViewVec); float spec = max(dot(nreflect, nview), 0.0); spec = pow(spec, 32.0); gl_FragColor = vec4 (min(kfinal + spec, 1.0), 1.0); } Examples The following example illustrates the rules specified by the "std140" layout. layout(std140) uniform Example { // Base types below consume 4 basic machine units // // base base align // rule align off. off. bytes used // ---- ------ ---- ---- ----------------------- float a; // 1 4 0 0 0..3 vec2 b; // 2 8 4 8 8..15 vec3 c; // 3 16 16 16 16..27 struct { // 9 16 28 32 (align begin) int d; // 1 4 32 32 32..35 bvec2 e; // 2 8 36 40 40..47 } f; // 9 16 48 48 (pad end) float g; // 1 4 48 48 48..51 float h[2]; // 4 16 52 64 64..67 (h[0]) // 80 80..83 (h[1]) // 4 16 84 96 (pad end of h) mat2x3 i; // 5/4 16 96 96 96..107 (i, column 0) // 112 112..123 (i, column 1) // 5/4 16 124 128 (pad end of i) struct { // 10 16 128 128 (align begin) uvec3 j; // 3 16 128 128 128..139 (o[0].j) vec2 k; // 2 8 140 144 144..151 (o[0].k) float l[2]; // 4 16 152 160 160..163 (o[0].l[0]) // 176 176..179 (o[0].l[1]) // 4 16 180 192 (pad end of o[0].l) vec2 m; // 2 8 192 192 192..199 (o[0].m) mat3 n[2]; // 6/4 16 200 208 208..219 (o[0].n[0], column 0) // 224 224..235 (o[0].n[0], column 1) // 240 240..251 (o[0].n[0], column 2) // 256 256..267 (o[0].n[1], column 0) // 272 272..283 (o[0].n[1], column 1) // 288 288..299 (o[0].n[1], column 2) // 6/4 16 300 304 (pad end of o[0].n) // 9 16 304 304 (pad end of o[0]) // 3 16 304 304 304..315 (o[1].j) // 2 8 316 320 320..327 (o[1].k) // 4 16 328 336 336..347 (o[1].l[0]) // 352 352..355 (o[1].l[1]) // 4 16 356 368 (pad end of o[1].l) // 2 8 368 368 368..375 (o[1].m) // 6/4 16 376 384 384..395 (o[1].n[0], column 0) // 400 400..411 (o[1].n[0], column 1) // 416 416..427 (o[1].n[0], column 2) // 432 432..443 (o[1].n[1], column 0) // 448 448..459 (o[1].n[1], column 1) // 464 464..475 (o[1].n[1], column 2) // 6/4 16 476 480 (pad end of o[1].n) // 9 16 480 480 (pad end of o[1]) } o[2]; }; Issues (1) How are offsets to elements in a uniform buffer correlated to uniform locations? Resolved: Traditional uniform locations were used in the glUniform API to access the private uniform storage. This API does not allow the use of glUniform to update uniforms stored in uniform blocks. Instead it uses the various means to update buffer objects, and exposes the byte offsets of the uniforms in the buffer object. So, in short, uniform locations and uniform offsets are similar concepts but unrelated. (2) Should uniforms declared bindable be excluded from a uniform buffer? Resolved: No, however, if a bindable uniform is declared inside a named uniform uniform block, the bindable declaration and all associated behavior of the bindable uniform extension will be superceded by the mechanisms defined in this extension to obtain information about the location of uniforms and to update the values of those uniforms. In other words, if the bindable modifier is used on a uniform declared within a named uniform block, it will be ignored. (3) Are there restrictions on the data types or the order in which uniforms are declared that are to be included as part of the uniform buffer? Resolved: The only restriction is that sampler uniforms can not be stored in a uniform buffer object. All other uniform types can be stored in a uniform block. (4) Should a uniform buffer be split into multiple uniform buffers on a per data type basis to simplify the buffer offset interface ? Resolved: No. This violates the intended "generic data store" convention of buffer objects. Users of this extension are free to group their uniform definitions on a per data-type basis in this manner and, indeed, it may, on some implementations, result in a more efficient uniform update model. (5) Should uniform buffers be scoped per shader (program stage) rather than per program (as in GLSL) ? Resolved: No, this extension does not change the per-program scope of uniforms. Uniforms in a uniform block, like traditional GLSL uniforms, are global to a program object. It's tricky because allowing uniforms to have per-stage scope exposes both a feature and the possibility for an application programming error. feature: an application that wants to use a uniform "foo" in two stages and wants uniform "foo" has different layouts and/or values in each stage (or possibly simply does not care if they do) vs. error: an application that wants to use a uniform "foo" in two stages and does not want them to have different values, but *accidentally* defines "foo" in each stage differently or binds different uniform buffers to each stage. Rather than enable this feature (and simultaneously add possibility for error) in this extension, we defer the choice to a future extension. Note however, some of the motivation for a per-stage scope for uniform names comes from a broader desire to augment the GLSL API with a set of per-stage program objects that do not need to be linked at all. This is possibly a valuable addition to the GL API, but is left to be defined by an additional extension. Such a future extension could, if desired, add syntax to the GLSL to allow any uniform (uniform block or default) to be defined with "per-stage" scope in a more comprehensive way. (6) Should AttachUniformBuffer take a argument? This issue is moot. Earlier versions of this extension included the additional ability to attach a uniform buffer object directly to a progam's uniform blocks instead of going through the per-context uniform buffer binding points. This feature has been deferred, possibly to be added in a future extension. If this routine were to be added and does not take a program argument, then it should work on the currently bound program object, and its name should be changed to ProgramUniformBuffer, to conform to precedent set by FramebufferTexture, et. all. Alternately, if AttachUniformBuffer requires a program argument, it would be for consistency with existing C API to GLSL (i.e., those that attach shaders to program objects and query program objects for information). RESOLUTION: RESOLVED, moot. (7) Should uniforms in a uniform block be identified by location or string? Resolved: By string and also by index (but not location). Name strings will be used to identify uniforms much as they are today. Uniform indices were available before for referring to uniforms because they provide a more efficient update mechanism to specify uniforms. Uniform block indices have been used in this extension for the same reason. The location API not used by this extension and is only relevant for the glUniform* API. RESOLUTION: RESOLVED, moot. (8) What is the order of operations under which a uniform buffer association is made with a program (or shader)? It is known that at very least, that the uniform buffer offsets and strides will be known at link time. Does the uniform buffer need to be attached to the program prior to linking in order to keep these offsets constant or can a uniform buffer be bound to a program at any time post-link effectively acting as substitute storage for the uniform data? RESOLVED: Uniform buffer objects are bound to the context's uniform buffer binding points, and this can happen at any time. However, the association of a program's uniform block to the context's uniform buffer binding points can only happen after linking because only then are uniform block indices known. (9) Can the existing Uniform API be used to update values in a uniform buffer? Resolved: No. The Uniform* API won't update values in a uniform buffer, which is reinforced by the fact that uniform block uniforms do not have a location. (10) When is the size of a uniform block's storage known? Resolved: Only after linking. Once a program is linked, the storage needed for a given uniform block can be determined by querying for UNIFORM_BLOCK_DATA_SIZE. If a uniform block needs more storage than the buffer object bound to the associated uniform buffer binding point can provide, results are undefined. This is no different than fetching off the end of an array. (11) Is it an error to call AttachUniformBuffer prior to linking the program designated by ? Resolved. This issue is moot because the AttachUniformBuffer was removed/deferred to a future extension. But if this API were added, then yes. INVALID_VALUE is generated if AttachUniformBuffer is used to attach a buffer to an invalid uniform block index. Prior to linking, there are no uniform block indices. (12) Some hardware does not support some of the GLSL data types natively (bools or ints perhaps). What limitations do we have in exposing the raw uniform data storage via the buffer object API ? Resolved: None, but note that some implementations without native support for these data types may have to copy the data in these data types into some more native data types. Also, queries are provided to expose the layout of the buffer objects to allow the buffers to be packed properly. (13) Are there expected limitations for dead uniform elimination using this extension? Resolved: yes. For starters, when using the "std140" layout, an implementation may not alter the storage layout in any way. This limitation includes dead uniform elimination. The standard layout must remain unchanged because an application will depend on it rather than querying for uniform offsets/strides. When using the "shared" layout, dead uniform elimination is again excluded because different uniforms could be eliminated based on different shaders' uniform usage. In order to preserve shareability of the uniform blocks, the full contingent of uniforms must remain. For the "packed" layout, an implementation may take the liberty of eliminating uniforms and uniform blocks that are not used by the paired shaders. Here, limitations exist only for arrays. Dead elements may be stripped from the end of an array that is never dynamically dereferenced. An application must query UNIFORM_SIZE before loading array data into the uniform buffer to ensure that trailing elements exist. Issue (24) deals with stripping leading elements from an array, and issue (25) deals with stripping arbitrary elements from an array, both of which are currently disallowed. Note that the default uniform block always exists even if it is empty. (14) Is it necessary to provide array uniform element offsets into a uniform buffer object? If so, this suggests string parsing of things such as "myuniform[12]". If not, this assumes array strides be guaranteed based on array data type for all hw platforms? Resolved: No. The stride is provided explictly by querying UNIFORM_ARRAY_STRIDE with GetActiveUniformsiv. (15) How are the values from static initializer values propagated to a buffer object once it is attached? Resolved: Static initialization values declared in a shader mapped to a uniform buffer are disallowed by the grammar and must be established through writes to the uniform buffer. (16) Is GetUniformBlockIndex needed? This information can be obtained (in reverse mapping) from GetActiveUniformBlock. Resolved: Yes. GetUniformBlockIndex allows the uniform block database to be queried in the most natural manner: step 1) do the expensive conversion from a uniform block name to a uniform block index, step 2) use the uniform block index to obtain all other uniform block data, which is a simple array dereference, not a search. (17) is GetUniformIndex needed? This information can be obtained (in reverse mapping) from GetActiveUniform. Resolved: Yes. See issue (16). (18) Should we add a separate function GetActiveUniformBlockBufferSize instead of using GetActiveUniformBlock to return everything. Resolved: No. This issue became moot when the more general function GetActiveUniformBlockiv was added. (19) Should we provide a mechanism for iterating over the uniforms in a particular uniform block? Resolved: Yes. This is provided by querying UNIFORM_BLOCK_ACTIVE_UNIFORMS with GetActiveUniformBlockiv. (20) Should we provide a means for the application to query the desired storage format for integers, booleans, and matrices, or should we specify a format and force non-conforming implementations to do a conversion? RESOLUTION: No queries will be introduced. Implementations that cannot handle the prescribed storage formats must convert as necessary. See also issue (48) (21) Should we delete the integer and boolean storage types in favor of implementation repacking of the data when the hardware doesn't support it? RESOLUTION: RESOLVED, no. Hardware that doesn't support the types must repack the uniform data if needed. This is true for all layout options. (22) How does the program notice new changes to the uniform buffer object? Should we add a new "UpdateUniforms()" call or use AttachUniformBuffer(), or UseProgram() to realize changes. RESOLUTION: Following the "standard" way in which object changes are noticed, the buffer object in question must be re-bound or re-attached if the changes to the buffer object come from another context. If the changes come from this context, then the intent is to follow the general object model decision here that governs how child/container object state changes are made. [Currently, this means that changes by this context will be noticed at next draw time, at the latest]. (23) The naming convention choosen for GetActiveUniformsiv and GetActivePartitionsiv is not a simple matter. First, considering that the list of uniforms passed into these routines must be active uniform indices, and is an error if not, suggests that the name "Active" in these function calls is redundant. GLSL established a precedent of using "Active" in the names of functions that require their uniform parameters to consist solely of active uniforms. For these routines, it is an error to include an inactive uniform as one of their input parameters. Consistency with this GLSL precedent is the reason we've choosen to include "Active" in these routine names. Second, note that GetActiveUniformsiv does not "get active uniforms" and GetActiveUniformBlocksiv does not "get active uniform blocks". There is a compelling argument therefore that these names are counterintuitive. In reality, these routines return parameters of active uniforms and active uniform blocks rather than the uniforms or uniform blocks themselves. Again, looking back at GLSL precedent note the conventions used for both GetProgramiv and GetShaderiv. Both of these routines have a argument and both of these routines are in fact returning parameters of programs and shaders respectively however "Parameters" was not included in the name. Further challenging this second point are two other considerations. First, the GL spec prior to GLSL does in fact use "Parameters" in the name of functions that match this pattern. Second, this spec itself includes the name of the output parameter in the name (specifically calls to get Indices and Names). In the end, because this specification has to work within the GLSL framework, it was decided that this precendent should prevail over all others. Therefore, these routines will not include "Parameters" in their names. Resolved: See above. (24) Do we need to be able to query UNIFORM_START to get the index of the first active element of an array? An application must query UNIFORM_SIZE to find the extent of an array at runtime because the GLSL compiler may have eliminated elements from the end of a static array during dead code elimination. If the application is not required to similarly query UNIFORM_START, the compiler must be prevented from eliminating elements from the start of an array. For example, if an application declares "uniform float myFloat[10];" and accesses only the single element myFloat[7] in the shader text, the compiler may eliminate elements 8-9 only. Querying UNIFORM_SIZE will give 8, and UNIFORM_OFFSET will give the offset of element 0. If we add UNIFORM_START, in this example, querying UNIFORM_SIZE will give 1, UNIFORM_START will give 7, and UNIFORM_OFFSET will give the offset of element 7 in the uniform buffer. Purely for symmetry, it seems that the compiler should be as free to strip leading elements as it is to strip trailing elements. After additional discussions, however, the working group decided not to introduce this complexity. This feature could be layered as an additional extension if desired. RESOLUTION: RESOLVED (25) Following issue (24), should we provide a mechanism to allow the compiler to strip *any* dead elements from a uniform array without restriction, not just leading and trailing elements? Resolved: No. Too cumbersome for the application to use. (26) Should we make any guarantees about the ordering of uniforms in the active uniform array, relative to their uniform block number? It might be useful to guarantee that the ordering of the uniforms in the active uniform array is such that all uniforms in a single uniform block form a contiguous subrange of the active uniform array. On the other hand, just knowing the order is probably not enough since you need to know offsets/strides, packing, etc. This extension provides uniform block-based uniform updates. This level of organization is efficient and requires no further augmentation as this issue suggests. RESOLUTION: RESOLVED, no (27) What is the difference between MAX_LOGICAL_UNIFORM_BUFFERS and MAX_COMBINED_UNIFORM_BUFFERS? MAX_LOGICAL_UNIFORM_BUFFERS is the maximum number of uniform buffer binding points on the context. MAX_COMBINED_UNIFORM_BUFFERS is the maximum number of uniform buffers that any one program can use at one time. Note, see issue (46) for a related issue with textures. RESOLUTION: RESOLVED (28) Should we have versions of GetActiveUniforms and GetActiveUniformBlocks that return intptr types so a cast is not required. No. Another extension can add them, and they have no real utility at this time except causing the app to allocate twice as much storage to store values that can't exceed 32 bits. RESOLUTION: RESOLVED, No. (29) Transform feedback writes primitive information to a buffer object tightly arranged and in accordance with the size of the attributes designated for transform feedback (or varyings thereof). If uniform buffers are to leverage data supplied from the transform feedback operation, yet uniforms are not guaranteed to be tightly packed, how can one reasonably use transform feedback to populate uniform buffers? DISCUSSION: As it stands, existing implementations pack uniform definitions on 16 byte boundaries, 4 byte boundaries or are tightly packed. If this is known for a given implementation, uniform declarations could of course be made such that they lined up on these boundaries. However, without a dedicated queryable interface in the GL C API, there is no way to guarantee the portability of this logic. RESOLUTION: resolved, compatibility with XFB output is only guaranteed for vec4 types in a "std140" layout uniform block: In order to facilitate the read-only nature of uniform and transform feedback data formatting, we've added to this specification a uniform buffer "std140" layout qualifier guarantee of vec4 types being tightly packed. This layout guarantee will provide portability of applications that wish to use transform feedback in conjunction with uniform buffers as they can simply rely on this data arrangement, declaring their uniforms accordingly, to allow ARB_uniform_buffer_object and EXT_transform_feedback to interoperate. (30) Should the "active" keyword in shader text be declared per uniform or per uniform block ? Note, this issue is mostly moot, as we've decided to use a different syntax in the GLSL. Earlier versions of this spec leveraged the concept of 'active' uniforms from GLSL that were defined with the initial GLSL API. The discussion that follows pertains to a feature where the user can declare uniforms and uniform blocks as active explicitly. DISCUSSION: Declaring a uniform active has the advantages of simplicity and little additional spec language to describe behavior. When a uniform is declared active, all of its members are considered active (for structs and arrays) and therefore the arrangement of the data in that uniform can be guaranteed to be consistent. Consistency of this uniform data arrangement can be used to share the uniform across muliple programs without worrying about dead code elimination changing the offsets and strides of uniform data. Declaring uniform blocks active has some of the advantages that were primary motivating factors for this specficiation being written. Namely, that uniforms did not have to be aggregated into structures in order to update them efficiently. In this case, uniforms don't have to be aggregated into structs in order to share them easily. Another advantage is the logical distinction of a group of shared uniforms that is analogous to how the uniform buffer object, also a shared entity, that backs them. If a uniform uniform block is declared active, all uniforms therein are considered active. It is presumed under this model, that an advisable usage pattern would be to gather the declaration of shared uniforms of multiple shaders into an atomic shader source call. Then each individual shader would carry declarations of uniforms unique to themselves. GLSL allows piecewise declaration of uniforms in multiple modules in a program. Piecewise declaration of shared uniform blocks carries with it some difficulties because missing pieces can change the layout of the uniform block. A) Should we disallow piecewise construction of uniform blocks declared active by setting a compile time error if this is attempted ? RESOLVED: Yes, piecewise construction of uniform blocks will be allowed. Proposal for active uniform block demarcation: Active uniform blocks are declared as followed: active uniform block foo; uniform a; uniform b; uniform c; uniform block; The first uniform block delimiter names the uniform block. The second uniform block, with no name argument, terminates the "foo" uniform block and indicates that any subsequent uniform definition will be part of the default uniform block. Subsequent declarations referring to uniform block "foo" augment the contents of the uniform block. These subsequent declarations, of course, can appear within the same shader or within other shader sources in the same program. This aggregation mechanism, and the use of piece-wise definitions of uniform blocks, has sharing implications. Considering the following example: ***************************** PROGRAM A Text: active uniform block foo; uniform a; uniform b; uniform block; ***************************** PROGRAM B Text: active uniform block foo; uniform b; uniform a; uniform block; ... some place later in the program text active uniform block foo; uniform e; uniform d; uniform block; ***************************** Both the order and the number of uniforms in the aggregate definition of 'foo' in program B must be considered for sharing the uniform buffer backing A & B corresponding to uniform block 'foo'. First, order. To avoid potential confusion with order of declarations of uniforms, all uniforms declared in a uniform block will be sorted in an implementation defined manner. By doing so, the implementation will allow sharing of uniform buffers with identical uniform declarations by name, type and number, but arranged in different orders. Second, mismatches in declarations of uniforms within 'foo' between two different programs. Because uniforms are sorted, partial matches of uniform declarations within uniform blocks are not guaranteed to have the same offsets when the buffer is bound to different programs. In our example, there are no guarantees that the offset of uniform 'a' and the offset of uniform 'b' would be the same in uniform block foo of program 'A' when compared to program 'B'. Applications must therefore use care when attempting to share uniform buffers between multiple programs because any mismatch in uniform name or type or the number of uniforms themselves between uniform block declarations will result in offsets without correlation and application errors should be expected if any assumptions about these offsets is made otherwise. This sharing behavior if of particular significance when defining shaders as it suggests that the shaders themselves, if they choose to define uniform blocks piecewise across given program text. This sharing model suggests defining all uniform uniform blocks that are expected to be shared as standalone shader text definitions to logically segragate them from uniform block declarations that can be changed in a piecewise fashion. In this manner, the logically separated shared uniform uniform block can be handled as a distinct ShaderSource call and effectively act as a header file where the uniform block definition is guaranteed to be the same when used in multiple programs thus allowing sharing and consistent offsets. RESOLUTION: RESOLVED Partitions, uniforms, and varyings can all have the "active" keyword applied to them. See rules q - t in the rules and concepts list following the opening summary to this spec. The resolution of issue (34) to use struct-like syntax for uniform block definition closes the issue on piecewise definition of uniform blocks discussed above. (31) ActiveVaryingNV() uses the GL C API to declare a varying active in contrast to declaring uniforms/uniform uniform blocks active as suggested in this specification. Is this inconsistency a concern ? RESOLUTION: RESOLVED, moot. Earlier versions of this spec declared uniforms and uniform blocks as active, and optionally extended this to varyings as well. Later versions of this spec deferred this concept out of the extension. The declaring a varying as active via function call requires that this call is made prior to link time and that it identifies the varying using a name string. It is more efficient to manage program resources using indices and is better in terms of locality of reference to make 'active' declarations in program text. We should consider whether we might want to add this back in in a future extension. (32) GetVaryingLocationNV() returns -1 if the designated name doesn't exist. Should we return -1 rather than a special purposed token if a uniform name doesn't exist to follow this precedent ? RESOLUTION: RESOLVED This specification uses indices which are unsigned integers and therefore our unsigned value of 0xFFFFFFFF is not called "-1" but acts effectively the same on platforms where GLint is 32-bit twos-complement. Also note, uniform (and varying locations) are signed which allows them to use -1 as a signifier, but uniform (and uniform block) indices are unsigned because they are used to iterate through uniforms (and uniform blocks). (33) Which uniform buffer object commands must be excluded from display lists? RESOLUTION: Resolved When used with 3.1 (where display lists have been removed altogether) obviously, this question is moot. For GL 2.0/3.0, this should be resolved with the following precedents: BindUniformBlock should follow the precedent of BindBufferRange, which does not get included in display lists. UniformBlockBinding should follow the precedent of glUniform (for setting samplers) which *does* get included in display lists. Note, the GL 2.1 spec says (p.244, section 5.4) that "GL commands that source data from buffer objects dereference the buffer object data in question at display list compile time, rather than encoding the buffer ID and buffer offset into the display list. Only GL commands that are executed immediately, rather than being compiled into a display list, are permitted to use a buffer object as a data sink." The same rules would affect uniform blocks sourcing data from buffer objects. So this basically means that only BindUniformBlock is excluded, (since all queries are already excluded), however see issue (55). Since we use the BindBufferRange API introduced by OpenGL 3.0, and those routines are already excluded, there's no additions to the display list exclusion list needed. (34) What should the syntax of uniform block demarcation be ? DISCUSSION: The two following syntaxes were considered: uniform block foo; uniform a; uniform b; uniform block; In this example, the "uniform block" keyword both opens and closes the uniform block. Second, a struct-like syntax: uniform myUniformBlock { int a; vec4 b; }; and packed uniform myUniformBlock { int a; vec4 b; }; where "packed" means that the uniform block might be optimized by the compiler to eliminate/re-order uniforms. This is functionally equivalent to the current uniform block syntax in this spec. RESOLUTION: RESOLVED, using the "struct-like" syntax above. (35) Should UBOs be bound to context binding points rather than to programs themselves ? DISCUSSION: Attaching UBOs to programs versus the context has the following advantages: UBOs and programs have natural encapsulation boundaries that fit with the conventions of object-oriented design programming. Alternately, binding UBOs to the context has the following advantages: Migration to the possible program environment object design expected in future versions of OpenGL will be handled more easily and won't require a semantics change because these context bindings will all be moved collectively to the PEO and UBO attachments will not have to be handled as a "special case" item. If we support per-context per-stage bindings, then we'll need the following additions to this extension: - a set number of binding points on the context for each stage (vertex/fragment/geometry) VERTEX_SHADER_BINDING_0..n GEOMETRY_SHADER_BINDING_0..n FRAGMENT_SHADER_BINDING_0..n or alternately, a unified set of per context bindings SHADER_BINDING_0..n - a new routine to bind a UBO to a per-stage context binding point BindUniformBuffer(enum target, uint uniformBlockIndex, uint buffer); - a new routine that defines the mapping of a uniform block name string to a per-stage binding point index void UniformBlockBinding(uint program, uint unit, const char* name); RESOLUTION: RESOLVED, Note per-context and per-program bindings serve two distinct use cases. Per-context: assumes that there is generally many to one mapping between programs and given set of uniform buffers. Per-program: assumes that there is a one to one mapping between programs and a given set of uniform buffers. The original ARB "assembly-language" programming extensions serviced both use cases (with "program locals" and "program environment" parameters). The GLSL programming API dropped the "program environment" / per-context storage of uniforms in favor of per-program only storage for uniforms. This API currently supports only the context binding model, but a future extension could add the per-program-object bindings if desired. (36) How is the query for MAX_{FRAGMENT|VERTEX}_UNIFORM_COMPONENTS affected by UBOs? DISCUSSION: MAX_{FRAGMENT|VERTEX}_UNIFORM_COMPONENTS traditionally referred to the limited amount of dedicated (often register based, sometimes per-stage) uniform storage. For implementations that support directly reading uniforms from arbitrary memory, the limit on uniform storage is generally not quantified by a single number of uniforms. Instead it is quantified by two numbers: the number of separate buffers that can be read at one time (per stage), and the sizes of one of those buffers. On the other hand for implementations that wish to support this extension but that still have this limited amount of dedicated uniform storage this single MAX_{FRAGMENT|VERTEX}_UNIFORM_COMPONENTS value is still valid. RESOLUTION: Resolved, as follows: We added a new set of integer implementation-dependent queries, named MAX_COMBINED_{VERTEX|GEOMETRY|FRAGMENT}_UNIFORM_COMPONENTS. These would indicate the maximum total number of uniforms available between the default uniform block and all uniform blocks. For this ARB version of the extension, the minimum maximum would be MAX_{VERTEX|GEOMETRY|FRAGMENT}_UNIFORM_COMPONENTS. For the 3.1 core version, the minimum maximum would be larger: MAX_{VERTEX|GEOMETRY|FRAGMENT}_UNIFORM_BLOCKS * MAX_UNIFORM_BLOCK_SIZE + MAX_{VERTEX|GEOMETRY|FRAGMENT}_UNIFORM_COMPONENTS. (37) Do we need MAX_{VERTEX|GEOMETRY|FRAGMENT}_UNIFORM_BUFFERS or can we merge these into a single value MAX_UNIFORM_BUFFERS that is the same for the 3 stages? DISCUSSION: 3 separate queries is needed only if we think implementations would have different values for each stage. RESOLUTION: currently 3 queries, plus a "combined" query. (38) What's the deal with UniformBlockBinding()? How does it work? What is it for? DISCUSSION: UniformBlockBinding can be defined in two different ways, depending on the precedent we'd like to use. It can either be similar to a uniform sampler (i.e., an indirection table that can choose a particular buffer to use after linking), or an attribute location (i.e., an indirection table that can choose a particular buffer to use PRIOR to linking). The current API chooses the former precedent (i.e., uniform samplers), and as a result, UniformBlockBinding can be called (in fact, must be called) after linking the program. If we desired to change this behavior, we'd need to modify UniformBlockBinding to take a uniform block *name* intead of *index*, because a uniform block index is only defined post-link. This is workable, but slightly less flexible for the developer, at the cost of an indirection. RESOLUTION: Use the "sampler" precedent, UniformBlockBinding is called post link. (39) Does the matrix packing need to be "per program" state or "per implementation" state? DISCUSSION: Is the choice of matrix packing really "per program"? If not, should we just use the per-context queries for this information? The former might be useful if we intend to expose some kind of per-program packing control in the shading language or API. If we don't, then the latter might be simpler. Or do we think we might go further and make this per-uniform state in the future? if so, then the current per-program query is also insufficient. After discussion with the working group, queries for matrix (and all other uniform layout) will be per-uniform, not per program, so these routines have been removed. RESOLUTION: Resolved, this issue is moot. (40) Are uniform block indices assumed to be "tightly packed"? Yes, an implementation will assign consecutive indices to active uniform blocks, starting with zero. Note that there is no prescribed ordering in which indices must be assigned. In other words, which uniform block indices are assigned to which uniform blocks is an implementation choice. An application must call GetUniformBlockIndex to find the mapping. RESOLUTION: Resolved, yes. (41) Is "uniform block" the right name? The GLSL group considered many names here: "uniform blocks", "commons", "uniform groups", etc. Regardless of what the GLSL calls these groupings, we need *some name* that we can describe in the API spec and in the API names. Currently we use "uniform block" for this, and the API seems to make sense, but could change if someone has a better name. RESOLUTION: RESOLVED, yes. (42) Should there be an "offset" for the base of the ubo so that an application can use collections uniforms within a buffer object? DISCUSSION: If we do this, we'd need an additional/augmented version of BindUniformBuffer that takes an offset, and a queriable required alignment for the offset. See also issue 55. Currently, we do now support this offset (via BindBufferRange) and an alignment query (UNIFORM_BUFFER_OFFSET_ALIGNMENT). The offset is per-context binding point state. We probably want to pick up UNIFORM_BUFFER_START and UNIFORM_BUFFER_SIZE queries, too. See issue (65) to track whether we add these. RESOLUTION: Resolved, there should be an offset for the base of a uniform block within a UBO. If an implementation can not support non-zero offsets, they can set UNIFORM_BUFFER_OFFSET_ALIGNMENT to a sufficiently large value. (43) Do we need the versions of the uniform queries that query the GL for the properties/names of multiple uniforms at one time? Or can we simplify those apis to only query for the property/name of one uniform at a time? DISCUSSION: The multiquery apis are useful for getting lists of uniform data at once, but are more complicated (require arrays of pointers to output values). Do we need these? RESOLUTION: Resolved, we'll replace GetActiveUniformNames with GetActiveUniformName, but keep the rest which have solid use cases. (44) What is the default value for UNIFORM_BLOCK_BINDING? Having the default values be set equal to the uniform block index at link time would be convenient. This would make it unnecessary for apps to call glUniformBlockBinding unless they wanted a non-default mapping. After some discussion, using texture samplers as precedent, then the default value should be zero. RESOLUTION. Resolved, default value is zero. (45) What is the default value of UNIFORM_BLOCK_BUFFER_BINDING? This is moot without the AttachUniformBuffer API. This was the query for the uniform buffer object bound directly to a uniform block in the program object. If we add this API in a future extension, it seems it should be zero. We would need for the spec to state the precedence of program attachments over context attachments. I.e., if the value of UNIFORM_BLOCK_BUFFER_BINDING is non-zero, then the backing for that uniform block comes from the specified uniform block uniform buffer binding, otherwise it comes from the unit binding, and hence from the context that is currently using the program. RESOLUTION. RESOLVED, moot. (46) How do the logical/combined maximums for UBOs and textures relate to each other? Textures have these queries: MAX_TEXTURE_IMAGE_UNITS maximum textures that can be used by the fragment stage. MAX_COMBINED_TEXTURE_IMAGE_UNITS maximum textures that can be used by all program stages at once. Ideally, MAX_TEXTURE_IMAGE_UNITS would be called "MAX_FRAGMENT_TEXTURE_IMAGE_UNITS" Also, most implementations use MAX_TEXTURE_IMAGE_UNITS to define the number of per-context binding points for textures, though technically, there's no requirement that the number of context binding points is equal to the number of fragment textures. For instance, if an implementation had the ability to use more vertex or geometry textures than fragment textures, then this scheme would break down because there would not be enough context binding points for these other stages. This spec tries to avoid this problem with the following queries: MAX_VERTEX_UNIFORM_BLOCKS MAX_GEOMETRY_UNIFORM_BLOCKS MAX_FRAGMENT_UNIFORM_BLOCKS MAX_COMBINED_UNIFORM_BLOCKS (much like "combined" for textures) MAX_UNIFORM_BUFFER_BINDINGS (# UBO binding points on context) For symmetry, we'd recommend that we make a similar update to textures in the 3.1 spec: MAX_FRAGMENT_SAMPLERS (= old MAX_TEXTURE_IMAGE_UNITS) MAX_GEOMETRY_SAMPLERS (= old MAX_GEOMETRY_TEXTURE_IMAGE_UNITS) MAX_VERTEX_SAMPLERS (= old MAX_VERTEX_TEXTURE_IMAGE_UNITS) MAX_COMBINED_SAMPLERS (= old MAX_COMBINED_TEXTURE_IMAGE_UNITS) MAX_TEXTURE_IMAGE_BINDINGS (# texture binding points on context) RESOLUTION: Resolved. The texture token name changes should be made in the 3.1 API spec, deprecating the old names. (47) Is using a keyword to specify packed/shared/std140 the best way to manage uniform block packing? What do they mean anyway? DISCUSSION: There are 3 use cases of interest: "packed" - implementation may optimize the layout to remove inactive uniforms and otherwise restructure the layout for efficiency. - application must query the GL for the uniform block layout "shared" - implementation may optimize the layout but must use the same layout across shaders so that the resulting layout can be shared by multiple shaders - application must query the GL for the uniform block layout "std140": - implementation must use a pre-determined layout, defined in this specification. - application need not query the implementation for layout information as it can be determined by reading the shader and the specification Other options considered included: - an API in the GL - a #pragma in the GLSL - gcc style __attribute__ tokens - others? RESOLUTION: resolved, we use a layout qualifier construct which includes identifiers for "packed", "std140", and "shared" which is the intial default. These qualifiers can be used either within a uniform block declaration, or at global scope causing subsequent uniform blocks with unspecified layouts to adopt a new default layout. (48) What is the "std140" packing layout? This extension is supposed to define a standard packing layout that applications can choose to use and know the uniform block data layout within the uniform buffer without querying the implementation. The user would need to opt-in to this layout. We need to define what this layout looks like. See also issue (20). RESOLUTION: resolved, standard layout is now in 2.15.3.1.2. (49) Will storage of int/ivec*/uint/uvec*/float/vec* be guaranteed to match the GLint, GLuint, and GLfloat types of the CPU's implementation? What if the CPU and GPU differ? What about indirect renderers? See also issues (20) and (48) RESOLVED: We've never figured out how to properly handle other buffer object extensions (e.g., VBO) in conjunction with indirect rendering with data type differences. This feature should continue that fine (?) tradition. Ignoring indirect rendering, if the native data types of the GLSL executable's processor differs from the client's representation, data should still be extracted from buffer objects using the client's representation. Mechanisms that could be used to accomplish this include: * having the driver making a copy of the buffer object for internal use, doing conversion during the copy; * having the GLSL executable's processor automatically convert data types as they are fetched; or * generating code to be executed by the GLSL executable's processor to manually perform data type conversions. If dealing with data type mismatches turns out to be a problem on some implementations, it might be possible to provide an extension where applications to avoid conversion overhead by storing data using the native data type of the GPU, instead of the CPU. (50) This extension needs to be sanitized to be written against the 2.1 and 3.0 core specs. What are the differences? Aside from the sanity checking for using the right section numbers and such, there are two other changes: 1) GetIntegeri_v doesn't exist in 2.0 so needs to be added by this extension for the 2.0 version 2) The "max components" query needs different behavior for a 2.1 vs. a 3.0/3.1 implementation. See issue (36) RESOLUTION: Resolved, interactions section added which details the differences when OpenGL 3.0 is supported. Spec is written against OpenGL 2.1, so that's where the section numbers come from. (51) Do we need to name the default uniform block with index 0 and name ""? This is done for symmetry and to allow iterating through all uniform blocks, including the default, and treat them similarly. On the other hand, it's a little weird since the default partition can not be used with a buffer object. On the third hand, maybe some day we will allow that. As a side note, if we go with a name, should it be "", or perhaps "gl_DefaultUniformBlock" or something like that. RESOLUTION: Resolved, do not reserve block number 0 for the default uniform block. The default uniform block no longer needs a name. If the uniform block index is queried for a uniform that is associated with the default uniform block, -1 is returned. (52) The current extension spec seems to specify "uint" indices, but the values in the queries such as GetActiveUniformBlockiv are returned as "int" values. Should we fix this? Need to double check the APIs to see if we'd have to duplicate some or all of the queries to make them type safe for signed vs. unsigned ints. RESOLUTION: resolved, No. There are a few other places in the GL query APIs that already suffer from this problem. (53) What are the UNIFORM_BLOCK_REFERENCED_BY_*_SHADER queries used for? The total number of uniform blocks in each stage may be subject to a per-stage limit on some implementations. These queries allow the user to query the program's uniform blocks to see which are used for each stage. RESOLUTION: resolved (54) How do the APIs that use uniform locations relate to the uniforms in named uniform blocks? And how do the APIs introduced by this extension relate to uniforms in the default uniform block? Basically, locations can't be used with uniforms in a uniform block, so that rules out any queries that require locations. However, the query APIs introduced by this extension can be used with all uniforms, including those in a default uniform block. RESOLUTION: resolved (55) Should we use the BindBufferBase/BindBufferRange APIs that were introduced in GL 3.0 instead of BindUniformBuffer? As defined, they'd work fine. One side issue: should the "offset" be part of the context binding? or should the uniform blocks get to each select their own offset within a single context binding? If implementations can support the latter, it may allow applications to get by with fewer context bindings. If not, then we should replace BindUniformBuffer with these routines, but for the 2.0 extension version we'd still need to add those routines and duplicate their spec language in this spec. See issue 42 for the resolution of this side issue. RESOLUTION: resolved, yes we should use BindBufferBase/Range. (56) Can a mapping from uniform block to uniform buffer object be queried? On one hand, it seems like GetActiveUniformBlock could handle it. On the other hand, this linking is indirect: a uniform block selects a binding point, and a binding point binds a UBO. The GL *could* do the indirect lookup for you, but the data would only be valid until you changed the unit binding, so it's a little fragile for the implementation to provide this query. RESOLUTION: Resolved, not needed, the user can do this. (57) Should we have MAX_UNIFORM_BUFFER_SIZE or a max size on uniform block data instead? The uniform buffer could be larger than the amount of uniform block(s) data inside it. Also see issue (36). RESOLUTION: Resolved, name is MAX_UNIFORM_BLOCK_SIZE. (58) Is there any expectation that uniforms stay in the order declared for the packed/shared layouts? This might make sharing easier, but is not clear if it's worth it / overly constraining. RESOLUTION: resolved, yes, names/types must retain declaration order (59) Do we need the glsl syntax for declaring arrays of uniform blocks? Deferred this feature to a future extension. RESOLUTION, resolved (60) When using this extension with OpenGL 2.1/3.0, do we require that uniform buffer object names must be generated with glGenBuffers to be used with these new entry points? For OpenGL 3.1 core, there is a blanket requirement to call glGen for object names. For OpenGL 2.x, there is not a requirement to call glGen but in 3.0, user-generated names have been deprecated. For 3.0, we added two new object types (FBO/VAO) that required the user to call glGen, but existing object types (textures/renderbuffers/buffer objects) could be used without calling glGen. We need to decide what to do with this when exporting this extension on 2.1 and 3.0. RESOLUTION: Resolved, this extension does not govern the creation of buffer objects. That's done by BindBuffer, which is not altered by this spec, so on 2.1 and 3.0 you'd be able to use any name, whereas on 3.1 you'd be required to call GenBuffers. (61) Do we need "instance name" syntax? RESOLUTION: resolved, deferred for now (62) Why don't the new tokens and entry points in this extension have "ARB" suffixes like other ARB extensions? RESOLVED: Unlike a normal ARB extension, this is a strict subset of functionality already approved in OpenGL 3.1. This extension exists only to support that functionality on older hardware that cannot implement a full OpenGL 3.1 driver. Since there are no possible behavior changes between the ARB extension and core features, source code compatibility is improved by not using suffixes on the extension. (63) Should we introduce a query of a program's longest uniform name length, similar to the ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH query of a program's longest uniform block name? RESOLUTION: Resolved, no. ACTIVE_UNIFORM_MAX_LENGTH serves this purpose well enough. No great need for a per uniform block query of the same. (64) What should the UNIFORM_OFFSET query return for uniforms that are associated with the default uniform block? Same for strides? RESOLUTION: Resolved, spec'd to return -1 in these cases. (65) Should we add queries for the base offset and size of the uniform buffer bound to a binding point? What should the names be? DISCUSSION: This would be analogous to the similar transform feedback queries. Names could be UNIFORM_BUFFER_START and UNIFORM_BUFFER_SIZE. RESOLUTION: Resolved, yes. (66) Should we provide some mechanism allow applications to annotate their uniform declarations to specify an offset by hand? Direct3D 10 does. An example of the D3D syntax: cbuffer D3DExample { float4 a : packoffset(c0); // bytes 0-15 float3 b : packoffset(c16); // bytes 256-267 (c0-c15 are all vec4s) float1 c : packoffset(c1.y); // bytes 20-23 } If so, how would we handle a mixed declaration that includes some uniforms with annotations and others without? RESOLVED: An annotation mechanism would be useful for fine-grained application control, but we will defer this. (67) Should we provide a mechanism to expose both row-major and column-major storage of matrices? If no controls are provided in GLSL 1.40, the default resolution for the UBO layout documentation would be to treat all matrices as column-major. We will also need to pick a default orientation for matrices with that use no GLSL language mechanism to declare orientation. Either way, the UBO GL API should provide a GetActiveUniform query to determine if an active matrix is stored in row- or column-major order. RECOMMENDATION: Provide a should have a type modifier for matrix declarations, for example: row_major mat4 matrix1; column_major mat4 matrix2; It may be desirable to have a global control (e.g., a #pragma) to specify that all matrices are row- or column-major. RESOLVED: Yes, we should provide this control. It is now available in the form of uniform block layout qualifiers. The identifiers "row_major" and "column_major" are allowed, with the latter serving as the initial default. These qualifiers can be specified on a per- matrix basis, a per-uniform block basis (affecting all matrices within the uniform block that have unspecified orders), or globally. In the latter case, all subsequent matrices with unspecified order will adopt a new default order. (68) Should the buffer layout be expressed in terms of standard GL types? For example, should the storage for a "vec3" be equivalent to "GLfloat [3]"? RESOLVED: Yes. One other alternative would be to specify exact type (e.g., "32-bit floats using IEEE 754 encoding", "32-bit two's complement integers", etc...). These choices will be roughly equivalent in practice, and it's probably better to use standard GL types. (69) Do we need to pad the end of structures and/or arrays using the standard packing rules? Or should we be able to squeeze data types with small alignment requirements in the "holes" left at the end of structures or arrays with larger alignment requirements? uniform ExamplePad { // with without // padding padding comments // ------- ------- ------------------------ struct { // vec3 a; // 0..11 0..11 } b; // add 4B of padding? float c; // 16..19 12..15 vec3 d[2]; // 32..43 16..27 align to 16B due to vec3 // 48..59 32..43 add 4B of padding? float e; // 64..67 44..47 struct { // align to 16B due to vec4 f; // 80..95 48..63 ivec2 g; // 96..103 64..71 } h; // add 8B of padding? uint i; // 112..115 72..75 } The strongest argument against padding is compactness. The strongest argument in favor of padding is to have a structure definition that can be matched with a similar structure definition in application code. For example, consider the following GLSL code: uniform Example { vec3 a[10]; float b; }; The standard layout rules suggest that the vec3 members of "a" are effectively padded out to vec4's in the array; so the natural C structure would look like: typedef struct { float x, y, z, pad; } vec3InArray; struct Example { vec3InArray a[10]; float b; } The problem is that without padding the end of arrays, the uniform "b" will be stored immediately after the last float in a[9], but with the C structure, that word will be consumed by a[9].pad, and "b" will be stored one word following. A similar issue arises with structures; common C compilers seem to pad the end of structures to the largest alignment of the atomic types used in the structure. For example, if you have: struct { double a; char b; } c; common compilers will generate code where sizeof(c)==16. We are effectively treating vectors and matrices as atomic types, so it seems to make sense that for GLSL code like: struct { vec4 a; float b; } c; it would follow that sizeof(c)==32. RESOLVED: Yes, we need to pad in support of the reasons above. (70) Should "bool" data types be represented as 8-bit quantities (a la GLboolean in most gl.h versions) or 32-bit? RESOLVED: Use 32-bit integers. Using GLboolean (8-bit) would be the closest match to the API types, but some implementations of this standard may prefer 32-bit integers at this point. We don't expect uniform blocks to contain enough bool-typed data where the wasted storage matters significantly. One other option considered was to have an implementation-dependent representation, which could be queried, but requiring applications to query and handle multiple basic data types seemed cumbersome. Even if we did this, we would still want to have a single representation for a fully-defined "std140" packing, at least. (71) What happens we are using indirect rendering where the data types used by the client and server differ, due to endianness or some other issues related to basic data type? What happens if the processor running the GLSL executable uses different data type representations than the application? DUPLICATE of issue (49) (72) What parameters should we provide for querying the layout of matrices (and arrays of matrices) in memory? RESOLVED: We expect that matrices will be stored as an array of column vectors or row vectors. There are two possibly independent strides: - bytes between columns/rows within a single matrix - bytes between matrices within an array of matrices The GetActiveUniform*() API for UBO will provide queries for both strides. For single matrices, the stride between columns/rows is the only parameter. Some implementations may provide tightly packed matrices, where a 3x3 column-major matrix might be represented with 9 consecutive floats with a 12-byte (3-float) stride between columns. Others, such as the "std140" packing above represents such a matrix as an array of 3 column or row vectors, but pads each row/column for a 16-byte (4-float) stride. For arrays of matrices, two queries would be needed for maximum flexibility. For example, a hypothetical implementation might pack 3x3 arrays tightly as 9 floats, but require that each array in the matrix be aligned on a 16-byte boundary. This would have a column stride of 12B, but would require a matrix stride of 48B, not 3*12=36B. If we didn't care about such implementations, an alternate approach would be to treat an array of N column-major matrices with C columns as though it were an array of N*C column vectors, as in the std140 layout. The stride between matrices would be derived from the stride between columns. Providing multiple queries seems like the safest choice, and doesn't have any significant down-side. The first stride query, between major vectors of a matrix, is UNIFORM_MATRIX_STRIDE. The latter query is actually the same UNIFORM_ARRAY_STRIDE query used for any type of array element. (73) Should GetActiveUniform allow you to query if a matrix is column- or row-major, so an app can determine the layout without knowing how the matrix is declared in the shader? RESOLVED: Yes, UNIFORM_IS_ROW_MAJOR. (74) What's language mechanism should be used for opting into standard layout? At the January 2009 F2F, it was recommended to specify a per-uniform block layout via a language mechanism such as: layout() uniform { ... }; where must be "std140" in the current standard. Future extensions and core versions could define additional identifiers (such as "std140novec4"). The mechanism could be further extended to include an identifier list if there is ever a need for very fine-grained control. There appears to be a strong desire for a global mechanism that doesn't require individually annotating each and every uniform block. Options considered include the #pragma described above and a GL API call that might set a "compiler flag" such as: glProgramParameteri(program, GL_UNIFORM_BLOCK_LAYOUT, GL_LAYOUT_STD140); It was noted that the GL API call, since implementations are permitted to do some or most code generation during glCompileShader(), where a program parameter would not be available. A similar shader parameter call could conceivably be provided. RESOLVED: We've adopted a layout qualifier construct which can be used to specify the "std140" standard layout either within a uniform block declaration or at global scope, affecting all subsequently declared uniform blocks with unspecified layout. (75) What is the story behind the "std140" packing, and the possible "std140vec4" alternative? RESOLVED: The "std140" packing is intended to provide a common device-independent layout for uniform blocks that can be supported by all OpenGL 3.1-capable GPUs. Applications using this packing do not need to query the offsets and strides of all its uniforms and can rely on the same packing being used on all OpenGL 3.1 implementations. While some implementations may be able to support a more space-efficient packing, "std140" does not attempt to provide any features not available on all platforms. Some of the limitations baked into this packing include: * scalars need to be size-aligned; * vectors are treated as atomic units, and need to be vector-size- aligned; * array elements and structures are aligned/padded to 16-byte boundaries The array/structure restriction is because some implementations treat uniform buffers as arrays of four-component vectors and may not be able to efficiently perform indexed array access with strides less than 16 bytes. The "std140novec4" alternate packing illustrates an alternate approach without required 16-byte alignment that might be exposed as a future vendor extension. Future versions of OpenGL/GLSL may choose to provide additional sets of canonical packing rules that may end up being more compact. (76) When using the standard layout, how is UNIFORM_BLOCK_DATA_SIZE determined? RESOLVED: The data size returned by the query is derived by taking the next free byte after all uniform block members (including any specified end-of-array or end-of-structure padding) and rounding up to the next vec4 boundary. It would be equivalent to the offset of a hypothetical vec4 member added to the end of the uniform block. There is no implementation-dependent padding of the uniform block data size when using the standard layout. Revision History (v68, 2015-06-23, srahman) - Add GLX protocol specification. (v67, 2013-08-17, jon) - Add extra 'const' qualifier for GetUniformIndices argument (Bug 10703). (v66, 2012-09-17, jon) - Remove _EXT suffix from GL_UNIFORM_BUFFER_EXT in sample code (Bug 7948). (v65, 2012-06-28, jon) - Remove INVALID_VALUE error for BindBufferRange when specifying a range beyond the current end of buffer. Define BindBufferBase as specifying a range as large as the actual buffer size at time of use, and return zero when querying the buffer size as a sentinel value for the buffer size indicating this behavior. Specify that the GL will never read from or write to beyond the end of a bound buffer (Bugs 7318 and 7329, matching OpenGL 4.2 core spec behavior). Remove dangling references to nonexistent BindBufferOffset. (v64, 2011-01-27, jon) - Change return value for start/size queries when no buffer bound from -1 to zero, to match state tables (Bug 7318). (v63, 2011-01-21, pbrown) - Add interaction with ARB_geometry_shader4 to indicate that MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS is defined there. (v62, 2009-03-26, jon) - Remove ARB suffixes for consistency with other extensions simultaneously introduced with new GL core features, intended to enable those features in older drivers. (v61, 2009-02-16, benj) - pickup latest changes to GLSL language (v60, 2009-02-12, benj) - revert the change to silently ignore INVALID_INDEX_ARB within passed to GetActiveUniformsivARB - picked up a few proposed language changes from Pat - updated table 2.utype to include types from extensions - added interactions for these extension types - fixed issue (40) resolution (v59, 2009-02-12, benj) - remove INVALID_OPERATION error when has not been linked, and instead just behave appropriately for the case where there are no active uniforms or uniform blocks - added GL 3.0 interaction regarding description of uniform initialization, which is limited to uniforms in the default block (v58, 2009-02-11, jon) - Add some more comments. (v57, 2009-02-11, benj) - restore 80-column width - change _STAGE to _SHADER in UNIFORM_BLOCK_REFERENCED_BY token names - silently ignore INVALID_INDEX_ARB in GetActiveUniformsivARB - clarify that matrices in the default uniform block return 0 for UNIFORM_IS_ROW_MAJOR - Replace Draw* with Begin or commands that perform an implicit Begin since the extension is written against GL 2.1 (v56, 2009-02-11, jon) - Accept some of Pat's edits and remove associated notes/comments. Add my comments on some others. (v55, 2009-02-11, pbrown) - Many edits attempting to make the spec read more clearly. - Added a number of notes and issues in the spec for additional edits. (v54, 2009-02-11, jon) - Note that uniform binding limits change when geometry shaders not supported, and update uniform state variable types. (v53, 2009-02-09, jon) - Restore an error accidentally removed from GetUniformLocation (at least, I think it was accidentaly). (v52, 2009-02-09, jon) - Resolve some issues as recommended by Bruce and leave his comments in for others Benj should look at. - Allow undefined behavior including termination if no buffer is bound backing a uniform block. (v51, 2009-02-08, jon) - Cleanup before core spec integration: - Change definition of INVALID_INDEX_ARB to avoid signed/unsigned conversion questions by making it an unsigned literal (would like to change the name too, it looks too much like an error). - Rephrase some query language for greater consistency with core spec. Duplicated error conditions in each affected call to avoid more state-dependent reading. (v50, 2009-02-08, benj) - resolve last four issues (47), (67), (74), (76) - update the GLSL changes for uniform blocks - update API descriptions to refer to packed/shared/std140 layouts - update the buffer overrun language courtesy of Bruce - rename APPLE to ARB in the issues list - misc. other cleanups (v49, 2009-02-05, benj) - change UBO overrun language to say "undefined behavior that may lead to GL interruption or termination" instead of just "undefined values" - flesh out Errors section (v48, 2009-02-04, benj) - add query for whether a matrix uniform is row- or column-major - add query for the stride between a matrix uniform's major vectors - apply one description of to all uniform query commands - update example code (v47, 2009-02-03, benj) - update packing rules and examples - standardize on "named" uniform block instead of "user-defined" - refactor UBO spec language so it is blended with old uniform language (v46, 2009-02-03, benj) - update token MAX token names re: issue (46) - rename "uniform block unit" to "uniform buffer binding point" - updated uniform block binding and uniform buffer binding overview - add queries for uniform buffer start and size re: issue (65) - resolved issues (46), (65), (69) - incorporated many more misc. suggestions from Bruce (v45, 2009-02-02, benj) - rename from APPLE to ARB - assigned token values - misc. suggestions from Bruce, more to come - pull issues over from Pat's packing doc - resolved issues (57), (60), (62), (63), (64), (65) (v44, 2009-01-30, benj) - resolved issues (20), (29), (42) - added MAX_COMBINED_{VERTEX|GEOMETRY|FRAGMENT}_UNIFORM_COMPONENTS queries with different minimum maxima for before and after GL 3.1, resolving issue (36) - replaced GetActiveUniformNamesAPPLE with GetActiveUniformNameAPPLE, resolving issue (43) - stop reserving uniform block index 0 for the default uniform block, resolving issue (51) - remove language saying uniform buffer range size must be aligned to UNIFORM_BUFFER_OFFSET_ALIGNMENT - make consistent use of "uniform block unit" instead of "uniform buffer unit" (v43, 2009-01-29, benj) - UNIFORM_BLOCK_NAME_LENGTH changed from 0 to 1 for the default uniform block, since "" still has a null terminator - UNIFORM_BLOCK_DATA_SIZE description updated to reflect how offset/stride queries are unnecessary for "standard" layout - Add language to GetUniformLocation to say that uniforms in named uniform blocks return -1, and that Uniform* are for loading uniforms of the default uniform block - update discussion of issues (13), (15), (21), (34) to align with current spec - sanitize uniform query descriptions (both pre-existing and new in this extension) to clarify handling of uniforms from default uniform blocks vs. named uniform blocks, resolving issue (54) - rename MAX_UNIFORM_BUFFER_SIZE to MAX_UNIFORM_BLOCK_SIZE per issue (57) - introduce language guaranteeing order of member offsets will match order within declaration per issue (58) - update some section #s (v42, 2009-01-28, benj) - introduce Pat's packing rules, including standard layout, resolving issues (48), (49) - add interactions with extensions and GL 3.0, resolving issue (50) - change names of MAX query names for uniform block per-stage, combined, and binding point limits - introduce BindBufferRange/BindBufferBase in place of BindUniformBufferAPPLE, resolving issue (55) - add missing query language in Chapter 6 - add missing UNIFORM_BUFFER_OFFSET_ALIGNMENT_APPLE from state tables - separate new state from implementation state in state tables - remove instance-name language and arrays of uniform blocks per resolution to issues (59), (61) - fix minor typos and cosmetic issues - reformat some lines to fit in 80 columns - replace tabs with spaces (v41, 2009-01-25, jsandmel) - incorporated resolutions/feedback from Portland F2F - resolved issues (33), (39), (44), (52), (55), (56), (58), (59) - added issue (61) (v40, 2009-01-25, jsandmel) - fixed a few typos noticed by Barthold Lichtenbelt - fixed up some white space in issues list (v39, 2009-01-21, jsandmel) - fixed a few typos noticed by Daniel Koch - added issue (60) (v38, 2009-01-21, jsandmel) - integrated feedback and questions from Bruce Merry - fixed typo in GetUniformIndices (missing const char**) - added length (output) parameter to GetActiveUniformBlockNameAPPLE for symmetry with GetActiveUniform - removed stale matrix packing queries (to be handled more generally with rest of packing language) - fixed wrong error language when validating arguments to be consistent with generic error language already in GL spec - make GetActiveUniformNamesAPPLE not write NULL to names entries for invalid indices - made validation the same as GetActiveUniform - added issues (57), (58), (59) (v37, 2009-01-19, jsandmel) - incorporated feedback from Pat Brown - added issues (47) - (56) - added note to interactions section - clarified layouts in overview section - fixed wrong error code in GetActiveUniformBlockivAPPLE - added additional description to parameters in GetActiveUniformNamesAPPLE - added note to GetActiveUniformsivAPPLE to make it more similar to GetActiveUniform wrt to program linking and type/size queries. - added todo for UniformBlockBindingAPPLE to clarify over better based on feedback from pat - increased MAX_UNIFORM_BUFFER_SIZE_APPLE from 64 to 16k - unresolved issue (33) re: display lists (v36, 2009-01-14, jsandmel) - added issue (48) requesting the standard layout and referred to this in various places - added missing UNIFORM_BLOCK_NAME_LENGTH_APPLE state variable - corrected references of GetIndexedIntegerv with GetIntegeri_v - fixed typo in description of UNIFORM_BLOCK_INDEX_APPLE - clarified UNIFORM_OFFSET_APPLE description further - clarified that several constantscan be queried with GetIntegerv - fixed a set of stale references to "partitions" (v35, 2009-01-14, jdr) - improved readability of a few areas - fixed a data type typo (v34, 2009-01-12, jsandmel) - added issue (47) and preliminary keyword support for packed, sharable, standard layouts (v33, 2009-01-11, jsandmel) - switched terminology from "partition" to "uniform block" - switched syntax from 'active' to 'packed', and changed default behavior - changed lots of function names to account for the above - cleaned up overview - dropped language talking about "binding" for the uniform block -> uniform block unit association, since it's not an object binding operation - added concept of "combined"/"logical" binding point max queries - incorporated most recent GLSL syntax from the GLSL working group for uniform blocks - removed the AttachUniformBufferAPPLE for per-program bindings of UBOs (v32, 2008-12-08, jsandmel) - added UNIFORM_BUFFER_OFFSET_ALIGNMENT_APPLE (v31, 2008-12-08, jsandmel) - minor updates to overview (this could still use more editing). (v30, 2008-12-08, jsandmel) - cleaned up function argument names for clarity - reformatted new procedures/tokens section - added concept of uniformBlockBinding (for context bindings) to distinguish from uniformBlockIndex - renamed MAX_VERTEX_UNIFORM_BUFFERS_APPLE -> MAX_VERTEX_UNIFORM_BUFFERS_APPLE and friends. - removed/simplified the unneeded per-stage quries for active partitions (under assumption that partition names are global per program) - de-assigned apple enums for most tokens while we work out the enums - added UNIFORM_BLOCK_REFERENCED_BY_VERTEX_STAGE_APPLE and friends to queries of each partition - clarified/cleaned up overview of uniform partitions - added more detail to each of the function descriptions to clarify how each of the arguments was to be handled - temporarily deleted the Errors section since it was partially stale need to add this back later - removed stale query for UNIFORM_LOCATION_APPLE from state table - cleaned up (most of) issues list with API changes - removed some AMD/NV'isms from the issues language (v29, 2008-11-24, jsandmel) - Added argument to query routines to indicate vtx/geom/fragment. - Still need to update sample code for this proposal. - Also need to still specify how uniform scoping works (cross stage or per stage). - Eliminated special "INVALID_INDEX_APPLE" value since the rest of the GLSL API uses "-1" to mean invalid index, so we use that here too. (v28, 2008-10-08, jsandmel) - Added more discussion to issue (35) regarding context vs. program bindings of UBOs. - Added prototypes for BindUniformBuffer API. - Added issue (36) about maximum uniform component API. - Integrated the proposed API for per-context bindings into issue (35) from NVIDIA's NV_ubo proposal. - Added issue (37) about if we need 3 values for MAX_{VERTEX|GEOMETRY|FRAGMENT}_UNIFORM_BUFFERS_APPLE. (2008-10-08, jdr) Grammar additions. Re-instated piece-wise partition definitions. Elaboration of issue 35. Addition of 36. Readability improvements. (2008-10-07, jdr) 18 in previous check-in -> not true. 18 *is* in this one. Skeltal issue for NV suggested context binding points. (2008-10-06, jdr) Incorporated Nick's and Matt's changes 2, 3, 4, 5, 6, 8, 12, 14, 16, 17, and 18. (2008-08-27, jdr) Additions to contributer list. (2008-07-22, jdr) Changed buffer minimums and contributor list per discussion with NVidia. (2008-06-19, jdr) Added issue 34 and language describing the decision to use struct-like syntax for partition definitions. Added explicit mention that AttachUniformBufferObjectAPPLE() was required after a uniform buffer object has been modified. Fixed examples. (2008-03-18, jdr) Provide resolution and spec language for "active" and "partition" resolving related issues. Appended "_object" to spec name. Added required GLSL v1.20.8 spec language. (2008-03-17, jdr) Removed issue 30 as it was a misread spec. Added resolutions for 29, 31, and 32 - made spec changes accordingly. Added proposal for active partition demarcation and sharing rules. (2008-03-14, jdr) Added issues 29-34 for transform feedback, scoping the "active" keyword, and following precedents. (2008-03-13, bb) Fixed incorrect error returns. (2008-03-13, bb) Changed the return value of GetUniformBlockIndexAPPLE to uint. Added INVALID_INDEX. Fixed Example code 2. Cleaned up line breaks. Cleaned up issues. Added issues 24-26. (2008-03-12, jdr) Added state tables and state retrieval segment. (2008-03-12, jdr) Rewrote advanced source example. Made a few minor fixes and additions that writing the example illuminated. (2008-03-11, jdr) After considerable dialog with BB around handling of bulk extraction of uniform meta-data, conclusions of dialog required sweeping changes to spec. Rewrote specification updates section. Added new tokens. Changed New Functions segment. Updated Errors segment. Added issue 23. (2008-03-04, jdr) Rewrote specification updates section. Rewrote error section. (2008-03-03, jdr) Rewrote overview to reflect partitioning. Re-arranged for spec worthiness. Cleaned up new procedures functions and defined aggregate layout function. Revised issues list to reflect partitioning, include more recent discussions, and used current accepted vernacular. (2008-03-03, bb) Resolved issue 19. Changed the return value of GetActivePartitionUniformInfoAPPLE to a void because it does not return locations. (2008-03-03, jdr) Changed to namespace to partitions. Added issues 21 & 22. Added aggregate uniform info query per partition. (2008-03-03, bb) Added separate partition support. Changed extension name to APPLE_uniform_buffer. (2008-02-27, jdr) Dumped program arguments. Changed "types" output array to "sizes" output array. Added expected scatter/gather logic in the example to advocate efficient schlepping of uniform data into the buffer. (2008-02-26, jdr) Changes to accomodate relative offsets. Revised example source. Error additions. Removed contact information for contributors list. (2008-02-25, jdr) Added source example. (2008-02-21, jdr) Added to issues list, resolutions of all issues excepting 16. Changes per meeting. Additions to procedures and explanations. 2.1 spec integration. Implementation Dependent State. (2008-02-19, jdr) Added to issues list, additions to procedures and explanations, errors. (2008-02-18, jdr) Added to issues list, modifications to procedures and explanations. (2008-02-16, jdr) Added to issues list and procedures. (2008-02-15, jdr) Initial revision, overview.