Name

    OES_shader_io_blocks

Name String

    GL_OES_shader_io_blocks

Contact

    Jon Leech (oddhack 'at' sonic.net)
    Daniel Koch, NVIDIA (dkoch 'at' nvidia.com)

Contributors

    Daniel Koch, NVIDIA (dkoch 'at' nvidia.com)
    Pat Brown, NVIDIA (pbrown 'at' nvidia.com)
    Slawomir Grajewski, Intel
    Graham Connor, Imagination
    Ben Bowman, Imagination
    Jonathan Putsman, Imagination

Notice

    Copyright (c) 2008-2013 The Khronos Group Inc. Copyright terms at
        http://www.khronos.org/registry/speccopyright.html

    Portions Copyright (c) 2013-2014 NVIDIA Corporation.

Status

    Approved by the OpenGL ES Working Group
    Ratified by the Khronos Board of Promoters on November 7, 2014

Version

    Last Modified Date: October 8, 2014
    Revision: 2

Number

    OpenGL ES Extension #213

Dependencies

    OpenGL ES 3.1 and OpenGL ES Shading Language 3.10 are required.

    This specification is written against the OpenGL ES 3.1 (March 17,
    2014) and OpenGL ES 3.10 Shading Language (March 17, 2014)
    Specifications.

    OES_shader_multisample_interpolation trivially affects the definition of
    this extension.

    OES_geometry_shader and EXT_geometry_shader interact with this extension.

    OES_tessellation_shader and EXT_tessellation_shader interact with this
    extension.

Overview

    This extension extends the functionality of interface blocks to
    support input and output interfaces in the OpenGL ES Shading Language.

    Input and output interface blocks are used for forming the
    interfaces between vertex, tessellation control, tessellation
    evaluation, geometry and fragment shaders. This accommodates passing
    arrays between stages, which otherwise would require multi-dimensional
    array support for tessellation control outputs and for tessellation
    control, tessellation evaluation, and geometry shader inputs.

    This extension provides support for application defined
    interface blocks which are used for passing application-specific
    information between shader stages.

    This extension moves the built-in "per-vertex" in/out variables
    to a new built-in gl_PerVertex block. This is necessary for
    tessellation and geometry shaders which require a separate
    instance for each vertex, but it can also be useful for vertex
    shaders.

    Finally, this extension allows the redeclaration of the
    gl_PerVertex block in order to reduce the set of variables that must
    be passed between shaders.

New Procedures and Functions

    None

New Tokens

    None

Additions to Chapter 7 of the OpenGL ES 3.1 Specification (Programs and Shaders)

    Modify section 7.4.1 "Shader Interface Matching":

    When multiple shader stages are active, the outputs of one stage form an
    interface with the inputs of the next stage.  At each such interface,
    shader inputs are matched up against outputs from the previous stage:

      * An output block is considered to match an input block in the
        subsequent shader if the two blocks have the same block name, and
        the members of the block match exactly in name, type, qualification,
        and declaration order.

      * An output variable is considered to match an input variable in the
        subsequent shader if:

        - the two variables match in name, type, and qualification; or

        - the two variables are declared with the same location layout
          qualifier and match in type and qualification.

    Variables or block members declared as structures are considered to
    match in type if and only if structure members match in name, type,
    qualification, and declaration order. Variables or block members
    declared as arrays are considered to match in type only if both
    declarations specify the same element type and array size. The rules for
    determining if variables or block members match in qualification are
    found in the OpenGL ES Shading Language Specification.

    For program objects containing multiple shaders, LinkProgram will check
    for mismatches on interfaces between shader stages in the program being
    linked and generate a link error if a mismatch is detected. A link error
    will be generated if any statically referenced input variable or block
    does not have a matching output.

    With separable program objects ...

    At an interface between program objects, the set of inputs and outputs
    are considered to match exactly if and only if:

      * Every declared input block or variable has a matching output,
        as described above.

      * There are no output blocks or user-defined output variables declared
        without a matching input block or variable declaration.

      * All matched input and output variables (in a block or otherwise) have
        identical precision qualification.

    When the set of inputs and outputs ...

    When using any built-in input or output in the gl_PerVertex block in
    separable program objects, shader code may redeclare that block prior
    to use. If the shader does not redeclare the block, the intrinsically
    declared definition of that block will be used.

    A separable program will fail to link if:

      * the shader uses a built-in block member not found in the
        (re)declaration of that block.

    There is one exception to this rule described below.

    As described above, an exact interface match requires matching built-in
    input and output blocks. At an interface between two non-fragment shader
    stages, the gl_PerVertex input and output blocks are considered to match
    if and only if the block members match exactly in name, type,
    qualification, and declaration order. At an interface involving the
    fragment shader stage, the presence or absence of any built-in output
    does not affect interface matching. At an interface involving the
    vertex shader stage, built-in outputs not found in a block in the
    vertex shader are considered to match the corresponding inputs found
    in the gl_PerVertex input block of the subsequent non-fragment stage,
    provided they match in precision qualification.

    Built-in inputs or outputs not found in blocks do not affect interface
    matching. Any such built-in inputs are well-defined unless they are
    derived from built-in outputs not written by the previous shader stage.

