Name
ARB_draw_indirect
Name Strings
GL_ARB_draw_indirect
Contact
Jeff Bolz, NVIDIA Corporation (jbolz 'at' nvidia.com)
Pat Brown, NVIDIA Corporation (pbrown 'at' nvidia.com)
Contributors
Barthold Lichtenbelt, NVIDIA
Bill Licea-Kane, AMD
Bruce Merry, ARM
Graham Sellers, AMD
Greg Roth, NVIDIA
Nick Haemel, AMD
Pierre Boudier, AMD
Piers Daniell, NVIDIA
Notice
Copyright (c) 2010-2013 The Khronos Group Inc. Copyright terms at
http://www.khronos.org/registry/speccopyright.html
Status
Complete. Approved by the ARB at the 2010/01/22 F2F meeting.
Approved by the Khronos Board of Promoters on March 10, 2010.
Version
Last Modified Date: 09/17/2012
Revision: 7
Number
ARB Extension #87
Dependencies
OpenGL 3.1 is required.
This extension is written against the OpenGL 3.2 specification with
the Compatibility Profile.
This extension interacts with NV_vertex_buffer_unified_memory.
This extension interacts with ARB_instanced_arrays.
This extension interacts with ARB_compatibility.
Overview
This extension provides a mechanism for supplying the arguments to a
DrawArraysInstanced or DrawElementsInstancedBaseVertex from buffer object
memory. This is not particularly useful for applications where the CPU
knows the values of the arguments beforehand, but is helpful when the
values will be generated on the GPU through any mechanism that can write
to a buffer object including image stores, atomic counters, or compute
interop. This allows the GPU to consume these arguments without a round-
trip to the CPU or the expensive synchronization that would involve. This
is similar to the DrawTransformFeedbackEXT command from
EXT_transform_feedback2, but offers much more flexibility in both
generating the arguments and in the type of Draws that can be accomplished.
IP Status
No known IP claims.
New Procedures and Functions
void DrawArraysIndirect(enum mode, const void *indirect);
void DrawElementsIndirect(enum mode, enum type, const void *indirect);
New Tokens
Accepted by the parameters of BindBuffer, BufferData,
BufferSubData, MapBuffer, UnmapBuffer, GetBufferSubData,
GetBufferPointerv, MapBufferRange, FlushMappedBufferRange,
GetBufferParameteriv, and CopyBufferSubData:
DRAW_INDIRECT_BUFFER 0x8F3F
Accepted by the parameter of GetIntegerv, GetBooleanv, GetFloatv,
and GetDoublev:
DRAW_INDIRECT_BUFFER_BINDING 0x8F43
Additions to Chapter 2 of the OpenGL 3.2 Specification (OpenGL Operation)
Add to Section 2.8.1 p. 40 (Drawing Commands)
The command
DrawArraysIndirect(enum mode, const void *indirect);
behaves as follows:
typedef struct {
GLuint count;
GLuint primCount;
GLuint first;
GLuint reservedMustBeZero;
} DrawArraysIndirectCommand;
if (mode is invalid) {
generate appropriate error
} else {
DrawArraysIndirectCommand *cmd = (DrawArraysIndirectCommand *)indirect;
DrawArraysInstanced(mode, cmd->first, cmd->count, cmd->primCount);
}
As with regular DrawArraysInstanced commands, the vertex attributes
may be sourced from client arrays or vertex buffer objects (if buffers
are bound). Unlike regular DrawArraysInstanced commands, the
argument is unsigned and cannot cause an error. The results are undefined
if is non-zero and may not result in program
termination.
The command
DrawElementsIndirect(enum mode, enum type, const void *indirect);
behaves as follows:
typedef struct {
GLuint count;
GLuint primCount;
GLuint firstIndex;
GLint baseVertex;
GLuint reservedMustBeZero;
} DrawElementsIndirectCommand;
if (mode or type is invalid, or no index buffer) {
generate appropriate error
} else {
DrawElementsIndirectCommand *cmd = (DrawElementsIndirectCommand *)indirect;
DrawElementsInstancedBaseVertex(mode, cmd->count, type,
cmd->firstIndex * size-of-type, cmd->primCount, cmd->baseVertex);
}
As with regular DrawElementsInstancedBaseVertex commands, the vertex
attributes may be sourced from client arrays or vertex buffer objects
(if objects are bound). Unlike regular DrawElementsInstancedBaseVertex
commands, the indices may not come from a client array and must come from
an index buffer. If no element array buffer is bound, an INVALID_OPERATION
error is generated. The results are undefined if is
non-zero and may not result in program termination.
All elements of DrawArraysIndirectCommand and
DrawElementsIndirectCommand are 32bit values, and both structures are
tightly packed.
Add to Section 2.9 (Buffer Objects)
Add to Table 2.7 (p. 48):
Target name Purpose Described in sections(s)
----------------------- ---------- -------------------------
DRAW_INDIRECT_BUFFER Indirect draw commands 2.9.9
Add a new Section 2.9.9 (Indirect Commands in Buffer Objects)
Arguments to DrawArraysIndirect and DrawElementsIndirect commands
may be stored in buffer objects.
Initially zero is bound to DRAW_INDIRECT_BUFFER. In the
compatibility profile, this indicates that DrawArraysIndirect and
DrawElementsIndirect are to source their arguments directly from the
pointer passed as their parameters. In the core profile,
an INVALID_OPERATION error is generated if zero is bound to
DRAW_INDIRECT_BUFFER and DrawArraysIndirect or DrawElementsIndirect
is called.
A buffer object is bound to DRAW_INDIRECT_BUFFER by calling
BindBuffer with set to DRAW_INDIRECT_BUFFER, and
set to the name of the buffer object. If no corresponding buffer
object exists, one is initialized as defined in section 2.9.
While a non-zero buffer object name is bound to DRAW_INDIRECT_BUFFER,
DrawArraysIndirect and DrawElementsIndirect source their arguments
from that buffer object, using their parameters as offsets
into the buffer object in the same fashion as described in section 2.9.3.
An INVALID_OPERATION error is generated if the commands source data
beyond the end of the buffer object or if is not word aligned.
Additions to Chapter 3 of the OpenGL 3.2 Specification (Rasterization)
None.
Additions to Chapter 4 of the OpenGL 3.2 Specification (Per-Fragment
Operations and the Frame Buffer)
None.
Additions to Chapter 5 of the OpenGL 3.2 Specification (Special Functions)
None.
Additions to Chapter 6 of the OpenGL 3.2 Specification (State and
State Requests)
None.
Additions to Appendix A of the OpenGL 3.2 Specification (Invariance)
None.
Additions to the AGL/GLX/WGL Specifications
None.
GLX Protocol
TBD.
Errors
INVALID_ENUM is generated by DrawArraysIndirect/DrawElementsIndirect
if is not a valid begin mode.
INVALID_ENUM is generated by DrawElementsIndirect if is not
one of UNSIGNED_BYTE, UNSIGNED_SHORT, or UNSIGNED_INT.
INVALID_OPERATION is generated by DrawElementsIndirect if no buffer
is bound to ELEMENT_ARRAY_BUFFER.
INVALID_OPERATION is generated by DrawArraysIndirect and
DrawElementsIndirect if zero is bound to DRAW_INDIRECT_BUFFER and if
the OpenGL context implements the core profile.
INVALID_OPERATION is generated by DrawArraysIndirect and
DrawElementsIndirect if commands source data beyond the end of a buffer
object or if is not word aligned.
New State
Update Table 6.11, p. 405 (Vertex Array Data not in Vertex Array objects)
Get Value Type Get Command Initial Value Sec Attribute
--------- ---- ----------- ------------- --- ---------
DRAW_INDIRECT_BUFFER_BINDING Z+ GetIntegerv 0 2.9 none
New Implementation Dependent State
None.
Dependencies on NV_vertex_buffer_unified_memory
If NV_vertex_buffer_unified_memory is supported, the following additional
edits are required:
Accepted by the parameter of GetBufferParameterui64vNV:
DRAW_INDIRECT_BUFFER.
Accepted by the parameter of DisableClientState,
EnableClientState, IsEnabled:
DRAW_INDIRECT_UNIFIED_NV 0x8F40
Accepted by the parameter of BufferAddressRangeNV
and the parameter of GetIntegerui64vNV:
DRAW_INDIRECT_ADDRESS_NV 0x8F41
Accepted by the parameter of GetIntegerv:
DRAW_INDIRECT_LENGTH_NV 0x8F42
In Section 2.8.1, mention that vertex attributes and indices may be
sourced from GPU addresses if VERTEX_ATTRIB_ARRAY_UNIFIED_NV/
ELEMENT_ARRAY_UNIFIED_NV are enabled.
Add to Section 2.9:
While DRAW_INDIRECT_UNIFIED_NV is enabled, DrawArraysIndirect and
DrawElementsIndirect, source their arguments from the address
specified by the command BufferAddressRange where is
DRAW_INDIRECT_ADDRESS_NV and is zero, added to the
parameter. If the commands source data beyond and including (
+ ), an INVALID_OPERATION error will be generated. If the draw
indirect address range does not belong to a buffer object that is
resident at the time of the Draw, undefined results, possibly
including program termination, may occur.
INVALID_OPERATION is generated by DrawElementsIndirect if no buffer
is bound to ELEMENT_ARRAY_BUFFER and DRAW_INDIRECT_UNIFIED_NV is
disabled.
INVALID_OPERATION is generated by DrawArraysIndirect and
DrawElementsIndirect if DRAW_INDIRECT_UNIFIED_NV is enabled and
commands source data beyond and including (address + length).
Update Table 6.11:
Get Value Type Get Command Initial Value Sec Attribute
--------- ---- ----------- ------------- --- ---------
DRAW_INDIRECT_UNIFIED_NV B IsEnabled FALSE 2.9 none
DRAW_INDIRECT_ADDRESS_NV Z64+ GetIntegerui64vNV 0 2.9 none
DRAW_INDIRECT_LENGTH_NV Z+ GetIntegerv 0 2.9 none
Dependencies on NV_vertex_buffer_unified_memory and ARB_compatibility
If the context version is greater than 3.0 and does not include
ARB_compatibility functionality, then EnableClientState and
DisableClientState have been deprecated and removed. This extension
adds back those commands if NV_vertex_buffer_unified_memory is supported,
but only requires that they accept the DRAW_INDIRECT_UNIFIED_NV token.
Dependencies on ARB_compatibility
When the ARB_compatibility extension is not supported, client arrays
cannot be used to source vertex attribute data.
Dependencies on ARB_instanced_arrays
This extension does not require ARB_instanced_arrays, but reserves
space in the Command structures such that a future extension could
add a "firstInstance" member which would initialize the instance
counter used for computing which vertex attrib array element to use.
Note that ARB_instanced_arrays does not currently support
"firstInstance", it only has a frequency divider.
Issues
(1) What is this good for?
RESOLVED: Compute interoperability. Recirculating results written via
image stores or atomic counters.
(2) Should we allow indirect draws from client memory? Should we have a
buffer object binding for this?
RESOLVED: YES. Although, using client vertex arrays would somewhat defeat
the purpose of this extension. Note that this issue only applies to
implementations supporting the ARB_compatibility extension.
One non-obvious restriction is that DrawElementsIndirect doesn't accept
an parameter, so an index buffer is required.
(3) How do we specify the index size for DrawElements calls?
RESOLVED: Passed into the command, not pulled out of the struct.
(4) For DrawElements calls, in what unit are the offsets into the index
buffer.
RESOLVED: In indices, not in bytes.
(5) Should the new state be part of the VAO?
RESOLVED: No.
(6) Should gl.h/glext.h provide structure definitions?
RESOLVED. No. It is not possible to define the structures in such a way
that all compilers would pack them correctly.
Revision History
Rev. Date Author Changes
---- -------- -------- ------------------------------------------------
7 09/17/2012 Jon Leech Remove BindBufferRange/Base from commands for
which DRAW_INDIRECT_BUFFER is a valid target
(Bug 7794).
6 03/07/2012 Jon Leech Add missing error when no indirect buffer is
bound and the indirect draw commands are
called (Bug 7211).
5 12/07/2009 pdaniell Remove ARB suffix from new tokens for core spec.
4 10/29/2009 pdaniell Convert to ARB.
3 10/21/2009 pdaniell Minor edits based on Bruce's feedback. Added
full list of Get* calls for new
DRAW_INDIRECT_BUFFER_BINDING_EXT token.
Specified behavior when reservedMustBeZero is
non-zero. Added INVALID_VALUE error when
is not a multiple of GLuint.
2 jbolz Internal revisions.
1 pbrown Internal revisions.