Name ARB_explicit_uniform_location Name Strings GL_ARB_explicit_uniform_location Contact Piers Daniell, NVIDIA (pdaniell 'at' nvidia.com) Contributors Bruce Merry Christophe Riccio, AMD Pat Brown, NVIDIA Notice Copyright (c) 2012-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 2012/06/12. Version Last Modified Date: 05/15/2012 Revision: 6 Number ARB Extension #128 Dependencies Requires OpenGL 3.3 or ARB_explicit_attrib_location. This extension interacts with ARB_shader_subroutine. This extension is written against the OpenGL 4.2 (Compatibility Profile) and the OpenGL Shading Language 4.20.11 specification. Overview This extension provides a method to pre-assign uniform locations to uniform variables in the default uniform block, including subroutine uniforms. This allows an application to modify the uniform values without requiring a GL query like GetUniformLocation, GetSubroutineUniformLocation and GetSubroutineIndex. IP Status No known IP claims. New Procedures and Functions None New Tokens Accepted by the parameter of GetBooleanv, GetIntegerv, GetFloatv, GetDoublev, and GetInteger64v: MAX_UNIFORM_LOCATIONS 0x826E Additions to Chapter 2 of the OpenGL 4.2 Specification (OpenGL Operation) Section 2.14.7 "Uniform Variables": Modify the third paragraph on page 114 to read: "When a program is successfully linked, all active uniforms, except for atomic counters, 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 any active uniform in the default uniform block which don't already have an explicit location defined in the shader. The generated locations will never take the location of a uniform with an explicit location defined in the shader, even if that uniform is determined to be inactive. The values of active uniforms in the default uniform block can be changed using this location and the appropriate Uniform* command (see below). These generated locations are invalidated and new ones assigned after each successful re-link. The explicitly defined locations and the generated locations must be in the range of 0 to MAX_UNIFORM_LOCATIONS minus one." Section 2.14.8 "Subroutine Uniform Variables": Modify the last paragraph on page 136 to read: "The command int GetSubroutineUniformLocation(uint program, enum shadertype, const char *name); will return the location of the subroutine uniform variable in the shader stage of type attached to , with behavior otherwise identical to GetUniformLocation. The value -1 will be returned if is not the name of an active subroutine uniform. The subroutine uniform may have an explicit location specified in the shader. At link time, all active subroutine uniforms without an explicit location will be assigned a unique location. The value ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS is the largest assigned or generated location plus one. An assigned location will never take the location of an explicitly assigned location in, even if that subroutine uniform is inactive. Between the location 0 and ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS minus one there may be unused locations either because they weren't assigned a subroutine uniform or because the subroutine uniform was determined to be inactive by the linker. These locations will be ignored when assigning the subroutine index as described below. There is an implementation-dependent limit on the number of active subroutine uniform locations in each shader stage; a program will fail to link if the number of subroutine uniform locations required is greater than the value of MAX_SUBROUTINE_UNIFORM_LOCATIONS or if an explicit subroutine uniform location is outside this limit. If has not been successfully linked, the error INVALID_OPERATION will be generated. For active subroutine uniforms declared as arrays, the declared array elements are assigned consecutive locations. Each function in a shader associated with a subroutine type is considered an active subroutine, unless the compiler conclusively determines that the function could never be assigned to an active subroutine uniform. The subroutine functions can be assigned an explicit index in the shader between 0 and MAX_SUBROUTINES minus one. At link time, all active subroutines without an explicit index will be assigned an index between 0 and ACTIVE_SUBROUTINES minus one. An assigned index will never take the same index of an explicitly assigned index in the shader, even if that subroutine is inactive. Between index 0 and ACTIVE_SUBROUTINES minus one there may be unused indices either because they weren't assigned an index by the linker or because the subroutine was determined to be inactive by the linker. If there are no explicitly defined subroutine indices in the shader the implementation must assign indices between 0 and ACTIVE_SUBROUTINES minus one with no index unused. It is recommended, but not required, the application assigns a range of tightly packed indices starting from zero to avoid indices between 0 and ACTIVE_SUBROUTINES minus one being unused. The index can be queried with the command: uint GetSubroutineIndex(uint program, enum shadertype, const char *name); where name is the null-terminated name of a function in the shader stage of type attached to . The value INVALID_INDEX will be returned if name is not the name of an active subroutine in the shader stage. After the program has been linked, the subroutine index will not change unless the program is re-linked." Modify the second paragraph on page 138 to read: "The name of an active subroutine can be queried given its subroutine index with the command: void GetActiveSubroutineName(uint program, enum shadertype, uint index, sizei bufsize, dizei *length, char *name); and specify the program and shader stage. must be a subroutine index in the range from zero to the value of ACTIVE_SUBROUTINES minus one for the shader stage. If is greater than or equal to the value of ACTIVE_SUBROUTINES, the error INVALID_VALUE is generated. The name of the selected subroutine is returned as a null- terminated string in name. The actual number of characters written into name, excluding the null terminator, is returned in length. If length is NULL, no length is returned. If the index refers to an unused subroutine index, the string returned in is an empty string and the length returned is zero. ..." Modify the last paragraph on page 138 to read: "The command void UniformSubroutinesuiv(enum shadertype, sizei count, const uint *indices); will load all active subroutine uniforms for shader stage with subroutine indices from , storing [i] into the uniform at location i. Any locations between 0 and ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS minus one which are not used will be ignored. If is not equal to the value of ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS for the program currently in use at shader stage , or if the uniform at location i is used and the value in [i] is greater than or equal to the value of ACTIVE_SUBROUTINES for the shader stage, the error INVALID_VALUE is generated. If the value of [i] for a used location specifies an unused index the error INVALID_VALUE is generated. If, for any subroutine index being loaded to a particular uniform location, the function corresponding to the subroutine index was not associated (as defined in section 6.1.2 of the OpenGL Shading Language Specification) with the type of the subroutine variable at that location, then the error INVALID_OPERATION is generated. If no program is active, the error INVALID_OPERATION is generated." Additions to Chapter 6 of the OpenGL 4.2 Specification (OpenGL Operation) Section 6.1.18 "Shader and Program Queries": Modify the second paragraph on page 501: "The command void GetUniformSubroutineuiv(enum shadertype, int location, uint *params); returns the value of the subroutine uniform at location for shader stage of the current program. If is greater than or equal to the value of ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS for the shader currently in use at shader stage , the error INVALID_VALUE is generated. If represents an unused location, the value INVALID_INDEX is returned and no error is generated. If no program is active, the error INVALID_OPERATION is generated." Additions to the AGL/GLX/WGL Specifications None. Dependencies on ARB_shader_subroutine If ARB_shader_subroutine is not supported, remove all references to subroutine uniform locations and subroutine indices. GLX protocol None Errors INVALID_VALUE is generated if an unused index is assigned to an active and used subroutine uniform variable by UniformSubroutinesuiv. New State None New Implementation Dependent State Changes to table 6.64, p. 568 (Implementation Dependent Values) Minimum Get Value Type Get Command Value Description Sec. Attribute --------- ---- ----------- ------- ----------- ---- --------- MAX_UNIFORM_LOCATIONS Z+ GetIntegerv 1024 Maximum number of user- 2.14.7 - assignable uniform locations Modifications to The OpenGL Shading Language Specification, Version 4.20.06 Including the following line in a shader can be used to control the language feature described in thie extension: #extension GL_ARB_explicit_uniform_location : where is as described in section 3.3. A new preprocessor #define is added to the OpenGL Shading Language: #define GL_ARB_explicit_uniform_location 1 Insert a new section called 4.4.3 "Uniform Variable Layout Qualifiers": "Layout qualifiers can be used for uniform variables and subroutine uniforms. The layout qualifier identifiers for uniform variables and subroutine uniforms are: layout-qualifier-id location = integer-constant The location idenifier can be used with default-block uniform variables and subroutine uniforms. The location specifies the location by which the OpenGL API can reference the uniform and update its value. Individual elements of a uniform array are assigned consecutive locations with the first element taking location . No two default-block uniform variables in the program can have the same location, even if they are unused, otherwise a compiler or linker error will be generated. No two subroutine uniform variables can have the same location in the same shader stage, otherwise a compiler or linker error will be generated. Valid locations for default-block uniform variable locations are in the range of 0 to the implementation-defined maximum number of uniform locations. Valid locations for subroutine uniforms are in the range of 0 to the implementation-defined per-stage maximum number of subroutine uniform locations minus one. Locations can be assigned to default-block uniform arrays and structures. The first inner-most scalar, vector or matrix member or element takes the specified and the compiler assigns the next inner-most member or element the next incremental location value. Each subsequent inner-most member or element gets incremental locations for the entire structure or array. This rule applies to nested structures and arrays and gives each inner-most scalar, vector, or matrix type a unique location. For arrays without an explicit size, the size is calculated based on its static usage. When the linker generates locations for uniforms without an explicit location, it assumes for all uniforms with an explicit location all their array elements and structure members are used and the linker will not generate a conflicting location, even if that element of member is deemed unused." Insert a new section called 4.4.4 "Subroutine Function Layout Qualifiers": "Layout qualifiers can be used for subroutine functions. The layout qualifier identifiers for subroutine functions are: layout-qualifier-id index = integer-constant Each subroutine with an index qualifier in the shader must be given a unique index, otherwise a compile or link error will be generated. The indices must be in the range of 0 to the implementation defined maximum number of subroutines minus one. It's recommended, but not required, that the shader assigns a range of tightly packed values starting from zero so that the GL subroutine function enumeration API returns a non-empty name for all active indices." Issues 1) Can the application mix uniforms with explicit locations with regular uniforms without explicit locations? RESOLVED: Yes, uniform locations assigned automatically at link time will not alias any uniform with explicit locations, even if those uniforms are inactive. 2) Can the application mix subroutine uniforms with explicit locations with subroutine uniforms without explicit locations? Also, can the application mix subroutines with explicit indices with subroutines without an index specified. RESOLVED: Yes, any subroutine uniforms without an explicit location will be assigned a location between 0 and ACTIVE_UNIFORM_SUBROUTINE_LOCATIONS minus 1 with a location that has not been used by the shader, regardless of whether it refers to a subroutine uniform that is unused. The value of ACTIVE_UNIFORM_SUBROUTINE_LOCATIONS is calculated as the max of the explicit location and automatically assigned location. If there are unused locations between 0 and ACTIVE_UNIFORM_SUBROUTINE_LOCATION, these will be ignored by UniformSubroutinesiv(). Similarily with the subroutine indices, the linker will allocate unused indices to the subroutines without an explicit index and the value of ACTIVE_SUBROUTINES will be the max of the largest explicit index and the linker assigned index. There may be unused indices between 0 and ACTIVE_SUBROUTINES minus 1 and UniformSubroutinesiv() will return an error if the app attempts to use an unused index with an active and used subroutine uniform. 3) How should an application determine unique default-block uniform variable locations? RESOLVED: Each transparent basic-type uniform variable consumes exactly one location, regarless of it's type. Transparent basic-types, as defined in section 4.1 are booleans, integers, floats, doubles, vectors and matrices. An array of basic-type uniforms consumes consecutive locations, incrementing by one for each consecutive element. Structures of basic-type uniforms assign consecutive locations to each member where the first base member takes the first location. These rules apply recursively to nested structures and arrays assigning consecutive locations each consecutive basic-type variable. Any uniform variables without an explicit location assigned will be assigned a unique location by the linker. It's implementation defined what locations the linker chooses for these variables, the only requirement being that these generated locations do not alias any explicitly defined locations. Note that subroutine uniform variables are not in the same namespace as default-block uniform variables. Subroutine uniform locations are per shader stage rather than per program and they are referenced through a different API so can have the same locations as uniform variables. 4) What happens if Uniform* is called with an explicitly defined uniform location, but that uniform is deemed inactive by the linker? RESOLVED: The call is ignored for inactive uniform variables and no error is generated. Uniforms without an explicit location that are determined to be inactive return -1 for the the location when GetUniformLocation is queried. Calling Uniform* with a location of -1 is also ignored. That behavior isn't changed. 5) What is the value of ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS after successfully compiling and linking a program? RESOLVED: The value of ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS is calculated per shader stage to be the max of the explicitly defined subroutine uniform variable locations and the generated locations for subroutine uniform variables without a defined location. The consequence of this is that there will be some locations between 0 and ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS minus one that are unused. UniformSubroutinesuiv ignores index entries for unused locations. 6) Does the application need to query ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS to figure out the parameter to UniformSubroutine? RESOLVED: No, it doesn't have to. If the application knows the shader source and it only uses explicit subroutine uniform variables locations it can figure out ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS by simply taking the maximum location defined plus one. If there are generated subroutine uniform locations the application will need to query ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS like before. 7) What is the value of ACTIVE_SUBROUTINES after successfully compiling and linking a program? RESOLVED: The value of ACTIVE_SUBROUTINES is calculated per shader stage to be the max of the explicitly defined subroutine index values and the generated indices for subroutines without a defined index. The consequence of this is that there will be some invalid indices between 0 and ACTIVE_SUBROUTINES minus one which don't reference any subroutine. If GetActiveSubroutineName is called with one of these unused indices, no error is generated but the returned will be an empty string and the will be zero. 8) Does the query for ACTIVE_UNIFORMS in the program include inactive uniform variables with explicit locations? RESOLVED: No, only the active default-block uniforms are included in this count. It's only the of inactive uniform variables that can be used with existing GL fuctions like Uniform*, UniformMatrix*, ProgramUniform*, etc. and are ignored. Otherwise these inactive uniforms operate like they did before this extension. 9) Should we introduce the concept of "location" in addition to the existing "index" for subroutine functions? This would make it more consistent with regular uniforms. You would use the "index" property for the purposes of enumerating the enties with GetActiveSubroutineName and "location" for the purposes of UniformSubroutinesuiv. This will avoid the issue of GetActiveSubroutineName having possibly empty strings returned for indices between 0 and ACTIVE_SUBROUTINES-1. RESOLVED: No, not at this time. The downside of introducing a "location" property is that we'll need to introduce a new function called GetSubroutineLocation, which would return an "int" where -1 means invalid location, and then use these values instead of indexes with UniformSubroutinesuiv. Unfortunately, UniformSubroutinesuiv takes an array of "uints". Also, it would be quite confusing to have both GetSubroutineLocation and GetSubroutineIndex, especially for existing apps that already used GetSubroutineIndex. It would be tricky to specify which should be used and tricky the support the transition of apps between OpenGL 4.2 and OpenGL 4.3 usage. And that complexity feels less attractive than the benefit of solving the enumeration issue. Apps that tightly pack their index assignments won't have a problem so in practice a holey enumeration would be an app choice. Revision History Rev. Date Author Changes ---- -------- -------- ----------------------------------------------- 6 05/15/12 pdaniell Fix the Errors section to match the added spec language. 5 04/26/12 pdaniell Add issue #9 and resolve all issues based on Dublin face to face discussion. Minor edits based on feedback from criccio. 4 04/25/12 pdaniell Edits based on feedback from pbrown. 3 04/24/12 pdaniell Further improvements and clarifications. Add MAX_UNIFORM_LOCATIONS. 2 04/23/12 pdaniell Fixes and improvements based on bmerry's feedback and discussions with pbrown. Add new issues. 1 10/26/11 pdaniell Initial version.