Performance problems with VBOs

B0f865cbedf576dc46395eded971a0e3
0
MG_Midget 101 Jun 07, 2004 at 22:54

Hi,

I’m trying to render large models using vertex buffer objects however I get incredibly poor performance. The problem seems to be related to glDisableClientState (GL_VERTEX_ARRAY);

Here is a code fragment which is executed each frame:

#ifdef HAVE_ACCEL_GL
  glBindBufferARB (GL_ARRAY_BUFFER_ARB, this->vertex_buffer_id_);
#endif

  glEnableClientState (GL_VERTEX_ARRAY);
  glEnableClientState (GL_NORMAL_ARRAY);
  glEnableClientState (GL_TEXTURE_COORD_ARRAY);

  for (int i = 0; i < this->buffer_metadata_size_; i++)
  {
    VertexBufferMetadata& metadata = this->buffer_metadata_[i];

    Surface* this_surface = metadata.surface;

    this_surface->enable ();

    // Acceleration points need to be relative to the start of the buffer
    char * offset = this->acceration_available() ? this->buffer_ : 0;

    glVertexPointer  (3, GL_FLOAT, 0, ptr (metadata.vertex_offset  - offset));
    glNormalPointer  (  GL_FLOAT, 0, ptr (metadata.normal_offset  - offset));
    glTexCoordPointer (3, GL_FLOAT, 0, ptr (metadata.texcoord_offset - offset));
 
    glDrawArrays (GL_TRIANGLES, 0, metadata.vertex_count);

    this_surface->disable ();
  }

  glDisableClientState (GL_VERTEX_ARRAY);
  glDisableClientState (GL_NORMAL_ARRAY);
  glDisableClientState (GL_TEXTURE_COORD_ARRAY);

For a modest sized model containing about 100,000 triangles I get a framerate of 4 fps. If I comment out the calls to glDisableClientState then the framerate climbs to about 32 fps (on a modest GeForce 2 Go laptop).

Why does this make such a huge difference? What am I doing wrong?
:sigh:

Any help is much appreciated.

9 Replies

Please log in or register to post a reply.

F7a4a748ecf664f189bb704a660b3573
0
anubis 101 Jun 08, 2004 at 07:13

make sure that you don’t keep the buffer data mapped and that you don’t write to the buffer

B0f865cbedf576dc46395eded971a0e3
0
MG_Midget 101 Jun 08, 2004 at 16:53

Hi Anubis,

Thanks for the reply :) I’m definatley not writing to the buffer and as far as I can tell, I’m not keeping the buffer data mapped but I will double check that.

I know this is a daft question – but could you tell me what the calls to glEnableClientState and glDisableClientState actually do? I have had difficulty finding a good explanation.

Cheers!

E74d63fbaf27a7bc3608d4c0938c7ed8
0
DANNER 101 Jun 08, 2004 at 18:21

@MG_Midget

Hi Anubis,

Thanks for the reply :) I’m definatley not writing to the buffer and as far as I can tell, I’m not keeping the buffer data mapped but I will double check that.

I know this is a daft question – but could you tell me what the calls to glEnableClientState and glDisableClientState actually do? I have had difficulty finding a good explanation.

Cheers!

glDisableClientState tells OpenGL to used the ‘current data’ rather than the data from your vertex array. So for instance, if you call glDisableClientState(GL_VERTEX_ARRAY), instead of geting the vertex data from your array when you call glDrawArrays, you’ll draw current vertex (which is specified by the last called glVertex*). If you call glDisableClientState(GL_NORMAL_ARRAY) you’ll draw with the current normal (the normal specifed by glNormal*).

I don’t know why it’s running so slowly for you. It sounds like your hitting a non-accelerated case and therefore running through Nvidia’s software renderer.

F7a4a748ecf664f189bb704a660b3573
0
anubis 101 Jun 08, 2004 at 23:11

are you a 100% positive that the call to glDisableCientState is causing your problems ? probably some other part of your programm interferes with normal execution

