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.

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.

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?