相关文章推荐
销魂的可乐  ·  hive sql ...·  1 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

Originally using glDrawElementsInstancedBaseVertex to draw the scene meshes. All the meshes vertex attributes are being interleaved in a single buffer object. In total there are only 30 unique meshes. So I've been calling draw 30 times with instance counts, etc. but now I want to batch the draw calls into one using glMultiDrawElementsIndirect . Since I have no experience with this command function, I've been reading articles here and there to understand the implementation with little success. ( For testing purposes all meshes are instanced only once ).

The command structure from the OpenGL reference page.

struct DrawElementsIndirectCommand
    GLuint vertexCount;
    GLuint instanceCount;
    GLuint firstVertex;
    GLuint baseVertex;
    GLuint baseInstance;
DrawElementsIndirectCommand commands[30];
// Populate commands.
for (size_t index { 0 }; index < 30; ++index)
    const Mesh* mesh{ m_meshes[index] };
    commands[index].vertexCount     = mesh->elementCount;
    commands[index].instanceCount   = 1; // Just testing with 1 instance, ATM.
    commands[index].firstVertex     = mesh->elementOffset();
    commands[index].baseVertex      = mesh->verticeIndex();
    commands[index].baseInstance    = 0; // Shouldn't impact testing?
// Create and populate the GL_DRAW_INDIRECT_BUFFER buffer... bla bla

Then later down the line, after setup I do some drawing.

// Some prep before drawing like bind VAO, update buffers, etc.
// Draw?
if (RenderMode == MULTIDRAW)
    // Bind, Draw, Unbind
    glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_indirectBuffer);
    glMultiDrawElementsIndirect (GL_TRIANGLES, GL_UNSIGNED_INT, nullptr, 30, 0);
    glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
    for (size_t index { 0 }; index < 30; ++index)
        const Mesh* mesh { m_meshes[index] };
        glDrawElementsInstancedBaseVertex(
            GL_TRIANGLES,
            mesh->elementCount,
            GL_UNSIGNED_INT,
            reinterpret_cast<GLvoid*>(mesh->elementOffset()),
            mesh->verticeIndex());

Now the glDrawElements... still works fine like before when switched. But trying glMultiDraw... gives indistinguishable meshes but when I set the firstVertex to 0 for all commands, the meshes look almost correct (at least distinguishable) but still largely wrong in places?? I feel I'm missing something important about indirect multi-drawing?

That's not how it works for indirect rendering. The firstVertex is not a byte offset; it's the first vertex index. So you have to divide the byte offset by the size of the index to compute firstVertex:

commands[index].firstVertex     = mesh->elementOffset() / sizeof(GLuint);

The result of that should be a whole number. If it wasn't, then you were doing unaligned reads, which probably hurt your performance. So fix that ;)

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.