Archived

This topic is now archived and is closed to further replies.

locking static buffers - an exception?

This topic is 5149 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Somewhere I remember reading that the real penalty from locking static vertex buffers comes from completely stalling the card. Would it be ok for me to lock a static buffer that is not actually being rendered from at the moment but will be in the near future, or should I just stick with dynamic? The lock would not occur often (every 20 seconds maybe?).

Share this post


Link to post
Share on other sites
It might be okay, so long as you''re not recycling the buffer from the not-so-distant past... by which I mean you haven''t used the buffer in the 3 possibly buffered previous frames.

On the other hand you never really know what the card is doing. The XBox D3D doesn''t take well to multithreading...fine it doesn''t take precautions about data in use in another thread. But if you are rendering in one thread, and in another thread you attempt to lock a completely new unused static buffer, it can cause graphical glitches... even though the data should have nothing to do with the data in the rendering thread.

While it''s not D3D on the PC, my point is that you have no idea what the card and driver are doing behind the scenes. Even though logically there should be no penalty, maybe there is. It''s something that I''d definately test on as many actual cards as I could, just to make sure they all behave.

Share this post


Link to post
Share on other sites
Do you have a good reason for making it static? Are there some limiting factors of a dynamic buffer that are keeping you from creating a dynamic buffer? From experience and information I''ve read, it seems that if you are going to lock a buffer more than once, ie, within the game loop, make the buffer dynamic. I can''t think of a situation which would prohibit the use of a dynamic buffer, but I''m sure there''s at least one.

    ___       ___       ___       ___       ___       ___       ___       ___   
/\ \ /\__\ /\ \ /\ \ /\ \ /\ \ /\ \ /\__\
/::\ \ /:/ _/_ _\:\ \ _\:\ \ \:\ \ /::\ \ /::\ \ /:/ _/_
/::\:\__\ /:/_/\__\ /::::\__\ /::::\__\ /::\__\ /::\:\__\ /::\:\__\ /::-"\__\
\/\:\/__/ \:\/:/ / \::;;/__/ \::;;/__/ /:/\/__/ \;:::/ / \:\:\/ / \;:;-",-"
\/__/ \::/ / \:\__\ \:\__\ \/__/ |:\/__/ \:\/ / |:| |
\/__/ \/__/ \/__/ \|__| \/__/ \|__|

Share this post


Link to post
Share on other sites
quote:
Original post by Fuzztrek
Do you have a good reason for making it static? Are there some limiting factors of a dynamic buffer that are keeping you from creating a dynamic buffer? From experience and information I''ve read, it seems that if you are going to lock a buffer more than once, ie, within the game loop, make the buffer dynamic. I can''t think of a situation which would prohibit the use of a dynamic buffer, but I''m sure there''s at least one.

It''s just that static buffers *usually* sit in video memory, and so are faster to render, while dynamic buffers are in AGP memory, so they''re faster to write to.

Additionally, the fact that D3D doesn''t support a "semi-static" buffer scheme explicitly causes lots of confusion to poeple. There''s been lots of discussion on DIRECTXDEV regarding this, and the last word is (from ATI, by Dave Horne, and he was seconded by an nVidia guy, so this applies to the 2 major IHVs):
quote:
I''ve been talking to our driver guys about how we manage VBs, and this is what happens in our drivers

1) We do not move STATIC VBs that are locked with 0 (ie no NOOVERWRITE/DISCARD flag set).

2) The driver doesn''t strictly place STATIC VBs in local vidmem and DYNAMIC VBs in AGP. A create of a STATIC VB will attempt local allocation first, followed by AGP if the local allocation fails. A create of a DYNAMIC VB will attempt AGP first, then local.

So you can see from point 2 that we treat the DYNAMIC flag as an indicator to use AGP memory, so the recommendation for our hardware (which should apply from R1xx onwards) would be to NOT use this flag if you plan on relatively infrequent updates. In this way, as long as you lock with 0 you should always get the local vidmem version for a STATIC VB, and never have to worry about the driver moving the VB around no matter how many times you lock it.

