Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Samples/Desktop/D3D12Multithreading/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,6 @@ extendedZipContent:
This sample demonstrates the use of multiple threads with Direct3D 12. An app can use multithreading to improve efficiency by building command lists on multiple threads asynchronously. The majority of the CPU cost is associated with command list building, not command list execution. Apps must ensure they never concurrently call methods on the same command list or command allocator.

### Optional features
This sample has been updated to build against the Windows 10 Anniversary Update SDK. In this SDK a new revision of Root Signatures is available for Direct3D 12 apps to use. Root Signature 1.1 allows for apps to declare when descriptors in a descriptor heap won't change or the data descriptors point to won't change. This allows the option for drivers to make optimizations that might be possible knowing that something (like a descriptor or the memory it points to) is static for some period of time.
This sample has been updated to build against the Windows 10 Anniversary Update SDK. In this SDK a new revision of Root Signatures is available for Direct3D 12 apps to use. Root Signature 1.1 allows for apps to declare when descriptors in a descriptor heap won't change or the data descriptors point to won't change. This allows the option for drivers to make optimizations that might be possible knowing that something (like a descriptor or the memory it points to) is static for some period of time.

This sample can be built with Enhanced Barriers. Make sure to have the latest driver installed and that your GPU supports this feature. To enable it, choose `<Config Option> (Enhanced Barriers)` option under the configuration dropdown. `<Config Option> (Legacy Barriers)` are also available if running on older hardware.
220 changes: 218 additions & 2 deletions Samples/Desktop/D3D12Multithreading/src/D3D12Multithreading.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,15 @@ void D3D12Multithreading::LoadPipeline()
));
}

#if defined(USE_ENHANCED_BARRIERS)
D3D12_FEATURE_DATA_D3D12_OPTIONS12 options12 = {};
ThrowIfFailed(m_device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS12, &options12, sizeof(options12)));
if (options12.EnhancedBarriersSupported != TRUE)
{
ThrowIfFailed(E_FAIL);
}
#endif // defined(USE_ENHANCED_BARRIERS)

// Describe and create the command queue.
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
Expand Down Expand Up @@ -270,7 +279,7 @@ void D3D12Multithreading::LoadAssets()
}

// Create temporary command list for initial GPU setup.
ComPtr<ID3D12GraphicsCommandList> commandList;
ComPtr<ID3D12GraphicsCommandList8> commandList;
ThrowIfFailed(m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocator.Get(), m_pipelineState.Get(), IID_PPV_ARGS(&commandList)));

// Create render target views (RTVs).
Expand All @@ -286,7 +295,11 @@ void D3D12Multithreading::LoadAssets()

