Permalink
Browse files

Add ANGLE_instanced_arrays spec

Trac #18156

git-svn-id: http://angleproject.googlecode.com/svn/trunk@967 736b8ea6-26fd-11df-bfd4-992fa37f6226
  • Loading branch information...
daniel@transgaming.com
daniel@transgaming.com committed Jan 27, 2012
1 parent 61d1122 commit 2c1370b0788154c2bd7535c9de302820ccca958f
Showing with 355 additions and 0 deletions.
  1. +355 −0 extensions/ANGLE_instanced_arrays.txt
@@ -0,0 +1,355 @@
+Name
+
+ ANGLE_instanced_arrays
+
+Name Strings
+
+ GL_ANGLE_instanced_arrays
+
+Contributors
+
+ Contributors to ARB_instanced_arrays
+ Nicolas Capens, TransGaming Inc.
+ James Helferty, TransGaming Inc.
+ Kenneth Russell, Google Inc.
+ Vangelis Kokkevis, Google Inc.
+
+Contact
+
+ Daniel Koch, TransGaming Inc. (daniel 'at' transgaming.com)
+
+Status
+
+ Draft
+
+Version
+
+ Last Modified Date: January 24, 2012
+ Author Revision: 2
+
+Number
+
+ OpenGL ES Extension #??
+
+Dependencies
+
+ OpenGL ES 2.0 is required.
+
+ This extension is written against the OpenGL ES 2.0 Specification.
+
+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.
+
+ 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 GetVertexAttribfv and
+ GetVertexAttribiv:
+
+ VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE 0x88FE
+
+New Procedures and Functions
+
+ void DrawArraysInstancedANGLE(enum mode, int first, sizei count,
+ sizei primcount);
+
+ void DrawElementsInstancedANGLE(enum mode, sizei count, enum type,
+ const void *indices, sizei primcount);
+
+ void VertexAttribDivisorANGLE(uint index, uint divisor);
+
+Additions to Chapter 2 of the OpenGL ES 2.0 Specification
+(OpenGL ES Operation)
+
+ Modify section 2.8 (Vertex Arrays), p. 21
+
+ After description of EnableVertexAttribArray / DisableVertexAttribArray
+ add the following:
+
+ "The command
+
+ void VertexAttribDivisorANGLE(uint index, uint divisor);
+
+ modifies the rate at which generic vertex attributes advance when
+ rendering multiple instances of primitives in a single draw call
+ (see DrawArraysInstancedANGLE and DrawElementsInstancedANGLE below).
+ 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 primitives being rendered.
+ An attribute is referred to as "instanced" if its <divisor> value is
+ non-zero."
+
+ Replace the text describing DrawArrays and DrawElements in the
+ "Transferring Array Elements" subsection of 2.8, from the second paragraph
+ through the end of the section with the following:
+
+ "The command
+
+ 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 by transferring elements <first> through <first> +
+ <count> - 1 of each enabled non-instanced array to the GL. <mode>
+ specifies what kind of primitives are constructed, as defined in section
+ 2.6.1.
+
+ If an enabled vertex attribute array is instanced (it has a non-zero
+ attribute <divisor> as specified by VertexAttribDivisorANGLE), the element
+ that is transferred to the GL is given by:
+
+ floor( <instance> / <divisor> ).
+
+ If an array corresponding to a generic attribute required by a vertex shader
+ is not enabled, then the corresponding element is taken from the current
+ generic attribute state (see section 2.7).
+
+ If an array corresponding to a generic attribute required by a vertex shader
+ is enabled, the corresponding current generic attribute value is unaffected
+ 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 );
+
+ is equivalent to the command sequence
+
+ DrawArraysOneInstance(mode, first, count, 0);
+
+ The command
+
+ void DrawArraysInstancedANGLE(enum mode, int first, sizei count,
+ sizei primcount);
+
+ behaves identically to DrawArrays except that <primcount>
+ instances of the range of elements are executed, and the
+ <instance> advances for each iteration. Instanced attributes that
+ have <divisor> N, (where N > 0, as specified by
+ VertexAttribDivisorANGLE) advance once every N instances.
+
+ It has the same effect as:
+
+ if (mode, count, or primcount is invalid)
+ generate appropriate error
+ else {
+ for (i = 0; i < primcount; i++) {
+ DrawArraysOneInstance(mode, first, count, i);
+ }
+ }
+
+ The command
+
+ void DrawElementsOneInstance( enum mode, sizei count, enum type,
+ void *indices, int instance );
+
+ does not exist in the GL, but is used to describe functionality in
+ the rest of this section. This command constructs a sequence of
+ geometric primitives by successively transferring the <count> elements
+ whose indices are stored in the currently bound element array buffer
+ (see section 2.9.2) at the offset defined by <indices> to the GL.
+ The <i>-th element transferred by DrawElementsOneInstance will be taken
+ from element <indices>[i] of each enabled non-instanced array.
+ <type> must be one of UNSIGNED_BYTE, UNSIGNED_SHORT, or UNSIGNED_INT,
+ indicating that the index values are of GL type ubyte, ushort, or uint
+ respectively. <mode> specifies what kind of primitives are constructed,
+ as defined in section 2.6.1.
+
+ If an enabled vertex attribute array is instanced (it has a non-zero
+ attribute <divisor> as specified by VertexAttribDivisorANGLE), the element
+ that is transferred to the GL is given by:
+
+ floor( <instance> / <divisor> );
+
+ If an array corresponding to a generic attribute required by a vertex
+ shader is not enabled, then the corresponding element is taken from the
+ current generic attribute state (see section 2.7). Otherwise, if an array
+ is enabled, the corresponding current generic attribute value is
+ unaffected by the execution of DrawElementsOneInstance.
+
+ The command
+
+ void DrawElements( enum mode, sizei count, enum type,
+ const void *indices);
+
+ behaves identically to DrawElementsOneInstance with the <instance>
+ parameter 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 DrawElementsInstancedANGLE(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 and the instance
+ advances between each set. Instanced attributes are advanced as they do
+ during the execution of DrawArraysInstancedANGLE. It has the same effect as:
+
+ if (mode, count, primcount, or type is invalid )
+ generate appropriate error
+ else {
+ for (int i = 0; i < primcount; i++) {
+ DrawElementsOneInstance(mode, count, type, indices, i);
+ }
+ }
+
+ If the number of supported generic vertex attributes (the value of
+ MAX_VERTEX_ATTRIBS) is <n>, then the client state required to implement
+ vertex arrays consists of <n> boolean values, <n> memory pointers, <n>
+ integer stride values, <n> symbolic constants representing array types,
+ <n> integers representing values per element, <n> boolean values
+ indicating normalization, and <n> integers representing vertex attribute
+ divisors.
+
+ In the initial state, the boolean values are each false, the memory
+ pointers are each NULL, the strides are each zero, the array types are
+ each FLOAT, the integers representing values per element are each four,
+ and the divisors are each zero."
+
+Additions to Chapter 3 of the OpenGL ES 2.0 Specification (Rasterization)
+
+ None
+
+Additions to Chapter 4 of the OpenGL ES 2.0 Specification (Per-Fragment
+Operations and the Framebuffer)
+
+ None
+
+Additions to Chapter 5 of the OpenGL ES 2.0 Specification (Special Functions)
+
+ None
+
+Additions to Chapter 6 of the OpenGL ES 2.0 Specification (State and State
+Requests)
+
+ In section 6.1.8, add VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE to the list of
+ pnames accepted by GetVertexAttribfv and GetVertexAttribiv.
+
+Additions to the AGL/EGL/GLX/WGL Specifications
+
+ None
+
+Dependencies on OES_element_index_uint
+
+ If OES_element_index_uint is not supported, removed all references
+ to UNSIGNED_INT indices and the associated GL data type uint in
+ the description of DrawElementsOneInstance.
+
+Errors
+
+ INVALID_VALUE is generated by VertexAttribDivisorANGLE if <index>
+ is greater than or equal to MAX_VERTEX_ATTRIBS.
+
+ INVALID_ENUM is generated by DrawElementsInstancedANGLE if <type> is
+ not one of UNSIGNED_BYTE, UNSIGNED_SHORT or UNSIGNED_INT.
+
+ INVALID_VALUE is generated by DrawArraysInstancedANGLE if <first>,
+ <count>, or <primcount> is less than zero.
+
+ INVALID_ENUM is generated by DrawArraysInstancedANGLE or
+ DrawElementsInstancedANGLE if <mode> is not one of the modes described in
+ section 2.6.1.
+
+ INVALID_VALUE is generated by DrawElementsInstancedANGLE if <count> or
+ <primcount> is less than zero.
+
+ INVALID_OPERATION is generated by DrawArraysInstancedANGLE or
+ DrawElementsInstancedANGLE if there is not at least one enabled
+ vertex attribute that has a <divisor> of zero.
+
+New State
+
+ Changes to table 6.7, p. 268 (Vertex Array Data)
+
+ Initial
+ Get Value Type Get Command Value Description Sec.
+ --------- ----- ----------- ------- ----------- ----
+ VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE 8*xZ+ GetVertexAttrib 0 Instance Divisor 2.8
+
+Issues
+
+ 1) Should vertex attribute zero be instance-able?
+
+ Resolved: Yes.
+ Discussion: In Direct3D 9 stream 0 must be specified as indexed data
+ and it cannot be instanced. In ANGLE we can work around this by
+ remapping any other stream that does have indexed data (ie a zero
+ attribute divisor) to stream 0 in D3D9. This works because the HLSL
+ vertex shader matches attributes against the stream by using the
+ shader semantic index.
+
+ 2) Can all vertex attributes be instanced simultaneously?
+
+ Resolved: No
+ Discussion: In rare cases it is possible for no attribute to have a
+ divisor of 0, meaning that all attributes are instanced and none of
+ them are regularly indexed. This in turn means each instance can only
+ have a single position element, and so it only actually renders
+ something when rendering point primitives. This is not a very
+ meaningful way of using instancing (which is likely why D3D restricts
+ stream 0 to be indexed regularly for position data in the first place).
+ We could implement it by drawing these points one at a time (essentially
+ emulating instancing), but it would not be very efficient and there
+ seems to be little-to-no value in doing so.
+
+ If all of the enabled attributes have a non-zero divisor, the draw
+ call should return INVALID_OPERATION.
+
+ 3) Direct3D 9 only supports instancing for DrawIndexedPrimitive which
+ corresponds to DrawElementsInstanced. Should we support
+ DrawArraysInstanced?
+
+ Resolved: Yes
+ Discussion: This can be supported easily enough by simply manufacturing
+ a linear index buffer of sufficient size and using that to do indexed
+ D3D9 drawing.
+
+ 4) How much data is needed in a buffer for an instanced attribute?
+
+ Resolved: Where stride is the value passed to VertexAttribPointer:
+
+ if stride > 0
+ size = stride * ceil(primcount / divisor);
+ else
+ size = elementsize * ceil(primcount / divisor);
+
+Revision History
+
+ #2 January 24, 2012 dgkoch
+ - fix typos, add clarifications, and more errors
+ #1 January 17, 2012 dgkoch
+ - initial GLES2 version from ARB_instanced_arrays

0 comments on commit 2c1370b

Please sign in to comment.