Home | History | Annotate | Download | only in extensions
      1 Name
      2 
      3     ANGLE_instanced_arrays
      4 
      5 Name Strings
      6 
      7     GL_ANGLE_instanced_arrays
      8 
      9 Contributors
     10 
     11     Contributors to ARB_instanced_arrays
     12     Nicolas Capens, TransGaming Inc.
     13     James Helferty, TransGaming Inc.
     14     Kenneth Russell, Google Inc.
     15     Vangelis Kokkevis, Google Inc.
     16 
     17 Contact
     18 
     19     Daniel Koch, TransGaming Inc. (daniel 'at' transgaming.com)
     20 
     21 Status
     22 
     23     Implemented in ANGLE r976.
     24 
     25 Version
     26 
     27     Last Modified Date: February 8, 2012
     28     Author Revision: 3
     29 
     30 Number
     31 
     32     OpenGL ES Extension #109
     33 
     34 Dependencies
     35 
     36     OpenGL ES 2.0 is required.
     37 
     38     This extension is written against the OpenGL ES 2.0 Specification.
     39 
     40 Overview
     41 
     42     A common use case in GL for some applications is to be able to
     43     draw the same object, or groups of similar objects that share
     44     vertex data, primitive count and type, multiple times.  This 
     45     extension provides a means of accelerating such use cases while 
     46     restricting the number of API calls, and keeping the amount of 
     47     duplicate data to a minimum.
     48     
     49     This extension introduces an array "divisor" for generic
     50     vertex array attributes, which when non-zero specifies that the
     51     attribute is "instanced."  An instanced attribute does not
     52     advance per-vertex as usual, but rather after every <divisor>
     53     conceptual draw calls.
     54     
     55     (Attributes which aren't instanced are repeated in their entirety
     56     for every conceptual draw call.)
     57     
     58     By specifying transform data in an instanced attribute or series
     59     of instanced attributes, vertex shaders can, in concert with the 
     60     instancing draw calls, draw multiple instances of an object with 
     61     one draw call.
     62 
     63 IP Status
     64 
     65     No known IP claims.
     66 
     67 New Tokens
     68 
     69     Accepted by the <pname> parameters of GetVertexAttribfv and 
     70     GetVertexAttribiv:
     71 
     72         VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE               0x88FE
     73 
     74 New Procedures and Functions
     75 
     76     void DrawArraysInstancedANGLE(enum mode, int first, sizei count,
     77             sizei primcount);
     78 
     79     void DrawElementsInstancedANGLE(enum mode, sizei count, enum type,
     80             const void *indices, sizei primcount);
     81 
     82     void VertexAttribDivisorANGLE(uint index, uint divisor);
     83 
     84 Additions to Chapter 2 of the OpenGL ES 2.0 Specification
     85 (OpenGL ES Operation)
     86 
     87     Modify section 2.8 (Vertex Arrays), p. 21
     88 
     89     After description of EnableVertexAttribArray / DisableVertexAttribArray
     90     add the following:
     91 
     92     "The command
     93 
     94         void VertexAttribDivisorANGLE(uint index, uint divisor);
     95 
     96     modifies the rate at which generic vertex attributes advance when
     97     rendering multiple instances of primitives in a single draw call
     98     (see DrawArraysInstancedANGLE and DrawElementsInstancedANGLE below).
     99     If <divisor> is zero, the attribute at slot <index> advances once
    100     per vertex.  If <divisor> is non-zero, the attribute advances once
    101     per <divisor> instances of the primitives being rendered.
    102     An attribute is referred to as "instanced" if its <divisor> value is
    103     non-zero."
    104 
    105     Replace the text describing DrawArrays and DrawElements in the
    106     "Transferring Array Elements" subsection of 2.8, from the second paragraph
    107     through the end of the section with the following:
    108 
    109     "The command
    110 
    111         void DrawArraysOneInstance( enum mode, int first, sizei count, int instance );
    112 
    113     does not exist in the GL, but is used to describe functionality in
    114     the rest of this section.  This function constructs a sequence of
    115     geometric primitives by transferring elements <first> through <first> +
    116     <count> - 1 of each enabled non-instanced array to the GL. <mode>
    117     specifies what kind of primitives are constructed, as defined in section
    118     2.6.1.
    119 
    120     If an enabled vertex attribute array is instanced (it has a non-zero
    121     attribute <divisor> as specified by VertexAttribDivisorANGLE), the element
    122     that is transferred to the GL is given by:
    123 
    124         floor( <instance> / <divisor> ).
    125 
    126     If an array corresponding to a generic attribute required by a vertex shader
    127     is not enabled, then the corresponding element is taken from the current
    128     generic attribute state (see section 2.7).
    129 
    130     If an array corresponding to a generic attribute required by a vertex shader
    131     is enabled, the corresponding current generic attribute value is unaffected 
    132     by the execution of DrawArraysOneInstance.
    133 
    134     Specifying <first> < 0 results in undefined behavior. Generating the error 
    135     INVALID_VALUE is recommended in this case.
    136 
    137     The command
    138 
    139         void DrawArrays( enum mode, int first, sizei count );
    140 
    141     is equivalent to the command sequence
    142     
    143         DrawArraysOneInstance(mode, first, count, 0);
    144 
    145     The command
    146 
    147         void DrawArraysInstancedANGLE(enum mode, int first, sizei count,
    148                 sizei primcount);
    149 
    150     behaves identically to DrawArrays except that <primcount>
    151     instances of the range of elements are executed, and the
    152     <instance> advances for each iteration. Instanced attributes that
    153     have <divisor> N, (where N > 0, as specified by
    154     VertexAttribDivisorANGLE) advance once every N instances.
    155     
    156     It has the same effect as: 
    157 
    158         if (mode, count, or primcount is invalid)
    159             generate appropriate error
    160         else {
    161             for (i = 0; i < primcount; i++) {
    162                 DrawArraysOneInstance(mode, first, count, i);
    163             }
    164         }
    165 
    166     The command
    167 
    168        void DrawElementsOneInstance( enum mode, sizei count, enum type,
    169             void *indices, int instance );
    170 
    171     does not exist in the GL, but is used to describe functionality in
    172     the rest of this section.  This command constructs a sequence of
    173     geometric primitives by successively transferring the <count> elements
    174     whose indices are stored in the currently bound element array buffer
    175     (see section 2.9.2) at the offset defined by <indices> to the GL.
    176     The <i>-th element transferred by DrawElementsOneInstance will be taken
    177     from element <indices>[i] of each enabled non-instanced array.
    178     <type> must be one of UNSIGNED_BYTE, UNSIGNED_SHORT, or UNSIGNED_INT, 
    179     indicating that the index values are of GL type ubyte, ushort, or uint
    180     respectively. <mode> specifies what kind of primitives are constructed,
    181     as defined in section 2.6.1.
    182 
    183     If an enabled vertex attribute array is instanced (it has a non-zero
    184     attribute <divisor> as specified by VertexAttribDivisorANGLE), the element
    185     that is transferred to the GL is given by:
    186 
    187         floor( <instance> / <divisor> );
    188 
    189     If an array corresponding to a generic attribute required by a vertex
    190     shader is not enabled, then the corresponding element is taken from the 
    191     current generic attribute state (see section 2.7). Otherwise, if an array
    192     is enabled, the corresponding current generic attribute value is 
    193     unaffected by the execution of DrawElementsOneInstance.
    194 
    195     The command
    196 
    197         void DrawElements( enum mode, sizei count, enum type,
    198              const void *indices);
    199 
    200     behaves identically to DrawElementsOneInstance with the <instance> 
    201     parameter set to zero; the effect of calling
    202 
    203         DrawElements(mode, count, type, indices);
    204 
    205     is equivalent to the command sequence:
    206 
    207        if (mode, count or type is invalid )
    208             generate appropriate error
    209         else
    210             DrawElementsOneInstance(mode, count, type, indices, 0);
    211 
    212     The command
    213 
    214         void DrawElementsInstancedANGLE(enum mode, sizei count, enum type,
    215                 const void *indices, sizei primcount);
    216 
    217     behaves identically to DrawElements except that <primcount>
    218     instances of the set of elements are executed and the instance
    219     advances between each set. Instanced attributes are advanced as they do
    220     during the execution of DrawArraysInstancedANGLE. It has the same effect as:
    221 
    222         if (mode, count, primcount, or type is invalid )
    223             generate appropriate error
    224         else {
    225             for (int i = 0; i < primcount; i++) {
    226                 DrawElementsOneInstance(mode, count, type, indices, i);
    227             }
    228         }
    229 
    230     If the number of supported generic vertex attributes (the value of 
    231     MAX_VERTEX_ATTRIBS) is <n>, then the client state required to implement
    232     vertex arrays consists of <n> boolean values, <n> memory pointers, <n>
    233     integer stride values, <n> symbolic constants representing array types,
    234     <n> integers representing values per element, <n> boolean values 
    235     indicating normalization, and <n> integers representing vertex attribute
    236     divisors. 
    237 
    238     In the initial state, the boolean values are each false, the memory
    239     pointers are each NULL, the strides are each zero, the array types are 
    240     each FLOAT, the integers representing values per element are each four,
    241     and the divisors are each zero."
    242 
    243 Additions to Chapter 3 of the OpenGL ES 2.0 Specification (Rasterization)
    244 
    245     None
    246 
    247 Additions to Chapter 4 of the OpenGL ES 2.0 Specification (Per-Fragment
    248 Operations and the Framebuffer)
    249 
    250     None
    251 
    252 Additions to Chapter 5 of the OpenGL ES 2.0 Specification (Special Functions)
    253 
    254     None
    255 
    256 Additions to Chapter 6 of the OpenGL ES 2.0 Specification (State and State
    257 Requests)
    258 
    259     In section 6.1.8, add VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE to the list of 
    260     pnames accepted by GetVertexAttribfv and GetVertexAttribiv.
    261 
    262 Additions to the AGL/EGL/GLX/WGL Specifications
    263 
    264     None
    265 
    266 Dependencies on OES_element_index_uint
    267 
    268     If OES_element_index_uint is not supported, removed all references
    269     to UNSIGNED_INT indices and the associated GL data type uint in 
    270     the description of DrawElementsOneInstance.
    271 
    272 Errors
    273 
    274     INVALID_VALUE is generated by VertexAttribDivisorANGLE if <index>
    275     is greater than or equal to MAX_VERTEX_ATTRIBS.
    276 
    277     INVALID_ENUM is generated by DrawElementsInstancedANGLE if <type> is
    278     not one of UNSIGNED_BYTE, UNSIGNED_SHORT or UNSIGNED_INT.
    279 
    280     INVALID_VALUE is generated by DrawArraysInstancedANGLE if <first>,
    281     <count>, or <primcount> is less than zero.
    282 
    283     INVALID_ENUM is generated by DrawArraysInstancedANGLE or 
    284     DrawElementsInstancedANGLE if <mode> is not one of the modes described in
    285     section 2.6.1.
    286 
    287     INVALID_VALUE is generated by DrawElementsInstancedANGLE if <count> or
    288     <primcount> is less than zero.
    289 
    290     INVALID_OPERATION is generated by DrawArraysInstancedANGLE or 
    291     DrawElementsInstancedANGLE if there is not at least one enabled
    292     vertex attribute array that has a <divisor> of zero and is bound to an
    293     active generic attribute value in the program used for the draw command.
    294 
    295 New State
    296 
    297     Changes to table 6.7, p. 268 (Vertex Array Data)
    298 
    299                                                                Initial
    300     Get Value                          Type   Get Command      Value    Description       Sec.  
    301     ---------                          -----  -----------      -------  -----------       ----
    302     VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE  8*xZ+  GetVertexAttrib  0        Instance Divisor  2.8
    303 
    304 Issues
    305 
    306     1) Should vertex attribute zero be instance-able?
    307 
    308        Resolved: Yes. 
    309        Discussion: In Direct3D 9 stream 0 must be specified as indexed data
    310        and it cannot be instanced. In ANGLE we can work around this by
    311        remapping any other stream that does have indexed data (ie a zero
    312        attribute divisor) to stream 0 in D3D9. This works because the HLSL
    313        vertex shader matches attributes against the stream by using the 
    314        shader semantic index.
    315 
    316     2) Can all vertex attributes be instanced simultaneously?
    317 
    318        Resolved: No
    319        Discussion: In rare cases it is possible for no attribute to have a 
    320        divisor of 0, meaning that all attributes are instanced and none of
    321        them are regularly indexed. This in turn means each instance can only
    322        have a single position element, and so it only actually renders
    323        something when rendering point primitives. This is not a very 
    324        meaningful way of using instancing (which is likely why D3D restricts
    325        stream 0 to be indexed regularly for position data in the first place).
    326        We could implement it by drawing these points one at a time (essentially
    327        emulating instancing), but it would not be very efficient and there
    328        seems to be little-to-no value in doing so.
    329 
    330        If all of the enabled vertex attribute arrays that are bound to active
    331        generic attributes in the program have a non-zero divisor, the draw
    332        call should return INVALID_OPERATION.
    333 
    334     3) Direct3D 9 only supports instancing for DrawIndexedPrimitive which
    335        corresponds to DrawElementsInstanced.  Should we support 
    336        DrawArraysInstanced?
    337 
    338        Resolved: Yes
    339        Discussion: This can be supported easily enough by simply manufacturing
    340        a linear index buffer of sufficient size and using that to do indexed
    341        D3D9 drawing.
    342 
    343     4) How much data is needed in a buffer for an instanced attribute?
    344 
    345        Resolved: Where stride is the value passed to VertexAttribPointer:
    346 
    347        if stride > 0
    348          size = stride * ceil(primcount / divisor);
    349        else
    350          size = elementsize * ceil(primcount / divisor);
    351 
    352 Revision History
    353 
    354     #3 February 8, 2012 dgkoch
    355        - clarify Issue 3 and the error condition for no indexed attributes
    356     #2 January 24, 2012 dgkoch
    357        - fix typos, add clarifications, and more errors
    358     #1 January 17, 2012 dgkoch
    359        - initial GLES2 version from ARB_instanced_arrays
    360