• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1Name
2
3    NV_bindless_multi_draw_indirect
4
5Name Strings
6
7    GL_NV_bindless_multi_draw_indirect
8
9Contact
10
11    Christoph Kubisch, NVIDIA (ckubisch 'at' nvidia.com)
12
13Contributors
14
15    Jeff Bolz, NVIDIA
16    Piers Daniell, NVIDIA
17    Markus Tavenrath, NVIDIA
18    Eric Werness, NVIDIA
19    Vincent Zhang, NVIDIA
20
21Status
22
23    Complete
24
25Version
26
27    Last Modified Date: July 3rd, 2015
28    Revision: 3
29
30Number
31
32    OpenGL Extension #432
33
34Dependencies
35
36    NV_vertex_buffer_unified_memory is required.
37
38    OpenGL 4.3 or ARB_multi_draw_indirect is required.
39
40    The extension is written against the OpenGL 4.3 Specification, Core Profile.
41
42Overview
43
44    This extension combines NV_vertex_buffer_unified_memory and
45    ARB_multi_draw_indirect to allow the processing of multiple drawing
46    commands, whose vertex and index data can be sourced from arbitrary
47    buffer locations, by a single function call.
48
49    The NV_vertex_buffer_unified_memory extension provided a mechanism to
50    specify vertex attrib and element array locations using GPU addresses.
51    Prior to this extension, these addresses had to be set through explicit
52    function calls. Now the ability to set the pointer addresses indirectly
53    by extending the GL_ARB_draw_indirect mechanism has been added.
54
55    Combined with other "bindless" extensions, such as NV_bindless_texture and
56    NV_shader_buffer_load, it is now possible for the GPU to create draw
57    commands that source all resource inputs, which are common to change
58    frequently between draw calls from the GPU: vertex and index buffers,
59    samplers, images and other shader input data stored in buffers.
60
61
62New Procedures and Functions
63
64        void MultiDrawArraysIndirectBindlessNV(enum mode,
65                                               const void *indirect,
66                                               sizei drawCount,
67                                               sizei stride,
68                                               int vertexBufferCount);
69
70        void MultiDrawElementsIndirectBindlessNV(enum mode,
71                                                 enum type,
72                                                 const void *indirect,
73                                                 sizei drawCount,
74                                                 sizei stride,
75                                                 int vertexBufferCount);
76
77New Tokens
78
79    None.
80
81Additions to Chapter 10 of the OpenGL 4.3 (Core) Specification (Vertex
82Specification and Drawing Commands)
83
84    Additions to Section 10.5, "Drawing Commands Using Vertex Arrays"
85
86    After the description of MultiDrawArraysIndirect and before the introduction of
87    DrawElementsOneInstance, insert the following on p.311:
88
89        The command
90
91        void MultiDrawArraysIndirectBindlessNV(enum mode,
92                                               const void *indirect,
93                                               sizei drawCount,
94                                               sizei stride,
95                                               int vertexBufferCount);
96
97    behaves similar to MultiDrawArraysIndirect, except that <indirect> is
98    treated as an array of <drawCount> DrawArraysIndirectBindlessCommandNV
99    structures.
100
101    It has the same effect as:
102
103        typedef struct {
104          GLuint   index;
105          GLuint   reserved;
106          GLuint64 address;
107          GLuint64 length;
108        } BindlessPtrNV;
109
110        typedef struct {
111          DrawArraysIndirectCommand   cmd;
112          BindlessPtrNV               vertexBuffers[];
113        } DrawArraysIndirectBindlessCommandNV;
114
115        if (<mode> is invalid)
116            generate appropriate error
117        else {
118            GLuint64 vtxAddresses[MAX_VERTEX_ATTRIBS];
119            GLsizeiptr vtxLengths[MAX_VERTEX_ATTRIBS];
120            for (i = 0; i < MAX_VERTEX_ATTRIBS) {
121              GetIntegerui64i_vNV(VERTEX_ATTRIB_ARRAY_ADDRESS_NV,i,&vtxAddresses[i]);
122              GetInteger64i_v(VERTEX_ATTRIB_ARRAY_LENGTH_NV ,i,&vtxLengths[i]);
123            }
124
125            const ubyte * ptr = (const ubyte *)indirect;
126            for (i = 0; i < drawCount; i++) {
127                const DrawArraysIndirectBindlessCommandNV* cmdNV =
128                              (DrawArraysIndirectBindlessCommandNV*)ptr;
129
130                if ( cmdNV->cmd.instanceCount != 0 ){
131                    for (n = 0; n < vertexBufferCount; n++){
132                      BufferAddressRangeNV(VERTEX_ATTRIB_ARRAY_ADDRESS_NV,
133                                           cmdNV->vertexBuffers[n].index
134                                           cmdNV->vertexBuffers[n].address,
135                                           cmdNV->vertexBuffers[n].length);
136                    }
137
138                    DrawArraysIndirect(mode,
139                                       (DrawArraysIndirectCommand*)ptr);
140                }
141                if (stride == 0)
142                {
143                    ptr +=  sizeof(DrawArraysIndirectCommand) +
144                           (sizeof(BindlessPtrNV) * vertexBufferCount);
145                } else
146                {
147                    ptr += stride;
148                }
149            }
150
151            for (i = 0; i < MAX_VERTEX_ATTRIBS) {
152              BufferAddressRangeNV(VERTEX_ATTRIB_ARRAY_ADDRESS_NV,i,vtxAddresses[i],vtxLengths[i]);
153            }
154        }
155
156    <drawCount> must be positive, otherwise an INVALID_VALUE error will be
157    generated.
158
159    After the description of MultiDrawElementsIndirect and before the introduction
160    of MultiDrawElementsBaseVertex, insert the following on p.316:
161
162        The command
163
164        void MultiDrawElementsIndirectBindlessNV(enum mode,
165                                                 enum type,
166                                                 const void *indirect,
167                                                 sizei drawCount,
168                                                 sizei stride,
169                                                 int vertexBufferCount);
170
171    behaves similar to MultiDrawElementsIndirect, except that <indirect> is
172    treated as an array of <drawCount> DrawElementsIndirectBindlessCommandNV
173    structures.
174
175    It has the same effect as:
176
177        typedef struct {
178          GLuint   index;
179          GLuint   reserved;
180          GLuint64 address;
181          GLuint64 length;
182        } BindlessPtrNV;
183
184        typedef struct {
185          DrawElementsIndirectCommand cmd;
186          GLuint                      reserved;
187          BindlessPtrNV               indexBuffer;
188          BindlessPtrNV               vertexBuffers[];
189        } DrawElementsIndirectBindlessCommandNV;
190
191        if (<mode> or <type> is invalid)
192            generate appropriate error
193        else {
194            GLuint64   idxAddress;
195            GLsizeiptr idxLength;
196            GetIntegerui64vNV(ELEMENT_ARRAY_ADDRESS_NV,&idxAddress);
197            GetInteger64v(ELEMENT_ARRAY_LENGTH_NV,&idxLength);
198
199            GLuint64 vtxAddresses[MAX_VERTEX_ATTRIBS];
200            GLsizeiptr vtxLengths[MAX_VERTEX_ATTRIBS];
201            for (i = 0; i < MAX_VERTEX_ATTRIBS) {
202              GetIntegerui64i_vNV(VERTEX_ATTRIB_ARRAY_ADDRESS_NV,i,&vtxAddresses[i]);
203              GetInteger64i_v(VERTEX_ATTRIB_ARRAY_LENGTH_NV ,i,&vtxLengths[i]);
204            }
205
206            const ubyte * ptr = (const ubyte *)indirect;
207            for (i = 0; i < primcount; i++) {
208                const DrawElementsIndirectBindlessCommandNV* cmdNV =
209                              (DrawElementsIndirectBindlessCommandNV*)ptr;
210
211                if ( cmdNV->cmd.instanceCount != 0 ) {
212                    BufferAddressRangeNV(ELEMENT_ARRAY_ADDRESS_NV,
213                                         0,
214                                         cmdNV->indexBuffer.address,
215                                         cmdNV->indexBuffer.length);
216
217                    for (n = 0; n < vertexBufferCount; n++){
218                      BufferAddressRangeNV(VERTEX_ATTRIB_ARRAY_ADDRESS_NV,
219                                           cmdNV->vertexBuffers[n].index
220                                           cmdNV->vertexBuffers[n].address,
221                                           cmdNV->vertexBuffers[n].length);
222                    }
223
224                    DrawElementsIndirect(mode,
225                                         type,
226                                         (DrawElementsIndirectCommand*)ptr);
227                }
228
229                if (stride == 0)
230                {
231                    ptr +=  sizeof(DrawElementsIndirectCommand) +
232                            sizeof(GLuint) +
233                            sizeof(BindlessPtrNV) +
234                           (sizeof(BindlessPtrNV) * vertexBufferCount);
235                } else
236                {
237                    ptr += stride;
238                }
239            }
240
241            BufferAddressRangeNV(ELEMENT_ARRAY_ADDRESS_NV,0,idxAddress,idxLengths);
242            for (i = 0; i < MAX_VERTEX_ATTRIBS) {
243              BufferAddressRangeNV(VERTEX_ATTRIB_ARRAY_ADDRESS_NV,i,vtxAddresses[i],vtxLengths[i]);
244            }
245        }
246
247    Modifications to Section 10.3.10 (p. 305) "Indirect Commands in Buffer Objects"
248
249    Modify both instances of "DrawArraysIndirect, DrawElementsIndirect,
250    MultiDrawArraysIndirect and MultiDrawElementsIndirect" on
251    p. 305 to read "DrawArraysIndirect, DrawElementsIndirect,
252    MultiDrawArraysIndirect, MultiDrawElementsIndirect,
253    MultiDrawArraysIndirectBindlessNV and MultiDrawElementsIndirectBindlessNV".
254
255
256Additions to the AGL/GLX/WGL Specifications
257
258    None.
259
260GLX Protocol
261
262    None.
263
264Errors
265
266    INVALID_VALUE is generated by MultiDrawArraysIndirectBindlessNV or
267    MultiDrawElementsIndirectBindlessNV if <drawCount> is negative.
268
269    INVALID_VALUE is generated by MultiDrawArraysIndirectBindlessNV or
270    MultiDrawElementsIndirectBindlessNV if <stride> is not a multipe of eight.
271
272    INVALID_OPERATION is generated by MultiDrawArraysIndirectBindlessNV or
273    MultiDrawElementsIndirectBindlessNV if the
274    VERTEX_ATTRIB_ARRAY_UNIFIED_NV client state is not enabled.
275
276    INVALID_OPERATION is generated by MultiDrawElementsIndirectBindlessNV
277    if the ELEMENT_ARRAY_UNIFIED_NV client state is not enabled.
278
279New State
280
281    None.
282
283New Implementation Dependent State
284
285    None.
286
287Issues
288
289    1) BufferAddressRangeNV is defined to take GLsizeiptr as length.
290       Should the length parameter inside the indirect structure be cast
291       to GLsizeiptr when passed as argument?
292
293    RESOLVED: When the indirect buffer is stored in host memory, the cast
294    should be performed, otherwise, 64-bit should be assumed.
295
296    2) BufferAddressRangeNV also covered fixed function vertex state, should
297       this be exposed in this extension?
298
299    NO, the named attributes aren't necessary, as it is very likely that
300    shaders are used to also handle the parameters of individual drawcalls.
301    For fixed function shading the interleaving of related state changes
302    with drawcalls would already be efficiently handled by regular
303    MultiDraw or NV_vertex_buffer_unified_memory functionality.
304
305    3) In which state should the vertex/index pointers be left after the
306       execution of the command?
307
308    RESOLVED: All pointers should be reset to what was last
309    specified by the client side using BufferAddressRangeNV.
310
311    4) How does this extension relate to the newer NV_command_list?
312
313    NV_command_list provides a more flexible draw indirect mechnanism. It
314    can be more efficient if there are redundancies in the vertex and index
315    buffer addresses, as it allows specifying addresses and drawcalls with
316    different frequencies in the command stream.
317
318Revision History
319
320    Rev.    Date      Author    Changes
321    ----  --------    --------  -----------------------------------------
322     1                ckubisch  Internal revisions
323     2    1/5/2015    ckubisch  bugfix, remove of "reserved" in
324                                DrawArraysIndirectBindlessCommandNV
325                                added reference to NV_command_list
326     3    7/3/2015    ckubisch  bugfix, wrong math used in the "if (stride == 0)"
327                                pointer advancing. GLsizeiptr for length instead of
328                                GLuint64