Vertex Buffer Objects and persistent bindings

I know that I can bind a client vertex attribute pointer to a bound array buffer, then bind another array buffer, and the vertex attribute pointer stays bound. In fact, I even ran into bugs in the ATI driver a while back where the color buffer pointer would still be error checked even when it’s turned off, so binding a short buffer with color, and later binding a large buffer without color, would cause a spurious error.

However, what I don’t quite get from the spec is whether the binding “switches” with the array buffers. For example, let’s assume I do the following:

  1. bind array buffer 1 (a cube)
  2. call VertexPointer(…)
  3. call DrawRangeElements() (displays cube)
  4. bind array buffer 2 (a sphere)
  5. call VertexPointer(…)
  6. call DrawRangeElements() (displays sphere)
  7. bind array buffer 1 again

Now, if I call DrawRangeElements() without first calling VertexPointer(), will it display a sphere of a cube? My intuition up until now would say “sphere,” but the VBO whitepaper from NVIDIA (from 2003) says to only call VertexPointer() ONCE per vertex buffer. That would only be possible if the bindings were “sticky” to the extent that switching back to a buffer with a previous binding would un-bind the current binding. That, in turn, means that a cube would be drawn.

So… inquiring minds want to know.

A sphere :slight_smile: There is no “automatical unbinding” going on, it just takes whatever buffer was current when you last called VertexPointer.

My interpretation is different than that of Zengar.
I think glVertexPointer and the others are part of the buffer object.
There is this glGetPointerv that you can try out.

Oh, gee, this helps tremendously. One of each! I feel like that guy with an angel on one shoulder, and a devil on the other.

I guess I’ll have to write some code.

I’ll guess you’d have :slight_smile: And tell us your findings!

I wrote some code, and the behavior I get is that I have to call glVertexPointer() after binding the buffer – i e, Zengar’s prediction. However, I would very much appreciate any pointer I can get into the spec that actually spells this out – all I’ve read has only seemed to implicitly assume some behavior in this regard.

Unfortunately vertex pointer aren’t bound per vertex buffer. Actually I think that OpenGL 3 vertex array object is the solution for this problem but until then we should describe each buffer before render. Consider the case where several buffer objects are used for a single draw call:

glBindBuffer(GL_ARRAY_BUFFER, BufferName[COLOR_OBJECT]);
glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0);

glBindBuffer(GL_ARRAY_BUFFER, BufferName[POSITION_OBJECT]);
glVertexPointer(2, GL_FLOAT, 0, 0);

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);

glDrawArrays(GL_TRIANGLES, 0, VertexCount);

glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);

We are just able to bind a single array buffer… how OpenGL could know which “color buffer object” it is supposed to used if we have several onces? It can’t.

According to the spec, ARRAY_BUFFER(_BINDING) is all client state. The buffer object itself only contains state for size, usage, access, mapped and map_pointers.

As such, I’d expect this scenario to at best display a sphere, or at worst end you up in undefined behaviour.

I see the problem., so I guess the pointers aren’t tracked by the VBO.
The spec suggest that each array has an associated buffer object binding, however buffer object don’t associate the pointer.
It is strange that the test I did worked.

Well, the semantics are well understood, and are what I expected. The only reason I asked was that I couldn’t actually find a page-and-line reference where the actual behavior is specified – and when reading that old NVIDIA whitepaper, it recommended using VertexPointer only once per buffer, so I started wondering. Perhaps it measn “only once per buffer per frame,” which would make a lot more sense.

Note that both kinds of semantics can be well supported; if bindings were sticky, binding a specific buffer would simply bind the arrays that are sticky in that buffer – not unbind any other arrays. However, as I said initially, the actual semantic makes more sense IMO.

APPLE_vertex_array_object exists to bind the client state to an object (VAO.)

Currently, I avoid redundant calls by packing static objects into the same VBO. That means I offset indices myself. I use 16 bit indices so sometimes a call to glVertexPointer is necessary.
If I use 32 bit indices, it would simply things, reduce call to glVertexPointer further, …

I think you are reading Using-VBO.pdf
I have a question of my own. Is this part still apply today and what does the driver do exactly?

Use glDrawRangeElements Instead of glDrawElements
Using range elements is more efficient for two reasons:
! If the specified range can fit into a 16-bit integer, the driver can optimize the
format of indices to pass to the GPU. It can turn a 32-bit integer format into a
16-bit integer format. In this case, there is a gain of 2×.
! The range is precious information for the VBO manager, which can use it to
optimize its internal memory configuration.

Yes; DrawRangeElements is almost always the preferred submission call over DrawElements or DrawArrays, where you have the data needed.

Jon, I found it in glspec20.pdf, “2.9 Buffer Objects”. Table 2.6 helped.

I hope someone within the ARB will find time to have a look at this subject, rewording or elaborating a bit (even with 3.x “around the corner” I expect 2.x and even 1.x programs to still be developed, not to mentioned maintained, for at least a decade or two more).

Thanks.