From 55542837175353018f68a483a4922496d64f2d05 Mon Sep 17 00:00:00 2001 From: Yunchao He Date: Mon, 9 Dec 2019 21:01:28 +0000 Subject: [PATCH] Implement readonly storage buffer on D3D12 backend This change implements D3D12 backend for readonly storage buffer. It uses SRV in root signature at API side and ByteAddressBuffer at shader side (has already been done in spirv-cross) for readonly storage buffer. BUG=dawn:180, dawn:284 Change-Id: Iafcd24835a75349ce719e9735752de50210a846f Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/14300 Reviewed-by: Austin Eng Reviewed-by: Corentin Wallez Commit-Queue: Yunchao He --- src/dawn_native/d3d12/BindGroupD3D12.cpp | 21 ++++++++++++++++++- .../d3d12/BindGroupLayoutD3D12.cpp | 6 +++--- src/dawn_native/d3d12/BufferD3D12.cpp | 4 ++++ src/dawn_native/d3d12/CommandBufferD3D12.cpp | 10 ++++++++- src/dawn_native/d3d12/PipelineLayoutD3D12.cpp | 3 ++- .../end2end/GpuMemorySynchronizationTests.cpp | 3 +-- 6 files changed, 39 insertions(+), 8 deletions(-) diff --git a/src/dawn_native/d3d12/BindGroupD3D12.cpp b/src/dawn_native/d3d12/BindGroupD3D12.cpp index 38ca3a4c97..60a67d2072 100644 --- a/src/dawn_native/d3d12/BindGroupD3D12.cpp +++ b/src/dawn_native/d3d12/BindGroupD3D12.cpp @@ -86,6 +86,26 @@ namespace dawn_native { namespace d3d12 { cbvUavSrvHeapStart.GetCPUHandle(*cbvUavSrvHeapOffset + bindingOffsets[bindingIndex])); } break; + case wgpu::BindingType::ReadonlyStorageBuffer: { + BufferBinding binding = GetBindingAsBufferBinding(bindingIndex); + + // Like StorageBuffer, SPIRV-Cross outputs HLSL shaders for readonly storage + // buffer with ByteAddressBuffer. So we must use D3D12_BUFFER_SRV_FLAG_RAW + // when making the SRV descriptor. And it has similar requirement for format, + // element size, etc. + D3D12_SHADER_RESOURCE_VIEW_DESC desc; + desc.Format = DXGI_FORMAT_R32_TYPELESS; + desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; + desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + desc.Buffer.FirstElement = binding.offset / 4; + desc.Buffer.NumElements = binding.size / 4; + desc.Buffer.StructureByteStride = 0; + desc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW; + d3d12Device->CreateShaderResourceView( + ToBackend(binding.buffer)->GetD3D12Resource().Get(), &desc, + cbvUavSrvHeapStart.GetCPUHandle(*cbvUavSrvHeapOffset + + bindingOffsets[bindingIndex])); + } break; case wgpu::BindingType::SampledTexture: { auto* view = ToBackend(GetBindingAsTextureView(bindingIndex)); auto& srv = view->GetSRVDescriptor(); @@ -103,7 +123,6 @@ namespace dawn_native { namespace d3d12 { } break; case wgpu::BindingType::StorageTexture: - case wgpu::BindingType::ReadonlyStorageBuffer: UNREACHABLE(); break; diff --git a/src/dawn_native/d3d12/BindGroupLayoutD3D12.cpp b/src/dawn_native/d3d12/BindGroupLayoutD3D12.cpp index b810710842..cce919634e 100644 --- a/src/dawn_native/d3d12/BindGroupLayoutD3D12.cpp +++ b/src/dawn_native/d3d12/BindGroupLayoutD3D12.cpp @@ -39,6 +39,7 @@ namespace dawn_native { namespace d3d12 { mBindingOffsets[binding] = mDescriptorCounts[UAV]++; break; case wgpu::BindingType::SampledTexture: + case wgpu::BindingType::ReadonlyStorageBuffer: mBindingOffsets[binding] = mDescriptorCounts[SRV]++; break; case wgpu::BindingType::Sampler: @@ -46,7 +47,6 @@ namespace dawn_native { namespace d3d12 { break; case wgpu::BindingType::StorageTexture: - case wgpu::BindingType::ReadonlyStorageBuffer: UNREACHABLE(); break; } @@ -101,12 +101,12 @@ namespace dawn_native { namespace d3d12 { switch (groupInfo.types[binding]) { case wgpu::BindingType::UniformBuffer: case wgpu::BindingType::StorageBuffer: + case wgpu::BindingType::ReadonlyStorageBuffer: mBindingOffsets[binding] = baseRegister++; break; case wgpu::BindingType::SampledTexture: case wgpu::BindingType::Sampler: case wgpu::BindingType::StorageTexture: - case wgpu::BindingType::ReadonlyStorageBuffer: UNREACHABLE(); break; } @@ -121,6 +121,7 @@ namespace dawn_native { namespace d3d12 { mBindingOffsets[binding] += descriptorOffsets[UAV]; break; case wgpu::BindingType::SampledTexture: + case wgpu::BindingType::ReadonlyStorageBuffer: mBindingOffsets[binding] += descriptorOffsets[SRV]; break; case wgpu::BindingType::Sampler: @@ -128,7 +129,6 @@ namespace dawn_native { namespace d3d12 { break; case wgpu::BindingType::StorageTexture: - case wgpu::BindingType::ReadonlyStorageBuffer: UNREACHABLE(); break; diff --git a/src/dawn_native/d3d12/BufferD3D12.cpp b/src/dawn_native/d3d12/BufferD3D12.cpp index b875403bf9..8f32c36091 100644 --- a/src/dawn_native/d3d12/BufferD3D12.cpp +++ b/src/dawn_native/d3d12/BufferD3D12.cpp @@ -52,6 +52,10 @@ namespace dawn_native { namespace d3d12 { if (usage & wgpu::BufferUsage::Storage) { resourceState |= D3D12_RESOURCE_STATE_UNORDERED_ACCESS; } + if (usage & kReadOnlyStorage) { + resourceState |= (D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | + D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + } if (usage & wgpu::BufferUsage::Indirect) { resourceState |= D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT; } diff --git a/src/dawn_native/d3d12/CommandBufferD3D12.cpp b/src/dawn_native/d3d12/CommandBufferD3D12.cpp index 1b8118ea6a..ac3f9cbb40 100644 --- a/src/dawn_native/d3d12/CommandBufferD3D12.cpp +++ b/src/dawn_native/d3d12/CommandBufferD3D12.cpp @@ -237,10 +237,18 @@ namespace dawn_native { namespace d3d12 { bufferLocation); } break; + case wgpu::BindingType::ReadonlyStorageBuffer: + if (mInCompute) { + commandList->SetComputeRootShaderResourceView(parameterIndex, + bufferLocation); + } else { + commandList->SetGraphicsRootShaderResourceView(parameterIndex, + bufferLocation); + } + break; case wgpu::BindingType::SampledTexture: case wgpu::BindingType::Sampler: case wgpu::BindingType::StorageTexture: - case wgpu::BindingType::ReadonlyStorageBuffer: UNREACHABLE(); break; } diff --git a/src/dawn_native/d3d12/PipelineLayoutD3D12.cpp b/src/dawn_native/d3d12/PipelineLayoutD3D12.cpp index 2cdd6cf1db..8d3dd175eb 100644 --- a/src/dawn_native/d3d12/PipelineLayoutD3D12.cpp +++ b/src/dawn_native/d3d12/PipelineLayoutD3D12.cpp @@ -46,10 +46,11 @@ namespace dawn_native { namespace d3d12 { return D3D12_ROOT_PARAMETER_TYPE_CBV; case wgpu::BindingType::StorageBuffer: return D3D12_ROOT_PARAMETER_TYPE_UAV; + case wgpu::BindingType::ReadonlyStorageBuffer: + return D3D12_ROOT_PARAMETER_TYPE_SRV; case wgpu::BindingType::SampledTexture: case wgpu::BindingType::Sampler: case wgpu::BindingType::StorageTexture: - case wgpu::BindingType::ReadonlyStorageBuffer: UNREACHABLE(); } } diff --git a/src/tests/end2end/GpuMemorySynchronizationTests.cpp b/src/tests/end2end/GpuMemorySynchronizationTests.cpp index ee6e045a7a..69f506ba46 100644 --- a/src/tests/end2end/GpuMemorySynchronizationTests.cpp +++ b/src/tests/end2end/GpuMemorySynchronizationTests.cpp @@ -688,5 +688,4 @@ TEST_P(MultipleWriteThenMultipleReadTests, OneBuffer) { EXPECT_PIXEL_RGBA8_EQ(RGBA8::kYellow, renderPass.color, max, max); } -DAWN_INSTANTIATE_TEST(MultipleWriteThenMultipleReadTests, - VulkanBackend); +DAWN_INSTANTIATE_TEST(MultipleWriteThenMultipleReadTests, D3D12Backend, VulkanBackend);