PDA

View Full Version : Calling glBufferSubData is crashing machine?



Duncan Champney
04-02-2008, 06:44 PM
I've recently updated my app to use VBOs for vertex data, normals, colors, and vertex indexes.

I keep those VBOs bound, and the glVertexPointer/glNormalPointer/glColorPointer/indexes vertex pointers pointing to the data in the VBO. I've built a display list that draws my app's polygon mesh using a series of calls to glDrawRangeElements().

Everything works beautifully until I need to change the vertex/normal data or the color data for my mesh.

When I need to update the mesh data, I set a rebuild_mesh flag. Then, in my draw routine, I update the mesh data in main memory. The new VBO code then tries to copy the updated vertex/normal data to the VBO using the call glBufferSubData.

Here's the code I use to try to update the data for my vertex/normal VBOs:



glBindBuffer(GL_ARRAY_BUFFER, VBO_buffers[vertexes]);
unsigned long malloc_size = sizeof(GLfloat) * mesh_w * mesh_h * 3;
glBufferSubData(GL_ARRAY_BUFFER, 0, malloc_size, meshVertices);

glBindBuffer(GL_ARRAY_BUFFER, VBO_buffers[normals]);
glBufferSubData(GL_ARRAY_BUFFER, 0, malloc_size, meshNormals);

The code is instrumented to check for errors after each call (those calls were removed above for clarity.) I'm not getting any errors.

At the first glBufferSubData call, the machine goes to the Bahamas and doesn't leave a forwarding address. (It stops responding to user input. Background processes continue to run, but nothing happens on the screen.) I have to do a forced shutdown in order to recover.

I've verified that the values being passed in are valid, and that my vertex and normals arrays are intact.

Is there some housekeeping I need to do before calling glBufferSubData, or is there some state in which this call is illegal?

Am I getting into trouble because my VBO is referenced by a display list? Do I need to delete the display list before updating the vertex data? I'm stumped.

Relic
04-03-2008, 12:34 AM
Am I getting into trouble because my VBO is referenced by a display list?

What do you mean with that?
Display lists copy data when they are built, afterwards they are static and unchangeable.
You cannot "reference" into vertex arrays or VBOs from display lists. Read the OpenGL specs on display lists and learn which functions are executed immediately and which are actually compiled into the display lists. E.g. all attribute pointer calls are executed immediately, glDraw* calls will compile the sourced vertex attribute data and render method into the display list.

Building display lists from VBOs is a pure waste of time, because if the data resides in video memory it will take extra long to copy it back into the display list.

CatDog
04-03-2008, 03:19 AM
Relic is right - what you're trying to do won't work. Compiling a display list means, that you pass all the data to the driver. You can not change it afterwards. You'll also never know, what kinds of processing and optimizing is done when compiling a display list. This is totally up to the driver implementation. After all, that's the trick with display lists: give all you have to the driver and let it compile your data for best performance on the current platform.

But, as I see it, this doesn't explain the crash. Why shouldn't it be possible to alter a VBO, after it was used in a display list? (Of course, this is just an educational question, since it would not change the already compiled display list.)

CatDog

Duncan Champney
04-03-2008, 04:01 AM
Am I getting into trouble because my VBO is referenced by a display list?

What do you mean with that?
Display lists copy data when they are built, afterwards they are static and unchangeable.
You cannot "reference" into vertex arrays or VBOs from display lists. Read the OpenGL specs on display lists and learn which functions are executed immediately and which are actually compiled into the display lists. E.g. all attribute pointer calls are executed immediately, glDraw* calls will compile the sourced vertex attribute data and render method into the display list.

Building display lists from VBOs is a pure waste of time, because if the data resides in video memory it will take extra long to copy it back into the display list.

Relic,

