Twitter  YouTube  E-Mail  RSS
The One Man MMO Project
The story of a lone developer's quest to build an online world :: MMO programming, design, and industry commentary
Corrupted Rendering with VBO's
By Robert Basler on 2018-12-15 00:55:51
Homepage: email:one at onemanmmo dot com

I'm making a blog post of this in case anyone else ever runs into this problem so that the web won't let them down.

I was having a problem where wrong, or maybe old vertex data was being rendered after the program had been running for a while. I checked everything, and as it turns out everything was in fact working exactly as designed. To try and narrow down the problem, I spent a day building a frame debugger so I could isolate the vertex/index data that was rendering incorrectly. Once I had this working I noticed that the VBO ID's of the meshes that were rendering incorrectly were ones that had been recycled by OpenGL.

[It does make pretty glitches.]

What I mean by recycled is that each time I needed a new VBO I would call glGenBuffers( 1, &mVboId ) to allocate one. When a VBO was no longer needed for rendering, I called glDeleteBuffers( 1, &mVboId ) to free it. I noticed that the result from glGenBuffers for the troublesome VBOs were the same IDs that were recently freed by glDeleteBuffers - they were being reused. Now according to the OpenGL documentation, this is perfectly acceptable, OpenGL is supposed to take care of it.

I then very carefully checked all of the handling of the new VBO and I had to conclude that creating a new buffer with glBufferData and then writing new buffer data with glBufferSubData to the recycled ID didn't actually work, even though no error was generated. What I was seeing was that trying to render with the recycled VBO actually rendered the old data.

For whatever reason, OpenGL wasn't freeing the memory and disconnecting everything when glDeleteBuffers was called. To try to help OpenGL along I thought I'd see what happened if I manually deleted the buffers. The documentation said that you can call glBufferData to delete the memory associated with a VBO, so I tried that before calling glDeleteBuffers. After deleting the memory, calls to glDrawElements with the recycled VBO crashed on a NULL pointer reference in the nVidia driver.

The only suggestion I found from anyone having a problem like me was to call glDisableClientState before the glDeleteBuffers call, that made no difference.

As an experiment, I commented out the glDeleteBuffers line, and all my rendering problems went away - although since this was a leak I could see the VBO ID's increasing the whole time the program ran. It went through about a hundred a minute, 4 billion possible ID's, it should be able to keep that up for - a really long time. That was obviously not a viable strategy. Luckily chr0n0kun suggested I recycle the VBO ID's myself. When I'm done with a VBO I free its memory with glBufferData and put it into a list. When I need a new VBO ID I check the list and only allocate a new ID if the list is empty. That took a few minutes to set up, and it works perfectly. The only down side is that I have to free all the ID's at shutdown.

So maybe this will help someone.

New Comment

Cookie Warning

We were unable to retrieve our cookie from your web browser. If pressing F5 once to reload this page does not get rid of this message, please read this to learn more.

You will not be able to post until you resolve this problem.

Comment (You can use HTML, but please double-check web link URLs and HTML tags!)
Your Name
Homepage (optional, don't include http://)
Email (optional, but automatically spam protected so please do)
Cats or dogs? (What's this?)

  Admin Log In

[Home] [Blog] [Video] [Shop] [Press Kit] [About]
Terms Of Use & Privacy Policy