PDA

View Full Version : UBO - Correct procedure for creation & binding



Althar
11-09-2014, 02:22 PM
Hello all,

I am getting back into OpenGL (last version I used was 2.0) after a couple of years working with OpenGLES 1.0 & 2.0. I have started messing around with UBO and am currently having a problem to do with binding points. I am not sure if this is due to a lack of understanding of how UBO and binding points work or something else, but here it goes.

I start off by creating my UBO



GLuint bindingPoint = 0;

GLuint uniformBufferId = 0;

// Generate the OpenGL uniform buffer
glGenBuffers(1, &uniformBufferId);
glBindBuffer(GL_UNIFORM_BUFFER, uniformBufferId);
glBindBufferBase(GL_UNIFORM_BUFFER, bindingPoint, uniformBufferId );

// Copy data over (if any)
glBufferData(GL_UNIFORM_BUFFER, blockSize, data, GL_DYNAMIC_DRAW);

As you can see, my UBO is set to binding point '0' - for which I have also bound my uniform block to using glUniformBlockBinding. As far as I am aware, all I would need to do in order to bind the UBO would be :


glBindBuffer( GL_UNIFORM_BUFFER, gl_uniformBuffer->getBufferId() );

For some odd reason however, when using gDebugger and watching the value of GL_UNIFORM_BUFFER_BINDING, I am finding that the binding point becomes '1' instead of '0' - as a result the only way I have found to get it to work is by explicitely calling glBindBufferBase with the correct binding point every time I bind the UBO :


glBindBuffer( GL_UNIFORM_BUFFER, gl_uniformBuffer->getBufferId() );
glBindBufferBase(GL_UNIFORM_BUFFER, gl_uniformBuffer->m_bindingPoint, gl_uniformBuffer->getBufferId() );

Should I only need to call glBindBuffer (ie. is the binding point compiled into the UBO in the same way VAOs compile the VBO and attributes ), or am I missing a fundamental point?

Thanks in advance,

carsten neumann
11-10-2014, 07:04 AM
In code like:


glBindBuffer(GL_UNIFORM_BUFFER, uniformBufferId);
glBindBufferBase(GL_UNIFORM_BUFFER, bindingPoint, uniformBufferId );


the glBindBuffer is not needed, glBindBuffer{Base,Range} bind the given buffer to the specific indexed bind point as well as the non-indexed bind point.



For some odd reason however, when using gDebugger and watching the value of GL_UNIFORM_BUFFER_BINDING, I am finding that the binding point becomes '1' instead of '0'


But isn't the name of your buffer object '1'? So calling glBindBuffer(GL_UNIFORM_BUFFER, 1) is supposed to have that effect, no? Sorry, I must be missing something.



Should I only need to call glBindBuffer (ie. is the binding point compiled into the UBO in the same way VAOs compile the VBO and attributes ).


AFAIK the shaders only 'access' the indexed bind points (i.e. those established with glBindBuffer{Base,Range}) and do not care about the non-indexed bind point, so as long as you don't remove your uniform buffer from the indexed bind point (by binding a different buffer or zero) you should not need to do any binding operations to have your shader access the buffer.

Althar
11-10-2014, 11:57 AM
Thanks for your reply,

In regards to GL_UNIFORM_BUFFER_BINDING, you are correct. I do not know what I was thinking as it does indeed indicate the index of the UBO bound and not the binding point (which is what I thought originally) : from that side, all is good then.

For testing purposes, I would switch UBO's mid frame (using glBindBuffer) - that being said, the binding point is not updated when I bind the UBO.

Are you essentially saying that glBindBuffer is the same thing as calling glBindBufferBase without specifying the binding point? If so, what is the value of this hidden binding point?

As a result, does this mean that in order to use my UBO, I simply need to call glBindBufferBase (provided I need it to pointing at a particular slot) ?

carsten neumann
11-10-2014, 12:17 PM
There is one non-indexed bind point and a number of indexed bind points. The non-indexed bind point allows you to manipulate the bound buffer in various ways, for example you can map its data storage (glMapBuffer(GL_UNIFORM_BUFFER, ...)) - note that there is no indexed variant of glMapBuffer, so the indexed binding points can not be used for mapping. On the other hand the shaders only "see" buffer objects bound to the indexed bind points.



Are you essentially saying that glBindBuffer is the same thing as calling glBindBufferBase without specifying the binding point? If so, what is the value of this hidden binding point?


No, glBindBuffer always manipulates only the non-indexed bind point, while glBindBufferBase manipulates both, the given indexed bind point and the non-indexed bind point - I don't know if there is any clever rationale for it changing both, but that's the way it's spec'ed.



As a result, does this mean that in order to use my UBO, I simply need to call glBindBufferBase (provided I need it to pointing at a particular slot) ?


Yup, the buffers bound to the indexed bind points are those a shader has access to.

Althar
11-10-2014, 01:47 PM
Right... this all makes sense now, thanks!

Yeah, I can sort of understand the logic behind it - on the other hand, I doubt many people are aware or understand how it works because none of the resources/tutorials I have found on the web make mention of it and most snippets will go about calling both functions without really thinking.

I was sort of hoping UBO would behave in the same way as VAO in the sense that you can compile internal states that get set whenever the buffer is bound - it sounds pointless to have to explicitly assign a binding point for your UBO when typically you will be using it with the same shader program, for which the binding points are not going to change.

Anyway, thanks again for clarifying - I have been scratching my head for days wondering why it would only work under "certain circumstances" when I was monkeying about with my code.