diff --git a/src/dawn/native/BUILD.gn b/src/dawn/native/BUILD.gn index dbfb01628b..486c8fa254 100644 --- a/src/dawn/native/BUILD.gn +++ b/src/dawn/native/BUILD.gn @@ -434,6 +434,8 @@ source_set("sources") { "d3d11/BindGroupD3D11.h", "d3d11/BindGroupLayoutD3D11.cpp", "d3d11/BindGroupLayoutD3D11.h", + "d3d11/BindGroupTrackerD3D11.cpp", + "d3d11/BindGroupTrackerD3D11.h", "d3d11/BufferD3D11.cpp", "d3d11/BufferD3D11.h", "d3d11/CommandBufferD3D11.cpp", diff --git a/src/dawn/native/CMakeLists.txt b/src/dawn/native/CMakeLists.txt index 683f072f29..5aeb6089cd 100644 --- a/src/dawn/native/CMakeLists.txt +++ b/src/dawn/native/CMakeLists.txt @@ -291,6 +291,8 @@ if (DAWN_ENABLE_D3D11) "d3d11/BindGroupD3D11.h" "d3d11/BindGroupLayoutD3D11.cpp" "d3d11/BindGroupLayoutD3D11.h" + "d3d11/BindGroupTrackerD3D11.cpp" + "d3d11/BindGroupTrackerD3D11.h" "d3d11/BufferD3D11.cpp" "d3d11/BufferD3D11.h" "d3d11/CommandBufferD3D11.cpp" diff --git a/src/dawn/native/d3d11/BindGroupTrackerD3D11.cpp b/src/dawn/native/d3d11/BindGroupTrackerD3D11.cpp new file mode 100644 index 0000000000..50585d1f31 --- /dev/null +++ b/src/dawn/native/d3d11/BindGroupTrackerD3D11.cpp @@ -0,0 +1,351 @@ +// Copyright 2023 The Dawn Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "dawn/native/d3d11/BindGroupTrackerD3D11.h" + +#include "dawn/common/Assert.h" +#include "dawn/native/Format.h" +#include "dawn/native/d3d/D3DError.h" +#include "dawn/native/d3d11/BindGroupD3D11.h" +#include "dawn/native/d3d11/BufferD3D11.h" +#include "dawn/native/d3d11/CommandRecordingContextD3D11.h" +#include "dawn/native/d3d11/DeviceD3D11.h" +#include "dawn/native/d3d11/PipelineLayoutD3D11.h" +#include "dawn/native/d3d11/SamplerD3D11.h" +#include "dawn/native/d3d11/TextureD3D11.h" + +namespace dawn::native::d3d11 { +namespace { + +bool CheckAllSlotsAreEmpty(CommandRecordingContext* commandContext) { + ID3D11DeviceContext1* deviceContext1 = commandContext->GetD3D11DeviceContext1(); + + // Reserve one slot for builtin constants. + constexpr uint32_t kReservedCBVSlots = 1; + + // Check constant buffer slots + for (UINT slot = 0; + slot < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - kReservedCBVSlots; ++slot) { + ID3D11Buffer* buffer = nullptr; + deviceContext1->VSGetConstantBuffers1(slot, 1, &buffer, nullptr, nullptr); + ASSERT(buffer == nullptr); + deviceContext1->PSGetConstantBuffers1(slot, 1, &buffer, nullptr, nullptr); + ASSERT(buffer == nullptr); + deviceContext1->CSGetConstantBuffers1(slot, 1, &buffer, nullptr, nullptr); + ASSERT(buffer == nullptr); + } + + // Check resource slots + for (UINT slot = 0; slot < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; ++slot) { + ID3D11ShaderResourceView* srv = nullptr; + deviceContext1->VSGetShaderResources(slot, 1, &srv); + ASSERT(srv == nullptr); + deviceContext1->PSGetShaderResources(slot, 1, &srv); + ASSERT(srv == nullptr); + deviceContext1->CSGetShaderResources(slot, 1, &srv); + ASSERT(srv == nullptr); + } + + // Check sampler slots + for (UINT slot = 0; slot < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; ++slot) { + ID3D11SamplerState* sampler = nullptr; + deviceContext1->VSGetSamplers(slot, 1, &sampler); + ASSERT(sampler == nullptr); + deviceContext1->PSGetSamplers(slot, 1, &sampler); + ASSERT(sampler == nullptr); + deviceContext1->CSGetSamplers(slot, 1, &sampler); + ASSERT(sampler == nullptr); + } + + // Check UAV slots + for (UINT slot = 0; slot < D3D11_1_UAV_SLOT_COUNT; ++slot) { + ID3D11UnorderedAccessView* uav = nullptr; + deviceContext1->CSGetUnorderedAccessViews(slot, 1, &uav); + ASSERT(uav == nullptr); + } + + return true; +} + +} // namespace + +BindGroupTracker::BindGroupTracker(CommandRecordingContext* commandContext) + : mCommandContext(commandContext) {} + +BindGroupTracker::~BindGroupTracker() { + if (mLastAppliedPipelineLayout) { + for (BindGroupIndex index : + IterateBitSet(mLastAppliedPipelineLayout->GetBindGroupLayoutsMask())) { + UnApplyBindGroup(index); + } + } + // All slots should be unbound here. + ASSERT(CheckAllSlotsAreEmpty(mCommandContext)); +} + +MaybeError BindGroupTracker::Apply() { + BeforeApply(); + + // A resource cannot be bound as both input resource and UAV at the same time, so to avoid this + // conflict, we need to unbind groups which are not used by the new pipeline. and unbind groups + // which are not inherited by the new pipeline. + if (mLastAppliedPipelineLayout) { + BindGroupLayoutMask unusedGroups = mLastAppliedPipelineLayout->GetBindGroupLayoutsMask() & + ~mPipelineLayout->GetBindGroupLayoutsMask(); + // Unset bind groups which are not used by the new pipeline and are not inherited. + for (BindGroupIndex index : IterateBitSet(mDirtyBindGroups | unusedGroups)) { + UnApplyBindGroup(index); + } + } + + for (BindGroupIndex index : IterateBitSet(mDirtyBindGroupsObjectChangedOrIsDynamic)) { + DAWN_TRY(ApplyBindGroup(index)); + } + + AfterApply(); + + return {}; +} + +MaybeError BindGroupTracker::ApplyBindGroup(BindGroupIndex index) { + ID3D11DeviceContext1* deviceContext1 = mCommandContext->GetD3D11DeviceContext1(); + BindGroupBase* group = mBindGroups[index]; + const ityp::vector& dynamicOffsets = mDynamicOffsets[index]; + const auto& indices = ToBackend(mPipelineLayout)->GetBindingIndexInfo()[index]; + + for (BindingIndex bindingIndex{0}; bindingIndex < group->GetLayout()->GetBindingCount(); + ++bindingIndex) { + const BindingInfo& bindingInfo = group->GetLayout()->GetBindingInfo(bindingIndex); + const uint32_t bindingSlot = indices[bindingIndex]; + + switch (bindingInfo.bindingType) { + case BindingInfoType::Buffer: { + BufferBinding binding = group->GetBindingAsBufferBinding(bindingIndex); + ID3D11Buffer* d3d11Buffer = ToBackend(binding.buffer)->GetD3D11Buffer(); + auto offset = binding.offset; + if (bindingInfo.buffer.hasDynamicOffset) { + // Dynamic buffers are packed at the front of BindingIndices. + offset += dynamicOffsets[bindingIndex]; + } + + switch (bindingInfo.buffer.type) { + case wgpu::BufferBindingType::Uniform: { + // https://learn.microsoft.com/en-us/windows/win32/api/d3d11_1/nf-d3d11_1-id3d11devicecontext1-vssetconstantbuffers1 + // Offset and size are measured in shader constants, which are 16 bytes + // (4*32-bit components). And the offsets and counts must be multiples + // of 16. + // WebGPU's minUniformBufferOffsetAlignment is 256. + DAWN_ASSERT(IsAligned(offset, 256)); + uint32_t firstConstant = static_cast(offset / 16); + uint32_t size = static_cast(Align(binding.size, 16) / 16); + uint32_t numConstants = Align(size, 16); + DAWN_ASSERT(offset + numConstants * 16 <= + binding.buffer->GetAllocatedSize()); + + if (bindingInfo.visibility & wgpu::ShaderStage::Vertex) { + deviceContext1->VSSetConstantBuffers1(bindingSlot, 1, &d3d11Buffer, + &firstConstant, &numConstants); + } + if (bindingInfo.visibility & wgpu::ShaderStage::Fragment) { + deviceContext1->PSSetConstantBuffers1(bindingSlot, 1, &d3d11Buffer, + &firstConstant, &numConstants); + } + if (bindingInfo.visibility & wgpu::ShaderStage::Compute) { + deviceContext1->CSSetConstantBuffers1(bindingSlot, 1, &d3d11Buffer, + &firstConstant, &numConstants); + } + break; + } + case wgpu::BufferBindingType::Storage: + case kInternalStorageBufferBinding: { + ASSERT(IsSubset(bindingInfo.visibility, wgpu::ShaderStage::Compute)); + ComPtr d3d11UAV; + DAWN_TRY_ASSIGN(d3d11UAV, ToBackend(binding.buffer) + ->CreateD3D11UnorderedAccessView1( + 0, binding.buffer->GetSize())); + UINT firstElement = offset / 4; + if (bindingInfo.visibility & wgpu::ShaderStage::Compute) { + deviceContext1->CSSetUnorderedAccessViews( + bindingSlot, 1, d3d11UAV.GetAddressOf(), &firstElement); + } + break; + } + case wgpu::BufferBindingType::ReadOnlyStorage: { + ComPtr d3d11SRV; + DAWN_TRY_ASSIGN(d3d11SRV, + ToBackend(binding.buffer) + ->CreateD3D11ShaderResourceView(offset, binding.size)); + if (bindingInfo.visibility & wgpu::ShaderStage::Vertex) { + deviceContext1->VSSetShaderResources(bindingSlot, 1, + d3d11SRV.GetAddressOf()); + } + if (bindingInfo.visibility & wgpu::ShaderStage::Fragment) { + deviceContext1->PSSetShaderResources(bindingSlot, 1, + d3d11SRV.GetAddressOf()); + } + if (bindingInfo.visibility & wgpu::ShaderStage::Compute) { + deviceContext1->CSSetShaderResources(bindingSlot, 1, + d3d11SRV.GetAddressOf()); + } + break; + } + case wgpu::BufferBindingType::Undefined: + UNREACHABLE(); + } + break; + } + + case BindingInfoType::Sampler: { + Sampler* sampler = ToBackend(group->GetBindingAsSampler(bindingIndex)); + ID3D11SamplerState* d3d11SamplerState = sampler->GetD3D11SamplerState(); + if (bindingInfo.visibility & wgpu::ShaderStage::Vertex) { + deviceContext1->VSSetSamplers(bindingSlot, 1, &d3d11SamplerState); + } + if (bindingInfo.visibility & wgpu::ShaderStage::Fragment) { + deviceContext1->PSSetSamplers(bindingSlot, 1, &d3d11SamplerState); + } + if (bindingInfo.visibility & wgpu::ShaderStage::Compute) { + deviceContext1->CSSetSamplers(bindingSlot, 1, &d3d11SamplerState); + } + break; + } + + case BindingInfoType::Texture: { + TextureView* view = ToBackend(group->GetBindingAsTextureView(bindingIndex)); + ComPtr srv; + DAWN_TRY_ASSIGN(srv, view->CreateD3D11ShaderResourceView()); + if (bindingInfo.visibility & wgpu::ShaderStage::Vertex) { + deviceContext1->VSSetShaderResources(bindingSlot, 1, srv.GetAddressOf()); + } + if (bindingInfo.visibility & wgpu::ShaderStage::Fragment) { + deviceContext1->PSSetShaderResources(bindingSlot, 1, srv.GetAddressOf()); + } + if (bindingInfo.visibility & wgpu::ShaderStage::Compute) { + deviceContext1->CSSetShaderResources(bindingSlot, 1, srv.GetAddressOf()); + } + break; + } + + case BindingInfoType::StorageTexture: { + return DAWN_UNIMPLEMENTED_ERROR("Storage textures are not supported"); + } + + case BindingInfoType::ExternalTexture: { + return DAWN_UNIMPLEMENTED_ERROR("External textures are not supported"); + } + } + } + return {}; +} + +void BindGroupTracker::UnApplyBindGroup(BindGroupIndex index) { + ID3D11DeviceContext1* deviceContext1 = mCommandContext->GetD3D11DeviceContext1(); + BindGroupLayoutBase* groupLayout = mLastAppliedPipelineLayout->GetBindGroupLayout(index); + const auto& indices = ToBackend(mLastAppliedPipelineLayout)->GetBindingIndexInfo()[index]; + + for (BindingIndex bindingIndex{0}; bindingIndex < groupLayout->GetBindingCount(); + ++bindingIndex) { + const BindingInfo& bindingInfo = groupLayout->GetBindingInfo(bindingIndex); + const uint32_t bindingSlot = indices[bindingIndex]; + + switch (bindingInfo.bindingType) { + case BindingInfoType::Buffer: { + switch (bindingInfo.buffer.type) { + case wgpu::BufferBindingType::Uniform: { + ID3D11Buffer* nullBuffer = nullptr; + if (bindingInfo.visibility & wgpu::ShaderStage::Vertex) { + deviceContext1->VSSetConstantBuffers1(bindingSlot, 1, &nullBuffer, + nullptr, nullptr); + } + if (bindingInfo.visibility & wgpu::ShaderStage::Fragment) { + deviceContext1->PSSetConstantBuffers1(bindingSlot, 1, &nullBuffer, + nullptr, nullptr); + } + if (bindingInfo.visibility & wgpu::ShaderStage::Compute) { + deviceContext1->CSSetConstantBuffers1(bindingSlot, 1, &nullBuffer, + nullptr, nullptr); + } + break; + } + case wgpu::BufferBindingType::Storage: + case kInternalStorageBufferBinding: { + ASSERT(IsSubset(bindingInfo.visibility, wgpu::ShaderStage::Compute)); + if (bindingInfo.visibility & wgpu::ShaderStage::Compute) { + ID3D11UnorderedAccessView* nullUAV = nullptr; + deviceContext1->CSSetUnorderedAccessViews(bindingSlot, 1, &nullUAV, + nullptr); + } + break; + } + case wgpu::BufferBindingType::ReadOnlyStorage: { + ID3D11ShaderResourceView* nullSRV = nullptr; + if (bindingInfo.visibility & wgpu::ShaderStage::Vertex) { + deviceContext1->VSSetShaderResources(bindingSlot, 1, &nullSRV); + } + if (bindingInfo.visibility & wgpu::ShaderStage::Fragment) { + deviceContext1->PSSetShaderResources(bindingSlot, 1, &nullSRV); + } + if (bindingInfo.visibility & wgpu::ShaderStage::Compute) { + deviceContext1->CSSetShaderResources(bindingSlot, 1, &nullSRV); + } + break; + } + case wgpu::BufferBindingType::Undefined: + UNREACHABLE(); + } + break; + } + + case BindingInfoType::Sampler: { + ID3D11SamplerState* nullSampler = nullptr; + if (bindingInfo.visibility & wgpu::ShaderStage::Vertex) { + deviceContext1->VSSetSamplers(bindingSlot, 1, &nullSampler); + } + if (bindingInfo.visibility & wgpu::ShaderStage::Fragment) { + deviceContext1->PSSetSamplers(bindingSlot, 1, &nullSampler); + } + if (bindingInfo.visibility & wgpu::ShaderStage::Compute) { + deviceContext1->CSSetSamplers(bindingSlot, 1, &nullSampler); + } + break; + } + + case BindingInfoType::Texture: { + ID3D11ShaderResourceView* nullSRV = nullptr; + if (bindingInfo.visibility & wgpu::ShaderStage::Vertex) { + deviceContext1->VSSetShaderResources(bindingSlot, 1, &nullSRV); + } + if (bindingInfo.visibility & wgpu::ShaderStage::Fragment) { + deviceContext1->PSSetShaderResources(bindingSlot, 1, &nullSRV); + } + if (bindingInfo.visibility & wgpu::ShaderStage::Compute) { + deviceContext1->CSSetShaderResources(bindingSlot, 1, &nullSRV); + } + break; + } + + case BindingInfoType::StorageTexture: { + UNREACHABLE(); + break; + } + + case BindingInfoType::ExternalTexture: { + UNREACHABLE(); + break; + } + } + } +} + +} // namespace dawn::native::d3d11 diff --git a/src/dawn/native/d3d11/BindGroupTrackerD3D11.h b/src/dawn/native/d3d11/BindGroupTrackerD3D11.h new file mode 100644 index 0000000000..7e8181b72f --- /dev/null +++ b/src/dawn/native/d3d11/BindGroupTrackerD3D11.h @@ -0,0 +1,42 @@ +// Copyright 2023 The Dawn Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_DAWN_NATIVE_D3D11_BINDGROUPTRACKERD3D11_H_ +#define SRC_DAWN_NATIVE_D3D11_BINDGROUPTRACKERD3D11_H_ + +#include "dawn/native/BindGroupTracker.h" +#include "dawn/native/d3d/d3d_platform.h" + +namespace dawn::native::d3d11 { + +class CommandRecordingContext; + +// We need convert WebGPU bind slot to d3d11 bind slot according a map in PipelineLayout, so we +// cannot inherit BindGroupTrackerGroups. +class BindGroupTracker : public BindGroupTrackerBase { + public: + explicit BindGroupTracker(CommandRecordingContext* commandContext); + ~BindGroupTracker(); + MaybeError Apply(); + + private: + MaybeError ApplyBindGroup(BindGroupIndex index); + void UnApplyBindGroup(BindGroupIndex index); + + CommandRecordingContext* const mCommandContext; +}; + +} // namespace dawn::native::d3d11 + +#endif // SRC_DAWN_NATIVE_D3D11_BINDGROUPTRACKERD3D11_H_ diff --git a/src/dawn/native/d3d11/CommandBufferD3D11.cpp b/src/dawn/native/d3d11/CommandBufferD3D11.cpp index 0aafc4051e..3b92b3a4f6 100644 --- a/src/dawn/native/d3d11/CommandBufferD3D11.cpp +++ b/src/dawn/native/d3d11/CommandBufferD3D11.cpp @@ -20,8 +20,6 @@ #include #include "dawn/common/WindowsUtils.h" -#include "dawn/native/BindGroup.h" -#include "dawn/native/BindGroupTracker.h" #include "dawn/native/CommandEncoder.h" #include "dawn/native/CommandValidation.h" #include "dawn/native/Commands.h" @@ -29,13 +27,12 @@ #include "dawn/native/RenderBundle.h" #include "dawn/native/VertexFormat.h" #include "dawn/native/d3d/D3DError.h" +#include "dawn/native/d3d11/BindGroupTrackerD3D11.h" #include "dawn/native/d3d11/BufferD3D11.h" #include "dawn/native/d3d11/ComputePipelineD3D11.h" #include "dawn/native/d3d11/DeviceD3D11.h" #include "dawn/native/d3d11/Forward.h" -#include "dawn/native/d3d11/PipelineLayoutD3D11.h" #include "dawn/native/d3d11/RenderPipelineD3D11.h" -#include "dawn/native/d3d11/SamplerD3D11.h" #include "dawn/native/d3d11/TextureD3D11.h" #include "dawn/native/d3d11/UtilsD3D11.h" @@ -53,174 +50,6 @@ DXGI_FORMAT DXGIIndexFormat(wgpu::IndexFormat format) { } } -class BindGroupTracker : public BindGroupTrackerBase { - public: - MaybeError Apply(CommandRecordingContext* commandContext) { - BeforeApply(); - for (BindGroupIndex index : IterateBitSet(mDirtyBindGroupsObjectChangedOrIsDynamic)) { - DAWN_TRY( - ApplyBindGroup(commandContext, index, mBindGroups[index], mDynamicOffsets[index])); - } - AfterApply(); - return {}; - } - - void AfterDispatch(CommandRecordingContext* commandContext) { - // Clear the UAVs after the dispatch, otherwise the buffer cannot be used as input in vertex - // or pixel stage. - for (UINT uav : mUnorderedAccessViews) { - ID3D11UnorderedAccessView* nullUAV = nullptr; - commandContext->GetD3D11DeviceContext1()->CSSetUnorderedAccessViews(uav, 1, &nullUAV, - nullptr); - } - mUnorderedAccessViews.clear(); - } - - private: - MaybeError ApplyBindGroup(CommandRecordingContext* commandContext, - BindGroupIndex index, - BindGroupBase* group, - const ityp::vector& dynamicOffsets) { - const auto& indices = ToBackend(mPipelineLayout)->GetBindingIndexInfo()[index]; - for (BindingIndex bindingIndex{0}; bindingIndex < group->GetLayout()->GetBindingCount(); - ++bindingIndex) { - const BindingInfo& bindingInfo = group->GetLayout()->GetBindingInfo(bindingIndex); - const uint32_t bindingSlot = indices[bindingIndex]; - - switch (bindingInfo.bindingType) { - case BindingInfoType::Buffer: { - BufferBinding binding = group->GetBindingAsBufferBinding(bindingIndex); - ID3D11Buffer* d3d11Buffer = ToBackend(binding.buffer)->GetD3D11Buffer(); - auto offset = binding.offset; - if (bindingInfo.buffer.hasDynamicOffset) { - // Dynamic buffers are packed at the front of BindingIndices. - offset += dynamicOffsets[bindingIndex]; - } - - auto* deviceContext = commandContext->GetD3D11DeviceContext1(); - - switch (bindingInfo.buffer.type) { - case wgpu::BufferBindingType::Uniform: { - // https://learn.microsoft.com/en-us/windows/win32/api/d3d11_1/nf-d3d11_1-id3d11devicecontext1-vssetconstantbuffers1 - // Offset and size are measured in shader constants, which are 16 bytes - // (4*32-bit components). And the offsets and counts must be multiples - // of 16. - DAWN_ASSERT(IsAligned(offset, 256)); - uint32_t firstConstant = static_cast(offset / 16); - uint32_t size = static_cast(Align(binding.size, 16) / 16); - uint32_t numConstants = Align(size, 16); - DAWN_ASSERT(offset + numConstants * 16 <= - binding.buffer->GetAllocatedSize()); - - if (bindingInfo.visibility & wgpu::ShaderStage::Vertex) { - deviceContext->VSSetConstantBuffers1(bindingSlot, 1, &d3d11Buffer, - &firstConstant, &numConstants); - } - if (bindingInfo.visibility & wgpu::ShaderStage::Fragment) { - deviceContext->PSSetConstantBuffers1(bindingSlot, 1, &d3d11Buffer, - &firstConstant, &numConstants); - } - if (bindingInfo.visibility & wgpu::ShaderStage::Compute) { - deviceContext->CSSetConstantBuffers1(bindingSlot, 1, &d3d11Buffer, - &firstConstant, &numConstants); - } - break; - } - case wgpu::BufferBindingType::Storage: { - ComPtr d3d11UAV; - DAWN_TRY_ASSIGN(d3d11UAV, ToBackend(binding.buffer) - ->CreateD3D11UnorderedAccessView1( - 0, binding.buffer->GetSize())); - UINT firstElement = offset / 4; - if (bindingInfo.visibility & wgpu::ShaderStage::Compute) { - deviceContext->CSSetUnorderedAccessViews( - bindingSlot, 1, d3d11UAV.GetAddressOf(), &firstElement); - // Record the bounded UAVs so that we can clear them after the - // dispatch. - mUnorderedAccessViews.emplace_back(bindingSlot); - } else { - return DAWN_INTERNAL_ERROR( - "Storage buffers are only supported in compute shaders"); - } - break; - } - case wgpu::BufferBindingType::ReadOnlyStorage: { - ComPtr d3d11SRV; - DAWN_TRY_ASSIGN(d3d11SRV, ToBackend(binding.buffer) - ->CreateD3D11ShaderResourceView( - offset, binding.size)); - if (bindingInfo.visibility & wgpu::ShaderStage::Vertex) { - deviceContext->VSSetShaderResources(bindingSlot, 1, - d3d11SRV.GetAddressOf()); - } - if (bindingInfo.visibility & wgpu::ShaderStage::Fragment) { - deviceContext->PSSetShaderResources(bindingSlot, 1, - d3d11SRV.GetAddressOf()); - } - if (bindingInfo.visibility & wgpu::ShaderStage::Compute) { - deviceContext->CSSetShaderResources(bindingSlot, 1, - d3d11SRV.GetAddressOf()); - } - break; - } - case wgpu::BufferBindingType::Undefined: - UNREACHABLE(); - } - break; - } - - case BindingInfoType::Sampler: { - Sampler* sampler = ToBackend(group->GetBindingAsSampler(bindingIndex)); - ID3D11SamplerState* d3d11SamplerState = sampler->GetD3D11SamplerState(); - if (bindingInfo.visibility & wgpu::ShaderStage::Vertex) { - commandContext->GetD3D11DeviceContext1()->VSSetSamplers(bindingSlot, 1, - &d3d11SamplerState); - } - if (bindingInfo.visibility & wgpu::ShaderStage::Fragment) { - commandContext->GetD3D11DeviceContext1()->PSSetSamplers(bindingSlot, 1, - &d3d11SamplerState); - } - if (bindingInfo.visibility & wgpu::ShaderStage::Compute) { - commandContext->GetD3D11DeviceContext1()->CSSetSamplers(bindingSlot, 1, - &d3d11SamplerState); - } - break; - } - - case BindingInfoType::Texture: { - TextureView* view = ToBackend(group->GetBindingAsTextureView(bindingIndex)); - ComPtr srv; - DAWN_TRY_ASSIGN(srv, view->CreateD3D11ShaderResourceView()); - if (bindingInfo.visibility & wgpu::ShaderStage::Vertex) { - commandContext->GetD3D11DeviceContext1()->VSSetShaderResources( - bindingSlot, 1, srv.GetAddressOf()); - } - if (bindingInfo.visibility & wgpu::ShaderStage::Fragment) { - commandContext->GetD3D11DeviceContext1()->PSSetShaderResources( - bindingSlot, 1, srv.GetAddressOf()); - } - if (bindingInfo.visibility & wgpu::ShaderStage::Compute) { - commandContext->GetD3D11DeviceContext1()->CSSetShaderResources( - bindingSlot, 1, srv.GetAddressOf()); - } - break; - } - - case BindingInfoType::StorageTexture: { - return DAWN_UNIMPLEMENTED_ERROR("Storage textures are not supported"); - } - - case BindingInfoType::ExternalTexture: { - return DAWN_UNIMPLEMENTED_ERROR("External textures are not supported"); - } - } - } - return {}; - } - - std::vector mUnorderedAccessViews; -}; - } // namespace // Create CommandBuffer @@ -457,7 +286,7 @@ MaybeError CommandBuffer::Execute() { MaybeError CommandBuffer::ExecuteComputePass(CommandRecordingContext* commandContext) { ComputePipeline* lastPipeline = nullptr; - BindGroupTracker bindGroupTracker = {}; + BindGroupTracker bindGroupTracker(commandContext); Command type; while (mCommands.NextCommandId(&type)) { @@ -470,12 +299,11 @@ MaybeError CommandBuffer::ExecuteComputePass(CommandRecordingContext* commandCon case Command::Dispatch: { DispatchCmd* dispatch = mCommands.NextCommand(); - DAWN_TRY(bindGroupTracker.Apply(commandContext)); + DAWN_TRY(bindGroupTracker.Apply()); DAWN_TRY(RecordNumWorkgroupsForDispatch(lastPipeline, commandContext, dispatch)); commandContext->GetD3D11DeviceContext()->Dispatch(dispatch->x, dispatch->y, dispatch->z); - bindGroupTracker.AfterDispatch(commandContext); break; } @@ -484,7 +312,7 @@ MaybeError CommandBuffer::ExecuteComputePass(CommandRecordingContext* commandCon // TODO(1716): figure how to update num workgroups builtins DispatchIndirectCmd* dispatch = mCommands.NextCommand(); - DAWN_TRY(bindGroupTracker.Apply(commandContext)); + DAWN_TRY(bindGroupTracker.Apply()); uint64_t indirectBufferOffset = dispatch->indirectOffset; Buffer* indirectBuffer = ToBackend(dispatch->indirectBuffer.Get()); @@ -492,8 +320,6 @@ MaybeError CommandBuffer::ExecuteComputePass(CommandRecordingContext* commandCon commandContext->GetD3D11DeviceContext()->DispatchIndirect( indirectBuffer->GetD3D11Buffer(), indirectBufferOffset); - bindGroupTracker.AfterDispatch(commandContext); - break; } @@ -612,7 +438,7 @@ MaybeError CommandBuffer::ExecuteRenderPass(BeginRenderPassCmd* renderPass, d3d11DeviceContext1->RSSetScissorRects(1, &scissor); RenderPipeline* lastPipeline = nullptr; - BindGroupTracker bindGroupTracker = {}; + BindGroupTracker bindGroupTracker(commandContext); std::array blendColor = {0.0f, 0.0f, 0.0f, 0.0f}; uint32_t stencilReference = 0; @@ -621,7 +447,7 @@ MaybeError CommandBuffer::ExecuteRenderPass(BeginRenderPassCmd* renderPass, case Command::Draw: { DrawCmd* draw = iter->NextCommand(); - DAWN_TRY(bindGroupTracker.Apply(commandContext)); + DAWN_TRY(bindGroupTracker.Apply()); DAWN_TRY(RecordFirstIndexOffset(lastPipeline, commandContext, draw->firstVertex, draw->firstInstance)); commandContext->GetD3D11DeviceContext()->DrawInstanced( @@ -633,7 +459,7 @@ MaybeError CommandBuffer::ExecuteRenderPass(BeginRenderPassCmd* renderPass, case Command::DrawIndexed: { DrawIndexedCmd* draw = iter->NextCommand(); - DAWN_TRY(bindGroupTracker.Apply(commandContext)); + DAWN_TRY(bindGroupTracker.Apply()); DAWN_TRY(RecordFirstIndexOffset(lastPipeline, commandContext, draw->baseVertex, draw->firstInstance)); commandContext->GetD3D11DeviceContext()->DrawIndexedInstanced( @@ -647,7 +473,7 @@ MaybeError CommandBuffer::ExecuteRenderPass(BeginRenderPassCmd* renderPass, // TODO(dawn:1716): figure how to setup built-in variables for indirect draw. DrawIndirectCmd* draw = iter->NextCommand(); - DAWN_TRY(bindGroupTracker.Apply(commandContext)); + DAWN_TRY(bindGroupTracker.Apply()); uint64_t indirectBufferOffset = draw->indirectOffset; Buffer* indirectBuffer = ToBackend(draw->indirectBuffer.Get()); ASSERT(indirectBuffer != nullptr); @@ -662,7 +488,7 @@ MaybeError CommandBuffer::ExecuteRenderPass(BeginRenderPassCmd* renderPass, // TODO(dawn:1716): figure how to setup built-in variables for indirect draw. DrawIndexedIndirectCmd* draw = iter->NextCommand(); - DAWN_TRY(bindGroupTracker.Apply(commandContext)); + DAWN_TRY(bindGroupTracker.Apply()); Buffer* indirectBuffer = ToBackend(draw->indirectBuffer.Get()); ASSERT(indirectBuffer != nullptr); @@ -755,7 +581,7 @@ MaybeError CommandBuffer::ExecuteRenderPass(BeginRenderPassCmd* renderPass, if (lastPipeline) { lastPipeline->ApplyDepthStencilState(commandContext, stencilReference); } - return {}; + break; } case Command::SetViewport: { diff --git a/src/dawn/native/d3d11/PhysicalDeviceD3D11.cpp b/src/dawn/native/d3d11/PhysicalDeviceD3D11.cpp index 1f80ec14e1..1235d393dd 100644 --- a/src/dawn/native/d3d11/PhysicalDeviceD3D11.cpp +++ b/src/dawn/native/d3d11/PhysicalDeviceD3D11.cpp @@ -156,7 +156,7 @@ MaybeError PhysicalDevice::InitializeSupportedLimitsImpl(CombinedLimits* limits) // Allocate half of the UAVs to storage buffers, and half to storage textures. limits->v1.maxStorageTexturesPerShaderStage = maxUAVsPerStage / 2; limits->v1.maxStorageBuffersPerShaderStage = maxUAVsPerStage - maxUAVsPerStage / 2; - limits->v1.maxSampledTexturesPerShaderStage = D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; + limits->v1.maxSampledTexturesPerShaderStage = D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; limits->v1.maxSamplersPerShaderStage = D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; limits->v1.maxColorAttachments = D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; diff --git a/src/dawn/native/d3d11/PipelineLayoutD3D11.cpp b/src/dawn/native/d3d11/PipelineLayoutD3D11.cpp index ac39e50546..268a2f0ee9 100644 --- a/src/dawn/native/d3d11/PipelineLayoutD3D11.cpp +++ b/src/dawn/native/d3d11/PipelineLayoutD3D11.cpp @@ -50,9 +50,11 @@ MaybeError PipelineLayout::Initialize() { break; case wgpu::BufferBindingType::Storage: case kInternalStorageBufferBinding: - case wgpu::BufferBindingType::ReadOnlyStorage: mIndexInfo[group][bindingIndex] = unorderedAccessViewIndex++; break; + case wgpu::BufferBindingType::ReadOnlyStorage: + mIndexInfo[group][bindingIndex] = shaderResourceViewIndex++; + break; case wgpu::BufferBindingType::Undefined: UNREACHABLE(); } diff --git a/src/dawn/tests/end2end/ComputeStorageBufferBarrierTests.cpp b/src/dawn/tests/end2end/ComputeStorageBufferBarrierTests.cpp index 4dbaf7321a..c9634a371f 100644 --- a/src/dawn/tests/end2end/ComputeStorageBufferBarrierTests.cpp +++ b/src/dawn/tests/end2end/ComputeStorageBufferBarrierTests.cpp @@ -202,6 +202,9 @@ TEST_P(ComputeStorageBufferBarrierTests, StorageAndReadonlyStoragePingPongInOneP // Test that Storage to Uniform buffer transitions work and synchronize correctly // by ping-ponging between Storage/Uniform usage in sequential compute passes. TEST_P(ComputeStorageBufferBarrierTests, UniformToStorageAddPingPong) { + // TODO(dawn:1721): D3D11 buffer cannot be uniform and storage at the same time. + DAWN_SUPPRESS_TEST_IF(IsD3D11()); + std::vector data(kNumValues, 0); std::vector expectedA(kNumValues, 0x1234 * kIterations); std::vector expectedB(kNumValues, 0x1234 * (kIterations - 1)); @@ -270,6 +273,9 @@ TEST_P(ComputeStorageBufferBarrierTests, UniformToStorageAddPingPong) { // Test that Storage to Uniform buffer transitions work and synchronize correctly // by ping-ponging between Storage/Uniform usage in one compute pass. TEST_P(ComputeStorageBufferBarrierTests, UniformToStorageAddPingPongInOnePass) { + // TODO(dawn:1721): D3D11 buffer cannot be uniform and storage at the same time. + DAWN_SUPPRESS_TEST_IF(IsD3D11()); + std::vector data(kNumValues, 0); std::vector expectedA(kNumValues, 0x1234 * kIterations); std::vector expectedB(kNumValues, 0x1234 * (kIterations - 1)); @@ -409,6 +415,7 @@ TEST_P(ComputeStorageBufferBarrierTests, IndirectBufferCorrectBarrier) { } DAWN_INSTANTIATE_TEST(ComputeStorageBufferBarrierTests, + D3D11Backend(), D3D12Backend(), MetalBackend(), OpenGLBackend(), diff --git a/src/dawn/tests/end2end/DrawIndirectTests.cpp b/src/dawn/tests/end2end/DrawIndirectTests.cpp index 8c0b28af51..b1ee3953f7 100644 --- a/src/dawn/tests/end2end/DrawIndirectTests.cpp +++ b/src/dawn/tests/end2end/DrawIndirectTests.cpp @@ -129,6 +129,7 @@ TEST_P(DrawIndirectTest, IndirectOffset) { } DAWN_INSTANTIATE_TEST(DrawIndirectTest, + D3D11Backend(), D3D12Backend(), MetalBackend(), OpenGLBackend(),