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

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 <pname> 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 <name> in the
    shader stage of type <shadertype> attached to <program>, with behavior
    otherwise identical to GetUniformLocation. The value -1 will be returned
    if <name> 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 <program> 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 <shadertype> attached to <program>. 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);

    <program> and <shadertype> specify the program and shader stage. <index>
    must be a subroutine index in the range from zero to the value of
    ACTIVE_SUBROUTINES minus one for the shader stage. If <index> 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 <name> 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 <shadertype>
    with subroutine indices from <indices>, storing <indices>[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 <count> is not equal to the value of
    ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS for the program currently in use at
    shader stage <shadertype>, or if the uniform at location i is used and
    the value in <indices>[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 <indices>[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 <location> for 
    shader stage <shadertype> of the current program. If <location> is
    greater than or equal to the value of ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS
    for the shader currently in use at shader stage <shadertype>, the error
    INVALID_VALUE is generated. If <location> 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 : <behavior>

    where <behavior> 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 <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 <location> 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 <index> 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 <count> 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 <name>
    returned will be an empty string and the <length> 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 <location> 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.
