Name EXT_multi_draw_indirect Name Strings GL_EXT_multi_draw_indirect Contact Daniel Koch, NVIDIA (dkoch 'at' nvidia.com) Contributors Dominik Witczak, Mobica Jonas Gustavsson, Sony Mobile Slawomir Grajewski, Intel Contributors to ARB_multi_draw_indirect Notice Copyright (c) 2012-2014 The Khronos Group Inc. Copyright terms at http://www.khronos.org/registry/speccopyright.html Portions Copyright (c) 2014 NVIDIA Corporation. Status Complete Version Last Modified Date: October 24, 2014 Revision: 4 Number OpenGL ES Extension #205 Dependencies OpenGL ES 3.1 is required. This specification is written against the OpenGL ES 3.1 (June 4, 2014) Specification. This extension interacts with EXT_base_instance. This extension interacts with EXT_geometry_shader. Overview The ARB_draw_indirect extension (included in OpenGL 4.0 and OpenGL ES 3.1) introduced mechanisms whereby the parameters for a draw function may be provided in a structure contained in a buffer object rather than as parameters to the drawing procedure. This is known as an indirect draw and is exposed as two new functions, glDrawArraysIndirect and glDrawElementsIndirect. Each of these functions generates a single batch of primitives. This extension builds on this functionality by providing procedures to invoke multiple draws from a single procedure call. This allows large batches of drawing commands to be assembled in server memory (via a buffer object) which may then be dispatched through a single function call. New Procedures and Functions void MultiDrawArraysIndirectEXT(enum mode, const void *indirect, sizei drawcount, sizei stride); void MultiDrawElementsIndirectEXT(enum mode, enum type, const void *indirect, sizei drawcount, sizei stride); New Tokens None. Additions to Chapter 10 of the OpenGL ES 3.1 Specification (Vertex Specification and Drawing Commands) Additions to 10.3.8, "Indirect Commands in Buffer Objects", p. 244 Add MultiDrawArraysIndirectEXT and MultiDrawElementsIndirectEXT to the list of "indirect commands" in the first paragraph of the section. In the second paragraph of the section replace the reference to "Draw*Indirect" commands with a reference to "*Draw*Indirect" so that it is clear that this statement applies to the MultiDraw variants of the commands as well. Update Table 10.3 "Indirect commands and corresponding indirect buffer targets" adding the following two rows: Indirect Command Name | Indirect Buffer --------------------------------------------------------- MultiDrawArraysIndirectEXT | DRAW_INDIRECT_BUFFER MultiDrawElementsIndirectEXT | DRAW_INDIRECT_BUFFER Additions to Section 10.5, "Drawing Commands using Vertex Arrays" (After the description of DrawArraysIndirect and before the introduction of DrawElementsOneInstance, insert the following on p.249) "The command void MultiDrawArraysIndirectEXT(enum mode, const void *indirect, sizei drawcount, sizei stride); behaves identically to DrawArraysIndirect, except that is treated as an array of DrawArraysIndirectCommand structures. contains the offset of the first element of the array within the buffer currently bound to the DRAW_INDIRECT buffer binding. specifies the distance, in basic machine units, between the elements of the array. If is zero, the array elements are treated as tightly packed. It is equivalent to if ( is invalid) generate appropriate error else { const ubyte * ptr = (const ubyte *); for (i = 0; i < ; i++) { DrawArraysIndirect(, (DrawArraysIndirectCommand*)ptr); if ( == 0) { ptr += sizeof(DrawArraysIndirectCommand); } else { ptr += ; } } } MultiDrawArraysIndirectEXT requires that all data sourced for the command, including the DrawArraysIndirectCommand structure, be in buffer objects, and cannot be called when the default vertex array object is bound. Errors An INVALID_VALUE is generated if is neither zero nor a multiple of four. An INVALID_VALUE error is generated if is not positive. An INVALID_OPERATION error is generated if zero is bound to VERTEX_ARRAY_BINDING, DRAW_INDIRECT_BUFFER, or to any enabled vertex array. An INVALID_OPERATION error is generated if the command would source data beyond the end of the buffer object. An INVALID_VALUE error is generated if is not a multiple of the size, in basic machine units of uint. [[ If EXT_geometry_shader is not supported. ]] An INVALID_OPERATION error is generated if transform feedback is active and not paused. [[ If EXT_base_instance is not supported. ]] Results are undefined if is non-zero, but may not result in program termination." (After the description of DrawElementsIndirect insert the following on p.253) "The command void MultiDrawElementsIndirectEXT(enum mode, enum type, const void *indirect, sizei drawcount, sizei stride); behaves identically to DrawElementsIndirect, except that is treated as an array of DrawElementsIndirectCommand structures. contains the offset of the first element of the array within the buffer currently bound to the DRAW_INDIRECT buffer binding. specifies the distance, in basic machine units, between the elements of the array. If is zero, the array elements are treated as tightly packed. must be a multiple of four, otherwise an INVALID_VALUE error is generated. It is equivalent to if ( or is invalid) generate appropriate error else { const ubyte * ptr = (const ubyte *); for (i = 0; i < ; i++) { DrawElementsIndirect(, , (DrawElementsIndirectCommand*)ptr); if ( == 0) { ptr += sizeof(DrawElementsIndirectCommand); } else { ptr += ; } } } MultiDrawElementsIndirectEXT requires that all data sourced for the command, including the DrawElementsIndirectCommand structure, be in buffer objects, and cannot be called when the default vertex array object is bound. Errors An INVALID_VALUE is generated if is neither zero nor a multiple of four. An INVALID_VALUE error is generated if is not positive. An INVALID_OPERATION error is generated if zero is bound to VERTEX_ARRAY_BINDING, DRAW_INDIRECT_BUFFER, ELEMENT_ARRAY_BUFFER, or to any enabled vertex array. An INVALID_OPERATION error is generated if the command would source data beyond the end of the buffer object. An INVALID_VALUE error is generated if is not a multiple of the size, in basic machine units of uint. [[ If EXT_geometry_shader is not supported. ]] An INVALID_OPERATION error is generated if transform feedback is active and not paused. [[ If EXT_base_instance is not supported. ]] Results are undefined if is non-zero, but may not result in program termination." Additions to the EGL/AGL/GLX/WGL Specifications None. Dependencies on EXT_base_instance If EXT_base_instance is not supported, the parameter in the Draw*IndirectCommand structures is not supported. Dependencies on EXT_geometry_shader If EXT_geometry_shader is not supported, transform feedback cannot be used with the Multi*DrawIndirect commands. GLX Protocol None. New State None. New Implementation Dependent State None. Issues Note: These issues apply specifically to the definition of the EXT_multi_draw_indirect specification, which is based on the OpenGL extension ARB_multi_draw_indirect as updated in OpenGL 4.x. ARB_multi_draw_indirect can be found in the OpenGL Registry. (0) This extension is based on ARB_multi_draw_indirect. What are the major differences? - Rebased against the ES 3.1 restructured specification - renamed the parameter to to match the GL 4.4 spec (and reflect what the parameter really is). - using the new commands with the default vertex array object, or client-side memory the draw indirect buffer, vertex arrays or index data is not permitted. - these commands cannot be used when transform feedback is enabled unless EXT_geometry_shader is supported. - these commands do not support the baseInstance parameter unless EXT_base_instance is supported. (1) What about the "baseInstance" parameter for indirect draws? It is still listed as reserved in the DrawElementsIndirectCommand structure. It is separately added as orthogonal functionality in the EXT_base_instance extension, although that should really be supported in order to get the full benefit of multi_draw_indirect. Since MultiDrawElementsIndirectEXT is defined in terms of DrawElementsIndirect the extension that adds support for base instance will automatically add support for in via MDI as well. (2) Should the new drawing commands be supported on the default vertex array object? RESOLVED: No. This extension follows the precedent of ES 3.1's Draw*Indirect capabilities, which disallow the commands with the default vertex array object. (3) Should the new drawing commands be supported with client-side memory? RESOLVED. No. Again, this extension follows the precedent of OpenGL ES 3.1's Draw*Indirect capabilities, which disallow the commands with client-side memory for the vertex arrays, element array, and draw indirect buffers. (4) The resolution of Issues (2) and (3) take the opposite resolution to the same questions raised in EXT_base_instance. Isn't that a little strange? RESOLVED. Yes, but that's the way we roll. The non-indirect drawing commands must support the ES2-level features for compatibility. Revision History Rev. Date Author Changes ---- -------- -------- ----------------------------------------- 4 10/24/2014 dkoch Mark as complete. 3 06/24/2014 dkoch Fixes from Dominik, dangling primcount refs, formatting of pseudocode. 2 06/20/2014 dkoch Require VAO and client-side memory for the MultiDraw*Indirect commands. List the full set of errors for the new cmds. Rebase to Jun 4 ES 3.1 spec. Add interactions with EXT_base_instance. Add interactions with EXT_geometry_shader. 1 03/18/2014 dkoch EXT version based on ARB_multi_draw_indirect v.3