Name

    EXT_base_instance

Name Strings

    GL_EXT_base_instance

Contact

    Daniel Koch, NVIDIA (dkoch 'at' nvidia.com)

Contributors

    Dominik Witczak, Mobica
    Jonas Gustavsson, Sony Mobile
    Slawomir Grajewski, Intel
    Contributors to ARB_base_instance

Notice

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

    Portions Copyright (c) 2014 NVIDIA Corporation.

Status

    Complete

Version

    Last Modified Date:         October 24, 2014
    Author Revision:            4

Number

    OpenGL ES Extension #203

Dependencies

    This specification is written against the OpenGL ES 3.1 (June 4, 2014)
    Specification, although it can apply to previous versions.

    OpenGL ES 3.0 is required.

    EXT_draw_elements_base_vertex is required.

    This extension interacts with EXT_multi_draw_indirect.

Overview

    This extension allows the offset within buffer objects used for instanced
    rendering to be specified. This is congruent with the <first> parameter
    in glDrawArrays and the <basevertex> parameter in glDrawElements. When
    instanced rendering is performed (for example, through
    glDrawArraysInstanced), instanced vertex attributes whose vertex attribute
    divisors are non-zero are fetched from enabled vertex arrays per-instance
    rather than per-vertex. However, in unextended OpenGL ES, there is no way
    to define the offset into those arrays from which the attributes are
    fetched. This extension adds that offset in the form of a <baseinstance>
    parameter to several new procedures.

    The <baseinstance> parameter is added to the index of the array element,
    after division by the vertex attribute divisor. This allows several sets of
    instanced vertex attribute data to be stored in a single vertex array, and
    the base offset of that data to be specified for each draw. Further, this
    extension exposes the <baseinstance> parameter as the final and previously
    undefined structure member of the draw-indirect data structure.

IP Status

    None.

New Procedures and Functions

    void DrawArraysInstancedBaseInstanceEXT(enum mode,
                                            int first,
                                            sizei count,
                                            sizei instancecount,
                                            uint baseinstance);

    void DrawElementsInstancedBaseInstanceEXT(enum mode,
                                              sizei count,
                                              enum type,
                                              const void *indices,
                                              sizei instancecount,
                                              uint baseinstance);

    void DrawElementsInstancedBaseVertexBaseInstanceEXT(enum mode,
                                                        sizei count,
                                                        enum type,
                                                        const void *indices,
                                                        sizei instancecount,
                                                        int basevertex,
                                                        uint baseinstance);

New Tokens

    None.

