Skip to content
This repository has been archived by the owner on Jun 16, 2018. It is now read-only.

Commit

Permalink
Add ANGLE_instanced_arrays spec
Browse files Browse the repository at this point in the history
Trac #18156

git-svn-id: http://angleproject.googlecode.com/svn/trunk@967 736b8ea6-26fd-11df-bfd4-992fa37f6226
  • Loading branch information
daniel@transgaming.com committed Jan 27, 2012
1 parent 61d1122 commit 2c1370b
Showing 1 changed file with 355 additions and 0 deletions.
355 changes: 355 additions & 0 deletions 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.