1Name 2 3 ARB_draw_elements_base_vertex 4 5Name Strings 6 7 GL_ARB_draw_elements_base_vertex 8 9Contributors 10 11 Daniel Koch, TransGaming 12 James Helferty, TransGaming 13 Jeff Bolz, NVIDIA 14 Bruce Merry, ARM 15 Ian Romanick, Intel 16 Jon Leech, Khronos 17 18Contact 19 20 Daniel Koch, TransGaming (daniel 'at' transgaming.com) 21 22Notice 23 24 Copyright (c) 2009-2013 The Khronos Group Inc. Copyright terms at 25 http://www.khronos.org/registry/speccopyright.html 26 27Specification Update Policy 28 29 Khronos-approved extension specifications are updated in response to 30 issues and bugs prioritized by the Khronos OpenGL Working Group. For 31 extensions which have been promoted to a core Specification, fixes will 32 first appear in the latest version of that core Specification, and will 33 eventually be backported to the extension document. This policy is 34 described in more detail at 35 https://www.khronos.org/registry/OpenGL/docs/update_policy.php 36 37Status 38 39 Complete. Approved by the ARB on July 3, 2009. 40 41Version 42 43 Last Modified Date: August 22, 2019 44 Version: 4 45 46Number 47 48 ARB Extension #62 49 50Dependencies 51 52 This extension is written against the OpenGL 3.1 Specification but 53 can apply to prior specifications. 54 55 This extension interacts with ARB_draw_instanced. 56 57 This extension interacts with EXT_draw_instanced. 58 59 This extension interacts with ARB_instanced_arrays. 60 61 This extension interacts with ARB_compatibility. 62 63Overview 64 65 This extension provides a method to specify a "base vertex offset" 66 value which is effectively added to every vertex index that is 67 transferred through DrawElements. 68 69 This mechanism can be used to decouple a set of indices from the 70 actual vertex array that it is referencing. This is useful if an 71 application stores multiple indexed models in a single vertex array. 72 The same index array can be used to draw the model no matter where 73 it ends up in a larger vertex array simply by changing the base 74 vertex value. Without this functionality, it would be necessary to 75 rebind all the vertex attributes every time geometry is switched and 76 this can have larger performance penalty. 77 78 For example consider the (very contrived and simple) example of 79 drawing two triangles to form a quad. In the typical example you 80 have the following setup: 81 82 vertices indices 83 ---------- ----- 84 0 | (-1, 1) | 0 | 0 | 85 1 | (-1, -1) | 1 | 1 | 86 2 | ( 1, -1) | 2 | 2 | 87 3 | ( 1, 1) | 3 | 3 | 88 ---------- 4 | 0 | 89 5 | 2 | 90 ----- 91 which is normally rendered with the call 92 93 DrawElements(TRIANGLES, 6, UNSIGNED_BYTE, &indices). 94 95 Now consider the case where the vertices you want to draw are not at 96 the start of a vertex array but are instead located at offset 100 97 into a larger array: 98 99 vertices2 indices2 100 ---------- ----- 101 .... 0 | 100 | 102 100 | (-1, 1) | 1 | 101 | 103 101 | (-1, -1) | 2 | 102 | 104 102 | ( 1, -1) | 3 | 103 | 105 103 | ( 1, 1) | 4 | 100 | 106 .... 5 | 102 | 107 ---------- ----- 108 109 The typical choices for rendering this are to rebind your vertex 110 attributes with an additional offset of 100*stride, or to create an 111 new array of indices (as indices2 in the example). However both 112 rebinding vertex attributes and rebuilding index arrays can be quite 113 costly activities. 114 115 With the new drawing commands introduced by this extension you can 116 instead draw using vertices2 and the new draw call: 117 118 DrawElementsBaseVertex(TRIANGLES, 6, UNSIGNED_BYTE, &indices, 100) 119 120New Procedures and Functions 121 122 void DrawElementsBaseVertex(enum mode, sizei count, enum type, 123 const void *indices, int basevertex); 124 125 void DrawRangeElementsBaseVertex(enum mode, uint start, uint end, 126 sizei count, enum type, const void *indices, int basevertex); 127 128 void DrawElementsInstancedBaseVertex(enum mode, sizei count, 129 enum type, const void *indices, sizei instancecount, int basevertex); 130 131 void MultiDrawElementsBaseVertex(enum mode, const sizei *count, enum type, 132 const void *const *indices, sizei drawcount, const int *basevertex) 133 134New Tokens 135 136 None 137 138Additions to Chapter 2 of the OpenGL 3.1 Specification (OpenGL Operation) 139 140 Add the following to the end of Section 2.8.1 "Transferring Array Elements" 141 142 "When one of the *BaseVertex drawing commands specified in section 143 2.8.2 is used, the primitive restart comparison occurs before the 144 <basevertex> offset is added to the array index." 145 146 Add the following to Section 2.8.2 "Drawing Commands" 147 148 "The commands 149 void DrawElementsBaseVertex(enum mode, sizei count, enum type, 150 const void *indices, int basevertex); 151 152 void DrawRangeElementsBaseVertex(enum mode, uint start, uint end, 153 sizei count, enum type, const void *indices, int basevertex); 154 155 void DrawElementsInstancedBaseVertex(enum mode, sizei count, 156 enum type, const void *indices, sizei instancecount, int basevertex); 157 158 are equivalent to the commands with the same base name (without the 159 "BaseVertex" suffix) except that the <i>th element transferred by 160 the corresponding draw call will be taken from element 161 <indices>[<i>] + <basevertex> 162 of each enabled array. If the resulting value is larger than the 163 maximum value representable by <type> it should behave as if the 164 calculation were upconverted to 32-bit unsigned integers (with 165 wrapping on overflow conditions). The operation is undefined if the 166 sum would be negative and should be handled as described in Section 167 2.9.2. For DrawRangeElementsBaseVertex, the index values must lie 168 between <start> and <end> inclusive, prior to adding the 169 <basevertex> offset. Index values lying outside the range 170 [<start>,<end>] are treated in the same way as DrawRangeElements. 171 172 The command 173 174 void MultiDrawElementsBaseVertex(enum mode, const sizei *count, 175 enum type, const void *const *indices, sizei drawcount, const int *basevertex); 176 177 behaves identically to DrawElementsBaseVertex except that 178 <drawcount> separate lists of elements are specified instead. It has 179 the same effect as: 180 181 for (i = 0; i < drawcount; i++) { 182 if (count[i] > 0) 183 DrawElementsBaseVertex(mode, count[i], type, indices[i], 184 basevertex[i]); 185 }" 186 187 188 In Section 2.9.5 "Array Indices in Buffer Offer Objects" add 189 references to the new drawing commands. 190 191 In the third paragraph, replace the second sentence (which begins 192 with "MultiDrawElements also sources...") with the following 193 sentences: 194 195 "DrawElementsBaseVertex, DrawRangeElementsBaseVertex, and 196 DrawElementsInstancedBaseVertex also source their vertices from that 197 buffer object, adding the <basevertex> offset to the appropriate 198 vertex index as a final step before indexing into the vertex buffer; 199 this does not affect the calculation of the base pointer for the 200 index array. Finally, MultiDrawElements and 201 MultiDrawElementsBaseVertex also source their indices from that 202 buffer object, using its <indices> parameter as a pointer to an 203 array of pointers that represet offsets into the buffer object." 204 205Additions to Chapter 3 of the OpenGL 3.1 Specification (Rasterization) 206 207 None 208 209Additions to Chapter 4 of the OpenGL 3.1 Specification (Per-Fragment 210Operations and the Frame Buffer) 211 212 None 213 214Additions to Chapter 5 of the OpenGL 3.1 Specification (Special 215Functions) 216 217 None 218 219Additions to Chapter 6 of the OpenGL 3.1 Specification (State and 220State Requests) 221 222 None 223 224Additions to the AGL/GLX/WGL Specifications 225 226 None 227 228Dependencies on OpenGL 3.1 229 230 If OpenGL 3.1 is not supported, ignore all references to 231 DrawElementsInstanced and DrawElementsInstancedBaseVertex 232 233Dependencies on the ARB_draw_instanced extension 234 235 If ARB_draw_instanced is supported, the functionality provided by 236 DrawElementsInstancedBaseVertex can also be described in terms of 237 DrawElementsInstancedARB instead of DrawElementsInstanced. 238 239Dependencies on the EXT_draw_instanced extension 240 241 If EXT_draw_instanced is supported, the functionality provided by 242 DrawElementsInstancedBaseVertex can also be described in terms of 243 DrawElementsInstancedEXT instead of DrawElementsInstanced. 244 245Dependencies on the ARB_instanced_arrays extension 246 247 If ARB_instanced_arrays is supported, the functionality provided by 248 DrawElementsInstancedBaseVertex can also be described in 249 terms of DrawElementsInstancedARB instead of DrawElementsInstanced. 250 251Dependencies on the ARB_compatibility extension 252 253 When the ARB_compatibility extension is supported, the base vertex 254 functionality applies to both buffer objects and client-side vertex 255 arrays. Additionally there may be some textual differences in the 256 specification because the behaviour of DrawElements is defined in 257 terms of ArrayElement, but the functionality remains the same. Note 258 in particular the interaction with the primitive restart index as 259 identified in Issue 5. 260 261 When ARB_compatibility is supported edit the first bullet point of 262 the "Shader Inputs" subsection of Section 2.14.7 "Shader Execution" 263 and replace the language enumerating the drawing commands which 264 specify a complete primitive for the purposes of defining 265 gl_VertexID to be more general purpose: 266 "(a vertex array drawing command other than ArrayElement)." 267 268Errors 269 270 The *BaseVertex commands have identical error conditions to the 271 non-*BaseVertex functions, and all values of <basevertex> are legal 272 (with the exception of ones which cause accesses outside of vertex 273 arrays or bound buffers as described in Section 2.9.2). 274 275New State 276 277 None 278 279New Implementation Dependent State 280 281 None 282 283Issues 284 285 1. What should this extension be called? 286 287 RESOLVED: Using ARB_draw_elements_base_vertex. 288 289 DISCUSSION: Using the base "draw_elements" since this extension 290 adds a new variant to the DrawElements family of commands which 291 takes an additional parameter. Since the new suffix on the 292 drawing commands is "BaseVertex" it makes sense to call this 293 "draw_elements_base_vertex" (and it is more aesthetically 294 pleasing then "draw_elements_basevertex". 295 296 Initial versions of this extension were called 297 "draw_elements_offset" (see Issue 9). 298 299 Other alternatives considered: index_offset or element_offset. 300 These variants might have been more suitable if we had used a 301 different mechanism for specifying the base vertex offset (see 302 Issue 2). 303 304 2. Should we have a per-draw call parameter or should this be 305 specified via some other mechanism (ELEMENT_ARRAY bind parameter, 306 global state, etc). 307 308 RESOLVED. Using per-draw call. 309 310 DISCUSSION: If per-draw call we need entry points to specify the 311 equivalent of DrawElements, DrawRangeElements, 312 DrawElementsInstanced and possibly MultiDrawElements, but with an 313 additional parameter. 314 315 Per binding point, such as 316 glBindBufferBaseVertex(ELEMENT_ARRAY_BUFFER, id, 1234)? If 317 per-ELEMENT_ARRAY binding point, the application will need to 318 rebind the index buffer every time they wish to adjust the 319 basevertex, which partially defeats the purpose of this 320 extension. As well this would make it more difficult to support 321 client arrays in an implementation which supports 322 ARB_compatibility. 323 324 If this is a global state, should it be server or client state? 325 Is it per-gc? We could have a separate API call, e.g. 326 glIndexOffset(1234), that would be per-VAO. This method doesn't 327 require rebinding buffers and would work fine for client vertex 328 arrays. In many ways though having a global state doesn't make 329 much sense, since it is may only relevant for a single draw call, 330 and encapsulating this in the VAO-state may mean that additional 331 VAO must be created. 332 333 3. This functionality seems vaguely familiar. Do any other APIs have 334 this functionality? 335 336 YES. This is equivalent to the BaseVertexIndex (d3d9) or 337 BaseVertexLocation (d3d10) indexed drawing parameters in 338 Direct3D. 339 340 4. Should there be a MultiDrawElementsBaseVertex? If so, should it 341 take a single basevertex or an array of them? 342 343 RESOLVED: YES. Let's add it for completeness. It seems to make 344 the most sense to pass in an array of basevertex parameters for 345 this command, as this provides the most flexibility, and it works 346 well to define it in terms of DrawElementsBaseVertex. 347 348 5. What are the interactions with primitive restart? 349 350 RESOLVED. The primitive restart comparison occurs before adding 351 the basevertex. 352 353 DISCUSSION: 354 DX10 and existing hardware do the primitive restart comparison 355 before adding the basevertex. It's really the only sane thing to 356 do, otherwise the app would have to change the restartindex to 357 depend on the basevertex. 358 359 This is counterintuitively not the result you would get if 360 DrawElements were still defined in terms of ArrayElement and you 361 defined these in the natural way 362 (ArrayElement(indices[i]+basevertex)), but this is likely what 363 developers want and also what the hardware does. 364 365 6. What happens if indices[i]+basevertex is larger than the max 366 value representable by <type>. 367 368 RESOLVED. Behave as if everything is upconverted to 32-bit 369 unsigned integers. If the addition over/underflows 32-bits, it 370 wraps. This is the behaviour D3D10 uses and likely how it is 371 implemented in hardware. 372 373 7. What happens if the sum is negative (ie indices[i]+basevertex < 0)? 374 375 RESOLVED: Undefined. This should be handled the same way as a 376 buffer that accesses out of bounds data. This is defined in 377 Section 2.9.2 "Effects of Accessing Outside of Buffer Bounds". If 378 detected this results in a GL error, otherwise it has undefined 379 results and may result in GL interruption or termination. This is 380 also undefined under Direct3D. 381 382 8. For DrawRangeElementsBaseVertex, is the intent that indices[i] 383 are all in [start,end] and not indices[i]+basevertex? 384 385 RESOLVED: YES, indices[i] must be in the range [start,end]. 386 387 DISCUSSION: There doesn't appear to be a hardware or driver 388 reason to prefer one interpretation over the other. D3D9 treats 389 the MinIndex parameter to the DrawIndexedPrimitive call as 390 relative to the index buffer, so in the interests of 391 compatibility we will make the same choice. 392 393 9. The word "offset" sounds like it should be measured in bytes. Is 394 there a better term we could use for this? 395 396 RESOLVED: Use "BaseVertex" and call the parameter <basevertex>. 397 398 BACKGROUND: 399 Initial drafts of this extension used the suffix "Offset" on the 400 DrawElement calls, and the new parameter was named 401 "vertexoffset". 402 403 DISCUSSION: What other term could we use? 404 405 Possibly something with "base" in it, partly because DX has that 406 in the name and partly because it reminds one of ListBase and 407 texture base level. However it does conflict with the meaning of 408 "base" in BindBufferBase... 409 410 10. Clarification is needed when using an ELEMENT_ARRAY_BUFFER, since 411 <indices> is actually an offset into a VBO rather than an array 412 itself. 413 414 DISCUSSION: When ELEMENT_ARRAY_BUFFERS are used to provide the 415 index data (as they must be in GL 3.1 without the 416 ARB_compatibility extension) the <indices> parameters to the 417 DrawElements calls are treated as offsets into the buffer objects 418 as described in Sections 2.9.4 and 2.9.5. 419 420 Logically this is as if a <realindices> array were computed as 421 follows: <type> realindices = (<type>)((byte)bufferptr + 422 ((byte)indices - (byte)NULL)) 423 424 Then base vertex offset is then computed as "realindices[i] + 425 basevertex" 426 427 11. Why do the new function entry points in this extension not have 428 the "ARB" suffixes like other ARB extensions? 429 430 RESOLVED: This extension is a strict subset of the functionality 431 already in OpenGL 3.2. This extension exists only to support that 432 functionality on older versions of OpenGL and on hardware which 433 is not OpenGL 3.x capable. Since there are no possible behavior 434 changes between the ARB extension and core features, source code 435 compatibility is improved by not using suffixes on the extension. 436 437Revision History 438 439 Rev. Date Author Changes 440 ---- -------- --------- ---------------------------------------- 441 0.1 4/29/09 dgkoch initial skeleton 442 0.2 4/30/09 dgkoch first cut at per-draw call spec 443 0.3 4/30/09 dgkoch add issues 4-10, fix some typos and error in the example 444 based on comments from JB, BM 445 0.4 5/06/09 dgkoch resolved issue 2, sticking with per-draw call 446 resolved issue 4, add MultiDrawElementsBaseVertex w/ array 447 resolved issue 5, primitive restart compare happens first 448 resolved issue 6, behave as if 32-bit, including wrapping 449 resolved issue 7, undefined behaviour 450 resolved issue 8, indices[i] lies in the range [start,end] 451 sugggested resolution for issue 9: "BaseVertex" 452 clarified issue 10 453 misc formatting and typo fixes 454 0.5 5/07/09 dgkoch flipped y-coord in example 455 fixed spacing and typos 456 added more disscussion to Issue 2 457 removed clause from Issue 7 which contradicted Issue 6 458 0.6 5/15/09 dgkoch add resolution to issue 9, and rename appropriately 459 resolve issue 1 460 add interactions/dependencies 461 minor updates to the overview 462 update textual edits to reflect issues 5-8, 10 463 add issue 11 464 0.7 5/18/09 dgkoch minor grammer, spelling and typographical errors 465 Add interaction with ARB_compatibility 466 1 6/26/09 dgkoch resync language with GL3.2 spec 467 Add more interactions with ARB_compatibility 468 2 7/21/09 dgkoch resync language with 20090630 3.2 spec 469 3 8/02/09 Jon Leech Reformat to 80 columns and assign ARB 470 extension number. 471 4 8/22/19 N Stewart Parameter naming and const aligned to 4.6 core spec. 472