Weird slowdown when using compiled vertex arrays

I’m working on a Quake 3 level viewer, and I’ve run into a really strange bug.

I have a big list of vertices, say 50,000, with colors and texture coordinates. So, I call glVertexPointer,glTexCoordPointer, glColorPointer, and then lock the arrays using glLockArraysEXT.

When I render, I process shaders, bind textures, set materials, and then call glDrawElements. It works well.

Now, I start to process Q3 visibility data. To save time when rendering, I don’t build the list of polygons dynamically, I just attach a boolean ‘DrawMe’ flag to each face. Instead of calling glDrawElements, I do this:

glBegin(GL_TRIANGLES);
for(i=sipIndex;i<sipIndex+sipCount;i++)
{
if(RD->PolyVis[i]) //<-my boolean flag
{
glArrayElement(RD->Polys[i].V1);
glArrayElement(RD->Polys[i].V2);
glArrayElement(RD->Polys[i].V3);
PolysPerFrame++;
}
}
glEnd();

Now, here comes the weird part:
I started to optimize, and I started keeping track of lists of polys that are ALL visible, so instead of doing the above glArrayElement thing, I could just call glDrawElements, so now, it looks something like this:

if(!DrawWholeChunk)
glBegin(GL_TRIANGLES);
for(i=sipIndex;i<sipIndex+sipCount;i++)
{
if(RD->PolyVis[i]) //<-my boolean flag
{
glArrayElement(RD->Polys[i].V1);
glArrayElement(RD->Polys[i].V2);
glArrayElement(RD->Polys[i].V3);
PolysPerFrame++;
}
}
glEnd();
}
else
{
glDrawElements(GL_TRIANGLES,sipCount*3,GL_UNSIGNED_INT,RD->Polys+sipIndex);
}

OK, this worked, but my frame-rate all of a sudden went down to 2 FPS. I spent a couple of hours trying to track the problem down, but the code seemed perfect. Just out of curiosity, I stopped using compiled vertex arrays, and what do you know, the FPS went back to normal! What the hell is going on? I read the specs, but there was nothing that suggested something like this could happen.

I don’t mind not using compiled arrays, but I was just interested if this is expected behavior.

My system specs:
Dual Pentium III 700s
nVidia GeForce 2 GTS(Elsa Gladiac)
Detonator 28.32 drivers

Thanks in advance.

-Shard

50,000 verts is a lot to pass in one call i think the recommended amount is about 4096 verts/indices
break the list into smaller lots

but then again 2fps seems very slow even if u exceed the limit

Yeah but remember, it worked fine when I commented out glLockArraysEXT…

-Shard

Lock arrays lets the implementation compile the transformed vertex data for reuse. If you try and lock too much I expect it could run out of on card memory and go slow because it does silly things like make copies back to AGP mapped host memory, or some other equally daft reason.

Draw a small ammount locking the array.
Redraw other passes with the locked array. Unlock.
Repeat until done.

You don’t want to do this too often, I assume you want to keep state changes to a minimum so making this too fine grained would probably not be the best idea.

[This message has been edited by dorbie (edited 06-24-2002).]

50,000 Verts is a bit to many to throw into a locked array. I have found using small blocks of locked arrays works best. Most of my locked arrays are for character models, of around 1500 polys, those work great in a locked array, but when i attempted to put an entire map into one array, it dropped the FPS to nothing, so stick with small batches.

Thanks guys, I tried to load a very small map, and it worked. Interesting…

So, I assume that the problem is that when there are too many verts being locked, the card doesn’t have enough memory and it forces paging to RAM… I’ll have to watch out for that.

Once again, thanks.

-Shard

50,000 is a lot of verts to draw with one texture/state (the scene must be very dull then again perhaps its just highly tesselated)

But shouldn’t that be handled by the driver internally: vertex/poly-count too high => ignore locking of the vertex-array.

Otherwise I have to do it in client code:


const unsigned int maxCVAVertices
= glGet(GL_MAX_CVA_VERTICES);
if(currentVertices <= maxCVAVertices) {
glLockArrayEXT(…);
}
// render
if(currentVertices <= maxCVAVertices) {
glUnlockEXT(…);
}

kab