New State

    None

New Implementation Dependent State

    None

Additions to the OpenGL ES Shading Language 3.10 Specification

    Including the following line in a shader can be used to control the
    language features described in this extension:

      #extension GL_OES_shader_io_blocks : <behavior>

    where <behavior> is as specified in section 3.4.

    A new preprocessor #define is added to the OpenGL ES Shading Language:

      #define GL_OES_shader_io_blocks 1

    If the OES_geometry_shader extension is enabled, the
    OES_shader_io_blocks extension is also implicitly enabled.

    If the OES_tessellation_shader extension is enabled, the
    OES_shader_io_blocks extension is also implicitly enabled.


    Modify section 3.8 "Identifiers:"

    Replace the second paragraph with the following:

    Identifiers starting with "gl_" are reserved for use by OpenGL ES, and
    may not be declared in a shader as either a variable or a function; this
    results in a compile-time error. However, as noted in the specification,
    there are some cases where previously declared variables can be redeclared,
    and predeclared "gl_" names are allowed to be redeclared in a shader only
    for these specific purposes. More generally, it is a compile-time error to
    redeclare a variable, including those starting "gl_".


    Modify section 4.3.4 "Input Variables":

    Add following the first paragraph on p. 39:

    ... superfluous declarations of input variables.

    Only the input variables that are statically read need to be written by
    the previous stage; it is allowed to have superfluous declarations of
    input variables. This is shown in the following table.