// Create the depth stencil.
{
#if defined(USE_ENHANCED_BARRIERS)
CD3DX12_RESOURCE_DESC1 shadowTextureDesc(
#else
CD3DX12_RESOURCE_DESC shadowTextureDesc(
#endif // defined(USE_ENHANCED_BARRIERS)
D3D12_RESOURCE_DIMENSION_TEXTURE2D,
0,
static_cast<UINT>(m_viewport.Width),
Expand All @@ -304,13 +317,26 @@ void D3D12Multithreading::LoadAssets()
clearValue.DepthStencil.Depth = 1.0f;
clearValue.DepthStencil.Stencil = 0;

#if defined(USE_ENHANCED_BARRIERS)
ThrowIfFailed(m_device->CreateCommittedResource3(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
D3D12_HEAP_FLAG_NONE,
&shadowTextureDesc,
D3D12_BARRIER_LAYOUT_DEPTH_STENCIL_WRITE,
&clearValue,
nullptr,
0,
nullptr,
IID_PPV_ARGS(&m_depthStencil)));
#else
ThrowIfFailed(m_device->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
D3D12_HEAP_FLAG_NONE,
&shadowTextureDesc,
D3D12_RESOURCE_STATE_DEPTH_WRITE,
&clearValue,
IID_PPV_ARGS(&m_depthStencil)));
#endif // defined(USE_ENHANCED_BARRIERS)

NAME_D3D12_OBJECT(m_depthStencil);

Expand All @@ -325,24 +351,50 @@ void D3D12Multithreading::LoadAssets()

// Create the vertex buffer.
{
#if defined(USE_ENHANCED_BARRIERS)
ThrowIfFailed(m_device->CreateCommittedResource3(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC1::Buffer(SampleAssets::VertexDataSize),
D3D12_BARRIER_LAYOUT_UNDEFINED,
nullptr,
nullptr,
0,
nullptr,
IID_PPV_ARGS(&m_vertexBuffer)));
#else
ThrowIfFailed(m_device->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(SampleAssets::VertexDataSize),
D3D12_RESOURCE_STATE_COPY_DEST,
nullptr,
IID_PPV_ARGS(&m_vertexBuffer)));
#endif // defined(USE_ENHANCED_BARRIERS)

NAME_D3D12_OBJECT(m_vertexBuffer);

{
#if defined(USE_ENHANCED_BARRIERS)
ThrowIfFailed(m_device->CreateCommittedResource3(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC1::Buffer(SampleAssets::VertexDataSize),
D3D12_BARRIER_LAYOUT_UNDEFINED,
nullptr,
nullptr,
0,
nullptr,
IID_PPV_ARGS(&m_vertexBufferUpload)));
#else
ThrowIfFailed(m_device->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(SampleAssets::VertexDataSize),
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&m_vertexBufferUpload)));
#endif // defined(USE_ENHANCED_BARRIERS)

// Copy data to the upload heap and then schedule a copy
// from the upload heap to the vertex buffer.
Expand All @@ -354,7 +406,24 @@ void D3D12Multithreading::LoadAssets()
PIXBeginEvent(commandList.Get(), 0, L"Copy vertex buffer data to default resource...");

UpdateSubresources<1>(commandList.Get(), m_vertexBuffer.Get(), m_vertexBufferUpload.Get(), 0, 0, 1, &vertexData);
#if defined(USE_ENHANCED_BARRIERS)
D3D12_BUFFER_BARRIER VertexBufBarriers[] =
{
CD3DX12_BUFFER_BARRIER(
D3D12_BARRIER_SYNC_COPY, // SyncBefore
D3D12_BARRIER_SYNC_VERTEX_SHADING, // SyncAfter
D3D12_BARRIER_ACCESS_COPY_DEST, // AccessBefore
D3D12_BARRIER_ACCESS_VERTEX_BUFFER, // AccessAfter
m_vertexBuffer.Get()
)
};

D3D12_BARRIER_GROUP VertexBufBarrierGroups[] = { CD3DX12_BARRIER_GROUP(_countof(VertexBufBarriers), VertexBufBarriers)};

commandList->Barrier(_countof(VertexBufBarrierGroups), VertexBufBarrierGroups);
#else
commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_vertexBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER));
#endif // defined(USE_ENHANCED_BARRIERS)

PIXEndEvent(commandList.Get());
}
Expand All @@ -367,25 +436,51 @@ void D3D12Multithreading::LoadAssets()

// Create the index buffer.
{
#if defined(USE_ENHANCED_BARRIERS)
ThrowIfFailed(m_device->CreateCommittedResource3(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC1::Buffer(SampleAssets::IndexDataSize),
D3D12_BARRIER_LAYOUT_UNDEFINED,
nullptr,
nullptr,
0,
nullptr,
IID_PPV_ARGS(&m_indexBuffer)));
#else
ThrowIfFailed(m_device->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(SampleAssets::IndexDataSize),
D3D12_RESOURCE_STATE_COPY_DEST,
nullptr,
IID_PPV_ARGS(&m_indexBuffer)));
#endif // defined(USE_ENHANCED_BARRIERS)

NAME_D3D12_OBJECT(m_indexBuffer);

{

#if defined(USE_ENHANCED_BARRIERS)
ThrowIfFailed(m_device->CreateCommittedResource3(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC1::Buffer(SampleAssets::IndexDataSize),
D3D12_BARRIER_LAYOUT_UNDEFINED,
nullptr,
nullptr,
0,
nullptr,
IID_PPV_ARGS(&m_indexBufferUpload)));
#else
ThrowIfFailed(m_device->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(SampleAssets::IndexDataSize),
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&m_indexBufferUpload)));

#endif // defined(USE_ENHANCED_BARRIERS)
// Copy data to the upload heap and then schedule a copy
// from the upload heap to the index buffer.
D3D12_SUBRESOURCE_DATA indexData = {};
Expand All @@ -396,7 +491,25 @@ void D3D12Multithreading::LoadAssets()
PIXBeginEvent(commandList.Get(), 0, L"Copy index buffer data to default resource...");

UpdateSubresources<1>(commandList.Get(), m_indexBuffer.Get(), m_indexBufferUpload.Get(), 0, 0, 1, &indexData);

