blob: 27899354fe68e360a883ae06ff2c7d0832f8c309 [file] [log] [blame]
Name
NV_instanced_arrays
Name Strings
GL_NV_instanced_arrays
Contributors
Contributors to ARB_instanced_arrays and ANGLE_instanced_arrays
Mathias Heyer, NVIDIA
Greg Roth, NVIDIA
Contact
Greg Roth, NVIDIA (groth 'at' nvidia 'dot' com)
Status
Complete
Version
Last Modified Date: Aug 28, 2012
Author Revision: 4
Number
OpenGL ES Extension #145
Dependencies
OpenGL ES 2.0 is required.
This extension is written against the OpenGL ES 2.0.25
Specification.
NV_draw_instanced affects the definition of this extension.
OES_element_index_uint affects the definition of this extension.
OES_vertex_array_object 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
limiting the number of required 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 NV_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.
New Procedures and Functions
void VertexAttribDivisorNV(uint index, uint divisor);
New Tokens
Accepted by the <pname> parameters of GetVertexAttribfv, and
GetVertexAttribiv:
VERTEX_ATTRIB_ARRAY_DIVISOR_NV 0x88FE
Additions to Chapter 2 of the OpenGL ES 2.0.25 Specification
(OpenGL ES Operation)
Modify section 2.8 (Vertex Arrays)
After description of EnableVertexAttribArray /
DisableVertexAttribArray add the following:
The internal counter <instanceID> is a 32-bit integer value which
may be read by a vertex shader as <gl_InstanceIDNV>, as
described in section 2.10.5.2. The value of this counter is
always zero, except as noted below.
The command
void VertexAttribDivisorNV(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.
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 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 the indicated elements of enabled arrays.
<mode> specifies what kind of primitives are constructed, as defined
in section 2.6.1. Elements <first> through <first> + <count> - 1 of
enabled non-instanced arrays are transferred to the GL.
If an enabled vertex attribute array is instanced (it has a non-zero
attribute <divisor> as specified by VertexAttribDivisorNV), 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 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 );
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 DrawArraysInstancedNV(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 instance advances
between each set. Instanced attributes that have <divisor> N, (where
N > 0, as specified by VertexAttribDivisorNV 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++) {
instanceID = i;
DrawArraysOneInstance(mode, first, count, i);
}
instanceID = 0;
}
The function
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 function constructs a sequence of
geometric primitives by successively transferring 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, 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 VertexAttribDivisorNV), 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,
void *indices );
behaves identically to DrawElementsOneInstance with <instance> 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 DrawElementsInstancedNV(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 for each iteration, and the instance
advances between each set. Instanced attributes are advanced as
they do during the execution of DrawArraysInstancedNV. 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++) {
instanceID = i;
DrawElementsOneInstance(mode, count, type, indices, i);
}
instanceID = 0;
}
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.
Modify section 2.10, "Vertex Array Objects" (Added by OES_vertex_array_object)
Add VERTEX_ATTRIB_ARRAY_DIVISOR_NV to the list of state included in
the vertex array object type vector.
Additions to Chapter 6 of the OpenGL ES 2.0.25 Specification (State and
State Requests)
In section 6.1.8, add VERTEX_ATTRIB_ARRAY_DIVISOR_NV to the list of
pnames accepted by GetVertexAttribfv and GetVertexAttribiv:
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.
Dependencies on NV_draw_instanced
If NV_draw_instanced is not supported, all references to
instanceID should be removed from section 2.8. This extension
will introduce the following additional New Procedures and
Functions:
void DrawArraysInstancedNV(enum mode, int first, sizei count,
sizei primcount);
void DrawElementsInstancedNV(enum mode, sizei count, enum type,
const void *indices, sizei primcount);
Dependencies on OES_vertex_array_object
If OES_vertex_array_object is not supported, ignore all edits to
section 2.10, "Vertex Array Objects".
Errors
INVALID_VALUE is generated by VertexAttribDivisorNV if <index>
is greater than or equal to MAX_VERTEX_ATTRIBS.
INVALID_ENUM is generated by DrawElementsInstancedNV if <type> is
not one of UNSIGNED_BYTE, UNSIGNED_SHORT or UNSIGNED_INT.
INVALID_VALUE is generated by DrawArraysInstancedNV if <first>,
<count>, or <primcount> is less than zero.
INVALID_ENUM is generated by DrawArraysInstancedNV or
DrawElementsInstancedNV if <mode> is not one of the modes described in
section 2.6.1.
INVALID_VALUE is generated by DrawElementsInstancedNV if <count> or
<primcount> is less than zero.
New State
Changes to table 6.2 (Vertex Array Data)
Initial
Get Value Type Get Command Value Description Sec. Attribute
--------- ---- --------------- ------- ----------- ---- ---------
VERTEX_ATTRIB_ARRAY_DIVISOR_NV 8xZ+ GetVertexAttrib 0 Instance Divisor 2.8 vertex-array
Issues
1) Should generic attrib zero be instance-able?
Resolved: Yes. Attribute zero does not necessarily contain
position information.
2) This extension must elaborate on the definition of functions
added by NV_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 NV_draw_instanced. As a result, some portions modified
by that extension are replaced in this extension. In the
event that NV_draw_instanced is not supported, this extension
reintroduces the draw calls from NV_draw_instanced.
3) Should current generic attributes be affected by the execution of
DrawArraysOneInstance?
Resolved: No. ANGLE says no. ARB says maybe. Defined behavior is
always better. The wishy washy ARB language is likely to permit
a software implementation without excessive state resetting. This
Is not terribly useful if implemented in software.
4) Can all vertex attributes be instanced simultaneously?
Resolved: No. 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).
Revision History
Rev. Date Author Changes
---- ------------- --------- ----------------------------------------
4 28 Aug 2012 groth Various spelling corrections and minor clarifications
3 20 Aug 2012 groth Add interaction with VAOs
2 19 Aug 2012 groth Correct section number
1 12 Aug 2012 groth Initial GLES2 version from ARB_instanced_arrays
with inspiration from ANGLE_instanced_arrays