Sign in to follow this  
raizen

VBO slow

Recommended Posts

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]

Share this post


Link to post
Share on other sites
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 this post


Link to post
Share on other sites
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...

Share this post


Link to post
Share on other sites
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 this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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 this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this