15bd8deadSopenharmony_ciName 25bd8deadSopenharmony_ci 35bd8deadSopenharmony_ci NV_bindless_multi_draw_indirect 45bd8deadSopenharmony_ci 55bd8deadSopenharmony_ciName Strings 65bd8deadSopenharmony_ci 75bd8deadSopenharmony_ci GL_NV_bindless_multi_draw_indirect 85bd8deadSopenharmony_ci 95bd8deadSopenharmony_ciContact 105bd8deadSopenharmony_ci 115bd8deadSopenharmony_ci Christoph Kubisch, NVIDIA (ckubisch 'at' nvidia.com) 125bd8deadSopenharmony_ci 135bd8deadSopenharmony_ciContributors 145bd8deadSopenharmony_ci 155bd8deadSopenharmony_ci Jeff Bolz, NVIDIA 165bd8deadSopenharmony_ci Piers Daniell, NVIDIA 175bd8deadSopenharmony_ci Markus Tavenrath, NVIDIA 185bd8deadSopenharmony_ci Eric Werness, NVIDIA 195bd8deadSopenharmony_ci Vincent Zhang, NVIDIA 205bd8deadSopenharmony_ci 215bd8deadSopenharmony_ciStatus 225bd8deadSopenharmony_ci 235bd8deadSopenharmony_ci Complete 245bd8deadSopenharmony_ci 255bd8deadSopenharmony_ciVersion 265bd8deadSopenharmony_ci 275bd8deadSopenharmony_ci Last Modified Date: July 3rd, 2015 285bd8deadSopenharmony_ci Revision: 3 295bd8deadSopenharmony_ci 305bd8deadSopenharmony_ciNumber 315bd8deadSopenharmony_ci 325bd8deadSopenharmony_ci OpenGL Extension #432 335bd8deadSopenharmony_ci 345bd8deadSopenharmony_ciDependencies 355bd8deadSopenharmony_ci 365bd8deadSopenharmony_ci NV_vertex_buffer_unified_memory is required. 375bd8deadSopenharmony_ci 385bd8deadSopenharmony_ci OpenGL 4.3 or ARB_multi_draw_indirect is required. 395bd8deadSopenharmony_ci 405bd8deadSopenharmony_ci The extension is written against the OpenGL 4.3 Specification, Core Profile. 415bd8deadSopenharmony_ci 425bd8deadSopenharmony_ciOverview 435bd8deadSopenharmony_ci 445bd8deadSopenharmony_ci This extension combines NV_vertex_buffer_unified_memory and 455bd8deadSopenharmony_ci ARB_multi_draw_indirect to allow the processing of multiple drawing 465bd8deadSopenharmony_ci commands, whose vertex and index data can be sourced from arbitrary 475bd8deadSopenharmony_ci buffer locations, by a single function call. 485bd8deadSopenharmony_ci 495bd8deadSopenharmony_ci The NV_vertex_buffer_unified_memory extension provided a mechanism to 505bd8deadSopenharmony_ci specify vertex attrib and element array locations using GPU addresses. 515bd8deadSopenharmony_ci Prior to this extension, these addresses had to be set through explicit 525bd8deadSopenharmony_ci function calls. Now the ability to set the pointer addresses indirectly 535bd8deadSopenharmony_ci by extending the GL_ARB_draw_indirect mechanism has been added. 545bd8deadSopenharmony_ci 555bd8deadSopenharmony_ci Combined with other "bindless" extensions, such as NV_bindless_texture and 565bd8deadSopenharmony_ci NV_shader_buffer_load, it is now possible for the GPU to create draw 575bd8deadSopenharmony_ci commands that source all resource inputs, which are common to change 585bd8deadSopenharmony_ci frequently between draw calls from the GPU: vertex and index buffers, 595bd8deadSopenharmony_ci samplers, images and other shader input data stored in buffers. 605bd8deadSopenharmony_ci 615bd8deadSopenharmony_ci 625bd8deadSopenharmony_ciNew Procedures and Functions 635bd8deadSopenharmony_ci 645bd8deadSopenharmony_ci void MultiDrawArraysIndirectBindlessNV(enum mode, 655bd8deadSopenharmony_ci const void *indirect, 665bd8deadSopenharmony_ci sizei drawCount, 675bd8deadSopenharmony_ci sizei stride, 685bd8deadSopenharmony_ci int vertexBufferCount); 695bd8deadSopenharmony_ci 705bd8deadSopenharmony_ci void MultiDrawElementsIndirectBindlessNV(enum mode, 715bd8deadSopenharmony_ci enum type, 725bd8deadSopenharmony_ci const void *indirect, 735bd8deadSopenharmony_ci sizei drawCount, 745bd8deadSopenharmony_ci sizei stride, 755bd8deadSopenharmony_ci int vertexBufferCount); 765bd8deadSopenharmony_ci 775bd8deadSopenharmony_ciNew Tokens 785bd8deadSopenharmony_ci 795bd8deadSopenharmony_ci None. 805bd8deadSopenharmony_ci 815bd8deadSopenharmony_ciAdditions to Chapter 10 of the OpenGL 4.3 (Core) Specification (Vertex 825bd8deadSopenharmony_ciSpecification and Drawing Commands) 835bd8deadSopenharmony_ci 845bd8deadSopenharmony_ci Additions to Section 10.5, "Drawing Commands Using Vertex Arrays" 855bd8deadSopenharmony_ci 865bd8deadSopenharmony_ci After the description of MultiDrawArraysIndirect and before the introduction of 875bd8deadSopenharmony_ci DrawElementsOneInstance, insert the following on p.311: 885bd8deadSopenharmony_ci 895bd8deadSopenharmony_ci The command 905bd8deadSopenharmony_ci 915bd8deadSopenharmony_ci void MultiDrawArraysIndirectBindlessNV(enum mode, 925bd8deadSopenharmony_ci const void *indirect, 935bd8deadSopenharmony_ci sizei drawCount, 945bd8deadSopenharmony_ci sizei stride, 955bd8deadSopenharmony_ci int vertexBufferCount); 965bd8deadSopenharmony_ci 975bd8deadSopenharmony_ci behaves similar to MultiDrawArraysIndirect, except that <indirect> is 985bd8deadSopenharmony_ci treated as an array of <drawCount> DrawArraysIndirectBindlessCommandNV 995bd8deadSopenharmony_ci structures. 1005bd8deadSopenharmony_ci 1015bd8deadSopenharmony_ci It has the same effect as: 1025bd8deadSopenharmony_ci 1035bd8deadSopenharmony_ci typedef struct { 1045bd8deadSopenharmony_ci GLuint index; 1055bd8deadSopenharmony_ci GLuint reserved; 1065bd8deadSopenharmony_ci GLuint64 address; 1075bd8deadSopenharmony_ci GLuint64 length; 1085bd8deadSopenharmony_ci } BindlessPtrNV; 1095bd8deadSopenharmony_ci 1105bd8deadSopenharmony_ci typedef struct { 1115bd8deadSopenharmony_ci DrawArraysIndirectCommand cmd; 1125bd8deadSopenharmony_ci BindlessPtrNV vertexBuffers[]; 1135bd8deadSopenharmony_ci } DrawArraysIndirectBindlessCommandNV; 1145bd8deadSopenharmony_ci 1155bd8deadSopenharmony_ci if (<mode> is invalid) 1165bd8deadSopenharmony_ci generate appropriate error 1175bd8deadSopenharmony_ci else { 1185bd8deadSopenharmony_ci GLuint64 vtxAddresses[MAX_VERTEX_ATTRIBS]; 1195bd8deadSopenharmony_ci GLsizeiptr vtxLengths[MAX_VERTEX_ATTRIBS]; 1205bd8deadSopenharmony_ci for (i = 0; i < MAX_VERTEX_ATTRIBS) { 1215bd8deadSopenharmony_ci GetIntegerui64i_vNV(VERTEX_ATTRIB_ARRAY_ADDRESS_NV,i,&vtxAddresses[i]); 1225bd8deadSopenharmony_ci GetInteger64i_v(VERTEX_ATTRIB_ARRAY_LENGTH_NV ,i,&vtxLengths[i]); 1235bd8deadSopenharmony_ci } 1245bd8deadSopenharmony_ci 1255bd8deadSopenharmony_ci const ubyte * ptr = (const ubyte *)indirect; 1265bd8deadSopenharmony_ci for (i = 0; i < drawCount; i++) { 1275bd8deadSopenharmony_ci const DrawArraysIndirectBindlessCommandNV* cmdNV = 1285bd8deadSopenharmony_ci (DrawArraysIndirectBindlessCommandNV*)ptr; 1295bd8deadSopenharmony_ci 1305bd8deadSopenharmony_ci if ( cmdNV->cmd.instanceCount != 0 ){ 1315bd8deadSopenharmony_ci for (n = 0; n < vertexBufferCount; n++){ 1325bd8deadSopenharmony_ci BufferAddressRangeNV(VERTEX_ATTRIB_ARRAY_ADDRESS_NV, 1335bd8deadSopenharmony_ci cmdNV->vertexBuffers[n].index 1345bd8deadSopenharmony_ci cmdNV->vertexBuffers[n].address, 1355bd8deadSopenharmony_ci cmdNV->vertexBuffers[n].length); 1365bd8deadSopenharmony_ci } 1375bd8deadSopenharmony_ci 1385bd8deadSopenharmony_ci DrawArraysIndirect(mode, 1395bd8deadSopenharmony_ci (DrawArraysIndirectCommand*)ptr); 1405bd8deadSopenharmony_ci } 1415bd8deadSopenharmony_ci if (stride == 0) 1425bd8deadSopenharmony_ci { 1435bd8deadSopenharmony_ci ptr += sizeof(DrawArraysIndirectCommand) + 1445bd8deadSopenharmony_ci (sizeof(BindlessPtrNV) * vertexBufferCount); 1455bd8deadSopenharmony_ci } else 1465bd8deadSopenharmony_ci { 1475bd8deadSopenharmony_ci ptr += stride; 1485bd8deadSopenharmony_ci } 1495bd8deadSopenharmony_ci } 1505bd8deadSopenharmony_ci 1515bd8deadSopenharmony_ci for (i = 0; i < MAX_VERTEX_ATTRIBS) { 1525bd8deadSopenharmony_ci BufferAddressRangeNV(VERTEX_ATTRIB_ARRAY_ADDRESS_NV,i,vtxAddresses[i],vtxLengths[i]); 1535bd8deadSopenharmony_ci } 1545bd8deadSopenharmony_ci } 1555bd8deadSopenharmony_ci 1565bd8deadSopenharmony_ci <drawCount> must be positive, otherwise an INVALID_VALUE error will be 1575bd8deadSopenharmony_ci generated. 1585bd8deadSopenharmony_ci 1595bd8deadSopenharmony_ci After the description of MultiDrawElementsIndirect and before the introduction 1605bd8deadSopenharmony_ci of MultiDrawElementsBaseVertex, insert the following on p.316: 1615bd8deadSopenharmony_ci 1625bd8deadSopenharmony_ci The command 1635bd8deadSopenharmony_ci 1645bd8deadSopenharmony_ci void MultiDrawElementsIndirectBindlessNV(enum mode, 1655bd8deadSopenharmony_ci enum type, 1665bd8deadSopenharmony_ci const void *indirect, 1675bd8deadSopenharmony_ci sizei drawCount, 1685bd8deadSopenharmony_ci sizei stride, 1695bd8deadSopenharmony_ci int vertexBufferCount); 1705bd8deadSopenharmony_ci 1715bd8deadSopenharmony_ci behaves similar to MultiDrawElementsIndirect, except that <indirect> is 1725bd8deadSopenharmony_ci treated as an array of <drawCount> DrawElementsIndirectBindlessCommandNV 1735bd8deadSopenharmony_ci structures. 1745bd8deadSopenharmony_ci 1755bd8deadSopenharmony_ci It has the same effect as: 1765bd8deadSopenharmony_ci 1775bd8deadSopenharmony_ci typedef struct { 1785bd8deadSopenharmony_ci GLuint index; 1795bd8deadSopenharmony_ci GLuint reserved; 1805bd8deadSopenharmony_ci GLuint64 address; 1815bd8deadSopenharmony_ci GLuint64 length; 1825bd8deadSopenharmony_ci } BindlessPtrNV; 1835bd8deadSopenharmony_ci 1845bd8deadSopenharmony_ci typedef struct { 1855bd8deadSopenharmony_ci DrawElementsIndirectCommand cmd; 1865bd8deadSopenharmony_ci GLuint reserved; 1875bd8deadSopenharmony_ci BindlessPtrNV indexBuffer; 1885bd8deadSopenharmony_ci BindlessPtrNV vertexBuffers[]; 1895bd8deadSopenharmony_ci } DrawElementsIndirectBindlessCommandNV; 1905bd8deadSopenharmony_ci 1915bd8deadSopenharmony_ci if (<mode> or <type> is invalid) 1925bd8deadSopenharmony_ci generate appropriate error 1935bd8deadSopenharmony_ci else { 1945bd8deadSopenharmony_ci GLuint64 idxAddress; 1955bd8deadSopenharmony_ci GLsizeiptr idxLength; 1965bd8deadSopenharmony_ci GetIntegerui64vNV(ELEMENT_ARRAY_ADDRESS_NV,&idxAddress); 1975bd8deadSopenharmony_ci GetInteger64v(ELEMENT_ARRAY_LENGTH_NV,&idxLength); 1985bd8deadSopenharmony_ci 1995bd8deadSopenharmony_ci GLuint64 vtxAddresses[MAX_VERTEX_ATTRIBS]; 2005bd8deadSopenharmony_ci GLsizeiptr vtxLengths[MAX_VERTEX_ATTRIBS]; 2015bd8deadSopenharmony_ci for (i = 0; i < MAX_VERTEX_ATTRIBS) { 2025bd8deadSopenharmony_ci GetIntegerui64i_vNV(VERTEX_ATTRIB_ARRAY_ADDRESS_NV,i,&vtxAddresses[i]); 2035bd8deadSopenharmony_ci GetInteger64i_v(VERTEX_ATTRIB_ARRAY_LENGTH_NV ,i,&vtxLengths[i]); 2045bd8deadSopenharmony_ci } 2055bd8deadSopenharmony_ci 2065bd8deadSopenharmony_ci const ubyte * ptr = (const ubyte *)indirect; 2075bd8deadSopenharmony_ci for (i = 0; i < primcount; i++) { 2085bd8deadSopenharmony_ci const DrawElementsIndirectBindlessCommandNV* cmdNV = 2095bd8deadSopenharmony_ci (DrawElementsIndirectBindlessCommandNV*)ptr; 2105bd8deadSopenharmony_ci 2115bd8deadSopenharmony_ci if ( cmdNV->cmd.instanceCount != 0 ) { 2125bd8deadSopenharmony_ci BufferAddressRangeNV(ELEMENT_ARRAY_ADDRESS_NV, 2135bd8deadSopenharmony_ci 0, 2145bd8deadSopenharmony_ci cmdNV->indexBuffer.address, 2155bd8deadSopenharmony_ci cmdNV->indexBuffer.length); 2165bd8deadSopenharmony_ci 2175bd8deadSopenharmony_ci for (n = 0; n < vertexBufferCount; n++){ 2185bd8deadSopenharmony_ci BufferAddressRangeNV(VERTEX_ATTRIB_ARRAY_ADDRESS_NV, 2195bd8deadSopenharmony_ci cmdNV->vertexBuffers[n].index 2205bd8deadSopenharmony_ci cmdNV->vertexBuffers[n].address, 2215bd8deadSopenharmony_ci cmdNV->vertexBuffers[n].length); 2225bd8deadSopenharmony_ci } 2235bd8deadSopenharmony_ci 2245bd8deadSopenharmony_ci DrawElementsIndirect(mode, 2255bd8deadSopenharmony_ci type, 2265bd8deadSopenharmony_ci (DrawElementsIndirectCommand*)ptr); 2275bd8deadSopenharmony_ci } 2285bd8deadSopenharmony_ci 2295bd8deadSopenharmony_ci if (stride == 0) 2305bd8deadSopenharmony_ci { 2315bd8deadSopenharmony_ci ptr += sizeof(DrawElementsIndirectCommand) + 2325bd8deadSopenharmony_ci sizeof(GLuint) + 2335bd8deadSopenharmony_ci sizeof(BindlessPtrNV) + 2345bd8deadSopenharmony_ci (sizeof(BindlessPtrNV) * vertexBufferCount); 2355bd8deadSopenharmony_ci } else 2365bd8deadSopenharmony_ci { 2375bd8deadSopenharmony_ci ptr += stride; 2385bd8deadSopenharmony_ci } 2395bd8deadSopenharmony_ci } 2405bd8deadSopenharmony_ci 2415bd8deadSopenharmony_ci BufferAddressRangeNV(ELEMENT_ARRAY_ADDRESS_NV,0,idxAddress,idxLengths); 2425bd8deadSopenharmony_ci for (i = 0; i < MAX_VERTEX_ATTRIBS) { 2435bd8deadSopenharmony_ci BufferAddressRangeNV(VERTEX_ATTRIB_ARRAY_ADDRESS_NV,i,vtxAddresses[i],vtxLengths[i]); 2445bd8deadSopenharmony_ci } 2455bd8deadSopenharmony_ci } 2465bd8deadSopenharmony_ci 2475bd8deadSopenharmony_ci Modifications to Section 10.3.10 (p. 305) "Indirect Commands in Buffer Objects" 2485bd8deadSopenharmony_ci 2495bd8deadSopenharmony_ci Modify both instances of "DrawArraysIndirect, DrawElementsIndirect, 2505bd8deadSopenharmony_ci MultiDrawArraysIndirect and MultiDrawElementsIndirect" on 2515bd8deadSopenharmony_ci p. 305 to read "DrawArraysIndirect, DrawElementsIndirect, 2525bd8deadSopenharmony_ci MultiDrawArraysIndirect, MultiDrawElementsIndirect, 2535bd8deadSopenharmony_ci MultiDrawArraysIndirectBindlessNV and MultiDrawElementsIndirectBindlessNV". 2545bd8deadSopenharmony_ci 2555bd8deadSopenharmony_ci 2565bd8deadSopenharmony_ciAdditions to the AGL/GLX/WGL Specifications 2575bd8deadSopenharmony_ci 2585bd8deadSopenharmony_ci None. 2595bd8deadSopenharmony_ci 2605bd8deadSopenharmony_ciGLX Protocol 2615bd8deadSopenharmony_ci 2625bd8deadSopenharmony_ci None. 2635bd8deadSopenharmony_ci 2645bd8deadSopenharmony_ciErrors 2655bd8deadSopenharmony_ci 2665bd8deadSopenharmony_ci INVALID_VALUE is generated by MultiDrawArraysIndirectBindlessNV or 2675bd8deadSopenharmony_ci MultiDrawElementsIndirectBindlessNV if <drawCount> is negative. 2685bd8deadSopenharmony_ci 2695bd8deadSopenharmony_ci INVALID_VALUE is generated by MultiDrawArraysIndirectBindlessNV or 2705bd8deadSopenharmony_ci MultiDrawElementsIndirectBindlessNV if <stride> is not a multipe of eight. 2715bd8deadSopenharmony_ci 2725bd8deadSopenharmony_ci INVALID_OPERATION is generated by MultiDrawArraysIndirectBindlessNV or 2735bd8deadSopenharmony_ci MultiDrawElementsIndirectBindlessNV if the 2745bd8deadSopenharmony_ci VERTEX_ATTRIB_ARRAY_UNIFIED_NV client state is not enabled. 2755bd8deadSopenharmony_ci 2765bd8deadSopenharmony_ci INVALID_OPERATION is generated by MultiDrawElementsIndirectBindlessNV 2775bd8deadSopenharmony_ci if the ELEMENT_ARRAY_UNIFIED_NV client state is not enabled. 2785bd8deadSopenharmony_ci 2795bd8deadSopenharmony_ciNew State 2805bd8deadSopenharmony_ci 2815bd8deadSopenharmony_ci None. 2825bd8deadSopenharmony_ci 2835bd8deadSopenharmony_ciNew Implementation Dependent State 2845bd8deadSopenharmony_ci 2855bd8deadSopenharmony_ci None. 2865bd8deadSopenharmony_ci 2875bd8deadSopenharmony_ciIssues 2885bd8deadSopenharmony_ci 2895bd8deadSopenharmony_ci 1) BufferAddressRangeNV is defined to take GLsizeiptr as length. 2905bd8deadSopenharmony_ci Should the length parameter inside the indirect structure be cast 2915bd8deadSopenharmony_ci to GLsizeiptr when passed as argument? 2925bd8deadSopenharmony_ci 2935bd8deadSopenharmony_ci RESOLVED: When the indirect buffer is stored in host memory, the cast 2945bd8deadSopenharmony_ci should be performed, otherwise, 64-bit should be assumed. 2955bd8deadSopenharmony_ci 2965bd8deadSopenharmony_ci 2) BufferAddressRangeNV also covered fixed function vertex state, should 2975bd8deadSopenharmony_ci this be exposed in this extension? 2985bd8deadSopenharmony_ci 2995bd8deadSopenharmony_ci NO, the named attributes aren't necessary, as it is very likely that 3005bd8deadSopenharmony_ci shaders are used to also handle the parameters of individual drawcalls. 3015bd8deadSopenharmony_ci For fixed function shading the interleaving of related state changes 3025bd8deadSopenharmony_ci with drawcalls would already be efficiently handled by regular 3035bd8deadSopenharmony_ci MultiDraw or NV_vertex_buffer_unified_memory functionality. 3045bd8deadSopenharmony_ci 3055bd8deadSopenharmony_ci 3) In which state should the vertex/index pointers be left after the 3065bd8deadSopenharmony_ci execution of the command? 3075bd8deadSopenharmony_ci 3085bd8deadSopenharmony_ci RESOLVED: All pointers should be reset to what was last 3095bd8deadSopenharmony_ci specified by the client side using BufferAddressRangeNV. 3105bd8deadSopenharmony_ci 3115bd8deadSopenharmony_ci 4) How does this extension relate to the newer NV_command_list? 3125bd8deadSopenharmony_ci 3135bd8deadSopenharmony_ci NV_command_list provides a more flexible draw indirect mechnanism. It 3145bd8deadSopenharmony_ci can be more efficient if there are redundancies in the vertex and index 3155bd8deadSopenharmony_ci buffer addresses, as it allows specifying addresses and drawcalls with 3165bd8deadSopenharmony_ci different frequencies in the command stream. 3175bd8deadSopenharmony_ci 3185bd8deadSopenharmony_ciRevision History 3195bd8deadSopenharmony_ci 3205bd8deadSopenharmony_ci Rev. Date Author Changes 3215bd8deadSopenharmony_ci ---- -------- -------- ----------------------------------------- 3225bd8deadSopenharmony_ci 1 ckubisch Internal revisions 3235bd8deadSopenharmony_ci 2 1/5/2015 ckubisch bugfix, remove of "reserved" in 3245bd8deadSopenharmony_ci DrawArraysIndirectBindlessCommandNV 3255bd8deadSopenharmony_ci added reference to NV_command_list 3265bd8deadSopenharmony_ci 3 7/3/2015 ckubisch bugfix, wrong math used in the "if (stride == 0)" 3275bd8deadSopenharmony_ci pointer advancing. GLsizeiptr for length instead of 3285bd8deadSopenharmony_ci GLuint64