Modifications to Chapter 10 of the OpenGL ES 3.1 Specification (Vertex
Specification and Drawing Commands)

    Modification to Section 10.5, "Drawing Commands using Vertex Arrays"

    (Modify the definition of DrawArraysOneInstance, to define the
    behaviour of the <baseinstance> parameter. Modify the 3rd paragraph
    of the definition of the command, p.247, as follows)

    "If an enabled vertex attribute array is instanced (it has a non-zero
    <divisor> as specified by VertexAttribDivisor), the element index that
    is transferred to the GL, for all vertices, is given by

        floor(<instance> / <divisor>) + <baseinstance>"


    (Replace the description of DrawArraysInstanced, p.248, with the
    following)

    "The command

        void DrawArraysInstancedBaseInstanceEXT(enum mode,
                                                int first,
                                                sizei count,
                                                sizei instancecount,
                                                uint baseinstance);

    behaves identically to DrawArrays, except that <instancecount> instances of
    the range of elements are executed and the value of <instance> advances for
    each iteration. Those attributes that have non-zero values for <divisor>,
    as specified by VertexAttribDivisor, advance once every <divisor>
    instances. Additionally, the first element within those instanced vertex
    attributes is specified in <baseinstance>.

    DrawArraysInstancedBaseInstanceEXT is equivalent to

        if (<mode>, <count>, or <instancecount> is invalid)
            generate  appropriate  error
        else {
            for  (i = 0; i < <instancecount>; i++) {
                DrawArraysOneInstance(<mode>, <first>, <count>, i,
                                      <baseinstance>);
            }
        }

    The command

        void DrawArraysInstanced(enum mode,
                                 int first,
                                 sizei count,
                                 sizei primcount);

    is equivalent to

        DrawArraysInstancedBaseInstanceEXT(<mode>, <first>, <count>,
                                           <instancecount>, 0);"



    (Update the definition of DrawArraysIndirect on p.248 as follows)

    "The command

        void  DrawArraysIndirect(enum mode, const void *indirect);

    is equivalent to

        typedef  struct {
            uint  count;
            uint  instanceCount;
            uint  first;
            uint  baseInstance;
        } DrawArraysIndirectCommand;

        DrawArraysIndirectCommand  *cmd  =
            (DrawArraysIndirectCommand *)indirect;

        DrawArraysInstancedBaseInstanceEXT(mode,
                                           cmd->first,
                                           cmd->count,
                                           cmd->instanceCount,
                                           cmd->baseInstance);"

    (Retain the remainder the description of DrawArraysIndirect, but
    delete the sentence "Results are undefined if <reservedMustBeZero> is
    non-zero, but may not result in program termination." from the Errors
    section.)


    (Modify the definition of DrawElementsOneInstance, to define the
    behaviour of the <baseinstance> parameter. Modify the 3rd paragraph
    of the definition of the command, p.249, as follows)

    "If an enabled vertex attribute array is instanced (it has a non-zero
    attribute divisor as specified by VertexAttribDivisor), the element that
    is transferred to the GL is given by:

        floor(<instance> / <divisor>) + <baseinstance>"


    (Update the text describing DrawElements, p.250, to mention the
    <baseinstance> parameter)

    "The command

        void DrawElements(enum mode,
                          sizei count,
                          enum type,
                          const void *indices);

    behaves identically to DrawElementsOneInstance with the <instance> and
    <baseinstance> parameters set to zero; the effect of calling ..."


    (Replace the description of DrawElementsInstanced, p.251, with the
    following)

    "The command

        void DrawElementsInstancedBaseInstanceEXT(enum mode,
                                                  sizei count,
                                                  enum type,
                                                  const void *indices,
                                                  sizei instancecount,
                                                  uint baseinstance);

    behaves identically to DrawElements except that <instancecount> instances
    of the set of elements are executed, the value of <instance> advances
    between each set. Instanced attributes are advanced as they do during
    execution of DrawArraysInstancedBaseInstaceEXT, and <baseinstance> has
    the same effect. It is equivalent to:

        if  (<mode>, <count>, <type> or <instancecount> is invalid)
            generate  appropriate  error
        else {
            for (int i = 0; i < <instancecount>;  i++) {
                DrawElementsOneInstance(<mode>, <count>, <type>, <indices>,
                                        i, <baseinstance>);
            }
        }

    The command

        void DrawElementsInstanced(enum mode, sizei count, enum type,
                                   const void *indices, sizei instancecount);

    behaves identically to DrawElementsInstancedBaseInstanceEXT except that
    <baseinstance> is zero. It is equivalent to

        DrawElementsInstancedBaseInstanceEXT(<mode>, <count>, <type>,
                                             <indices>, <instancecount>, 0);"


    (Add to the list of functions which include DrawElementsBaseVertexEXT,
    DrawRangeElementsBaseVertexEXT, and DrawElementsInstancedBaseVertexEXT
    (as added by EXT_draw_elements_base_vertex))

        void DrawElementsInstancedBaseVertexBaseInstanceEXT(enum mode,
                                                        sizei count,
                                                        enum type,
                                                        const void *indices,
                                                        sizei instancecount,
                                                        int basevertex,
                                                        uint baseinstance);

    (Append a new paragraph after the description of DrawElementsBaseVertexEXT,
    DrawRangeElementsBaseVertexEXT, and DrawElementsInstancedBaseVertexEXT
    (as added by EXT_draw_elements_base_vertex))

    "For DrawElementsInstancedBaseVertexBaseInstanceEXT, <baseinstance> is
    used to offset the element from which instanced vertex attributes (those
    with a non-zero divisor as specified by VertexAttribDivisor) are taken."


    (Update the definition of DrawElementsIndirect on p.252 as follows)

    "The command

        void  DrawElementsIndirect(enum mode,
                                   enum type,
                                   const void *indirect );

    is equivalent to:

        typedef  struct {
            uint  count;
            uint  instanceCount;
            uint  firstIndex;
            int   baseVertex;
            uint  baseInstance;
        } DrawElementsIndirectCommand;

        if  (no element array buffer is bound) {
            generate appropriate error
        } else {
            DrawElementsIndirectCommand *cmd =
                (DrawElementsIndirectCommand *)indirect;

            DrawElementsInstancedBaseVertexBaseInstanceEXT(
                                            mode,
                                            cmd->count,
                                            type,
                                            cmd->firstIndex * size-of-type,
                                            cmd->instanceCount,
                                            cmd->baseVertex,
                                            cmd->baseInstance);
        }"

    (Retain the remainder of the description of DrawElementsIndirect, but
    delete the sentence "Results are undefined if <reservedMustBeZero> is
    non-zero, but may not result in program termination." from the Errors
    section.)

