PDA

View Full Version : how to mapping the vbo more effectively



Jambo
04-25-2009, 08:25 AM
I create a vertex buffer object,and want to change the buffer data every frame,the only idea to do this is

1:Make a temp buffer, change this buffer data and then using glBufferSubData to change the vbo buffer
2:mapping the vbo buffer

I tend to use the second,but I found that if the vbo is a big buffer,it would use a long time

so is there any idea to mapping the vbo more effectively?????

dletozeun
04-25-2009, 10:56 AM
Mapping a vbo may be long because the driver have to sometimes wait that the gpu releases it after rendering a frame. This causes a driver stall and may lead to an application stall too if it has only one main thread.
To make glMapBuffer return immediatly, you have to invalidate the vbo data calling glBufferData( ..., NULL ) on the bound vbo. This way you reallocate buffer data for the current vbo that you can map almost instantly. The previous vbo data is completely lost and freed when the gpu has finished to use it.

If you have only litthe chunk of data to replace, I think it is better to use glBufferSubData in this case.

You can also use two vbos and ping pong between them: the first is used in the current frame rendering, the second is a copy of the first and is updated.

Eosie
04-25-2009, 01:04 PM
It's also worth using glMapBufferRange(target, 0, size, GL_MAP_WRITE_BIT | <u>GL_MAP_INVALIDATE_BUFFER_BIT</u>) to map the entire buffer.

Jambo
04-25-2009, 06:58 PM
OK,but if I calling glBufferData(...,NULL),the vbo's data would be cleared,isn't it?

dletozeun
04-26-2009, 05:09 AM
That's correct, as I said.

So if you want to update only little data chunks, that is not very efficient indeed. The ping pong method may be more convenient in this case.

In addition, with this last method, updating a large piece of data in a mapped buffer is not instantaneous, so you can do something like this:

Maintain 2 vbos with the same data: vbo1 and vbo2:

1) use vbo1 for drawing
2) Map the vbo2 for update in the main thread
3) Once vbo2 mapped, update its content in second thread and notify the main thread when the operation is terminated
4) Unmap the vbo2 in the main thread
5) switch between vbo1 and vbo2 and use vbo2 for drawing

This way the vbo2 update is not blocking the main thread as it is done in a second one.

dletozeun
04-26-2009, 05:19 AM
I must admit that it is not a very light way and it requires a little bit of work.
If you always need to update little continuous data subset, the glBufferSubData calls should be sufficient.
If you need to update non-continuous data subsets the glMapBufferRange is interesting as Eosie said but it requires the ARB_map_buffer_range extension. See:
http://www.opengl.org/registry/specs/ARB/map_buffer_range.txt

Jambo
04-26-2009, 06:43 PM
Thanks all~~ ,I intent to use one vbo,because I used it to update a skeleton model's skin,the vbo should be cleared every frame,so I think using glBufferData(...,NULL) is more effectively