improving performance of a dynamic vertex buffer

Started by
3 comments, last by DieterVW 14 years, 7 months ago
I am using a dynamic vertex buffer to draw things in my game that change almost every step (sprites, billboards, ...). The method I use now is: - Use one dynamic vertex buffer (100kb). - When drawing something, copy it to the vertex buffer and call DrawPrimitive. - Next time, lock the vertex buffer with the nooverwrite flag and copy the data to the next part of the vertex buffer and call DrawPrimitive. - When the vertex buffer is full, lock with the discard flag and start over again. Is this the best way, or are there better ways to do this (for example using 2 smaller vertex buffers and swap them when they are full)? Another question, what should I do if the vertex format changes? Now I am doing this:
if(writepos%vertexformatsize!=0) {
writepos += vertexformatsize-writepos%vertexformatsize;
}
I wanted to use stream offsets but apparently these are not supported on all computers. Is this the best way to do this, or should I use a separate buffer for every vertex format?
Advertisement
You want to avoid lock/unlock multiple times per frame on the same dynamic vertex buffer. If you have 10 particle effects all with the same vertex buffer format then you want to:

1) Lock the buffer
2) for each particle type add vertex data to buffer and keep count of primitive count for that type
3) unlock the buffer
4) for each particle type set the texture, and draw primitives

If you have different dynamic vertex types then have multiple vertex buffers, one for each type of vertex data.

Hope that helps...
My Apps:Putt Nutz
Thank you, I will try that. But what should I do if the vertex buffer is not large enough to store all the data?
If the buffer is full, you'll need to unlock, and draw what you've got. If you don't draw before locking again with discard, the previous data will be lost and undrawable.

You only need the 1 dynamic VB. Switching between 2 buffers is what the dynamic buffer will do behind the scenes for you (called vertex buffer renaming by the hardware vendors).

Locking a dynamic buffer multiple times per frame isn't that bad, but you do want to keep it to a minimum. You also want to keep draw calls to a minimum, as each one is slow. Drawing each sprite is a bad idea.

You want to:
lock,
Write as much as I can (until I need to switch textures, blend modes, etc or the buffer is full),
Unlock,
Draw,

While you can attempt to fill multiple draw calls worth of data and lock just once, it's usually more hassle to get working and the benefit is minuscule.
It is important to understand what is going on in a dynamic vertex buffer in order to know the affects of locks. Dynamic buffers are CPU side data allocations that the driver transfers for you as needed based on draw calls. For this reason calling lock no overwrite many times should have little/no affect on performance. The driver is only worried about using the data you've submitted draw calls for, and you've made the gaurantee that you won't change that data. So the lock is pretty much free.

Calling discard when the buffer is full will not result in data loss. The driver will actually make a new buffer behind the scenes and allow you to write to that instead. Thus, your previous data still sitting in the pipe is safe from a discard lock. Without using a query every time, it would be difficult to know for sure that buffered data was no longer needed -- and this would be somewhat annoying and ultimately it's unecessary since the drivers are managing it for you.

Instancing is still an advantage here since it reduces draw calls.

This topic is closed to new replies.

Advertisement