Name EXT_draw_elements_base_vertex Name Strings GL_EXT_draw_elements_base_vertex Contact Daniel Koch, NVIDIA (dkoch 'at' nvidia.com) Contributors Shannon Woods, Google Dominik Witczak, Mobica Contributors to ARB_draw_elements_base_vertex Notice Copyright (c) 2009-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: August 11, 2020 Version: 4 Number OpenGL ES Extension #204 Dependencies This specification is written against the OpenGL ES 3.1 (June 4, 2014) Specifications, but can apply to prior specifications. Requires OpenGL ES 2.0. This extension interacts with OpenGL ES 3.1. This extension interacts with OpenGL ES 3.0. This extension interacts with EXT_draw_instanced. This extension interacts with NV_draw_instanced. This extension interacts with EXT_instanced_arrays. This extension interacts with ANGLE_instanced_arrays. This extension interacts with NV_instanced_arrays. This extension interacts with EXT_multi_draw_arrays. Overview This extension provides a method to specify a "base vertex offset" value which is effectively added to every vertex index that is transferred through DrawElements. This mechanism can be used to decouple a set of indices from the actual vertex array that it is referencing. This is useful if an application stores multiple indexed models in a single vertex array. The same index array can be used to draw the model no matter where it ends up in a larger vertex array simply by changing the base vertex value. Without this functionality, it would be necessary to rebind all the vertex attributes every time geometry is switched and this can have larger performance penalty. For example consider the (very contrived and simple) example of drawing two triangles to form a quad. In the typical example you have the following setup: vertices indices ---------- ----- 0 | (-1, 1) | 0 | 0 | 1 | (-1, -1) | 1 | 1 | 2 | ( 1, -1) | 2 | 2 | 3 | ( 1, 1) | 3 | 3 | ---------- 4 | 0 | 5 | 2 | ----- which is normally rendered with the call DrawElements(TRIANGLES, 6, UNSIGNED_BYTE, &indices). Now consider the case where the vertices you want to draw are not at the start of a vertex array but are instead located at offset 100 into a larger array: vertices2 indices2 ---------- ----- .... 0 | 100 | 100 | (-1, 1) | 1 | 101 | 101 | (-1, -1) | 2 | 102 | 102 | ( 1, -1) | 3 | 103 | 103 | ( 1, 1) | 4 | 100 | .... 5 | 102 | ---------- ----- The typical choices for rendering this are to rebind your vertex attributes with an additional offset of 100*stride, or to create an new array of indices (as indices2 in the example). However both rebinding vertex attributes and rebuilding index arrays can be quite costly activities. With the new drawing commands introduced by this extension you can instead draw using vertices2 and the new draw call: DrawElementsBaseVertexEXT(TRIANGLES, 6, UNSIGNED_BYTE, &indices, 100) New Procedures and Functions void DrawElementsBaseVertexEXT(enum mode, sizei count, enum type, const void *indices, int basevertex); [[ If OpenGL ES 3.0 is supported: ]] void DrawRangeElementsBaseVertexEXT(enum mode, uint start, uint end, sizei count, enum type, const void *indices, int basevertex); void DrawElementsInstancedBaseVertexEXT(enum mode, sizei count, enum type, const void *indices, sizei instancecount, int basevertex); [[ If EXT_multi_draw_arrays is supported: ]] void MultiDrawElementsBaseVertexEXT(enum mode, const sizei *count, enum type, const void * const *indices, sizei drawcount, const int *basevertex); New Tokens None Additions to Chapter 10 of the OpenGL ES 3.1 Specification (Vertex Specification and Drawing Commands) Modify section 10.3.7 "Array Indices in Buffer Objects" p. 244, adding the following to the end of the third paragraph (beginning with "While a non-zero buffer object name..." "DrawElementsBaseVertexEXT, DrawRangeElementsBaseVertexEXT, and DrawElementsInstancedBaseVertexEXT also source their indices from that buffer object, adding the offset to the appropriate vertex index as a final step before indexing into the vertex buffer; this does not affect the calculation of the base pointer for the index array." [[ If EXT_multi_draw_arrays is supported: ]] "Finally, MultiDrawElementsEXT and MultiDrawElementsBaseVertexEXT also source their indices from that buffer object, using its parameter as a pointer to an array of pointers that represent offsets into the buffer object." Modify section 10.5 "Drawing Commands Using Vertex Arrays" as follows: Replace the definition and paragraph describing DrawElementsInstancedBaseVertex, bottom of p. 252 with the following: "The commands void DrawElementsBaseVertexEXT(enum mode, sizei count, enum type, const void *indices, int basevertex); void DrawRangeElementsBaseVertexEXT(enum mode, uint start, uint end, sizei count, enum type, const void *indices, int basevertex); void DrawElementsInstancedBaseVertexEXT(enum mode, sizei count, enum type, const void *indices, sizei instancecount, int basevertex); are equivalent to the commands with the same base name (without the "BaseVertexEXT" suffix) except that the th element transferred by the corresponding draw call will be taken from element [] + of each enabled array. If the resulting value is larger than the maximum value representable by it should behave as if the calculation were upconverted to 32-bit unsigned integers (with wrapping on overflow conditions). The operation is undefined if the sum would be negative and should be handled as described in Section 6.4. For DrawRangeElementsBaseVertexEXT, the index values must lie between and inclusive, prior to adding the offset. Index values lying outside the range [,] are treated in the same way as DrawRangeElements." [[ If EXT_multi_draw_arrays is supported: ]] "The command void MultiDrawElementsBaseVertexEXT(enum mode, const sizei *count, enum type, const void *const *indices, sizei drawcount, const int *basevertex); behaves identically to DrawElementsBaseVertexEXT except that separate lists of elements are specified instead. It has the same effect as: if ( or is invalid) generate appropriate error else { for (i = 0; i < ; i++) if ([i] > 0) DrawElementsBaseVertexEXT(, [i], , [i], [i]); }" Additions to the EGL/AGL/GLX/WGL Specifications None Dependencies on OpenGL ES 3.1 If OpenGL ES 3.1 is not supported apply the following modifications to the OpenGL ES 3.0.3 specification: Add the following to the end of Section 2.8.1 "Transferring Array Elements" "When one of the *BaseVertex drawing commands specified in section 2.8.3 is used, the primitive restart comparison occurs before the offset is added to the array index." Replace the following references relative to the ES 3.1 specification with the following references to the ES 3.0.3 specification: Edits to section 10.3.7 "Array Indices in Buffer Objects" in ES 3.1 become edits to section 2.9.7 "Array Indices in Buffer Objects" in ES 3.0.3. Edits to section 10.5 "Draw Command using Vertex Arrays" in ES 3.1 become edits to section 2.8.3 "Drawing Commands" in ES 3.0.3. Replace references to section 6.4 in ES 3.1 with references to section 2.9.4 in ES 3.0.3. Dependencies on OpenGL ES 3.0 If OpenGL ES 3.0 is not supported, ignore all references to DrawElementsInstanced and DrawElementsInstancedBaseVertexEXT (unless one of the instanced_array or draw_instanced extensions is present). If OpenGL ES 3.0 is not supported, ignore all references to DrawRangeElements and DrawRangeElementsBaseVertexEXT. If OpenGL ES 3.0 is not supported, ignore all references to primitive restart index. Dependencies on the EXT_draw_instanced extension If EXT_draw_instanced is supported, the functionality provided by DrawElementsInstancedBaseVertexEXT can also be described in terms of DrawElementsInstancedEXT instead of DrawElementsInstanced. Dependencies on the NV_draw_instanced extension If NV_draw_instanced is supported, the functionality provided by DrawElementsInstancedBaseVertexEXT can also be described in terms of DrawElementsInstancedNV instead of DrawElementsInstanced. Dependencies on the EXT_instanced_arrays extension If EXT_instanced_arrays is supported, the functionality provided by DrawElementsInstancedBaseVertexEXT can also be described in terms of DrawElementsInstancedEXT instead of DrawElementsInstanced. Dependencies on the ANGLE_instanced_arrays extension If ANGLE_instanced_arrays is supported, the functionality provided by DrawElementsInstancedBaseVertexEXT can also be described in terms of DrawElementsInstancedANGLE instead of DrawElementsInstanced. Dependencies on the NV_instanced_arrays extension If ARB_instanced_arrays is supported, the functionality provided by DrawElementsInstancedBaseVertexEXT can also be described in terms of DrawElementsInstancedNV instead of DrawElementsInstanced. Errors The *BaseVertexEXT commands have identical error conditions to the non-*BaseVertexEXT functions, and all values of are legal (with the exception of ones which cause accesses outside of vertex arrays or bound buffers as described in Section 6.4). New State None New Implementation Dependent State None Issues Note: These issues apply specifically to the definition of the EXT_draw_elements_base_vertex specification, which is based on the OpenGL extension ARB_draw_elements_base_vertex as updated in OpenGL 4.4. ARB_draw_elements_base_vertex can be found in the OpenGL Registry. (0) This extension is based on ARB_draw_elements_base_vertex. What are the major differences? - rebased on OpenGL ES 3.1 - renamed the "primcount" parameter to "instancecount" per GL4 - MultiDrawElementsBaseVertexEXT is only available if GL_EXT_multi_draw_arrays is supported. (1) Should we include MultiDrawElementsBaseVertexEXT in this extension? RESOLVED: Yes, but only if EXT_multi_draw_arrays is supported, since multi draw calls are not available in unextended OpenGL ES 2 or 3. (2) Should we allow client memory to be used for vertex attributes and for the in the *BaseVertexEXT commands? RESOLVED: Yes. Since these are defined in terms of the non-BaseVertex commands which already supports client memory for vertex attributes and indices it makes sense to include support for these new commands as well. (3) Which commands are supported on OpenGL ES 2.0 implementations that support this extension? RESOLVED: Only DrawElementsBaseVertexEXT, unless one of the instancing extensions is supported in which case DrawElementsInstancedBaseVertexEXT is also supported. DrawRangeElementsBaseVertexEXT is not supported because OpenGL ES 2.0 doesn't include DrawRangeElements. (4) Which commands are supported on OpenGL ES 3.0 implementations? RESOLVED: All of the new drawing commands are applicable to OpenGL ES 3.0 implementations. (5) Does the value of gl_VertexID in the shading language include the the value of the offset? RESOLVED: Yes. This is as clarified by Khronos bugs 12202 and 12756 and is consistent with the overview of ARB_shader_draw_parameters. Essentially, the value of gl_VertexID should be the index of the vertex that is being passed to the shader. - DrawArrays: first + i - DrawElements: indices[i] - DrawElementsBaseVertex: indices[i] + basevertex Revision History Rev. Date Author Changes ---- -------- --------- ---------------------------------------------- 4 08/11/20 pdaniell Renamed the 'primcount' parameter of MultiDrawElementsBaseVertexEXT in the "New Procedures and Functions" section to 'drawcount' to match the extension spec body. 3 09/30/14 dkoch Resolved issues 1, 2 as proposed. Added issue 5. Mark complete. 2 06/24/14 dkoch Add EXT_multi_draw_arrays interactions and typographical fixes from Dominik. 1 04/05/14 dkoch Intial version for ES based on ARB_draw_elements_base_vertex v3.