got a curious question about how vertex buffers and draw primitive work

Started by
4 comments, last by Evil Steve 14 years, 1 month ago
Ok this might seem like a dumb question or just strange, but I was thinking last night when I couldn't sleep and now I just have to ask. When I bind a vertexbuffer to a stream and use drawprimitive, does that vertexbuffer become unavailable until the drawprimitive call is done? Take for example. 1: Fill vertexbuffer and set it 2: DrawPrimitive, using the vertexbuffer. 3: Lock vertexbuffer and refill it. Do I have to wait for step 2 and the GPU to finish before I can move onto step 3? I'm assuming you have to wait, but I'm not sure how the process works really.
[ dev journal ]
[ current projects' videos ]
[ Zolo Project ]
I'm not mean, I just like to get to the point.
Advertisement
no. You can fill the vertex buffer as much as you want.

Quote:Original post by howie_007
no. You can fill the vertex buffer as much as you want.


so then what exactly is the drawback of locking the vertexbuffer?
[ dev journal ]
[ current projects' videos ]
[ Zolo Project ]
I'm not mean, I just like to get to the point.
Yes and no. That's what the flags to Lock() are for.

With a static vertex buffer (One created without the D3DUSAGE_DYNAMIC flag), when you Lock() with no flags: The driver assumes you need read/write access. So it'll wait for the GPU to finish using it, and then allow the Lock().
With a static vertex buffer, locking with the D3DLOCK_READONLY flag: If the vertex buffer is in D3DPOOL_MANAGED, then locking it will just give you a pointer to the system memory copy, so no touching of the driver/GPU involved. If it's created in D3DPOOL_DEFAULT, then you'll probably get a stall as the GPU shuffles things around to let you access it, and transfers the contents to the CPU (Data going the "wrong way" across the AGP/PCI-E bus is slow).

With a dynamic vertex buffer, things get a bit more confusing. When you lock the buffer, you should pass either D3DLOCK_NOOVERWRITE or D3DLOCK_NOOVERWRITE as the flags. When you use D3DLOCK_NOOVERWRITE, you're making a promise to the GPU that you're not going to modify any vertices in the buffer that it might be using (Which means any vertices since the buffer was created, or the last time it was locked with D3DLOCK_NOOVERWRITE). That allows D3D and the driver to let you write to one part of the buffer while the GPU is reading from another - which is very quick.
When you use the D3DLOCK_DISCARD flag, you're telling the driver that you want to throw away the buffer and start again. Internally, that creates another copy of the buffer - the GPU continues to use the "old" copy until it's done, and you get given back a brand new copy - which the GPU isn't using, so there's no stalls to access it.

In general:
1. NEVER read from a vertex buffer if you can help it. Reading is extremely slow - keep a copy of the vertices in system memory (I.e. in memory allocated with malloc/new) if you need to read them.
2. Read This for more details about efficiently using dynamic vertex buffers.
Quote:Original post by Evil Steve
Yes and no. That's what the flags to Lock() are for.

With a static vertex buffer (One created without the D3DUSAGE_DYNAMIC flag), when you Lock() with no flags: The driver assumes you need read/write access. So it'll wait for the GPU to finish using it, and then allow the Lock().
With a static vertex buffer, locking with the D3DLOCK_READONLY flag: If the vertex buffer is in D3DPOOL_MANAGED, then locking it will just give you a pointer to the system memory copy, so no touching of the driver/GPU involved. If it's created in D3DPOOL_DEFAULT, then you'll probably get a stall as the GPU shuffles things around to let you access it, and transfers the contents to the CPU (Data going the "wrong way" across the AGP/PCI-E bus is slow).

With a dynamic vertex buffer, things get a bit more confusing. When you lock the buffer, you should pass either D3DLOCK_NOOVERWRITE or D3DLOCK_NOOVERWRITE as the flags. When you use D3DLOCK_NOOVERWRITE, you're making a promise to the GPU that you're not going to modify any vertices in the buffer that it might be using (Which means any vertices since the buffer was created, or the last time it was locked with D3DLOCK_NOOVERWRITE). That allows D3D and the driver to let you write to one part of the buffer while the GPU is reading from another - which is very quick.
When you use the D3DLOCK_DISCARD flag, you're telling the driver that you want to throw away the buffer and start again. Internally, that creates another copy of the buffer - the GPU continues to use the "old" copy until it's done, and you get given back a brand new copy - which the GPU isn't using, so there's no stalls to access it.

In general:
1. NEVER read from a vertex buffer if you can help it. Reading is extremely slow - keep a copy of the vertices in system memory (I.e. in memory allocated with malloc/new) if you need to read them.
2. Read This for more details about efficiently using dynamic vertex buffers.


Thank you steve, I was just curious because the 2D renderer I'm working on rebuilds the vertex buffers all the time ,they rarely stay the same so i was just wandering how it all worked, and the type of impact I'm making with my current method of rendering.
[ dev journal ]
[ current projects' videos ]
[ Zolo Project ]
I'm not mean, I just like to get to the point.
Quote:Original post by freeworld
Thank you steve, I was just curious because the 2D renderer I'm working on rebuilds the vertex buffers all the time ,they rarely stay the same so i was just wandering how it all worked, and the type of impact I'm making with my current method of rendering.
That's generally perfectly fine. If the data is changing all the time, you have to get it from the CPU to the GPU at some point, and dynamic resources are pretty much the most efficient way to do that. ID3DXSprite uses a dynamic vertex buffer internally for all of its drawing.

So long as you only lock a buffer once per frame (Which may mean keeping a system memory copy of the data, then doing a Lock(), memcpy() and Unlock()), it should be good.

This topic is closed to new replies.

Advertisement