• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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