[?? clarify this is for internal interfaces only]
    -----------------------------------------------------------------------------------
    |                             | Consuming Shader (input variables)                |
    |  Treatment of Mismatched    +---------------------------------------------------+
    |     Input Variables         | No          | Declared but  | Declared and        |
    |                             | Declaration | no Static Use | Static Use          |
    +-----------------------------+-------------+---------------+---------------------|
    |            | No Declaration | Allowed     | Allowed       | Link-Time Error     |
    | Generating |----------------+-------------+---------------+---------------------|
    | Shader     | Declared but   | Allowed     | Allowed       | Allowed (values     |
    | (output    | no Static Use  |             |               | are undefined)      |
    | variables) |----------------+-------------+---------------+---------------------|
    |            | Declared and   |             |               | Allowed (values are |
    |            | Static Use     | Allowed     | Allowed       | potentially undef.) |
    |            |                |             |               |                     |
    -----------------------------------------------------------------------------------

    Consumption errors are based on static use only. Compilation may
    generate a warning, but not an error, for any dynamic use the compiler
    can deduce that might cause consumption of undefined values.

    See section 7 "Built-in Variables" ...


    (Modify the first paragraph, starting "The output of the vertex shader",
    on p. 41):

    The fragment shader inputs form an interface with the last active shader
    in the vertex processing pipeline. For this interface, the last active
    shader stage output variables and fragment shader input variables of the
    same name must match in type and qualification, with a few exceptions...


    (Modify the third paragraph on p. 41):

    Shaders can ensure matches across such interfaces either by using input
    and output layout qualifiers (sections 4.4.1 "Input Layout Qualifiers"
    and 4.4.2 "Output Layout Qualifiers") or by using identical input and
    output declarations of blocks or variables. Complete rules for interface
    matching are found ...


    Modify section 4.3.9 "Interface Blocks":

    Input, output, uniform, and buffer variable declarations can be grouped
    into named interface blocks to provide coarser granularity backing than
    is achievable with individual declarations. They can have an optional
    instance name, used in the shader to reference their members. An output
    block of one programmable stage is backed by a corresponding input block
    in the subsequent programmable stage. A uniform block is backed by the
    application with a buffer object. A block of buffer variables, called a
    shader storage block, is also backed by the application with a buffer
    object. It is a compile-time error to have an input block in a vertex
    shader or an output block in a fragment shader; these uses are reserved
    for future use.

    An interface block is started by an "in", "out", "uniform", or "buffer"
    keyword, followed by a block name, followed by an open curly brace ( { )
    as follows:

    (modify the grammar rules after the third paragraph)

      interface-block:
        layout-qualifier_opt interface-storage-qualifier block-name
        { member-list } instance-name_opt ;

      interface-storage-qualifier:
        in
        out
        uniform
        buffer

        ...

    Each of the above elements ...

    ... with four uniforms grouped inside it.

    Types and declarators are the same as for other input, output, uniform,
    and buffer variable declarations outside blocks, with these exceptions:

    * opaque types are not allowed
    * structure definitions cannot be nested inside a block

    Any of these would result in a compile-time error. Otherwise, built-in
    types, previously declared structures, and arrays of these are allowed
    as the type of a declarator in the same manner they are allowed outside
    a block.

    If no optional qualifier is used in a member-declaration, the
    qualification of the variable is just in, out, uniform, or buffer as
    determined by interface-storage-qualifier. If optional qualifiers are
    used, they can include interpolation qualifiers and storage qualifiers,
    and they must declare an input, output, or uniform variable consistent
    with the interface qualifier of the block: input, output, uniform, and
    buffer variables can only be declared in in, out, uniform, and shader
    storage blocks, respectively.

    Repeating the "in", "out", "uniform", or "buffer" interface qualifier
    for a member's storage qualifier is optional. "centroid in" and "sample
    in" variables are consistent with "in" blocks, and "centroid out" and
    "sample out" variables are consistent with "out" blocks.

    A <shader interface> is defined to be one of these:

        * All the uniform variables of a program. This spans all compilation
          units linked together within one program.
        * All the buffer blocks declared in a program.
        * The boundary between adjacent programmable pipeline stages: This
          spans all the outputs declared in all compilation units of the
          first stage and all the inputs declared in all compilation units
          of the second stage. Note that the fragment shader is considered
          to have a shared boundary with the previous adjacent stage even
          though in practice, all values passed from prior stages to the
          fragment shader first pass through the rasterizer and
          interpolator.

    The block name (block-name) is used to match interfaces: an output block
    of one pipeline stage will be matched to an input block with the same
    name in the subsequent pipeline stage. For uniform or shader storage
    blocks, the application uses the block name to identify the block. Block
    names have no other use within a shader beyond interface matching; it is
    a compile-time error to use a block name at global scope for anything
    other than as a block name (e.g., use of a block name for a global
    variable name or function name is currently reserved). It is a
    compile-time error to use the same block name for more than one block
    declaration in the same shader interface (as defined above) within one
    shader, even if the block contents are identical.

    Matched block names within a shader interface (as defined above) must
    match in terms of having the same number of declarations with the same
    sequence of types, precisions, and the same sequence of member names, as
    well as having the same member-wise layout qualification (see next
    section). Matched uniform block names (but not input or output block
    names) must also either all be lacking an instance name or all having an
    instance name, putting their members at the same scoping level. When
    instance names are present on matched block names, it is allowed for the
    instance names to differ; they need not match for the blocks to match.
    Furthermore, if a matching block is declared as an array, then the array
    sizes must also match (or follow array matching rules for the interface
    between a vertex and a geometry shader). Any mismatch will generate a
    link-time error. A block name is allowed to have different definitions
    in different interfaces within the same shader, allowing, for example,
    an input block and output block to have the same name.

    If an instance name (instance-name) is not used, the names declared
    inside the block are scoped at the global level and accessed as if they
    were declared outside the block. If an instance name is used, then it
    puts all the members inside a scope within its own name space, accessed
    with the field selector ( . ) operator (analogously to structures). For
    example,

        uniform Transform_1
        {
            mat4 modelview;  // API will use "modelview"
        }
        uniform Transform_2
        {
            mat4 projection; // API will use "Transform_2.projection"
        } transform_2;       // instance name
        mat4 projection;     // different than transform_2.projection
        mat4 modelview;      // illegal, already defined

    Outside the shading language (i.e., in the API), members are similarly
    identified except the block name is always used in place of the instance
    name (API accesses are to interfaces, not to shaders). If there is no
    instance name, then the API does not use the block name to access a
    member, just the member name.

    Within an interface, all declarations of the same global name must be
    for the same object and must match in type and in whether they declare a
    variable or member of a block with no instance name. The API also needs
    this name to uniquely identify an object in the interface. It is a
    link-time error if any particular interface contains

        * two different blocks, each having no instance name, and each
          having a member of the same name, or
        * a variable outside a block, and a block with no instance name,
          where the variable has the same name as a member in the block.

        out Vertex {
            vec4 Position;  // API transform/feedback will use "Vertex.Position"
            vec2 Texture;
        } Coords;           // shader will use "Coords.Position"
        out Vertex2 {
            vec4 Color;     // API will use "Color"
            float Color2;
        };
        // in same program as Vertex2 above:
        out Vertex3 {
            float Intensity;
            vec4 Color;     // ERROR, name collision with Color in Vertex2
        };
        float Color2;       // ERROR, collides with Color2 in Vertex2

    For blocks declared as arrays, the array index must also be included
    when accessing members, as in this example

        uniform Transform { // API uses "Transform[2]" to refer to instance 2
            mat4 ModelViewMatrix;
            mat4 ModelViewProjectionMatrix;
            float Deformation;
        } transforms[4];
        ...
        ... = transforms[2].ModelViewMatrix; // shader access of instance 2
        // API uses "Transform.ModelViewMatrix" to query an offset or other query

    For uniform or shader storage blocks declared as an array, each
    individual array element corresponds to a separate buffer object,
    backing one instance of the block. As the array size indicates the
    number of buffer objects needed, uniform and shader storage block array
    declarations must specify an array size. All indices used to index a
    uniform or shader storage block array must be constant integral
    expressions.

    When using OpenGL ES API entry points to identify the name of an
    individual block in an array of blocks, the name string must include an
    array index (e.g., Transform[2]). When using OpenGL ES API entry points
    to refer to offsets or other characteristics of a block member, an array
    index must not be specified (e.g., Transform.ModelViewMatrix).

    There are implementation dependent limits on the number of uniform
    blocks and the number of shader storage blocks that can be used per
    stage. If either limit is exceeded, it will cause a link-time error.


    Modify section 4.4 "Layout Qualifiers":

    Layout qualifiers can appear in several forms of declaration. They can
    appear as part of an interface block definition or block member, as
    shown in the grammar in the previous section. They can also appear with
    just an interface qualifier (a storage qualifier that is "in", "out", or
    "uniform") to establish layouts of other declarations made with that
    interface qualifier:

      layout-qualifier interface-qualifier ;

    ...

    The layout-qualifier expands to

      layout-qualifier :
        layout ( layout-qualifier-id-list )

      layout-qualifier-id-list :
        layout-qualifier-id
        layout-qualifier-id , layout-qualifier-id-list

      layout-qualifier-id
        layout-qualifier-name
        layout-qualifier-name = layout-qualifier-value

    The tokens used for layout-qualifier-name are identifiers, not keywords.
    Generally, they can be listed in any order. Order-dependent meanings
    exist only if explicitly called out below. Similarly, these identifiers
    are not case sensitive, unless explicitly noted otherwise.

    More than one layout qualifier may appear in a single declaration.
    Additionally, the same layout-qualifier-name can occur multiple times
    within a layout qualifier or across multiple layout qualifiers in the
    same declaration. When the same layout-qualifier-name occurs multiple
    times, in a single declaration, the last occurrence overrides the former
    occurrence(s). Further, if such a layout-qualifier-name will effect
    subsequent declarations or other observable behavior, it is only the
    last occurrence that will have any effect, behaving as if the earlier
    occurrence(s) within the declaration are not present. This is also true
    for overriding layout-qualifier-names, where one overrides the other
    (e.g., row_major vs. column_major); only the last occurrence has any
    effect.

      [[ The last paragraph of this section in GLSL 4.40 and the really nice
         table of layout qualifiers from different stages could be inserted
         at this point, but aren't necessary. ]]

    4.4.1 Input Layout Qualifiers

    Some input layout qualifiers apply to all shader languages and some
    apply only to specific languages. The latter are discussed in separate
    sections below.

    All shaders, except compute shaders, allow "location" layout qualifiers
    on input variable declarations, input block declarations, and input
    block member declarations.

    The layout qualifier identifier for inputs is:

      layout-qualifier-id
        location = integer-constant

    Only one argument is accepted.  For example,

      layout(location = 3) in vec4 normal;

    will establish that the shader input <normal> is assigned to vector
    location number 3. For vertex shader inputs, the location specifies the
    number of the vertex attribute from which input values are taken. For
    inputs of all other shader types, the location specifies a vector number
    that can be used to match against outputs from a previous shader stage,
    even if that shader is in a different program object.

    The following language describes how many locations are consumed by a
    given type.  However, geometry shader inputs, tessellation control shader
    inputs and outputs, and tessellation evaluation inputs all have an
    additional level of arrayness relative to other shader inputs and outputs.
    This outer array level is removed from the type before considering how
    many locations the type consumes.

    If a shader input is any scalar or vector type, it will consume a single
    location.

    If the declared input (after potentially removing an outer array level as
    just described above) is an array of size <n> and each of the elements
    takes <m> locations, it will be assigned <m> * <n> consecutive locations
    starting with the location specified. For example,

      layout (location = 6) in vec4 colors[3];

    will establish that the shader input <colors> is assigned to vector
    location numbers 6, 7, and 8.

    If the declared input is an <n> x <m> matrix, it will be assigned multiple
    locations starting with the location specified. The number of locations
    assigned for each matrix will be the same as for an <n>-element array of
    <m>-component vectors. For example,

      layout (location = 9) in mat4 transforms[2];

    will establish that shader input <transforms> is assigned to vector
    locations 9-16, with <transforms[0]> being assigned to locations 9-12,
    and <transforms[1]> being assigned to locations 13-16.

    If the declared input is a structure or block, its members will be
    assigned consecutive locations in their order of declaration, with the
    first member assigned the location provided in the layout qualifier. For
    a structure, this process applies to the entire structure. It is a
    compile-time error to use a location qualifier on a member of a
    structure. For a block, this process applies to the entire block, or
    until the first member is reached that has a location layout qualifier.
    When a block member is declared with a location qualifier, its location
    comes from that qualifier: The member's location qualifier overrides the
    block-level declaration. Subsequent members are again assigned
    consecutive locations, based on the newest location, until the next
    member declared with a location qualifier. The values used for locations
    do not have to be declared in increasing order.

    If a block has no block-level location layout qualifier, it is required
    that either all or none of its members have a location layout qualifier,
    or a compile-time error results.

    The locations consumed by block and structure members are determined by
    applying the rules above recursively as though the structure member were
    declared as an input variable of the same type. For example:

      layout(location = 3) in struct S {
          vec3 a;                         // gets location 3
          mat2 b;                         // gets locations 4 and 5
          vec4 c[2];                      // gets locations 6 and 7
          layout (location = 8) vec2 A;   // ERROR, can't use on struct member
      } s;

      layout(location = 4) in block {
          vec4 d;                         // gets location 4
          vec4 e;                         // gets location 5
          layout(location = 7) vec4 f;    // gets location 7
          vec4 g;                         // gets location 8
          layout (location = 1) vec4 h;   // gets location 1
          vec4 i;                         // gets location 2
          vec4 j;                         // gets location 3
          vec4 k;                         // ERROR, location 4 already used
      };

    The number of input locations available to a shader is limited. For
    vertex shaders, the limit is the advertised number of vertex attributes.
    For all other shaders, the limit is implementation-dependent and must be
    no less than one fourth of the advertised maximum input component count.
    A program will fail to link if any attached shader uses a location
    greater than or equal to the number of supported locations, unless
    device-dependent optimizations are able to make the program fit within
    available hardware resources.

    A program will fail to link if explicit location assignments leave the
    linker unable to find space for other variables without explicit
    assignments.

    For the purposes of determining if a non-vertex input matches an output
    from a previous shader stage, the location layout qualifier (if any)
    must match.

    If a vertex shader input variable with no location assigned in the
    shader text has a location specified through the OpenGL ES API, the
    API-assigned location will be used. Otherwise, such variables will
    be assigned a location by the linker. See section 2.11.5 "Vertex
    Attributes" of the OpenGL ES 3.1 Graphics System Specification for
    more details.

    It is an error if more than one input or element of a matrix input is
    bound to the same location.


    Add new subsection 4.4.1.fs:

    4.4.1.fs Fragment Shader Inputs

    Fragment shaders can have an input layout for redeclaring the built-in
    variable gl_FragCoord:

      in vec4 gl_FragCoord; // redeclaration that changes nothing is allowed

    The built-in gl_FragCoord is only predeclared in fragment shaders, so
    redeclaring it in any other shader language results in a compile-time
    error.

    Fragment shaders also allow the following layout qualifier on "in" only
    (not with variable declarations)

          layout-qualifier-id
                early_fragment_tests

    to request that fragment tests be performed before fragment shader
    execution, as described in section 3.9.2 "Early Fragment Tests" of the
    OpenGL ES Specification.

    For example, specifying

        layout(early_fragment_tests) in;

    will make per-fragment tests be performed before fragment shader
    execution. In addition, it is an error to statically write to
    gl_FragDepth in the fragment shader.

    If this is not declared, per-fragment tests will be performed after
    fragment shader execution.

    4.4.1.1 Compute Shader Inputs ...


    Replace section 4.4.2

    4.4.2 Output Layout Qualifiers

    Some output layout qualifiers apply to all shader languages and some
    apply only to specific languages. The latter are discussed in separate
    sections below.

    As with input layout qualifiers, all shaders except compute shaders
    allow location layout qualifiers on output variable declarations, output
    block declarations, and output block member declarations.

    The layout qualifier identifier for outputs is:

      layout-qualifier-id
          location = integer-constant

    The usage and rules for applying the location qualifier to blocks and
    structures are exactly as described in section 4.4.1 "Input Layout
    Qualifiers".


    This qualifier may appear at most once with a declaration. For example,

      layout(location = 3) out vec4 color;

    will establish that the fragment shader output color is assigned to
    fragment color 3.

    For fragment shader outputs, the location specifies the color output
    number receiving the values of the output. For outputs of all other
    shader stages, the location specifies a vector number that can be used
    to match against inputs in a subsequent shader stage, even if that
    shader is in a different program object.

    Declared outputs of scalar or vector type consume a single location.

    If the declared output is an array, it will be assigned consecutive
    locations starting with the location specified. For example,

      layout(location = 2) out vec4 colors[3];

    will establish that <colors> is assigned to vector location numbers 2,
    3, and 4.

    If the declared output is an n x m matrix, it will be assigned multiple
    locations starting with the location specified. The number of locations
    assigned will be the same as for an n-element array of m-component
    vectors.

    If the declared output is a structure, its members will be assigned
    consecutive locations in the order of declaration, with the first member
    assigned the location specified for the structure. The number of
    locations consumed by a structure member is determined by applying the
    rules above recursively as though the structure member were declared as
    an output variable of the same type.

    Location layout qualifiers may be used on output variables declared as
    structures, but it is a compile-time error to use them on individual
    members. Location layout qualifiers may be used on output blocks and
    output block members.

    The number of output locations available to a shader is limited. For
    fragment shaders, the limit is the advertised number of draw buffers.
    For all other shaders, the limit is implementation-dependent and must be
    no less than one fourth of the advertised maximum output component
    count (compute shaders have no outputs.) A program will fail to link if
    any attached shader uses a location greater than or equal to the number
    of supported locations, unless device-dependent optimizations are able
    to make the program fit within available hardware resources.
    Compile-time errors may also be given if at compile time it is known the
    link will fail. A negative output location will result in a compile-time
    error.

    A program will fail to link if any of the following occur:

      * any two fragment shader output variables are assigned to the same
        location
      * if any two output variables from the same vertex stage are assigned
        to the same location.

    For all shader types, a program will fail to link if explicit location
    assignments leave the linker unable to find space for other variables
    without explicit assignments.

    If an output variable has no location assigned in the shader text, it
    will be assigned a location by the linker. See section 3.9.2 "Shader
    Execution" of the OpenGL ES Specification for more details.

    For the purposes of determining if a non-fragment output matches an
    input from a subsequent shader stage, the location layout qualifier (if
    any) must match.


    (Add new subsection 4.4.2.fs):

    4.4.2.fs Fragment Outputs

    Fragment shaders can have an output layout for redeclaring the built-in
    variable gl_FragDepth:

      out float gl_FragDepth; // redeclaration that changes nothing is allowed

    The built-in gl_FragDepth is only predeclared in fragment shaders, so
    redeclaring it in any other shader language results in a compile-time
    error.


    (Remove subsection 4.5.1 "Linking of Vertex Outputs and Fragment
    Inputs". Note that the table from this section is moved to section
    4.3.4, while most of the interface matching language is now dealt with
    in "Shader Interface Matching" in the OpenGL ES Specification as
    modified by this extension.)


    (Modify the first two paragraphs of section 7.1 "Vertex Shader Special
    Variables", moving one paragraph up one level to the introduction of
    chapter 7):

    7 Built-in Variables

    Some OpenGL operations occur in fixed functionality and need to provide
    values to or receive values from shader executables. Shaders communicate
    with fixed-function OpenGL pipeline stages, and optionally with other
    shader executables, through the use of built-in input and output
    variables.

    7.1 Vertex Shader Special Variables

    In the vertex language, the built-ins are intrinsically declared as
    follows:

      in highp int gl_VertexID;
      in highp int gl_InstanceID;

      out gl_PerVertex {
          highp vec4  gl_Position;
          highp float gl_PointSize;
      };

    The variable gl_Position is intended for writing the homogeneous vertex
    position. It can be written at any time during shader execution. This
    value will be used by the following shader stage, or if there are no
    other shaders prior to the fragment shader, by primitive assembly,
    clipping, culling, and other fixed functionality operations that operate
    on primitives after vertex processing has occurred. Its value is
    undefined after vertex processing if the vertex shader does not write
    gl_Position.

    The variable gl_PointSize ...

    Add a new section 7.io following section 7.3 "Built-In Uniform State":

    7.io Redeclaring Built-in Blocks

    The gl_PerVertex block can be redeclared in a shader to explicitly
    indicate what subset of the members will be used. This is necessary to
    establish the interface between multiple programs. If the gl_PerVertex
    block is not redefined in a given program, the intrinsically declared
    definition of that block is used for the program interface.

    For example:

      out gl_PerVertex {
        highp vec4 gl_Position;   // will use gl_Position
        highp float gl_PointSize; // will use gl_PointSize
        highp vec4 t;             // error, only gl_PerVertex members allowed
      }; // no other members of gl_PerVertex will be used

    This establishes the output interface the shader will use with the
    subsequent pipeline stage. It must be a subset of the built-in members
    of gl_PerVertex. Such a redeclaration can also add the invariant
    qualifier and interpolation qualifiers.

    Other layout qualifiers, like location, cannot be added to such a
    redeclaration, unless specifically stated.

    If a built-in interface block is redeclared, it must appear in the
    shader before any use of any member included in the built-in
    declaration, or a compile-time error will result. It is also a
    compile-time error to redeclare the block more than once or to redeclare
    a built-in block and then use a member from that built-in block that was
    not included in the redeclaration. Also, if a built-in interface block
    is redeclared, no member of the built-in declaration can be redeclared
    outside the block redeclaration. If multiple shaders using members of a
    built-in block belonging to the same interface are linked together in
    the same program, they must all redeclare the built-in block in the same
    way, as described in section 4.3.7 "Interface Blocks" for interface
    block matching, or a link-time error will result. It will also be a
    link-time error if some shaders in a program redeclare a specific
    built-in interface block while another shader in that program does not
    redeclare that interface block yet still uses a member of that interface
    block. If a built-in block interface is formed across shaders in
    different programs, the shaders must all redeclare the built-in block in
    the same way (as described for a single program), or the values passed
    along the interface are undefined.

Dependencies on OES_shader_multisample_interpolation

    If OES_shader_multisample_interpolation is not supported, references to
    "sample in", "sample out" and the extension should be ignored.

Dependencies on OES_geometry_shader and EXT_geometry_shader

    If OES_geometry_shader or EXT_geometry_shader is enabled, this extension
    is implicitly enabled for geometry shaders.

    If OES_geometry_shader or EXT_geometry_shader is not supported, ignore all
    references to geometry shaders.

Dependencies on OES_tessellation_shader and EXT_tessellation_shader

    If OES_tessellation_shader or EXT_tessellation_shader is enabled, this
    extension is implicitly enabled for tessellation control and evaluation
    shaders.

    If OES_tessellation_shader or EXT_tessellation_shaders is not supported,
    ignore all references to tessellation shaders.

Issues

    (1) What functionality was removed from interface blocks relative to
        GL 4.4?

      - Interactions with features not supported by the underlying
        ES 3.1 API and Shading Language, including:
          * gl_ClipDistance shader inputs and outputs.
          * "component" layout
          * location aliasing
          * fragment shader output "index" layout
          * fragment shader gl_FragDepth layout "depth*" qualifiers
          * double-precision scalars and vectors
          * matching across shader stages with different qualifiers (other
            than precision and "in"/"out").
          * References allowing or assuming more than one shader object per
            pipeline stage.
          * gl_PerFragment is not added (only exists in compatibility profile).

    (2) What functionality was changed and added relative to interface blocks
        in GL 4.4?

      - separable shaders are not required to redeclare the gl_PerVertex block.
      - clarifications on types allowed for vertex and fragment shader inputs
        from ES 3.0.

    (3) Are any grammar additions required in chapter 9?

    There may be something needed for supporting interface blocks on in/out
    declarations, but I believe not, since the existing GLSL-ES 3.10 grammar
    already has these as storage_qualifier tokens.

    (4) Shader Interface Matching rules have been updated to relax precision
        matching on shader outputs and inputs, as previously required in ES
        3.0. This was changed during 3.1 development but is now proposed to
        return to 3.0 behavior, matching this extension.

    RESOLVED. Per Bug 11189, when using a program that contains both sides
    of an interface, the precision qualifier on inputs/outputs does not need
    to match.  However for two separable programs, the precision qualifiers
    on inputs/outputs are required to match on the external interfaces.
    Failing to do so results in a validation error.

    (5) In section 4.3.7 "Interface Matching", the corresponding part of
        desktop GLSL 4.40 (pp. 49-50) has some material that's very
        different than GLSL-ES language. Still need to review its
        applicability here.

    UNRESOLVED.  This should be addressed by rebasing on the ES 3.1 specs.

    (6) Should we allow re-declaring the gl_PerVertex block?

    DISCUSSION:  If we do, we need to update Section 3.8 with language from
    Section 3.7 in the GLSL 4.4 spec about redeclaring 'gl_' variables.
    If we don't, applications will always pay the space for gl_PointSize,
    and would never be able to have 'invariant' or different interpolation
    or precision qualifiers on vertex, tessellation, or geometry shader
    built-in outputs. This seems undesirable.

    RESOLVED: Yes. Section 3.8 updated.

    (7) What is the behavior of LinkProgram with respect to gl_PerVertex
        blocks?

    DISCUSSION:
    a) When using monolithic programs, gl_PerVertex does not need to be
       redeclared in any shader stage.

    b) When using separable programs with only OpenGL ES 3.1-level
       functionality (vertex and fragment only), gl_PerVertex does not need to
       be redeclared.  In fact, gl_PerVertex can't be redeclared, since no
       language mechanism exists in unextended ES 3.1 to do so.  Adding such a
       requirement merely due to the presence of this extension would break
       valid OpenGL ES 3.1-level applications.  The lack of a redeclaration
       requirement in OpenGL ES 3.1 is a difference relative to OpenGL 4.1,
       but the reasons why we added this requirement in OpenGL 4.1 (many
       shader stages, a larger set of built-ins, and the desire to be able to
       treat gl_PerVertex members like other "regular" varyings) don't exist
       in unextended ES 3.1.

    c) When using separable programs, any shader with the ability to redeclare
       gl_PerVertex could require redeclaration when any of its members are
       used. This would be mostly compatible with OpenGL 4.1, which requires
       all stages to redeclare and provides the ability to do so in all
       stages. However, since the intrinsically declared gl_PerVertex blocks
       are actually fairly small in ES, redeclaring gl_PerVertex is optional
       in ES. The basic rules here are:

       - gl_PerVertex exists iff OES_shader_io_blocks is enabled.
       - OES_shader_io_blocks is always enabled if OES_geometry_shader
         or OES_tesselation_shader is enabled.
       - OES_shader_io_blocks can be optionally enabled for VS and FS.

    (8) What happens when you use the following together in a program
    pipeline?
      - a separable vertex-only program A which doesn't enable
          OES_shader_io_blocks, and
      - a separable program B containing a tessellation or geometry shader

    DISCUSSION: This was not an issue in OpenGL because separable shaders
    were added (in GL 4.1) after geometry shaders and input blocks were
    added (in GL 3.2), so any separable program with a vertex shader could
    redeclare gl_PerVertex. There are basically 3 options:

    a) Driver has to make any combination of VS outputs in A and redeclared
       input gl_PerVertex block in B work correctly.
    b) Lack of redeclaring gl_PerVertex in A implies interface mismatch with
       redeclared gl_PerVertex in B. Per the standard rules, if there is no
       complete interface match, all inputs are undefined except for
       individual variables that match by location, just as with user-
       defined variables.  Built-ins can't be assigned numeric locations, so
       would be considered not to match.
    c) It is an error. The vertex shader must be modified to support
       being used in combination with geometry and tessellation shaders.

    RESOLVED: (a) There will only be one or at most two (if
    OES_geometry_point_size is enabled) outputs from the vertex shader
    that would need to be matched up with the gl_PerVertex block in the
    next shader. It doesn't seem onerous to just make it work, and it is
    desirable to be able to just drop a geometry shader into an otherwise
    valid ES 3.1 application without modifying the vertex shader.

    (9) Why are there so many edits to section 4.4.1 and 4.4.2 and what
    really changed?

    Some of this is due to restructuring to create subsections specific to
    different shader stages, some appears to be correct (but potentially
    redundant) language from GLSL 4.40, and some is useful block-related
    language.

    (10) One of the new matching requirements for ES 3.1 is that
    interpolation qualifies don't need to match. Is that true for block
    members as well, or just loose variables?

    RESOLVED.  This is true for block members as well.
    In general, we'll allow the same rules for matching variables and
    block members. Then a block matches iff the block members match.

[?? still need to apply/verify edits for this].

Revision History

    Rev.    Date    Author    Changes
    ----  --------  --------- -------------------------------------------------

     2    08/10/2014   olson     Removed contradictory language forbidding
                                 location layout qualifiers on output blocks
                                 or output block members (Bug 12831)
     1    06/18/2014   dkoch     Initial OES version based on EXT.
                                 No functional changes.
