diff --git a/Samples/Desktop/D3D12Multithreading/readme.md b/Samples/Desktop/D3D12Multithreading/readme.md index c74a861c1..1447e4bf9 100644 --- a/Samples/Desktop/D3D12Multithreading/readme.md +++ b/Samples/Desktop/D3D12Multithreading/readme.md @@ -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. \ No newline at end of file +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 is built with Enhanced Barriers. The sample will use Enhanced Barriers if the hardware supports it. If not, Legacy Barriers will be used instead. \ No newline at end of file diff --git a/Samples/Desktop/D3D12Multithreading/src/D3D12Multithreading.cpp b/Samples/Desktop/D3D12Multithreading/src/D3D12Multithreading.cpp index f28999d41..e0a37d919 100644 --- a/Samples/Desktop/D3D12Multithreading/src/D3D12Multithreading.cpp +++ b/Samples/Desktop/D3D12Multithreading/src/D3D12Multithreading.cpp @@ -14,6 +14,7 @@ #include "FrameResource.h" D3D12Multithreading* D3D12Multithreading::s_app = nullptr; +bool D3D12Multithreading::s_bIsEnhancedBarriersEnabled = false; extern "C" { __declspec(dllexport) extern const UINT D3D12SDKVersion = 618; } extern "C" { __declspec(dllexport) extern const char* D3D12SDKPath = u8".\\D3D12\\"; } @@ -96,6 +97,10 @@ void D3D12Multithreading::LoadPipeline() )); } + D3D12_FEATURE_DATA_D3D12_OPTIONS12 options12 = {}; + ThrowIfFailed(m_device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS12, &options12, sizeof(options12))); + s_bIsEnhancedBarriersEnabled = static_cast(options12.EnhancedBarriersSupported); + // Describe and create the command queue. D3D12_COMMAND_QUEUE_DESC queueDesc = {}; queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; @@ -270,7 +275,7 @@ void D3D12Multithreading::LoadAssets() } // Create temporary command list for initial GPU setup. - ComPtr commandList; + ComPtr 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). @@ -304,13 +309,29 @@ void D3D12Multithreading::LoadAssets() clearValue.DepthStencil.Depth = 1.0f; clearValue.DepthStencil.Stencil = 0; - 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))); + if (s_bIsEnhancedBarriersEnabled) + { + ThrowIfFailed(m_device->CreateCommittedResource3( + &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), + D3D12_HEAP_FLAG_NONE, + &CD3DX12_RESOURCE_DESC1(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))); + } NAME_D3D12_OBJECT(m_depthStencil); @@ -325,24 +346,56 @@ void D3D12Multithreading::LoadAssets() // Create the vertex buffer. { - 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))); - - NAME_D3D12_OBJECT(m_vertexBuffer); - + if (s_bIsEnhancedBarriersEnabled) + { + 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_UPLOAD), + &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(SampleAssets::VertexDataSize), - D3D12_RESOURCE_STATE_GENERIC_READ, + D3D12_RESOURCE_STATE_COPY_DEST, nullptr, - IID_PPV_ARGS(&m_vertexBufferUpload))); + IID_PPV_ARGS(&m_vertexBuffer))); + } + + NAME_D3D12_OBJECT(m_vertexBuffer); + + { + if (s_bIsEnhancedBarriersEnabled) + { + 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))); + } // Copy data to the upload heap and then schedule a copy // from the upload heap to the vertex buffer. @@ -354,8 +407,26 @@ 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); - commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_vertexBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER)); + if (s_bIsEnhancedBarriersEnabled) + { + 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)); + } PIXEndEvent(commandList.Get()); } @@ -367,24 +438,56 @@ void D3D12Multithreading::LoadAssets() // Create the index buffer. { - 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))); - - NAME_D3D12_OBJECT(m_indexBuffer); - + if (s_bIsEnhancedBarriersEnabled) + { + 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_UPLOAD), + &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(SampleAssets::IndexDataSize), - D3D12_RESOURCE_STATE_GENERIC_READ, + D3D12_RESOURCE_STATE_COPY_DEST, nullptr, - IID_PPV_ARGS(&m_indexBufferUpload))); + IID_PPV_ARGS(&m_indexBuffer))); + } + + NAME_D3D12_OBJECT(m_indexBuffer); + + { + if (s_bIsEnhancedBarriersEnabled) + { + 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))); + } // Copy data to the upload heap and then schedule a copy // from the upload heap to the index buffer. @@ -396,7 +499,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); - commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_indexBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_INDEX_BUFFER)); + if (s_bIsEnhancedBarriersEnabled) + { + 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)); + } PIXEndEvent(commandList.Get()); } @@ -453,26 +574,59 @@ void D3D12Multithreading::LoadAssets() D3D12_TEXTURE_LAYOUT_UNKNOWN, D3D12_RESOURCE_FLAG_NONE); - ThrowIfFailed(m_device->CreateCommittedResource( - &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), - D3D12_HEAP_FLAG_NONE, - &texDesc, - D3D12_RESOURCE_STATE_COPY_DEST, - nullptr, - IID_PPV_ARGS(&m_textures[i]))); + if (s_bIsEnhancedBarriersEnabled) + { + ThrowIfFailed(m_device->CreateCommittedResource3( + &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), + D3D12_HEAP_FLAG_NONE, + &CD3DX12_RESOURCE_DESC1(texDesc), + D3D12_BARRIER_LAYOUT_COPY_DEST, + nullptr, + nullptr, + 0, + nullptr, + IID_PPV_ARGS(&m_textures[i]))); + } + else + { + ThrowIfFailed(m_device->CreateCommittedResource( + &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), + D3D12_HEAP_FLAG_NONE, + &texDesc, + D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, + IID_PPV_ARGS(&m_textures[i]))); + } NAME_D3D12_OBJECT_INDEXED(m_textures, i); { const UINT subresourceCount = texDesc.DepthOrArraySize * texDesc.MipLevels; UINT64 uploadBufferSize = GetRequiredIntermediateSize(m_textures[i].Get(), 0, subresourceCount); - 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]))); + + if (s_bIsEnhancedBarriersEnabled) + { + 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]))); + } // Copy data to the intermediate upload heap and then schedule a copy // from the upload heap to the Texture2D. @@ -482,7 +636,30 @@ void D3D12Multithreading::LoadAssets() textureData.SlicePitch = tex.Data->Size; UpdateSubresources(commandList.Get(), m_textures[i].Get(), m_textureUploads[i].Get(), 0, 0, subresourceCount, &textureData); - commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_textures[i].Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE)); + + if (s_bIsEnhancedBarriersEnabled) + { + 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)); + } } // Describe and create an SRV. @@ -914,8 +1091,37 @@ void D3D12Multithreading::BeginFrame() { m_pCurrentFrameResource->Init(); - // 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)); + if (s_bIsEnhancedBarriersEnabled) + { + D3D12_TEXTURE_BARRIER BeginFrameBarriers[] = + { + // Using SYNC_NONE and ACCESS_NO_ACCESS with Enhanced Barrier to avoid unnecessary sync/flush. + // Using them explicitly tells the GPU it is okay to immediately transition + // the layout without waiting for preceding work to complete. + // In this case, the legacy barrier would flush and finish any preceding work that may potentially be reading from the RT + // resource (in this case there is none) + 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)); + } // Clear the render target and depth stencil. const float clearColor[] = { 0.0f, 0.0f, 0.0f, 1.0f }; @@ -940,8 +1146,32 @@ void D3D12Multithreading::EndFrame() { m_pCurrentFrameResource->Finish(); - // 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)); + if (s_bIsEnhancedBarriersEnabled) + { + D3D12_TEXTURE_BARRIER EndFrameBarriers[] = + { + // Using SYNC_NONE and ACCESS_NO_ACCESS with Enhanced Barrier means subsequent + // commands are unblocked without having to wait for the barrier to complete. + 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)); + } ThrowIfFailed(m_pCurrentFrameResource->m_commandLists[CommandListPost]->Close()); } diff --git a/Samples/Desktop/D3D12Multithreading/src/D3D12Multithreading.h b/Samples/Desktop/D3D12Multithreading/src/D3D12Multithreading.h index 5cb0061a7..929fd501e 100644 --- a/Samples/Desktop/D3D12Multithreading/src/D3D12Multithreading.h +++ b/Samples/Desktop/D3D12Multithreading/src/D3D12Multithreading.h @@ -57,6 +57,8 @@ class D3D12Multithreading : public DXSample static D3D12Multithreading* Get() { return s_app; } + static bool IsEnhancedBarriersEnabled() { return s_bIsEnhancedBarriersEnabled; } + virtual void OnInit(); virtual void OnUpdate(); virtual void OnRender(); @@ -78,7 +80,7 @@ class D3D12Multithreading : public DXSample CD3DX12_VIEWPORT m_viewport; CD3DX12_RECT m_scissorRect; ComPtr m_swapChain; - ComPtr m_device; + ComPtr m_device; ComPtr m_renderTargets[FrameCount]; ComPtr m_depthStencil; ComPtr m_commandAllocator; @@ -128,6 +130,8 @@ class D3D12Multithreading : public DXSample FrameResource* m_pCurrentFrameResource; int m_currentFrameResourceIndex; + static bool s_bIsEnhancedBarriersEnabled; + struct ThreadParameter { int threadIndex; diff --git a/Samples/Desktop/D3D12Multithreading/src/FrameResource.cpp b/Samples/Desktop/D3D12Multithreading/src/FrameResource.cpp index 9c498aa02..8d2c3faf0 100644 --- a/Samples/Desktop/D3D12Multithreading/src/FrameResource.cpp +++ b/Samples/Desktop/D3D12Multithreading/src/FrameResource.cpp @@ -13,7 +13,7 @@ #include "FrameResource.h" #include "SquidRoom.h" -FrameResource::FrameResource(ID3D12Device* pDevice, ID3D12PipelineState* pPso, ID3D12PipelineState* pShadowMapPso, ID3D12DescriptorHeap* pDsvHeap, ID3D12DescriptorHeap* pCbvSrvHeap, D3D12_VIEWPORT* pViewport, UINT frameResourceIndex) : +FrameResource::FrameResource(ID3D12Device10* pDevice, ID3D12PipelineState* pPso, ID3D12PipelineState* pShadowMapPso, ID3D12DescriptorHeap* pDsvHeap, ID3D12DescriptorHeap* pCbvSrvHeap, D3D12_VIEWPORT* pViewport, UINT frameResourceIndex) : m_fenceValue(0), m_pipelineState(pPso), m_pipelineStateShadowMap(pShadowMapPso) @@ -67,13 +67,29 @@ FrameResource::FrameResource(ID3D12Device* pDevice, ID3D12PipelineState* pPso, I clearValue.DepthStencil.Depth = 1.0f; clearValue.DepthStencil.Stencil = 0; - ThrowIfFailed(pDevice->CreateCommittedResource( - &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), - D3D12_HEAP_FLAG_NONE, - &shadowTexDesc, - D3D12_RESOURCE_STATE_DEPTH_WRITE, - &clearValue, - IID_PPV_ARGS(&m_shadowTexture))); + if (D3D12Multithreading::IsEnhancedBarriersEnabled()) + { + ThrowIfFailed(pDevice->CreateCommittedResource3( + &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), + D3D12_HEAP_FLAG_NONE, + &CD3DX12_RESOURCE_DESC1(shadowTexDesc), + D3D12_BARRIER_LAYOUT_DEPTH_STENCIL_WRITE, + &clearValue, + nullptr, + 0, + nullptr, + IID_PPV_ARGS(&m_shadowTexture))); + } + else + { + ThrowIfFailed(pDevice->CreateCommittedResource( + &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), + D3D12_HEAP_FLAG_NONE, + &shadowTexDesc, + D3D12_RESOURCE_STATE_DEPTH_WRITE, + &clearValue, + IID_PPV_ARGS(&m_shadowTexture))); + } NAME_D3D12_OBJECT(m_shadowTexture); @@ -121,20 +137,47 @@ FrameResource::FrameResource(ID3D12Device* pDevice, ID3D12PipelineState* pPso, I // Create the constant buffers. const UINT constantBufferSize = (sizeof(SceneConstantBuffer) + (D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT - 1)) & ~(D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT - 1); // must be a multiple 256 bytes - ThrowIfFailed(pDevice->CreateCommittedResource( - &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), - D3D12_HEAP_FLAG_NONE, - &CD3DX12_RESOURCE_DESC::Buffer(constantBufferSize), - D3D12_RESOURCE_STATE_GENERIC_READ, - nullptr, - IID_PPV_ARGS(&m_shadowConstantBuffer))); - ThrowIfFailed(pDevice->CreateCommittedResource( - &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), - D3D12_HEAP_FLAG_NONE, - &CD3DX12_RESOURCE_DESC::Buffer(constantBufferSize), - D3D12_RESOURCE_STATE_GENERIC_READ, - nullptr, - IID_PPV_ARGS(&m_sceneConstantBuffer))); + + if (D3D12Multithreading::IsEnhancedBarriersEnabled()) + { + ThrowIfFailed(pDevice->CreateCommittedResource3( + &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), + D3D12_HEAP_FLAG_NONE, + &CD3DX12_RESOURCE_DESC1::Buffer(constantBufferSize), + D3D12_BARRIER_LAYOUT_UNDEFINED, + nullptr, + nullptr, + 0, + nullptr, + IID_PPV_ARGS(&m_shadowConstantBuffer))); + ThrowIfFailed(pDevice->CreateCommittedResource3( + &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), + D3D12_HEAP_FLAG_NONE, + &CD3DX12_RESOURCE_DESC1::Buffer(constantBufferSize), + D3D12_BARRIER_LAYOUT_UNDEFINED, + nullptr, + nullptr, + 0, + nullptr, + IID_PPV_ARGS(&m_sceneConstantBuffer))); + } + else + { + ThrowIfFailed(pDevice->CreateCommittedResource( + &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), + D3D12_HEAP_FLAG_NONE, + &CD3DX12_RESOURCE_DESC::Buffer(constantBufferSize), + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_PPV_ARGS(&m_shadowConstantBuffer))); + ThrowIfFailed(pDevice->CreateCommittedResource( + &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), + D3D12_HEAP_FLAG_NONE, + &CD3DX12_RESOURCE_DESC::Buffer(constantBufferSize), + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_PPV_ARGS(&m_sceneConstantBuffer))); + } // Map the constant buffers and cache their heap pointers. CD3DX12_RANGE readRange(0, 0); // We do not intend to read from this resource on the CPU. @@ -254,13 +297,57 @@ void FrameResource::Init() void FrameResource::SwapBarriers() { - // Transition the shadow map from writeable to readable. - m_commandLists[CommandListMid]->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_shadowTexture.Get(), D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE)); + if (D3D12Multithreading::IsEnhancedBarriersEnabled()) + { + D3D12_TEXTURE_BARRIER ShadowTextureBarriers[] = + { + CD3DX12_TEXTURE_BARRIER( + D3D12_BARRIER_SYNC_DEPTH_STENCIL, // SyncBefore + D3D12_BARRIER_SYNC_PIXEL_SHADING, // SyncAfter + D3D12_BARRIER_ACCESS_DEPTH_STENCIL_WRITE, // AccessBefore + D3D12_BARRIER_ACCESS_SHADER_RESOURCE, // AccessAfter + D3D12_BARRIER_LAYOUT_DEPTH_STENCIL_WRITE, // LayoutBefore + D3D12_BARRIER_LAYOUT_SHADER_RESOURCE, // LayoutAfter + m_shadowTexture.Get(), + CD3DX12_BARRIER_SUBRESOURCE_RANGE(0xffffffff), // All subresources + D3D12_TEXTURE_BARRIER_FLAG_NONE + ) + }; + D3D12_BARRIER_GROUP ShadowTextureBarrierGroups[] = { CD3DX12_BARRIER_GROUP(_countof(ShadowTextureBarriers), ShadowTextureBarriers) }; + m_commandLists[CommandListMid]->Barrier(_countof(ShadowTextureBarrierGroups), ShadowTextureBarrierGroups); + } + else + { + // Transition the shadow map from writeable to readable. + m_commandLists[CommandListMid]->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_shadowTexture.Get(), D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE)); + } } void FrameResource::Finish() { - m_commandLists[CommandListPost]->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_shadowTexture.Get(), D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_DEPTH_WRITE)); + if (D3D12Multithreading::IsEnhancedBarriersEnabled()) + { + D3D12_TEXTURE_BARRIER FinishTexBarrier[] = + { + CD3DX12_TEXTURE_BARRIER( + D3D12_BARRIER_SYNC_PIXEL_SHADING, // SyncBefore + D3D12_BARRIER_SYNC_DEPTH_STENCIL, // SyncAfter + D3D12_BARRIER_ACCESS_SHADER_RESOURCE, // AccessBefore + D3D12_BARRIER_ACCESS_DEPTH_STENCIL_WRITE, // AccessAfter + D3D12_BARRIER_LAYOUT_SHADER_RESOURCE, // LayoutBefore + D3D12_BARRIER_LAYOUT_DEPTH_STENCIL_WRITE, // LayoutAfter + m_shadowTexture.Get(), + CD3DX12_BARRIER_SUBRESOURCE_RANGE(0xffffffff), // All subresources + D3D12_TEXTURE_BARRIER_FLAG_NONE + ) + }; + D3D12_BARRIER_GROUP FinishTexBarrierGroups[] = { CD3DX12_BARRIER_GROUP(_countof(FinishTexBarrier), FinishTexBarrier) }; + m_commandLists[CommandListPost]->Barrier(_countof(FinishTexBarrierGroups), FinishTexBarrierGroups); + } + else + { + m_commandLists[CommandListPost]->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_shadowTexture.Get(), D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_DEPTH_WRITE)); + } } // Sets up the descriptor tables for the worker command list to use diff --git a/Samples/Desktop/D3D12Multithreading/src/FrameResource.h b/Samples/Desktop/D3D12Multithreading/src/FrameResource.h index 845c9cc03..37dd09fb4 100644 --- a/Samples/Desktop/D3D12Multithreading/src/FrameResource.h +++ b/Samples/Desktop/D3D12Multithreading/src/FrameResource.h @@ -25,7 +25,7 @@ class FrameResource ID3D12CommandList* m_batchSubmit[NumContexts * 2 + CommandListCount]; ComPtr m_commandAllocators[CommandListCount]; - ComPtr m_commandLists[CommandListCount]; + ComPtr m_commandLists[CommandListCount]; ComPtr m_shadowCommandAllocators[NumContexts]; ComPtr m_shadowCommandLists[NumContexts]; @@ -50,7 +50,7 @@ class FrameResource D3D12_GPU_DESCRIPTOR_HANDLE m_sceneCbvHandle; public: - FrameResource(ID3D12Device* pDevice, ID3D12PipelineState* pPso, ID3D12PipelineState* pShadowMapPso, ID3D12DescriptorHeap* pDsvHeap, ID3D12DescriptorHeap* pCbvSrvHeap, D3D12_VIEWPORT* pViewport, UINT frameResourceIndex); + FrameResource(ID3D12Device10* pDevice, ID3D12PipelineState* pPso, ID3D12PipelineState* pShadowMapPso, ID3D12DescriptorHeap* pDsvHeap, ID3D12DescriptorHeap* pCbvSrvHeap, D3D12_VIEWPORT* pViewport, UINT frameResourceIndex); ~FrameResource(); void Bind(ID3D12GraphicsCommandList* pCommandList, BOOL scenePass, D3D12_CPU_DESCRIPTOR_HANDLE* pRtvHandle, D3D12_CPU_DESCRIPTOR_HANDLE* pDsvHandle);