PDA

View Full Version : gl*Pointer calls purely setup when used with VBO?



Swoop
02-25-2009, 02:14 PM
When rendering using glVertexPointer and friends with the usage they were originally implemented with, youd pass a pointer to the specific data before making a draw call

glEnableClientState(...)
gl*Pointer(...)
...
glDraw*(...)
...
glDisableClientState(...)

with vbos, are these calls now strictly for setup? and dont need to be called before each glDraw* once vbo has been bound

// vbo setup usage?
glGenBuffers()
glBindBuffer()
glBufferData()
glEnableClientState(...)
gl*Pointer(...)
...

// vbo draw simply...?, with no need for gl*Pointer calls before
// draw call?
glBindBuffer()
glDraw*(...) // just do the call?

Im asking because because im confused by two sources. The first is the nVIDIA's "Using VBO's" document which says

"Avoid Calling glVertexPointer() more than once per VBO..."
"...glVertexPointer should be called one time for one VBO..."
"...The binding operation is cheap compared to the setup of various pointers..."

which makes me think they should only be called at setup...

The other source is the small code examples at the bottom of the ARB VBO spec. Where they seem to call gl*Pointer just before drawing whether they are giving a traditional usage example or an example of using VBOs

So im wondering, if gl*pointer calls do setup, and are potentially costly do you only call them when setting up the VBO?

ScottManDeath
02-25-2009, 02:53 PM
OpenGL 3.0 / http://www.opengl.org/registry/specs/ARB/vertex_array_object.txt let you store the vertex pointer and vertex buffer objects setup into a separate state object.

Swoop
02-25-2009, 03:21 PM
But when dealing with just VBOs and an older opengl 2.1 version, are the gl*Pointer calls required before drawing?

scratt
02-25-2009, 05:37 PM
The glPointerCalls are an offset into the bound VBO, not an address of data.

The VBO binding is what sets the base address of a buffer.

When you call any pointer function *after* binding a VBO it knows that it must look at the VBO and use the 'address' it is passed as an offset into the VBO, not an address in memory. If you don't call glxxPointer (after binding a VBO) then that pointer will keep pointing to wherever it was pointing to before you bound the VBO.

The reason that it is recommended that you only call glVertexPointer once per VBO is AFAIK that this is when OpenGL does all of it's pointer related setup and calculations, so it is a *relatively* expensive call. But a necessary one. The act of binding a buffer is not that expensive supposedly. (You may also have read that you should call glVertexPointer last. This is also because of the reason I just outlined I guess. It's when everything is 'setup'. Although I have called them out of sequence and got away with it.)

That last paragraph is a little confusing from my point of view too. I used to have lots of individual VBOs and bind and unbind them and have all the pointers with a NULL offset into the buffer. I still called them though, even with NULL. Because if you don't then they don't get updated. So you still need to call them as the value in the pointer call is important even when it's a 0 offset.

Using that method when profiling I found that I had a fairly high percentage of Buffer Bindings going on, so I modified my system so that each VBO held lots of objects, and I only bound the VBO once, and then updated the pointers as I drew different portions of the VBO.

(If you rationalize this then basically whether you bind lots of buffers, or bind one, and use portions of it, you are still going to be calling glxxPointer each time you change the object you want to draw.)

The last method profiled better for me. So from my experience I wouldn't worry about the glVertexPointer call being slow. If you are drawing multiple instances of the same objects, try to batch them together, but otherwise just make sure you either call all the relevant pointers after binding a new buffer, or keep updating those pointers (glVertexPointer being important and called last) if you are reusing the same VBO over and over again.

But yes, in short, you need to call glxxPointer.