VBO slow

Started by
5 comments, last by Nitrogen 18 years ago
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);}
}
what's wrong? please help me [Edited by - raizen on March 26, 2006 7:01:10 AM]
Advertisement
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.
Quote:Original post by gold
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.


With my code if i don't use lightmap and i don't update the vertexs it is very fast...
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); }

Quote:Original post by gold
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); }


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

but why do when i use lightmap it became slow?
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.
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.
Delphi C++ OpenGL Development: www.nitrogen.za.org

This topic is closed to new replies.

Advertisement