I was afraid of that. I read an OpenGL reference rather than the spec, and from that, wasn't quite clear on what is read at list compile-time and what is read at the time the list was invoked. I was hoping (against hope) that since the vertex data is "server side" in a VBO, it would be read when the list is invoked.
By the way, why would building a display list take <u>extra time</u> if the data resides in video/vs main memory? I would think it would be a little faster than reading the data from main memory.
I only added display lists on top of VBOs as an experiment to see why I was getting such poor performance with VBOs. I expected VBOs to be FASTER than display lists, but they are significantly slower.
I'd love to find out that there was something I'm doing that is making VBOs so slow to execute. I'm currently creating VBOs that contain my entire mesh, which can be quite large. I changed my code to use glDrawRangeElements and draw within the limits returned by GL_MAX_ELEMENTS_VERTICES & GL_MAX_ELEMENTS_INDICES, but it didn't help.
I was planning to add code to split my VBOs up into smaller VBOs, but I'm not sure it's going to help. It will reduce the memory footprint for each VBO, but will require a lot more drawing commands in order to render the whole mesh. Do you have any advice on that?
I guess that if I can't get decent performance out of VBOs i'll go back to regular indexed vertex arrays, and just delete and rebuild my display list every time my vertex data changes. I'll change my code to create multiple display lists in order to handle really large meshes.

Relic
04-03-2008, 05:15 AM
By the way, why would building a display list take extra time if the data resides in video/vs main memory? I would think it would be a little faster than reading the data from main memory.

Because display list compilation is something done on the CPU and reading from video memory is slow.
You don't need VBOs to build display lists. Simply use standard vertex arrays then.


I expected VBOs to be FASTER than display lists, but they are significantly slower.

For completely static data, display lists have the advantage that they are pure server side and the driver can optimize a display list in whatever way is required to make it run fast.
If you apply the same or let's say similar optimizations to your VBOs you will get the same speed if you're HW bound.

Means, you definitely need to work on your VBOs a little more.
I would say start with interleaving your vertex attribute data.
Then optimize the indexing.


I was planning to add code to split my VBOs up into smaller VBOs, but I'm not sure it's going to help. It will reduce the memory footprint for each VBO, but will require a lot more drawing commands in order to render the whole mesh. Do you have any advice on that?
Keep the vertex data in the 64k vertices per VBO range to be able to use unsigned short indices.
Keep the number of indices per drawing call below 1 million indices.
That should run fast on most implementations.

Duncan Champney
04-10-2008, 12:14 PM
Means, you definitely need to work on your VBOs a little more.
I would say start with interleaving your vertex attribute data.
Then optimize the indexing.

Keep the vertex data in the 64k vertices per VBO range to be able to use unsigned short indices.
Keep the number of indices per drawing call below 1 million indices.
That should run fast on most implementations.


Relic,

I've been off doing other things, and am getting ready to try my hand at VBOs again. My code is currently using vertex arrays (not VBOs) to build display lists, and building the display lists is rather slow, but once they're built rendering is quite quick. If the user changes the height or color data for my mesh I have to go back and recreate the display lists, which is slow again.

I'd like to be able to use VBOs and get similar performance.

I have a couple of questions. Since calls like glDrawElements use byte offsets when they are indexing into a VBO, doesn't that mean that the entire size of my VBO would be limited to 64k bytes if I want to use unsigned short indexing?

For really large plots, that would make for a LOT of VBOs (say a 4500x4500 vertex plot. )

I figure I'll need 3 floats/vertex, 3 floats/normal, and 4 bytes/color. That's 28 bytes per vertex/normal/color. For my 4500x4500 vertex mesh, that's 567,000,0000 bytes. Dividing that into 64 kilobyte chunks, that's about 8650 VBOs I'd have to create. It seems like there would be a lot of call overhead in setting up and binding that many VBOs in order to render my mesh.

CatDog
04-10-2008, 06:00 PM
Since calls like glDrawElements use byte offsets when they are indexing into a VBO, doesn't that mean that the entire size of my VBO would be limited to 64k bytes if I want to use unsigned short indexing?
No. Have a close look to the definition first:


void glDrawElements( GLenum mode,
GLsizei count,
GLenum type,
const GLvoid *indices )

An "element" is used to address one vertex from a vertex array by its index. Relic suggested to use GL_UNSIGNED_SHORT for the element "type". This means, you can address 64k <u>different</u> vertices from this element array. Each vertex has 28 Byte, so to fit 64k vertices in one VBO, its size has to be 64k*28B = 1792kB = 1,75MB.

CatDog