Obviously there are things to be careful of. First, there is the potential stall if the VB is still in use. Second, there is the issue of "sparse" updates. In general it is way better to update large consecutive areas of memory in local vidmem, and not a good idea to do a large number of small updates. Of course, how infrequent and sparse your updates are will affect how you manage the updates.

It''s also possible that the DirectX runtime might get involved before we get to see the Lock. Someone from Microsoft might care to comment on this.

If you''d like to read the whole thread, it''s titled "flickers while using D3DLOCK_NOOVERWRITE"

Muhammad Haggag

Share this post


Link to post
Share on other sites
quote:
Original post by Raloth
Somewhere I remember reading that the real penalty from locking static vertex buffers comes from completely stalling the card. Would it be ok for me to lock a static buffer that is not actually being rendered from at the moment but will be in the near future, or should I just stick with dynamic? The lock would not occur often (every 20 seconds maybe?).


It depends on how you lock it. If you previously fill it, and then lock it to update it, then it cannot be used to do any rendering.
You can also lock it with D3DLOCK_DISCARD, this will create a new memory area which you can fill with vertex data while the old one will still be used to draw until you unlock.
Another technique is that when you need to draw eg. 1000 triangles to create a vertex buffer big enough for 5000. Then you first fill it, call drawprimitive with offset 0 and count 1000. Then lock it with D3DLOCK_APPEND, write another 1000, from then on render with offset 1000 and count 1000. If the offset+count exceeds the total size, then use D3DLOCK_DISCARD and start from 0 again.

Share this post


Link to post
Share on other sites
quote:
Original post by Fuzztrek
Do you have a good reason for making it static? Are there some limiting factors of a dynamic buffer that are keeping you from creating a dynamic buffer?


I can think of a good one. Something that changes once every minute or so, but you render every frame. You don''t want to send the data to the card 3600 times a minute, just once every 3600 frames.

To get away with this, as I alluded to, you''d have to have an active buffer, and an inactive buffer. Render using the inactive buffer. When it comes time to change, lock in inactive buffer, change the data, unlock it, then swap the two buffer pointers. You''re now rendering with the new data, and giving the old buffer time to "cool down".

As I said though, I''d test it with everything from GeForce 256 on up, rather than blindly assuming it works.

Share this post


Link to post
Share on other sites
Hmm. I don''t really see why you would need, nor want, two vertex buffers. I would think it would make it a LOT slower. I see what you mean about sending data to the card, however I doubt it would make that big of a difference (you could probably say the same thing about locking a static buffer if it only contained a few vertices), but like everything, the only *sure* way to know how fast or how slow something is would be to benchmark. I, personally, would follow the SDK advice and always make a buffer dynamic if you are going to lock it more than once during the course of your application.

    ___       ___       ___       ___       ___       ___       ___       ___   
/\ \ /\__\ /\ \ /\ \ /\ \ /\ \ /\ \ /\__\
/::\ \ /:/ _/_ _\:\ \ _\:\ \ \:\ \ /::\ \ /::\ \ /:/ _/_
/::\:\__\ /:/_/\__\ /::::\__\ /::::\__\ /::\__\ /::\:\__\ /::\:\__\ /::-"\__\
\/\:\/__/ \:\/:/ / \::;;/__/ \::;;/__/ /:/\/__/ \;:::/ / \:\:\/ / \;:;-",-"
\/__/ \::/ / \:\__\ \:\__\ \/__/ |:\/__/ \:\/ / |:| |
\/__/ \/__/ \/__/ \|__| \/__/ \|__|

Share this post


Link to post
Share on other sites
I''ve seen it suggested that it''s faster to use static VBs than dynamic if the data changes less often than approximately every 5 frames.

You''d need and want two buffers to avoid the stall. The GPU is using one buffer, and you''re using the other one. It shouldn''t be slow, but I''d test it.

If a static buffer only contained a few vertices it may still stall a long long time, if the VB is in use and is far into the render queue. The lock time stall has nothing to do with the number of vertices in the buffer.

Share this post


Link to post
Share on other sites