GL_EXT_compiled_vertex_arrays & LockArrays

Umm… quick one. When exactly are you supposed to lock the array?

Obviously after you enable the client, but do you lock it before or after the call(s) to gl*******Pointer()?

The documentation looks like before, but it doesn’t make much sense that way.

Thanx,
Siwko

You’re right, the documentation for this extension doesn’t make much sense. It’s a bad situation for both app and driver developers.

The best answer I can provide is: I don’t know myself. (!!!) But changing pointers outside the lock is probably better if possible.

  • Matt

I believe the extension implicitly requires the driver to detect state changes (modelview, new Pointer calls etc) and flush it’s “compiled state” until the next draw call, so you could lock whenever you want.

However, if you look at the way Quake does it (with GLTrace), it first sets up all per-object state, then call LockArrays(), then does multiple texture state changes and DrawElements calls, then unlocks. Chances are that you’ll be compatible with most cards if you do it the same way…

yup, that’s exactly how I did it in my little
renderer and it’s been reported to work
correctly under a couple of chipsets…

I believe when you attempt to change
pointers after lock has been issued,
the behavior is undefined…

So I’m going to assume:

glEnableClientState(…);
gl*Pointer(…);
glLockArraysEXT(…);
glDrawElements(…) (or glDraw
);
glUnlockArraysEXT();
glDisableClientState(…);

Is that what every body is using?

Also, should I be locking and unlocking every frame, or should I lock, then run rendering until I’m thru with the Array (scene change, prog exit, etc), then unlock?

Siwko

Err… here, look. This is what I’m doing:

// Part of the body of the Render() method:
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

// == For some reason there isn’t any interleaved format with 2 texcoord, 3 vertex, 4 color, and 3 normal
// == using T2F, C4UB, V3F, N3F. I don’t honestly know why.
// glInterleavedArrays(GL_T2F_C4UB_V3F, 0, pVertexBuf);
glVertexPointer(3, GL_FLOAT, sizeof(VERTEXBUFFER), &pVertexBuf[0].Vertex);
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VERTEXBUFFER), &pVertexBuf[0].ColorWithAlpha);
glNormalPointer(GL_FLOAT, sizeof(VERTEXBUFFER), &pVertexBuf[0].Normal);
glTexCoordPointer(2, GL_FLOAT, sizeof(VERTEXBUFFER), &pVertexBuf[0].TexCoord);

if(glLockArraysEXT)
glLockArraysEXT(0, tMap.GetXSize() * tMap.GetYSize());

// glDrawArrays(GL_POINTS, 0, tMap.GetXSize() * tMap.GetYSize());

for(long i = 0; i < tMap.GetYSize() - 1; i++)
{
glDrawElements(GL_TRIANGLE_STRIP, tMap.GetXSize(), GL_UNSIGNED_INT, tMap.GetIndices(i));
}

glUnlockArraysEXT();

glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
// … Continue rendering other stuff …

Is this the correct methodology for using this extension?

Siwko

I believe that you can change, at a minimum, the glTexCoordPointer() (and the bound texture) while the arrays are still locked; else it wouldn’t be useful for multi-pass texturing (which it is).

I’m really just using it to accelerate the strip generation. The texture coordinates are really not even used (I’m not binding a texture - I just have it in the vertex structure format in case I decide to use it).

What I’m mostly asking is whether I’m using the locks correctly and are they in the correct place(s)?

Siwko

Just a side note - you should probably add “if (glUnlockArraysEXT)”

Originally posted by ET3D:
Just a side note - you should probably add “if (glUnlockArraysEXT)”

Oops, duh.

Siwko

Yes, your locks are pretty good, although you might not get much of a speed-up the way you’re using them here (especially if you were using glDrawRangeElements()).