Additions to the EGL/AGL/GLX/WGL Specifications

    None.

Dependencies on EXT_multi_draw_indirect.

    If EXT_multi_draw_indirect is supported, this extension adds <baseInstance>
    support for the MultiDraw*Indirect commands as well, because they share
    the same command structures.

Errors

    The errors for DrawArraysInstancedBaseInstanceEXT are equivalent to the
    errors for DrawArraysInstanced, but are repeated here for clarity:

    - An INVALID_ENUM error is generated if <mode> is not one of the primitive
      types defined in section 10.1.
    - Specifying <first> < 0 results in undefined behavior. Generating an
      INVALID_VALUE error is recommended in this case.
    - An INVALID_VALUE error is generated if <count> is negative.

    The errors for DrawElementsInstancedBaseInstanceEXT and
    DrawElementsInstancedBaseVertexBaseInstanceEXT are equivalent to the
    errors for DrawElementsInstanced, but are repeated here for clarity:

    - An INVALID_ENUM error is generated if <mode> is not one of the primitive
      types defined in section 10.1.
    - An INVALID_ENUM error is generated if <type> is not UNSIGNED_BYTE,
      UNSIGNED_SHORT, or UNSIGNED_INT.
    - Using an index value greater than MAX_ELEMENT_INDEX will result in
      undefined implementation-dependent behavior, unless primitive restart is
      enabled (see section 10.3.4) and the index value is 2^32 − 1.

New State

    None.

New Implementation Dependent State

    None.

Conformance Testing

    TBD.

Issues

    Note: These issues apply specifically to the definition of the
    EXT_base_instance specification, which is based on the OpenGL
    extension ARB_base_instance as updated in OpenGL 4.4.
    ARB_base_instance can be found in the OpenGL Registry.

    (1) What functionality was removed from ARB_base_instance?

    Nothing. Although there is less language here because ES 3.1 already
    includes some of the reorganizing that the original extension added.

    (2) What functionality was changed and added relative to
        ARB_base_instance?

      - EXT_base_instance more closely matches the language of OpenGL 4.4
      - the <primCount> parameter was renamed to <instanceCount>

    (3) Do these new draw calls require a vertex array object to be bound?

    RESOLVED: No. The DrawArrays and DrawArraysInstanced commands do not
    require a vertex array object to be bound in ES 3.1 and since these are
    specializations of DrawArraysInstancedBaseInstanceEXT, it also does not
    require one to be bound.  Similarly the DrawElements and
    DrawElementsInstanced commands do not require a vertex array object to be
    bound in ES 3.1, and since these commands are specializations of
    DrawElementsInstancedBaseInstanceEXT and
    DrawElementsInstancedBaseVertexBaseInstanceEXT, these commands also do not
    require one to be bound.

    (4) Do these new draw calls support client memory arrays?

    RESOLVED: Yes. There are no restrictions on using client-side memory for
    the other direct drawing commands in ES 3.1, so these command support
    them as well. As per issue (3), the old commands are specializations of
    the new commands, so we keep a comparable feature set.


Revision History

    Rev.    Date      Author    Changes
    ----  ----------  --------  -----------------------------------------
    4     10/24/2014  dkoch     Mark complete and issues resolved.

    3     06/24/2014  dkoch     Fix typographical issues noted by Dominik.

    2     06/20/2014  dkoch     Add interaction with EXT_multi_draw_indirect.

    1     06/13/2014  dkoch     Initial version for ES based on v6 of
                                ARB_base_instance.
