Jump to content
  • Advertisement
Sign in to follow this  
skytiger

Why isn't there a queued SetData() ?

This topic is 2492 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

So many CPU to GPU problems are caused by a lack of a queued SetData() command in DirectX

(SetData() is "out-of-band" as it isn't a queued command like DrawPrimitives())

We know data can be transferred in the command queue - that is how DrawUserPrimitives() works

So why not allow incremental updates to vertex buffers as a queued command?

Share this post


Link to post
Share on other sites
Advertisement
In general stuffing lots of data into the command buffer is slow. You really don't want to have to do it if you don't have to.

Drivers handle per-frame updates of dynamic resources through other means. Typically it will cycle through a ring buffer of memory (or multiple copies of a resource) in sync with GPU frames, so that the GPU can be pulling from one area of memory while the CPU writes to a different area.

Share this post


Link to post
Share on other sites
One approach that works reasonably well is to use a D3DPOOL_MANAGED resource. Lock it, write into it, then Unlock when done. You won't stall the pipeline as you're Locking/Unlocking the system memory copy, and while it may need to stall for updating the GPU memory copy you have some measure of control over when that stall may happen (for textures at least) using D3DLOCK_NO_DIRTY_UPDATE and AddDirtyRect.

It's worth noting that D3D10/11 have UpdatesubResource which meets the criteria of a "queued SetData". Vendors don't recommend it for use with textures, but I've personally found at least one use case where it's measurably faster than the preferred approach - updating hundreds of small scattered subrects in a texture (real world example: lightmaps).

Share this post


Link to post
Share on other sites
We know data can be transferred in the command queue - that is how DrawUserPrimitives() works
N.B. you can use this mechanism to update a resource if you want to -- e.g. issuing a draw-points command to plot individual pixels into a texture -- however, you'll discover why it's usually a worse idea than the usual way of doing things when your command buffer fills up ;)
So why not allow incremental updates to vertex buffers as a queued command?
Buffer updates are queued (assuming you use the appropriate create/lock flags), just in a different way.

Share this post


Link to post
Share on other sites
Thanks for those useful posts.

I am thinking about keeping an index buffer "defragmented" so I can use a single Draw() call,
this requires updating a percentage of the index buffer every frame.

(edit)

Oh I see there is no automatic copy operation
so there is only appending data with NoOverwrite
or rebuilding everything with Discard
or lock waits with Default

which brings me back to the original question ...

I can see no good reason for not supporting queued incremental updates.

In a terrain renderer, for example, only the vertices that are changing between not-potentially-visible and potentially-visible
need to be loaded/unloaded from the GPU - which is a tiny percentage!

The way DX9 is designed forces us to: update the entire index buffer every frame *and* forces the GPU to maintain multiple versions of the buffers.

Sending 2kb per frame via command buffer versus 100kb per frame via SetData() has to be more sensible.

Share this post


Link to post
Share on other sites
If you're interested in fast as possible cpu to gpu copies, you should look into getting an AMD fusion processor. Data isn't really copied anywhere, but rather telling the cpu to access certain portions of memory and vice versa. Of coarse you'd also have to use opencl.

Share this post


Link to post
Share on other sites

One approach that works reasonably well is to use a D3DPOOL_MANAGED resource. Lock it, write into it, then Unlock when done


That does sound like a perfect solution, except for DX docs:

Resource management (D3DPOOL_MANAGED) is not recommended for resources which change with high frequency. For example, vertex and index buffers which are used to traverse a scene graph every frame rendering only geometry visible to the user changes every frame. Since managed resources are backed by system memory, the constant changes must be updated in system memory, which can cause a severe degradation in performance. For this particular scenario, D3DPOOL_DEFAULT along with D3DUSAGE_DYNAMIC should be used.

(Of course only profiling will give a true answer)

Share this post


Link to post
Share on other sites

We know data can be transferred in the command queue - that is how DrawUserPrimitives() works
Nope. DrawUserPrimitives internally causes an unqueued SetData before queueing a regular draw command.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!