#if defined(USE_ENHANCED_BARRIERS)
D3D12_BUFFER_BARRIER BufBarriers[] =
{
CD3DX12_BUFFER_BARRIER(
D3D12_BARRIER_SYNC_COPY, // SyncBefore
D3D12_BARRIER_SYNC_INDEX_INPUT, // SyncAfter
D3D12_BARRIER_ACCESS_COPY_DEST, // AccessBefore
D3D12_BARRIER_ACCESS_INDEX_BUFFER, // AccessAfter
m_indexBuffer.Get()
)
};

D3D12_BARRIER_GROUP BufBarrierGroups[] = { CD3DX12_BARRIER_GROUP(_countof(BufBarriers), BufBarriers)};

commandList->Barrier(_countof(BufBarrierGroups), BufBarrierGroups);
#else
commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_indexBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_INDEX_BUFFER));
#endif // defined(USE_ENHANCED_BARRIERS)

PIXEndEvent(commandList.Get());
}
Expand Down Expand Up @@ -440,6 +553,32 @@ void D3D12Multithreading::LoadAssets()
{
// Describe and create a Texture2D.
const SampleAssets::TextureResource &tex = SampleAssets::Textures[i];

#if defined(USE_ENHANCED_BARRIERS)
CD3DX12_RESOURCE_DESC1 texDesc(
D3D12_RESOURCE_DIMENSION_TEXTURE2D,
0,
tex.Width,
tex.Height,
1,
static_cast<UINT16>(tex.MipLevels),
tex.Format,
1,
0,
D3D12_TEXTURE_LAYOUT_UNKNOWN,
D3D12_RESOURCE_FLAG_NONE);

ThrowIfFailed(m_device->CreateCommittedResource3(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
D3D12_HEAP_FLAG_NONE,
&texDesc,
D3D12_BARRIER_LAYOUT_COPY_DEST,
nullptr,
nullptr,
0,
nullptr,
IID_PPV_ARGS(&m_textures[i])));
#else
CD3DX12_RESOURCE_DESC texDesc(
D3D12_RESOURCE_DIMENSION_TEXTURE2D,
0,
Expand All @@ -460,19 +599,33 @@ void D3D12Multithreading::LoadAssets()
D3D12_RESOURCE_STATE_COPY_DEST,
nullptr,
IID_PPV_ARGS(&m_textures[i])));
#endif // defined(USE_ENHANCED_BARRIERS)

NAME_D3D12_OBJECT_INDEXED(m_textures, i);

{
const UINT subresourceCount = texDesc.DepthOrArraySize * texDesc.MipLevels;
UINT64 uploadBufferSize = GetRequiredIntermediateSize(m_textures[i].Get(), 0, subresourceCount);
#if defined(USE_ENHANCED_BARRIERS)
ThrowIfFailed(m_device->CreateCommittedResource3(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC1::Buffer(uploadBufferSize),
D3D12_BARRIER_LAYOUT_UNDEFINED,
nullptr,
nullptr,
0,
nullptr,
IID_PPV_ARGS(&m_textureUploads[i])));
#else
ThrowIfFailed(m_device->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize),
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&m_textureUploads[i])));
#endif // defined(USE_ENHANCED_BARRIERS)

// Copy data to the intermediate upload heap and then schedule a copy
// from the upload heap to the Texture2D.
Expand All @@ -482,7 +635,28 @@ void D3D12Multithreading::LoadAssets()
textureData.SlicePitch = tex.Data->Size;

UpdateSubresources(commandList.Get(), m_textures[i].Get(), m_textureUploads[i].Get(), 0, 0, subresourceCount, &textureData);
#if defined(USE_ENHANCED_BARRIERS)
D3D12_TEXTURE_BARRIER TexturesBarriers[] =
{
CD3DX12_TEXTURE_BARRIER(
D3D12_BARRIER_SYNC_COPY, // SyncBefore
D3D12_BARRIER_SYNC_PIXEL_SHADING, // SyncAfter
D3D12_BARRIER_ACCESS_COPY_DEST, // AccessBefore
D3D12_BARRIER_ACCESS_SHADER_RESOURCE, // AccessAfter
D3D12_BARRIER_LAYOUT_COPY_DEST, // LayoutBefore
D3D12_BARRIER_LAYOUT_SHADER_RESOURCE, // LayoutAfter
m_textures[i].Get(),
CD3DX12_BARRIER_SUBRESOURCE_RANGE(0xffffffff), // All subresources
D3D12_TEXTURE_BARRIER_FLAG_NONE
)
};

