# VBO slow

## Recommended Posts

raizen    122
I implemented VBO and my engine became slower!!!! it's slow when i refresh vertex and when i use dynamic texture(lightmap) create my vbo buffer:
void VboSNE::endVertex() {

if(vVBO) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboid[0]);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, nver*3*sizeof(float), vertex, GL_STATIC_DRAW_ARB);

delete[] vertex;
vertex = NULL;
}
}
void VboSNE::endNormal() {

if(nVBO) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboid[1]);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, nnor*3*sizeof(float), norm, GL_STATIC_DRAW_ARB);

delete[] norm;
norm = NULL;
}
}
void VboSNE::endTextureCoord() {

if(tVBO) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboid[2]);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, ntex*2*sizeof(float), texver, GL_STATIC_DRAW_ARB);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);

glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboid[3]);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, ntex*2*sizeof(float), texver, GL_STATIC_DRAW_ARB);

glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboid[4]);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, ntex*2*sizeof(float), texver, GL_STATIC_DRAW_ARB);
}
}

apply it:
void VboSNE::drawVBO() {

if(vVBO) {
glEnableClientState(GL_VERTEX_ARRAY);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboid[0]);
glVertexPointer(3, GL_FLOAT, 0, 0);
}
if(nVBO) {
glEnableClientState(GL_NORMAL_ARRAY);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboid[1]);
glNormalPointer(GL_FLOAT, 0, 0);
}
if(tVBO) {
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboid[2]);
glTexCoordPointer(2, GL_FLOAT, 0, 0);

glClientActiveTextureARB(GL_TEXTURE1_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboid[3]);
glTexCoordPointer(2, GL_FLOAT, 0, 0);

if(lightModel==LIGHTMAP) {
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboid[4]);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
}
}
glDrawArrays(mode, 0, nver);
if(tVBO) {glDisableClientState(GL_TEXTURE_COORD_ARRAY);}
if(nVBO) {glDisableClientState(GL_NORMAL_ARRAY);}
if(vVBO) {glDisableClientState(GL_VERTEX_ARRAY);}
}


##### Share on other sites
gold    412
The problem may be the fact you are making 20 API calls to perform a single draw. This is the Achilles heel of VBOs, the setup involved. There are various proposals under consideration for fixing this (e.g. a vertex array set extension which allows you to atomically bind a state vector) but today here are a few suggestions to try:

1) If you are always rendering from the same set of VBOs, leave them enabled include of respecifying and enable/disable per draw call.

2) If possible, combine multiple objects into a single VBO or set of VBOs, and use a different "start" per object in DrawArrays. See also: MultiDrawArrays

3) If the geometry is static, consider using display lists instead; especially if the batch size is small.

The overhead of setting up VBOs kills small batch sizes, whereas large batches amortize the setup.

##### Share on other sites
raizen    122
Quote:
 Original post by goldThe problem may be the fact you are making 20 API calls to perform a single draw. This is the Achilles heel of VBOs, the setup involved. There are various proposals under consideration for fixing this (e.g. a vertex array set extension which allows you to atomically bind a state vector) but today here are a few suggestions to try:1) If you are always rendering from the same set of VBOs, leave them enabled include of respecifying and enable/disable per draw call.2) If possible, combine multiple objects into a single VBO or set of VBOs, and use a different "start" per object in DrawArrays. See also: MultiDrawArrays3) If the geometry is static, consider using display lists instead; especially if the batch size is small.The overhead of setting up VBOs kills small batch sizes, whereas large batches amortize the setup.

With my code if i don't use lightmap and i don't update the vertexs it is very fast...

##### Share on other sites
gold    412
When you say "update the vertexs" (sic) you mean execution of VboSNE::endVertex()? Are you doing this per frame? If so you are effectively destroying and re-creating your VBOs every frame, which is guaranteed to be slow. A far better technique is to create your VBOs in an initialization phase with:

glBufferData(GL_ARRAY_BUFFER, MAX_VERTS*3*sizeof(GLfloat), NULL, GL_DYNAMIC_DRAW);
(or use GL_STREAM_DRAW, depending on how frequently you change the geometry)

And populate them each time with:

glBufferSubData(GL_ARRAY_BUFFER, 0, nver*3*sizeof(GLfloat), vertex);

The difference here is you are re-using the VBO instead of re-creating it each time. What you are doing now is equivalent to { if (ptr) free(ptr); ptr = malloc(size); }

##### Share on other sites
raizen    122
Quote:
 Original post by goldWhen you say "update the vertexs" (sic) you mean execution of VboSNE::endVertex()? Are you doing this per frame? If so you are effectively destroying and re-creating your VBOs every frame, which is guaranteed to be slow. A far better technique is to create your VBOs in an initialization phase with:glBufferData(GL_ARRAY_BUFFER, MAX_VERTS*3*sizeof(GLfloat), NULL, GL_DYNAMIC_DRAW);(or use GL_STREAM_DRAW, depending on how frequently you change the geometry)And populate them each time with:glBufferSubData(GL_ARRAY_BUFFER, 0, nver*3*sizeof(GLfloat), vertex);The difference here is you are re-using the VBO instead of re-creating it each time. What you are doing now is equivalent to { if (ptr) free(ptr); ptr = malloc(size); }

ty!!!!!!!!!!!!!
i think this is the problem ^^

but why do when i use lightmap it became slow?

##### Share on other sites
gold    412
I imagine a similar issue, are you updating your lightmap per frame? How are you doing this? e.g. CopyTexImage vs CopyTexSubImage is analogous to BufferData vs BufferSubData; the latter refills the existing container whereas the former re-creates it.

By the way, this is a common problem; the new object model proposal addresses this by making it clear when you are creating an object vs when you are changing the contents of an existing object.

Simpler API --> better application code.

##### Share on other sites
Nitrogen    154
I have two suggestions:

I read somewhere that the glVertexPointer and glNormalPointer and all those functions are very slow. IIRC, you should be able to call those functions just once when you've finished uploading your VBOs to the gfxcard.

Second, I dont know if this still applies but when I first tried out vertex arrays, I had a massive slowdown when I enabled environment mapping (automatic texture coord generation), but I dont know if that was just my gfx card or driver at the time.