зеркало из https://github.com/AvaloniaUI/angle.git
356 строки
13 KiB
Plaintext
356 строки
13 KiB
Plaintext
|
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
|