D3D12_BARRIER_GROUP TextureBarrierGroups[] = { CD3DX12_BARRIER_GROUP(_countof(TexturesBarriers), TexturesBarriers) };

commandList->Barrier(_countof(TextureBarrierGroups), TextureBarrierGroups);
#else
commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_textures[i].Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE));
#endif // defined(USE_ENHANCED_BARRIERS)
}

// Describe and create an SRV.
Expand Down Expand Up @@ -914,8 +1088,29 @@ void D3D12Multithreading::BeginFrame()
{
m_pCurrentFrameResource->Init();

#if defined(USE_ENHANCED_BARRIERS)
D3D12_TEXTURE_BARRIER BeginFrameBarriers[] =
{
CD3DX12_TEXTURE_BARRIER(
D3D12_BARRIER_SYNC_NONE, // SyncBefore
D3D12_BARRIER_SYNC_RENDER_TARGET, // SyncAfter
D3D12_BARRIER_ACCESS_NO_ACCESS, // AccessBefore
D3D12_BARRIER_ACCESS_RENDER_TARGET, // AccessAfter
D3D12_BARRIER_LAYOUT_PRESENT, // LayoutBefore
D3D12_BARRIER_LAYOUT_RENDER_TARGET, // LayoutAfter
m_renderTargets[m_frameIndex].Get(),
CD3DX12_BARRIER_SUBRESOURCE_RANGE(0xffffffff), // All subresources
D3D12_TEXTURE_BARRIER_FLAG_NONE
)
};

D3D12_BARRIER_GROUP BeginFrameBarriersGroups[] = { CD3DX12_BARRIER_GROUP(_countof(BeginFrameBarriers), BeginFrameBarriers) };

m_pCurrentFrameResource->m_commandLists[CommandListPre]->Barrier(_countof(BeginFrameBarriersGroups), BeginFrameBarriersGroups);
#else
// Indicate that the back buffer will be used as a render target.
m_pCurrentFrameResource->m_commandLists[CommandListPre]->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_frameIndex].Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET));
#endif // defined(USE_ENHANCED_BARRIERS)

// Clear the render target and depth stencil.
const float clearColor[] = { 0.0f, 0.0f, 0.0f, 1.0f };
Expand All @@ -940,8 +1135,29 @@ void D3D12Multithreading::EndFrame()
{
m_pCurrentFrameResource->Finish();

#if defined(USE_ENHANCED_BARRIERS)
D3D12_TEXTURE_BARRIER EndFrameBarriers[] =
{
CD3DX12_TEXTURE_BARRIER(
D3D12_BARRIER_SYNC_RENDER_TARGET, // SyncBefore
D3D12_BARRIER_SYNC_NONE, // SyncAfter
D3D12_BARRIER_ACCESS_RENDER_TARGET, // AccessBefore
D3D12_BARRIER_ACCESS_NO_ACCESS, // AccessAfter
D3D12_BARRIER_LAYOUT_RENDER_TARGET, // LayoutBefore
D3D12_BARRIER_LAYOUT_PRESENT, // LayoutAfter
m_renderTargets[m_frameIndex].Get(),
CD3DX12_BARRIER_SUBRESOURCE_RANGE(0xffffffff), // All subresources
D3D12_TEXTURE_BARRIER_FLAG_NONE
)
};

D3D12_BARRIER_GROUP EndFrameBarrierGroups[] = { CD3DX12_BARRIER_GROUP(_countof(EndFrameBarriers), EndFrameBarriers) };

m_pCurrentFrameResource->m_commandLists[CommandListPost]->Barrier(_countof(EndFrameBarrierGroups), EndFrameBarrierGroups);
#else
// Indicate that the back buffer will now be used to present.
m_pCurrentFrameResource->m_commandLists[CommandListPost]->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_frameIndex].Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT));
#endif // defined(USE_ENHANCED_BARRIERS)

ThrowIfFailed(m_pCurrentFrameResource->m_commandLists[CommandListPost]->Close());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class D3D12Multithreading : public DXSample
CD3DX12_VIEWPORT m_viewport;
CD3DX12_RECT m_scissorRect;
ComPtr<IDXGISwapChain3> m_swapChain;
ComPtr<ID3D12Device> m_device;
ComPtr<ID3D12Device10> m_device;
ComPtr<ID3D12Resource> m_renderTargets[FrameCount];
ComPtr<ID3D12Resource> m_depthStencil;
ComPtr<ID3D12CommandAllocator> m_commandAllocator;
Expand Down
Loading