Sign in to follow this  

[D3D12] Unmap resource while command list is being recorded

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

Say I have a simple frame is set up as follows:

ID3D12CommandAllocator::Reset

ID3D12GraphicsCommandList::Reset

ID3D12Resource::Map  <- this is for a cbuffer

[ copy a new matrix to the mapped pointer for the cbuffer ]

ID3D12Resource::Unmap

[ submit draw calls ]

ID3D12GraphicsCommandList::Close

ID3D12CommandQueue::ExecuteCommandLists

 

Is there any problem with mapping/unmapping that buffer while the command list is being recorded?  The page on Unmap says "Unmap also flushes the CPU cache, when necessary, so that GPU reads to this address reflect any modifications made by the CPU."  I am seeing some weird behaviour when I update the buffer in this manner (single frames where objects jump around), and I don't if I move the map/memcpy/unmap to before the Resets.  But I'm confused, because I would think that the GPU won't try to access that data until after the call to ExecuteCommandLists.

Share this post


Link to post
Share on other sites

Are you synchronizing so that the previous frame is done reading from that cbuffer before you do the memcpy?

 

In general, mapping/unmapping does pretty much nothing on most architectures other than return a pointer, so the memcpy is the interesting thing going on here. And the memcpy should have no interaction with recording of the command list, just the execution.

Share this post


Link to post
Share on other sites

Huh.  So at the end of each frame (after all command lists have been submitted), I signal a fence. (via D3D12CommandQueue::Signal)  At the beginning of a frame I wait on that previously signaled fence (via ID3D12Fence::SetEventOnComplete and WaitForSingleObject).  The memcpy of new data won't take effect until the ID3D12CommandQueue has reached the end of the commands for that previous frame.

 

So my original understanding was correct; mapping/unmapping the buffer while recording a command list should be fine.  Which means I have an issue elsewhere.

Edited by Funkymunky

Share this post


Link to post
Share on other sites

So my original understanding was correct; mapping/unmapping the buffer while recording a command list should be fine.

Yes, you just have to make sure not to map/upmap a resource while the GPU is executing a command list that references that resource. 

at the end of each frame (after all command lists have been submitted), I signal a fence. (via D3D12CommandQueue::Signal)  At the beginning of a frame I wait on that previously signaled fence (via ID3D12Fence::SetEventOnComplete and WaitForSingleObject).

Note that this should work fine, but will give seriously reduced performance compared to a typical D3D11/GL application. This means that the CPU submits a batch of work to the GPU and then has to sit around and wait for the GPU to finish executing that work before the CPU begins to prepare the next frame. Likewise the GPU is sitting around idle waiting for each frame to be delivered by the CPU.
To get ideal performance, you need the CPU and GPU work to overlap, so the CPU is preparing frame N+1 or N+2 while the GPU is executing frame N. ... but doing so means that resource management is suddenly a much harder problem, as the GPU will always be working with the resource that you've given it.

Edited by Hodgman

Share this post


Link to post
Share on other sites

So my original understanding was correct; mapping/unmapping the buffer while recording a command list should be fine.  Which means I have an issue elsewhere.


As Hodgman says, you have to make sure you aren't reusing a buffer which is already being referenced/used by the GPU - it sounds like you are reusing a buffer which is currently being referenced by the GPU in some way; in this case a single constant buffer which you are updating each frame rather than having N-buffers or a large buffer which you only use a segment of each frame (which might be the best way to go).

Share this post


Link to post
Share on other sites
Ok, so do you associate the buffer with the upcoming fence somehow, and stall the CPU right before calling map until that fence has been completed?
i.e. how are you ensuring that the resource isn't in use by the GPU when you map it? Do you have a ring/double buffer of resources?

Share this post


Link to post
Share on other sites

This topic is 399 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this