PDA

View Full Version : help on VAR's



ironhelix
07-18-2002, 11:30 AM
ok guys...I have a few questions firstoff, and then some code

(1) do you need to use interleaved vertex arrays?
(2) how expensive is the setting of your VARs?

look at this code - it looks really bad when rendered (I don't have GF, someone else is testing it for me, so I can't fool around too much)

rbuf = &rstf->bufarray[chunk];
glVertexPointer(3,GL_FLOAT,0,(GLvoid *)rbuf->vertexarray);
glNormalPointer(GL_FLOAT,0,(GLvoid *)rbuf->normalarray);
glTexCoordPointer(2,GL_FLOAT,0,(GLvoid *)rbuf->texcoordarray);
if (global_glInfo.NV_VAR) {
glVertexArrayRangeNV((sizeof(float) * (257 * 257)),rbuf->vertexarray);
GLboolean parms[5];
glGetBooleanv(GL_VERTEX_ARRAY_RANGE_VALID_NV,parms );
if (!parms[0]) {
printf("\nNV_VAR not initialized correctly");
}
}
else if (global_glInfo.CVA) glLockArraysEXT(0,rbuf->numelems);
for (int texnum = 0; texnum < 64; texnum++) {
if (rbuf->drawelementsnum[texnum] > 0) {
if (global_glInfo.NV_VAR)
glSetFenceNV(world->ren->tex.nvfence[0],GL_ALL_COMPLETED_NV);
glBindTexture(GL_TEXTURE_2D,rbuf->drawelementstex[texnum]);
glDrawElements(rbuf->drawelementstype[texnum],rbuf->drawelementsnum[texnum],GL_UNSIGNED_INT,(GLvoid *)rbuf->drawelementsarray[texnum]);
if (global_glInfo.NV_VAR)
glFinishFenceNV(world->ren->tex.nvfence[0]);
}
}
if ((!global_glInfo.NV_VAR) && (global_glInfo.CVA)) glUnlockArraysEXT();

the interleaved arrays aren't too much trouble if that's what I need to do
it does not output anything about the VAR being invalid
and it renders fine on the fallback path for no VAR.......
you can almost see 1 or 2 polygons fine with this apparently

knackered
07-18-2002, 12:42 PM
Have you done:
glEnableClientState(GL_VERTEX_ARRAY_RANGE_NV);

BTW, your fence finish is in the wrong place, in order to take advantage of the speed increase VAR offers.
You should finish your fence just before you set it up again - you only need to do a "finish" just before you need to either change the vertex data or draw the vertex data again. What your code seems to be doing is calling drawelements, then waiting for the fence to finish - the whole point about var is that drawelements will return instantly, after sending a request to the card to pull the vertex data across, so you can get on with the rest of the code, rather than waiting for the card to process the vertex data. Effectively, you're not using VAR at all! http://www.opengl.org/discussion_boards/ubb/smile.gif

[This message has been edited by knackered (edited 07-18-2002).]

ironhelix
07-18-2002, 12:55 PM
ok, this fixes it:

rbuf = &rstf->bufarray[chunk];
glInterleavedArrays(GL_T2F_N3F_V3F,0,(GLvoid *)rbuf->vntarray);
if (global_glInfo.NV_VAR) {
glSetFenceNV(world->ren->tex.nvfence[0],GL_ALL_COMPLETED_NV);
glVertexArrayRangeNV(rbuf->vntarraysize,rbuf->vntarray);
glFinishFenceNV(world->ren->tex.nvfence[0]);

GLboolean parms[5];
glGetBooleanv(GL_VERTEX_ARRAY_RANGE_VALID_NV,parms );
if (!parms[0]) {
printf("\nNV_VAR not initialized correctly");
}
}
else if (global_glInfo.CVA) glLockArraysEXT(0,rbuf->numelems);
for (int texnum = 0; texnum < 64; texnum++) {
if (rbuf->drawelementsnum[texnum] > 0) {
if (global_glInfo.NV_VAR)
glSetFenceNV(world->ren->tex.nvfence[0],GL_ALL_COMPLETED_NV);
glBindTexture(GL_TEXTURE_2D,rbuf->drawelementstex[texnum]);
glDrawElements(rbuf->drawelementstype[texnum],rbuf->drawelementsnum[texnum],GL_UNSIGNED_INT,(GLvoid *)rbuf->drawelementsarray[texnum]);
if (global_glInfo.NV_VAR)
glFinishFenceNV(world->ren->tex.nvfence[0]);
}
}
if ((!global_glInfo.NV_VAR) && (global_glInfo.CVA)) glUnlockArraysEXT();


but it's still slow
should I glLockArrays() still? and you're telling me it should look like:

if (global_glInfo.NV_VAR)
glFinishFenceNV(world->ren->tex.nvfence[0]);
<texture...>
<draw elements...> glSetFenceNV(world->ren->tex.nvfence[0],GL_ALL_COMPLETED_NV);

for each loop since I'm drawing from it 64 times?

also should I try to minizmie the glVertexArrayRangeNV() calls by not doing them during the render pass?

Ysaneya
07-18-2002, 11:08 PM
You should only call glVertexArrayRangeNV once in your code: after you allocated video memory. Certainly not every frame, and even less every pass, or it'll kill your framerate. Be sure that you don't render 64 times the same geometry (a common mistake when doing some tests); be sure that you are storing your indices in system memory, and not video memory; do not use glLockArrays, it's useless with VAR; and to answer your questions:

1) there's functionnally no difference between VAR and normal vertex arrays once you've done the setup and allocated your memory. Just set up the pointer and draw your geometry. This implies that all standard formats, interleaved or not, are compatible.

2) very expensive; ideally you should allocate memory, setup the range, and do not change anything again. Mixing video / AGP memory ( which involves a range setup ) is not a good idea, but can give a small speed improvement if you're geometry limited and running our of video memory. Using and testing fences is pretty cheap, i've successfully used up to 1000 fences and it's no big deal.

If you really want to know all the ins-and-outs of VAR, check the specifications and demos on NVidia's website.

Y.

knackered
07-19-2002, 03:57 AM
Originally posted by Ysaneya:
there's functionnally no difference between VAR and normal vertex arrays once you've done the setup and allocated your memory.

Not entirely true. For instance, you are limited to 65535 per drawelements with VAR (on a gf2 anyway).
Check the specs, as ysaneya says.
Also, there's a nice little VAR tutorial here:- http://www.uni-karlsruhe.de/~uli2/index.html
Just click on the "VAR Tutorial" link on the left hand side.

Nicolas Lelong
07-19-2002, 05:44 AM
Hi,

also note that double-sided GL lighting is a _HUGE_ performance killer when using VAR (at least on GF2) - I learnt it the hard way trying to figure out what made my VAR stuff slower that immediate mode....

[This message has been edited by Nicolas Lelong (edited 07-19-2002).]