4
$\begingroup$

I'm trying to use glMultiDrawArraysIndirect to render a batch of object.

In my example I have a cube and a sphere (in this order) in a VBO and a GL_SHADER_STORAGE_BUFFER (SSBO) that contains matrix transforms as well as a GL_DRAW_INDIRECT_BUFFER (DIB) that contains the draw commands.

The allocation of both the SSBO and DIB are managed by a custom class.

I can currently render both objects successfully, each using their own transform. The problem I'm encountering is rendering just the sphere by specifying an offset. As per the OpenGL spec:

If a buffer is bound to the GL_DRAW_INDIRECT_BUFFER binding at the time of a call to glMultiDrawArraysIndirect, indirect is interpreted as an offset, in basic machine units, into that buffer and the parameter data is read from the buffer rather than from client memory.

but doing the following code to render results in nothing being rendered:

// Calculates the offset & size and calls BindBufferRange 
this->_indrMatrixBuffer.BindBufferRange(0, 1, 1);
// A simple call to glBindBuffer, binding to GL_DRAW_INDIRECT_BUFFER
this->_indrBuffer.BindBuffer();
// Render
glMultiDrawArraysIndirect(GL_TRIANGLES, (void*)sizeof(DAICmd), 1, 0);

The DAICmd is a struct of four unsigned int (as per the spec)

At first I though it might be my custom class but calling glMultiDrawArraysIndirect(GL_TRIANGLES, 0, 1, 0); and keeping the matrix buffer offset renders the cube in the spheres position!

What am I missing to get this to work?


Extra notes

  • Both the SSBO & DIB are mapped using the flags GL_MAP_WRITE_BIT, GL_MAP_PERSISTENT_BIT and GL_MAP_COHERENT_BIT and are created with the same flags plus GL_DYNAMIC_STORAGE_BIT
  • I'm using OpenGL 4.5
  • Using glMultiDrawArraysIndirect(GL_TRIANGLES, (void*)sizeof(DAICmd), 1, 0); does not produce an error when using glGetError()
  • Using KHR_debug produces no errors either
$\endgroup$
  • 2
    $\begingroup$ Code looks right on a first glance. Are you checking for GL errors? Do you have KHR_debug output set up? $\endgroup$ – Nathan Reed Oct 26 '15 at 2:41
  • $\begingroup$ Updated my question. $\endgroup$ – Soapy Oct 26 '15 at 9:11
2
$\begingroup$

The problem was my class handling the population fo the draw indirect commands.

Each time I added a new command to the indirect buffer I also incremented the baseInstance, so the cube had baseInstance = 0 and the sphere had baseInstance = 1.

The reason why it doesn't render the sphere is because glMultiDrawArraysIndirect pretty much evaluates as glDrawArraysInstancedBaseInstance(mode, cmd->first, cmd->count, cmd->instanceCount, cmd->baseInstance); (as per the OGL wiki).

The drawID is calculated as (gl_InstanceID / divisor) +baseInstance (link), which means that the drawID is out of range when trying to render with an offset, as the sphere now appears as the first element in the indirect buffer.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.