Skip to content

Resource Barriers

Chuck Walbourn edited this page Apr 22, 2020 · 17 revisions

When you are rendering or running a compute shader, many threads of work are executed on the GPU which in most cases is massively parallel hardware. In order to ensure all pending work (like rendering to a texture) is completed before you use the results in another operation, you have two choices:

  1. You can insert a fence, submit the command-list, and wait for the GPU to stall
  2. You can insert a resource barrier into the command-list which indicates the point at which one state moves to the next.

For example, when uploading textures you first copy the data a 'upload heap' source (which requires the source texture to be in D3D12_RESOURCE_STATE_COPY_SOURCE, and the VRAM texture resource be in D3D12_RESOURCE_STATE_COPY_DEST), then you want to render that just-loaded texture (which typically requires the VRAM texture resource to be in D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE).

Transition Resource Barriers

A number of DirectX Tool Kit for DX12 classes include support these state transition resource barriers. For example, the ResourceUploadBatch lets you automatically queue a transition like the one in the example above:

ResourceUploadBatch resourceUpload(device);

resourceUpload.Begin();

resourceUpload.Upload(texture.Get(), 0, &textureData, 1);

resourceUpload.Transition(
    texture.Get(),
    D3D12_RESOURCE_STATE_COPY_DEST,
    D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);

auto uploadResourcesFinished = resourceUpload.End(m_deviceResources->GetCommandQueue());

uploadResourcesFinished.wait();

In fact, this is done automatically by the DDSTextureLoader / WICTextureLoader since this is the most common use case.

There are similar Transition methods available for GeometricPrimitive and Model when utilizing static vertex buffers & index buffers.

Creating resource barriers

The easiest way to create your own resource barriers is to utilize a D3DX12 helper. Here's a case where you want to transition from being a source of a copy to something used by a compute shader:

auto barrier = CD3DX12_RESOURCE_BARRIER::Transition(texture, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
commandList->ResourceBarrier(1, &barrier);

If to simplify code flow you decide to track state with a variable, you may find the DirectXHelpers TransitionResource method useful.

TransitionResource(commandList, texture, m_txtState, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);

...

TransitionResource(commandList, texture, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, m_txtState);

Batching resource barriers

If you need to execute a number of resource barriers at once, it's best to insert them in a batch. This allows the driver to decide how to handle it based on the GPU architecture. For example, here we have two barriers submitting at once:

D3D12_RESOURCE_BARRIER barriers[2];
barriers[0] = CD3DX12_RESOURCE_BARRIER::Transition(uavBuffer,
    D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
barriers[1] = CD3DX12_RESOURCE_BARRIER::Transition(texture,
    D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_SOURCE);
commandList->ResourceBarrier(_countof(barriers), barriers);

If you have a set of barriers you apply and then reverse, you may find DirectXHelpers's ScopedBarrier class useful:

{
    D3D12_RESOURCE_BARRIER barriers[2];
    barriers[0] = CD3DX12_RESOURCE_BARRIER::Transition(uavBuffer,
        D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
    barriers[1] = CD3DX12_RESOURCE_BARRIER::Transition(texture,
        D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_SOURCE);
    ScopedBarrier rb(commandList, barriers);

    ...

    // At the end of the scope, the same barrier with all the states swapped is executed
}

Further reading

Using Resource Barriers to Synchronize Resource States in Direct3D 12

A Look Inside D3D12 Resource State Barriers

DirectX 12: Resources Barriers and You (You-Tube)

For Use

  • Universal Windows Platform apps
  • Windows desktop apps
  • Windows 11
  • Windows 10
  • Xbox One
  • Xbox Series X|S

Architecture

  • x86
  • x64
  • ARM64

For Development

  • Visual Studio 2022
  • Visual Studio 2019 (16.11)
  • clang/LLVM v12 - v18
  • MinGW 12.2, 13.2
  • CMake 3.20

Related Projects

DirectX Tool Kit for DirectX 11

DirectXMesh

DirectXTex

DirectXMath

Tools

Test Suite

Model Viewer

Content Exporter

DxCapsViewer

See also

DirectX Landing Page

Clone this wiki locally