| Name |
| |
| ARB_instanced_arrays |
| |
| Name Strings |
| |
| GL_ARB_instanced_arrays |
| |
| Contributors |
| |
| Michael Gold, NVIDIA |
| James Helferty, TransGaming Inc. |
| Daniel Koch, TransGaming Inc. |
| John Rosasco, Apple |
| Mark Kilgard, NVIDIA |
| Piers Daniell, NVIDIA |
| |
| Contact |
| |
| James Helferty, TransGaming Inc. (james 'at' transgaming.com) |
| Daniel Koch, TransGaming Inc. (daniel 'at' transgaming.com) |
| |
| Notice |
| |
| Copyright (c) 2008-2013 The Khronos Group Inc. Copyright terms at |
| http://www.khronos.org/registry/speccopyright.html |
| |
| Status |
| |
| Approved by the ARB on July 11, 2008. |
| |
| Version |
| |
| Last Modified Date: August 8, 2013 |
| Author Revision: 7 |
| |
| EXT_direct_state_access interacton added with revision 7. |
| |
| Number |
| |
| ARB Extension #49 |
| |
| Dependencies |
| |
| OpenGL 1.1 is required. |
| |
| This extension is written against the OpenGL 2.1 Specification. |
| |
| ARB_draw_instanced affects the definition of this extension. |
| |
| EXT_draw_instanced affects the definition of this extension. |
| |
| EXT_gpu_shader4 affects the definition of this extension. |
| |
| Overview |
| |
| A common use case in GL for some applications is to be able to |
| draw the same object, or groups of similar objects that share |
| vertex data, primitive count and type, multiple times. This |
| extension provides a means of accelerating such use cases while |
| restricting the number of API calls, and keeping the amount of |
| duplicate data to a minimum. |
| |
| In particular, this extension specifies an alternative to the |
| read-only shader variable introduced by ARB_draw_instanced. It |
| uses the same draw calls introduced by that extension, but |
| redefines them so that a vertex shader can instead use vertex |
| array attributes as a source of instance data. |
| |
| This extension introduces an array "divisor" for generic |
| vertex array attributes, which when non-zero specifies that the |
| attribute is "instanced." An instanced attribute does not |
| advance per-vertex as usual, but rather after every <divisor> |
| conceptual draw calls. |
| |
| (Attributes which aren't instanced are repeated in their entirety |
| for every conceptual draw call.) |
| |
| By specifying transform data in an instanced attribute or series |
| of instanced attributes, vertex shaders can, in concert with the |
| instancing draw calls, draw multiple instances of an object with |
| one draw call. |
| |
| IP Status |
| |
| No known IP claims. |
| |
| New Tokens |
| |
| Accepted by the <pname> parameters of GetVertexAttribdv, |
| GetVertexAttribfv, and GetVertexAttribiv: |
| |
| VERTEX_ATTRIB_ARRAY_DIVISOR_ARB 0x88FE |
| |
| New Procedures and Functions |
| |
| void VertexAttribDivisorARB(uint index, uint divisor); |
| |
| When EXT_direct_state_access is present: |
| |
| void VertexArrayVertexAttribDivisorEXT(uint vaobj, uint index, uint divisor); |
| |
| Additions to Chapter 2 of the OpenGL 2.1 Specification |
| (OpenGL Operation) |
| |
| Modify section 2.8 (Vertex Arrays), p. 23 |
| |
| (remove modifications to section 2.8 made by ARB_draw_instanced |
| and EXT_draw_instanced, and replace everything from the second |
| paragraph, p. 27 through the second paragraph, p. 30) |
| The internal counter <instanceID> is a 32-bit integer value which |
| may be read by a vertex program as <vertex.instance>, as described |
| in section 2.X.3.2, or vertex shader as <gl_InstanceIDARB>, as |
| described in section 2.15.4.2. The value of this counter is |
| always zero, except as noted. |
| |
| The command |
| |
| void VertexAttribDivisorARB(uint index, uint divisor); |
| |
| modifies the rate at which generic vertex attributes advance when |
| rendering multiple instances of primitives in a single draw call. |
| If <divisor> is zero, the attribute at slot <index> advances once |
| per vertex. If <divisor> is non-zero, the attribute advances once |
| per <divisor> instances of the set(s) of vertices being rendered. |
| An attribute is referred to as <instanced> if its <divisor> value |
| is non-zero. |
| |
| The function |
| |
| void ArrayElementInstanced( int i, int instance ); |
| |
| does not exist in the GL, but is used to describe functionality in |
| the rest of this section. This function transfers the <i>th |
| element of every enabled, non-instanced array and the |
| floor(<instance>/<divisor>)'th element of every enabled instanced |
| array to the GL. The effect of ArrayElementInstanced(i) is the |
| same as the effect of the command sequence |
| |
| if (normal array enabled) |
| Normal3[type]v(normal array element i); |
| if (color array enabled) |
| Color[size][type]v(color array element i); |
| if (secondary color array enabled) |
| SecondaryColor3[type]v(secondary color array element i); |
| if (fog coordinate array enabled) |
| FogCoord[type]v(fog coordinate array element i); |
| for (j = 0; j < textureUnits; j++) { |
| if (texture coordinate set j array enabled) |
| MultiTexCoord[size][type]v(TEXTURE0 + j, texture coordinate set j array element i); |
| } |
| if (color index array enabled) |
| Index[type]v(color index array element i); |
| if (edge flag array enabled) |
| EdgeFlagv(edge flag array element i); |
| for (j = 1; j < genericAttributes; j++) { |
| if (generic vertex attribute j array enabled) { |
| if (VERTEX_ATTRIB_ARRAY_DIVISOR_ARB[j] > 0) |
| k = floor(instance / VERTEX_ATTRIB_ARRAY_DIVISOR_ARB[j]); |
| else |
| k = i; |
| if (generic vertex attribute j array normalization flag is set, and |
| type is not FLOAT or DOUBLE) |
| VertexAttrib[size]N[type]v(j, generic vertex attribute j array element k); |
| else |
| VertexAttrib[size][type]v(j, generic vertex attribute j array element k); |
| } |
| } |
| if (generic attribute array 0 enabled) { |
| if (VERTEX_ATTRIB_ARRAY_DIVISOR_ARB[0] > 0) |
| k = floor(instance / VERTEX_ATTRIB_ARRAY_DIVISOR_ARB[0]); |
| else |
| k = i; |
| if (generic vertex attribute 0 array normalization flag is set, and |
| type is not FLOAT or DOUBLE) |
| VertexAttrib[size]N[type]v(0, generic vertex attribute 0 array element k); |
| else |
| VertexAttrib[size][type]v(0, generic vertex attribute 0 array element k); |
| } else if (vertex array enabled) { |
| Vertex[size][type]v(vertex array element i); |
| } |
| |
| where <textureUnits> and <genericAttributes> give the number of |
| texture coordinate sets and generic vertex attributes supported by |
| the implementation, respectively. "[size]" and "[type]" |
| correspond to the size and type of the corresponding array. For |
| generic vertex attributes, it is assumed that a complete set of |
| vertex attribute commands exists, even though not all such |
| functions are provided by the GL. |
| |
| The command |
| |
| void ArrayElement( int i ); |
| |
| behaves identically to ArrayElementInstanced with the instance |
| set to zero; it is equivalent to calling |
| |
| ArrayElementInstanced(i, 0); |
| |
| Changes made to array data between the execution of Begin and the |
| corresponding execution of End may affect calls to ArrayElement |
| that are made within the same Begin/End period in non-sequential |
| ways. That is, a call to ArrayElement that precedes a change to |
| array data may access the changed data, and a call that follows a |
| change to array data may access original data. |
| |
| Specifying i < 0 results in undefined behavior. Generating the |
| error INVALID VALUE is recommended in this case. |
| |
| The function |
| |
| void DrawArraysOneInstance( enum mode, int first, sizei count, int instance ); |
| |
| does not exist in the GL, but is used to describe functionality in |
| the rest of this section. This function constructs a sequence of |
| geometric primitives using elements <first> through <first> + |
| <count> - 1 of each enabled, non-instanced array and the |
| <instance>th element of each enabled, instanced array. <mode> |
| specifies what kind of primitives are constructed; it accepts the |
| same token values as the mode parameter of the Begin command. The |
| effect of |
| |
| DrawArraysOneInstance (mode, first, count, int instance); |
| |
| is the same as the effect of the command sequence |
| |
| Begin(mode); |
| for (int i = 0; i < count ; i++) |
| ArrayElementInstanced(first+ i, instance); |
| End(); |
| |
| with one exception: the current normal coordinates, color, |
| secondary color, color index, edge flag, fog coordinate, texture |
| coordinates, and generic attributes are each indeterminate after |
| execution of DrawArraysOneInstance, if the corresponding array is |
| enabled. Current values corresponding to disabled arrays are not |
| modified by the execution of DrawArraysOneInstance. |
| |
| Specifying first < 0 results in undefined behavior. Generating |
| the error INVALID_VALUE is recommended in this case. |
| |
| The command |
| |
| void DrawArrays( enum mode, int first, sizei count ); |
| |
| behaves identically to DrawArraysOneInstance with the instance |
| set to zero; the effect of calling |
| |
| DrawArrays(mode, first, count); |
| |
| is equivalent to the command sequence: |
| |
| if (mode or count is invalid ) |
| generate appropriate error |
| else |
| DrawArraysOneInstance(mode, first, count, 0); |
| |
| The command |
| |
| void DrawArraysInstancedARB(enum mode, int first, sizei count, |
| sizei primcount); |
| |
| behaves identically to DrawArrays except that <primcount> |
| instances of the range of elements are executed, the value of |
| <instanceID> advances for each iteration, and the instanced |
| elements advance per instance depending on the value of the divisor |
| for that vertex attribute set with VertexAttribDivisorARB. It has the |
| same effect as: |
| |
| if (mode or count is invalid) |
| generate appropriate error |
| else { |
| for (i = 0; i < primcount; i++) { |
| instanceID = i; |
| DrawArraysOneInstance(mode, first, count, i); |
| } |
| instanceID = 0; |
| } |
| |
| The command |
| |
| void MultiDrawArrays( enum mode, int *first, |
| sizei *count, sizei primcount ); |
| |
| behaves identically to DrawArraysInstancedARB except that |
| <primcount> separate ranges of elements are specified instead, |
| all elements are treated as though they are not instanced, |
| and the value of <instanceID> stays at 0. It has the same |
| effect as: |
| |
| if (mode is invalid) |
| generate appropriate error |
| else { |
| for (i = 0; i < primcount; i++) { |
| if (count[i] > 0) |
| DrawArraysOneInstance(mode, first[i], count[i], 0); |
| } |
| } |
| |
| The function |
| |
| void DrawElementsOneInstance( enum mode, sizei count, enum type, |
| void *indices ); |
| |
| does not exist in the GL, but is used to describe functionality in |
| the rest of this section. This function constructs a sequence of |
| geometric primitives using the <count> elements whose indices are |
| stored in indices. <type> must be one of UNSIGNED_BYTE, |
| UNSIGNED_SHORT, or UNSIGNED_INT, indicating that the values in |
| <indices> are indices of GL type ubyte, ushort, or uint |
| respectively. <mode> specifies what kind of primitives are |
| constructed; it accepts the same token values as the mode |
| parameter of the Begin command. The effect of |
| |
| DrawElementsOneInstance (mode, count, type, indices); |
| |
| is the same as the effect of the command sequence |
| |
| Begin(mode); |
| for (int i = 0; i < count ; i++) |
| ArrayElementInstanced(indices[i], instance); |
| End(); |
| |
| with one exception: the current normal coordinates, color, |
| secondary color, color index, edge flag, fog coordinate, texture |
| coordinates, and generic attributes are each indeterminate after |
| execution of DrawElementsOneInstance, if the corresponding array is |
| enabled. Current values corresponding to disabled arrays are not |
| modified by the execution of DrawElementsOneInstance. |
| |
| The command |
| |
| void DrawElements( enum mode, sizei count, enum type, |
| void *indices ); |
| |
| behaves identically to DrawElementsOneInstance with the instance |
| paremeter set to zero; the effect of calling |
| |
| DrawElements(mode, count, type, indices); |
| |
| is equivalent to the command sequence: |
| |
| if (mode, count or type is invalid ) |
| generate appropriate error |
| else |
| DrawElementsOneInstance(mode, count, type, indices, 0); |
| |
| The command |
| |
| void DrawElementsInstancedARB(enum mode, sizei count, enum type, |
| const void *indices, sizei primcount); |
| |
| behaves identically to DrawElements except that <primcount> |
| instances of the set of elements are executed, the value of |
| <instanceID> advances between each set, and the instance |
| advances between each set. It has the same effect as: |
| |
| if (mode, count, or type is invalid ) |
| generate appropriate error |
| else { |
| for (int i = 0; i < primcount; i++) { |
| instanceID = i; |
| DrawElementsOneInstance(mode, count, type, indices, i); |
| } |
| instanceID = 0; |
| } |
| |
| The command |
| |
| void MultiDrawElements( enum mode, sizei *count, |
| enum type, void **indices, sizei primcount ); |
| |
| behaves identically to DrawElementsInstancedARB except that |
| <primcount> separate sets of elements are specified instead, all |
| elements are treated as though they are not instanced, and the |
| value of <instanceID> stays at 0. It has the same effect as: |
| |
| if (mode, count, or type is invalid ) |
| generate appropriate error |
| else { |
| for (int i = 0; i < primcount; i++) |
| DrawElementsOneInstance(mode, count[i], type, indices[i], 0); |
| } |
| |
| The command |
| |
| void DrawRangeElements( enum mode, uint start, |
| uint end, sizei count, enum type, void *indices ); |
| |
| is a restricted form of DrawElements. ... |
| |
| Modify section 2.8 (Vertex Arrays), p. 23 |
| |
| (remove section before final paragraph, p. 30, that was added by |
| ARB_draw_instanced and EXT_draw_instanced) |
| |
| Modify section 2.8 (Vertex Arrays), p. 33 |
| |
| (in the list of client state required to implement vertex arrays add) |
| ... <n> integers representing vertex attribute divisors, ... |
| |
| (in the list of initial state add) |
| ... the divisors are each zero, ... |
| |
| Additions to Chapter 5 of the OpenGL 2.1 Specification |
| (Special Functions) |
| |
| The error INVALID_OPERATION is generated if DrawArraysInstancedARB |
| or DrawElementsInstancedARB is called during display list |
| compilation. |
| |
| Additions to Chapter 6 of the OpenGL 2.1 Specification (State and State |
| Requests) |
| |
| In section 6.1.14, add to the list of pnames accepted by |
| GetVertexAttrib*v: VERTEX_ATTRIB_ARRAY_DIVISOR_ARB |
| |
| ************************************************************************ |
| |
| Additions to the AGL/EGL/GLX/WGL Specifications |
| |
| None |
| |
| Dependencies on OpenGL 1.4 |
| |
| If OpenGL 1.4 is not supported, all discussion of MultiDrawArrays |
| and MultiDrawElements should be removed from section 2.8. |
| |
| Dependencies on ARB_draw_instanced |
| |
| If neither ARB_draw_instanced nor EXT_draw_instanced is supported, |
| all references to instanceID should be removed from section 2.8. |
| |
| If ARB_draw_instanced is not supported, all references to gl_InstanceIDARB |
| should be removed from section 2.8. This extension will introduce |
| the following additional New Procedures and Functions: |
| |
| void DrawArraysInstancedARB(enum mode, int first, sizei count, |
| sizei primcount); |
| void DrawElementsInstancedARB(enum mode, sizei count, enum type, |
| const void *indices, sizei primcount); |
| |
| Dependencies on EXT_draw_instanced |
| |
| If EXT_draw_instanced is supported, then DrawArraysInstancedEXT |
| is aliased to DrawArraysInstancedARB, and DrawElementsInstancedEXT |
| is aliased to DrawElementsInstancedARB. |
| |
| If neither ARB_draw_instanced nor EXT_draw_instanced is supported, |
| all references to instanceID should be removed from section 2.8. |
| |
| Dependencies on EXT_gpu_shader4 |
| |
| If EXT_gpu_shader4 is not supported, all references to gl_InstanceID |
| should be removed from section 2.8. |
| |
| Dependencies on EXT_direct_state_access |
| |
| When EXT_direct_state_access is present, add a new entry point that takes a |
| vertex array object handle: |
| |
| void VertexArrayVertexAttribDivisorEXT(uint vaobj, uint index, uint divisor); |
| |
| This command behaves identically to glVertexAttribDivisorEXT |
| except it modifies the state of the vertex array object named |
| by its initial vaobj parameter (rather than the currently bound |
| vertex array object). The vertex array object named by vaobj must |
| be generated by GenVertexArrays (and not since deleted); otherwise |
| an INVALID_OPERATION error is generated. |
| |
| GetVertexArrayIntegeri_vEXT must accept VERTEX_ATTRIB_ARRAY_DIVISOR_ARB to return |
| the vertex array object's vertex attrib array divisor state. |
| |
| Errors |
| |
| INVALID_VALUE is generated by VertexAttribDivisorARB if <index> |
| is greater than or equal to MAX_VERTEX_ATTRIBS. |
| |
| INVALID_ENUM is generated by DrawElementsInstancedARB if <type> is |
| not one of UNSIGNED_BYTE, UNSIGNED_SHORT or UNSIGNED_INT. |
| |
| INVALID_VALUE is generated by DrawArraysInstancedARB if <first> is |
| less than zero. |
| |
| New State |
| |
| Changes to table 6.7, p. 268 (Vertex Array Data) |
| |
| Initial |
| Get Value Type Get Command Value Description Sec. Attribute |
| --------- ---- ----------- ------- ----------- ---- --------- |
| VERTEX_ATTRIB_ARRAY_DIVISOR_ARB 16+ xZ+ GetVertexAttrib 0 Instance Divisor 2.8 vertex-array |
| |
| Issues |
| |
| 1) Should legacy arrays be supported, or only generic vertex |
| attribs? |
| |
| Resolved: It is possible to render instanced objects which use |
| legacy array types but only the generic arrays may have a |
| divisor. |
| |
| 2) Should generic attrib zero be instance-able? |
| |
| Resolved: Yes. This was added in revision 5 of the spec. |
| |
| Prior to revision 5 of this spec, attempting to call |
| VertexAttribDivisorARB with attrib=0 generated INVALID_VALUE. |
| It was originally thought that this implied issuing a vertex at |
| lower frequency than the associated attribs (due to the special |
| properties of vertex attribute zero in GL 2.x and the compatibility |
| profiles). That would be true if the immediate-mode model of |
| instancing was to make an attribute call only once every <N> vertices |
| for instanced attributes -- you wouldn't want to specify a new vertex |
| once every <N> vertices! But that's not the model -- the frequency |
| <N> is only used to translate an incoming array element <i> into an |
| attribute index <k>. Immediate mode calls are still specified as |
| happening for every vertex. Given this definition, it is not |
| necessary to do anything differently for attribute zero. |
| |
| 3) How is ArrayElement affected by this extension? |
| |
| Resolved: Arrays with a non-zero divisor return the first |
| element of the array, as if instanceID is fixed at zero. This |
| allows legacy varray draw calls to give instancing behavior |
| but are still defined in terms of ArrayElement. |
| |
| 4) Should DrawArraysInstanced and DrawElementsInstanced be compiled |
| into display lists? |
| |
| Resolved: No, calling these during display list compilation |
| generate INVALID_OPERATION. This matches EXT_draw_instanced |
| and ARB_draw_instanced. |
| |
| 5) Is it useful to have instancing for the MultiDraw* functions? |
| |
| Resolved: We will follow the lead of EXT_draw_instanced and |
| ARB_draw_instanced in not extending these functions. |
| |
| 6) This extension must elaborate on the definition of functions |
| added by ARB_draw_instanced. How do we do this in a manner such |
| that both extensions may coexist? |
| |
| Resolved: This extension is specified so that it applies on |
| top of ARB_draw_instanced and EXT_draw_instanced. As a |
| result, some portions modified by those extensions are |
| replaced in this extension. In the event that those |
| extensions are not supported, this extension reintroduces |
| the draw calls from ARB_draw_instanced. |
| |
| 7) How should EXT_direct_state_access interact with this extension? |
| |
| Resolved: Add glVertexArrayVertexAttribDivisorEXT selector-free |
| vertex array object command and glGetVertexArrayIntegeri_vEXT |
| query must accept VERTEX_ATTRIB_ARRAY_DIVISOR_ARB to return the |
| vertex array object's vertex attrib array divisor state. |
| |
| The DSA interaction was added July 2013. If implementations |
| respond to a wglGetProcAddress, etc. query for |
| "glVertexArrayVertexAttribDivisorEXT" with a NULL pointer, |
| the DSA functionality is not available. |
| |
| Revision History |
| |
| #7 August 6, 2013 mjk |
| - Add EXT_direct_state_access interaction |
| #6 February 11, 2010 dgkoch |
| - sync language with GL3.3, add required and initial state for divisors |
| #5 January 13, 2010 dgkoch |
| - update spec so that specifying a divisor on vertex attrib 0 is legal (5796) |
| - update resolution of Issue 2 appropriately. |
| #4 January 1, 2010, Jon Leech |
| - Correct Errors section to match spec body |
| #3 July 8, 2008, jhelferty |
| - expanded Overview |
| - changed name of GLSL instance ID variable to follow naming conventions, |
| and match ARB_draw_instanced. |
| - made dependencies and interactions more explicit |
| #2 May 14 2008, jhelferty |
| - changed pname to VERTEX_ATTRIB_ARRAY_DIVISOR_ARB |
| - added dependencies on ARB_draw_instanced |
| - update to GL 2.1 language |
| #1 May 12 2008, dgkoch |
| - copied from NVX_instanced_arrays and renamed. removed original revision history |