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 Specification Update Policy Khronos-approved extension specifications are updated in response to issues and bugs prioritized by the Khronos OpenGL Working Group. For extensions which have been promoted to a core Specification, fixes will first appear in the latest version of that core Specification, and will eventually be backported to the extension document. This policy is described in more detail at https://www.khronos.org/registry/OpenGL/docs/update_policy.php 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.