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