B0f865cbedf576dc46395eded971a0e3
0
MG_Midget 101 Jun 09, 2004 at 10:57

Hi Anubis,

I’m probably about 95% sure that it is the call to glDisableClientState that is causing my problems. Let me give you a little background to explain why.

I’m implementing a library for haptic rendering (force feedback) of large scale virtual environments. The library supports a number of 3D primitives which can be rendered in immediate mode. I got OK performance using all the tricks like culling, spatial partitioning etc. but of course – I’m wasn’t really making full use of the gpu to efficiently render large numbers of triangles.

I then implemented a vertex buffer class which takes an stl Vector of triangles sorted according to their material property. I setup the vertex buffer object as per my example code (the code fragment I posted is actually in a render method for my vertex buffer class). Each of my objects in the environment tessellate themselves into the stl Vector, the vertex buffer class is constructed from this Vector, and then it’s render method is called within the main rendering loop of the application.

In the render method for the vertex buffer I step through all the different material types contained in my vertex buffer and render all the triangles of a given type, switching the material properties as required. At first I thought that the bottlenck may have been caused by switching material properties but I eliminated that by making my whole model render with a single material.

I gradually made the vertex buffer simpler and simpler by commenting out various bits but even with just GL_VERTEX_ARRAY enabled (and then disabled after glDrawArrays), I still get the same problem.

I am running on a Linux box and I’m beginning to wonder if there might be a bug in the nvidia driver for linux. My next plan of attack is to get a simple c or c++ program that uses vertex buffer objects to render at least 10,000 triangles and try running it on my machine to see if it exhibits the same problem.

Cheers!

F7a4a748ecf664f189bb704a660b3573
0
anubis 101 Jun 09, 2004 at 12:57

I then implemented a vertex buffer class which takes an stl Vector of triangles sorted according to their material property. I setup the vertex buffer object as per my example code (the code fragment I posted is actually in a render method for my vertex buffer class). Each of my objects in the environment tessellate themselves into the stl Vector, the vertex buffer class is constructed from this Vector, and then it’s render method is called within the main rendering loop of the application.

are you using any kind of LOD algorithms ? i mean are you tetesselating parts of your environment each frame ? if that’s the case make sure you configure your vbo to handle this correctly (making it a dynamic vbo).

also i guess that there is an upper size limit for a vbo (speaking of performance not technical possibilities). for older nvidia cards i remember that the limit was around 10,000 triangles after that the performance might probably drop again (i can’t confirm this but you might want to give it a try).

B0f865cbedf576dc46395eded971a0e3
0
MG_Midget 101 Jun 09, 2004 at 17:35

Hi Anubis,

No….am trying to avoid implementing LOD (unless I find I need it) as I think modern graphics cards can handle enough triangles to render pretty large models at a reasonable level of detail….but I’m trying to prove that to my boss.

Anyhow, I have good news :D ….I found the reason for my poor frame rate. It seems to be a driver issue. After spending much of today trying to simplify my code and identify the real problem, I finally gave up and tried an update to my graphics drivers. My framerate with VBOs for a modest oil/gas platform model (around 2000 geometric primitives) is now about 60 fps on my “long in the tooth” modest Geforce 2 Go laptop (Hurrah!). On a desktop machine with a Geforce FX card, I get a fantastic framerate with reasonably large-scale models :) ….well worth it!

Thanks for all your helpful comments.

Cheers!

Fdbdc4176840d77fe6a8deca457595ab
0
dk 158 Jun 09, 2004 at 17:47

For future reference, I found this document to be very helpful: http://developer.nvidia.com/object/using_VBOs.html It talks about how to use VBOs properly.

F7a4a748ecf664f189bb704a660b3573
0
anubis 101 Jun 09, 2004 at 22:45

driver issues are mean because usually they are not the problem so it’s the last place you look. well, one can avoid things like this by always using the latest driver :) old geforce cards might not even support vbos in hardware (i know my radeon9000 M doesn’t).