glDrawCommandsNV and uniform buffers

Hi,
I’m using the NV Command List extension and have some questions about the use of uniform buffers together with glDrawCommandsNV. According to the spec. it says (about glDrawCommandsNV) that:
“The current binding state of vertex, element and uniform buffers will not be effective but must be set via commands within the buffer, other state will however be inherited from the current OpenGL context.”
As I read it, I then have to supply anything related to the uniform buffers (bindless/address) in the command/token buffer? I have done that and it works great!
Now, I’ve also tried to skip adding anything related to uniform buffers in the command/token buffer and instead used a “regular” OpenGL approach for the uniform buffers (just glBindBufferBase(GL_UNIFORM_BUFFER,…), NO glEnableClientState(GL_UNIFORM_BUFFER_UNIFIED_NV), and NO layout(commandBindableNV) uniform in the shader) and that seems to also work well. My question is now, is this going to be consistent behaviour? Or did I just get lucky because there are some fallback mechanisms in the driver or something?
The reason I’m asking is that I want to re-use the same command/token buffer when rendering depth textures for shadows, but my shader for doing that has different content/size/number of uniform buffers in that case, so if I must supply uniform buffer information through the command/token buffer I will have to create a separate command/token buffer for that case. I know that I can probably do some kung-fu to make re-use possible anyway, but I wanted to fully understand the behaviour.
So, to summarize: Can I use a “regular” OpenGL approach for uniform buffers (no command/token/bindless/address) together with glDrawCommandsNV? I know that the spec. says that default-block uniforms works, but I’m not sure about uniform buffers. It does work, but can I rely on it?
Also, just to clarify, this is how I typically use the uniform buffer(s) it in the shader:
struct UBOUniformData
{
mat4 viewMatrix;
mat4 viewProjMatrix;
vec4 lightDirWS;
};

layout(std140, binding=1) uniform UBOUniformDataBuffer {
UBOUniformData uboUniforms;
};

Thanks,
Mikael

Hi Mikael,

it indeed will work as you found out already. Basically glDrawCommands* triggers a relatively heavy validation in the drawcall, more than regular drawcalls since we don’t know what state was changed by the tokens on the GPU. That’s why it’s faster to do the binds in the tokens, rather than on the driver side.

you can also use different offsets to trigger different bindings

{ubobindingsA,ubobindingsB,drawcalls…}

Then you can draw with 2 ranges by passing different offsets & sizes: first range is using the appropriate ubobindings section, second the drawcalls.

Christoph,
Thanks for your quick response!

Ok, so then I should actually read the spec (for glDrawCommandsNV) as “If the client states for VERTEX_ATTRIB_ARRAY_UNIFIED_NV, ELEMENT_ARRAY_UNIFIED_NV and UNIFORM_BUFFER_UNIFIED_NV are enabled, the current binding state of vertex, element and uniform buffers will not be effective…"? And this is not something that just happens to work in the current drivers? This is the behaviour we can also expect from future drivers?

About the heavy validation cost, that is per glDrawCommandsNV call, right? So if I have very few glDrawCommandsNV calls per frame I would not really see any major performance difference between using “regular” OpenGL UBO binds and tokenized? Or is there any other difference in cost “during” the individual draw calls from the token buffer?

Great suggestion also with the offset/sizes stuff, wasn’t aware of that!

Anyway, I would also like to thank you for this extension and the great work you’ve done with “CAD scene rendering techniques” and occlusion culling. I’m using it here with huge CAD-models (50-150 million triangles) that also happen to have a lot of occlusion and the performance is really great!

/Mikael

Ok, I see now that my above ”modification” to the spec was not correct…

I did some tests and it appears that there is flexibility in uniform buffers in that we can use “regular” OpenGL binds (no need to place in token buffer).
However, vertex attrib arrays must be added to token buffer / use bindless.

So, things are a bit more clear now!

I’m still interested to hear more about the “validation costs”, though :)

/Mikael

Yes, the CPU validation occurs only per glDrawCommands*NV and is more expensive than a regular glDrawArrays/Elements etc.
Glad things are working out well.