Synchronize

If you are good at fencing you will be good at DX12

Fence

A fence is an UINT64 that can be used to synchronize the CPU with the GPU queues and also the GPU queue with each other.

Create a Fence

Create it with the ID3D12Device::CreateFence() method. It takes a the start value (integer), option flags and the pointer to return the fence in.

Get the value of a fence

To get the value of the fence use ID3D12Fence::GetCompletedValue()

CPU: Set the value

Use ID3D12Fence::Signal () to set the fence value on the CPU.

GPU: Set the value

You use ID3D12CommandQueue::Signal() and when the GPU reaches that point in the queue it will change the fence value.

Do things when a fence changes to a value

Use ID3D12Fence::SetEventOnCompletion() to select a event object and the value of the fence for the event to be signalled.

Make a GPU queue wait on another GPU queue

If you have more then one queue, for example Direct and a Copy one, use ID3D12CommandQueue::Wait() to make it wait for a fence. It will wait until the fence value is the same or exceed the value given as a wait parameter.

Resource States

When a resource is used it needs to be in the correct state. It's state is changed with ID3D12GraphicsCommandList::ResourceBarrier(). To describe each change a D3D12_RESOURCE_BARRIER() structure is used. The function takes an array of structures so try to batch barriers to be done at the same time. Avoid doing redundant transitions. There are three types of barrier descriptions.

D3D12_RESOURCE_TRANSITION_BARRIER

This barrier tells the GPU to transition a resource or subresources from one state to another. One must give both the state the it have now (before) and the one it it should change to (after). In the structure one needs to fill in the resource and the subresource index. It is possible to use D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES (0xffffffff) to change all subresources in the resource at the same time.

Always use the most contrained state possible on a resource so avoid COMMON and GENERIC_READ. COMMON is needed for CPU access to textures and GENERIC_READ for upload heaps.

Split resource barriers

A split barrier is made up of two barrier with one set with the flag FLAG_BEGIN_ONLY and the next with FLAG_END_ONLY. The other parameters need to be the same to the both commands and the resource will by in a no-access condition between the two barriers. It is possible to do other work between the barriers. The transition might complete before the end flag and then the cost of the transition is more or less free.

D3D12_RESOURCE_ALIASING_BARRIER

Used to change the usage of tiled resources.

D3D12_RESOURCE_UAV_BARRIER

With this one can make sure that all Read/Write operations is finished after this barrier is done.