How to bind uniform buffer object using Direct State Access

Is there an equivalent of binding a uniform buffer object using Direct State Access instead of glBindBuffer?

glGenBuffers(1, &ubo);
glBindBuffer(GL_UNIFORM_BUFFER, ubo);
glBufferData(GL_UNIFORM_BUFFER, size, nullptr, GL_STATIC_DRAW)
glBindBuffer(GL_UNIFORM_BUFFER, 0);
glBindBufferRange(GL_UNIFORM_BUFFER, 0, uboMatrices, 0, 2 * sizeof(glm::mat4));

glBindBuffer(GL_UNIFORM_BUFFER, uboMatrices);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(glm::mat4), glm::value_ptr(projection));
glBindBuffer(GL_UNIFORM_BUFFER, 0);  

I can start like below, but what would I do after that?

glCreateBuffers(1, &ubo);
glNamedBufferData(ubo, size, nullptr, GL_STATIC_DRAW)

Direct state access is so that you don’t have to bind a buffer to the context just to modify it. What you have to do to use it has (largely) not changed.

So if you want to use that buffer as a UBO for a rendering process, that part doesn’t change. You have to bind a range of it to a UBO index and set up the program appropriately.

The glBindBufferRange call doesn’t change. You still need to bind buffers in order to get draw calls to use them.

In general, any indexed binding is required. Non-indexed bindings are typically obsoleted by DSA functions; there will be a function which allows you to pass the object name (ID) directly rather than requiring the object to be bound to a target.

I see, thanks!

What about glBufferSubData and glBufferData?

Can I write:

glNamedBufferData(ubo, size, nullptr, GL_STATIC_DRAW);

Instead of:

glBindBuffer(GL_UNIFORM_BUFFER, ubo);
glBufferData(GL_UNIFORM_BUFFER, size, nullptr, GL_STATIC_DRAW)
glBindBuffer(GL_UNIFORM_BUFFER, 0);

Clearly not right since I didn’t specify anywhere that ubo is a GL_UNIFORM_BUFFER? I’m guessing the below wouldn’t work then?

glGenBuffers(1, &ubo);
glNamedBufferData(ubo, size, nullptr, GL_STATIC_DRAW);
glBindBufferRange(GL_UNIFORM_BUFFER, 0, uboMatrices, 0, 2 * sizeof(glm::mat4));

glBindBuffer(GL_UNIFORM_BUFFER, uboMatrices);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(glm::mat4), glm::value_ptr(projection));
glBindBuffer(GL_UNIFORM_BUFFER, 0);  


Please ignore my previous response, I misunderstood your explanation. Thanks for the help!

That’s because you don’t have to. Buffer objects are not typed. A buffer is never a “UBO”; UBO is simply how you can use a buffer. Any buffer can be used for uniform data, vertex data, index data, pixel transfers, and more, and a single buffer can be used for any or all of these at the same time.

That’s not saying that you should try to do that, to use one buffer object for all of your data. My point is that you could.

Buffers are just fancy pointers to GPU-accessible memory. malloc and memcpy don’t care how you eventually use the pointers they return or copy into. Similarly, when you allocate storage for a buffer or modify the contents of that storage, it doesn’t matter how you will eventually use it.

Yes. But it’s limited to the NVIDIA bindless extensions:

  • glBufferAddressRangeNV( GL_UNIFORM_BUFFER_ADDRESS_NV, <index>, <address>, <length> )

General info:

Some of the extensions implementing NVIDIA bindless:

NV_command_list (also NVIDIA only) offers a token, UniformAddressCommandNV, that you can serialize into the token buffer to change an active UBO by address, similar to glBufferAddressRangeNV(), but without requiting a separate GL call to be invoked.