Multi Draw Indirect from multiple VBOs

I find the current Multi Draw Indirect quite limitating…

Would it be much more powerful if one could also render from multiple VBOs and IBOs with just one call?

It would be much more powerful. It’s also not something hardware can actually do. How would you even specify which buffer was in use? You can’t possibly expect the hardware to know what an OpenGL buffer object name refers to. Anything more than that would require using actual GPU memory pointers.

NVIDIA, with their ability to use actual GPU memory pointers, comes the closest. Not even Vulkan lets you do this.

[QUOTE=Alfonse Reinheart;1281677]It would be much more powerful. It’s also not something hardware can actually do. How would you even specify which buffer was in use? You can’t possibly expect the hardware to know what an OpenGL buffer object name refers to. Anything more than that would require using actual GPU memory pointers.

NVIDIA, with their ability to use actual GPU memory pointers, comes the closest. Not even Vulkan lets you do this.[/QUOTE]

Something like a list of VBO (and IBO) names (or memory pointers since the hw have no concept of names)?

How would you propose for this to work with interleaved vertex attribs and/or vertex attrib binding?

Honestly I didn’t think that far right now, it was a pure propose. I hope some more talented and experienced dev than me could think of some solution about that. :smiley:

Well, keeping it simple, given one uses the same program, all the meshes’ attributes shall be coherent/shared between each mesh.

Strictly speaking the scenario I’m thinking of, and I should have been clearer about this (I got the terminology totally the wrong way around), is where the vertex attribs for a single mesh are sourced from 2 or more buffers. For example:

glBindBuffer (GL_ARRAY_BUFFER, vbo1);
glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 0, (void *) 0);

glBindBuffer (GL_ARRAY_BUFFER, vbo2);
glVertexAttribPointer (1, 2, GL_FLOAT, GL_FALSE, 0, (void *) 0);

glBindBuffer (GL_ARRAY_BUFFER, vbo3);
glVertexAttribPointer (2, 3, GL_FLOAT, GL_FALSE, 0, (void *) 0);

In this scenario the vertex data is already been sourced from multiple buffers, so your hypothetical API would need to support this and be clear about the distinction between this and what you’re proposing.

Let me rephrase the second part of my post, since it was kind of misleading because I got confused…

Let suppose we have 2 meshes, m0 and m1. Normally one would do:


        gl4.glVertexAttribFormat(attribIndex0, 3, GL_FLOAT, false, VertexA.offset0);
        gl4.glVertexAttribFormat(attribIndex1, 3, GL_FLOAT, false, VertexA.offset1);

        gl4.glVertexAttribBinding(attribIndex0, bindingIndex0);
        gl4.glVertexAttribBinding(attribIndex1, bindingIndex0);

        gl4.glVertexBindingDivisor(bindingIndex0, 0);

        gl4.glEnableVertexAttribArray(attribIndex0);
        gl4.glEnableVertexAttribArray(attribIndex1);

        gl4.glBindVertexBuffer(bindinIndex0,
                vbo00,
                0,
                VertexA.SIZE);

and m1


        gl4.glVertexAttribFormat(attribIndex0, 3, GL_FLOAT, false, VertexA.offset0);
        gl4.glVertexAttribFormat(attribIndex1, 3, GL_FLOAT, false, VertexA.offset1);
        gl4.glVertexAttribFormat(attribIndex2, 3, GL_FLOAT, false, VertexB.offset2);

        gl4.glVertexAttribBinding(attribIndex0, bindingIndex0);
        gl4.glVertexAttribBinding(attribIndex1, bindingIndex0);
        gl4.glVertexAttribBinding(attribIndex2, bindingIndex1);

        gl4.glVertexBindingDivisor(bindingIndex0, 0);
        gl4.glVertexBindingDivisor(bindingIndex1, 1);

        gl4.glEnableVertexAttribArray(attribIndex0);
        gl4.glEnableVertexAttribArray(attribIndex1);
        gl4.glEnableVertexAttribArray(attribIndex2);

        gl4.glBindVertexBuffer(bindinIndex0,
                vbo10,
                0,
                VertexA.SIZE);
        gl4.glBindVertexBuffer(bindinIndex1,
                vbo11,
                0,
                VertexB.SIZE);

Instead here we could pass/store for each mesh a list with the VBO names (or pointers), so:

[ [vbo00, null //disabled], [vbo10, vbo11] ]

The whole point of a draw indirect call is that the GPU reads and processes the actual indirect drawing data directly, without any CPU intervention.

Well, OpenGL buffer object names are all CPU constructs; the GPU has absolutely no idea what they mean. So you can’t use OpenGL object names. Instead, you would have to convert an object name into something the GPU could natively understand. And that would probably have to be some kind of pointer.

As for changing vertex formats between draw calls, no. If you could do that from an indirect command, you can basically do anything. Especially since some hardware has no vertex fetching hardware, and therefore emulates it by patching your vertex shader (also another reason why indirect buffer accesses wouldn’t work; hardware’s too diverse).