d3d11: fix indirect draw and dispatch

Bug: dawn:1716
Bug: dawn:1791
Change-Id: I6027a9ab8b33bfaf80d32300eed11fe7df5135e3
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/131760
Reviewed-by: Austin Eng <enga@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Peng Huang <penghuang@chromium.org>
This commit is contained in:
Peng Huang 2023-05-05 21:50:39 +00:00 committed by Dawn LUCI CQ
parent 283b3a042f
commit 300ec34c72
5 changed files with 54 additions and 15 deletions

View File

@ -309,16 +309,21 @@ MaybeError CommandBuffer::ExecuteComputePass(CommandRecordingContext* commandCon
} }
case Command::DispatchIndirect: { case Command::DispatchIndirect: {
// TODO(1716): figure how to update num workgroups builtins
DispatchIndirectCmd* dispatch = mCommands.NextCommand<DispatchIndirectCmd>(); DispatchIndirectCmd* dispatch = mCommands.NextCommand<DispatchIndirectCmd>();
DAWN_TRY(bindGroupTracker.Apply()); DAWN_TRY(bindGroupTracker.Apply());
uint64_t indirectBufferOffset = dispatch->indirectOffset;
Buffer* indirectBuffer = ToBackend(dispatch->indirectBuffer.Get()); Buffer* indirectBuffer = ToBackend(dispatch->indirectBuffer.Get());
if (lastPipeline->UsesNumWorkgroups()) {
// Copy indirect args into the uniform buffer for built-in workgroup variables.
DAWN_TRY(Buffer::Copy(commandContext, indirectBuffer, dispatch->indirectOffset,
sizeof(uint32_t) * 3, commandContext->GetUniformBuffer(),
0));
}
commandContext->GetD3D11DeviceContext()->DispatchIndirect( commandContext->GetD3D11DeviceContext()->DispatchIndirect(
indirectBuffer->GetD3D11Buffer(), indirectBufferOffset); indirectBuffer->GetD3D11Buffer(), dispatch->indirectOffset);
break; break;
} }
@ -470,29 +475,49 @@ MaybeError CommandBuffer::ExecuteRenderPass(BeginRenderPassCmd* renderPass,
} }
case Command::DrawIndirect: { case Command::DrawIndirect: {
// TODO(dawn:1716): figure how to setup built-in variables for indirect draw.
DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>(); DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>();
DAWN_TRY(bindGroupTracker.Apply());
uint64_t indirectBufferOffset = draw->indirectOffset;
Buffer* indirectBuffer = ToBackend(draw->indirectBuffer.Get()); Buffer* indirectBuffer = ToBackend(draw->indirectBuffer.Get());
ASSERT(indirectBuffer != nullptr); ASSERT(indirectBuffer != nullptr);
DAWN_TRY(bindGroupTracker.Apply());
if (lastPipeline->GetUsesVertexOrInstanceIndex()) {
// Copy StartVertexLocation and StartInstanceLocation into the uniform buffer
// for built-in variables.
uint64_t offset =
draw->indirectOffset +
offsetof(D3D11_DRAW_INSTANCED_INDIRECT_ARGS, StartVertexLocation);
DAWN_TRY(Buffer::Copy(commandContext, indirectBuffer, offset,
sizeof(uint32_t) * 2, commandContext->GetUniformBuffer(),
0));
}
commandContext->GetD3D11DeviceContext()->DrawInstancedIndirect( commandContext->GetD3D11DeviceContext()->DrawInstancedIndirect(
indirectBuffer->GetD3D11Buffer(), indirectBufferOffset); indirectBuffer->GetD3D11Buffer(), draw->indirectOffset);
break; break;
} }
case Command::DrawIndexedIndirect: { case Command::DrawIndexedIndirect: {
// TODO(dawn:1716): figure how to setup built-in variables for indirect draw.
DrawIndexedIndirectCmd* draw = iter->NextCommand<DrawIndexedIndirectCmd>(); DrawIndexedIndirectCmd* draw = iter->NextCommand<DrawIndexedIndirectCmd>();
DAWN_TRY(bindGroupTracker.Apply());
Buffer* indirectBuffer = ToBackend(draw->indirectBuffer.Get()); Buffer* indirectBuffer = ToBackend(draw->indirectBuffer.Get());
ASSERT(indirectBuffer != nullptr); ASSERT(indirectBuffer != nullptr);
DAWN_TRY(bindGroupTracker.Apply());
if (lastPipeline->GetUsesVertexOrInstanceIndex()) {
// Copy StartVertexLocation and StartInstanceLocation into the uniform buffer
// for built-in variables.
uint64_t offset =
draw->indirectOffset +
offsetof(D3D11_DRAW_INDEXED_INSTANCED_INDIRECT_ARGS, BaseVertexLocation);
DAWN_TRY(Buffer::Copy(commandContext, indirectBuffer, offset,
sizeof(uint32_t) * 2, commandContext->GetUniformBuffer(),
0));
}
commandContext->GetD3D11DeviceContext()->DrawIndexedInstancedIndirect( commandContext->GetD3D11DeviceContext()->DrawIndexedInstancedIndirect(
indirectBuffer->GetD3D11Buffer(), draw->indirectOffset); indirectBuffer->GetD3D11Buffer(), draw->indirectOffset);
@ -701,7 +726,12 @@ MaybeError CommandBuffer::RecordFirstIndexOffset(RenderPipeline* renderPipeline,
MaybeError CommandBuffer::RecordNumWorkgroupsForDispatch(ComputePipeline* computePipeline, MaybeError CommandBuffer::RecordNumWorkgroupsForDispatch(ComputePipeline* computePipeline,
CommandRecordingContext* commandContext, CommandRecordingContext* commandContext,
DispatchCmd* dispatchCmd) { DispatchCmd* dispatchCmd) {
// TODO(dawn:1705): only update the uniform buffer when the value changes. if (!computePipeline->UsesNumWorkgroups()) {
// Workgroup size is not used in shader, so we don't need to update the uniform buffer. The
// original value in the uniform buffer will not be used, so we don't need to clear it.
return {};
}
uint32_t data[4] = { uint32_t data[4] = {
dispatchCmd->x, dispatchCmd->x,
dispatchCmd->y, dispatchCmd->y,

View File

@ -88,4 +88,8 @@ void ComputePipeline::InitializeAsync(Ref<ComputePipelineBase> computePipeline,
CreateComputePipelineAsyncTask::RunAsync(std::move(asyncTask)); CreateComputePipelineAsyncTask::RunAsync(std::move(asyncTask));
} }
bool ComputePipeline::UsesNumWorkgroups() const {
return GetStage(SingleShaderStage::Compute).metadata->usesNumWorkgroups;
}
} // namespace dawn::native::d3d11 } // namespace dawn::native::d3d11

View File

@ -36,6 +36,8 @@ class ComputePipeline final : public ComputePipelineBase {
MaybeError Initialize() override; MaybeError Initialize() override;
bool UsesNumWorkgroups() const;
private: private:
using ComputePipelineBase::ComputePipelineBase; using ComputePipelineBase::ComputePipelineBase;
~ComputePipeline() override; ~ComputePipeline() override;

View File

@ -107,9 +107,6 @@ class ComputeDispatchTests : public DawnTest {
void IndirectTest(std::vector<uint32_t> indirectBufferData, void IndirectTest(std::vector<uint32_t> indirectBufferData,
uint64_t indirectOffset, uint64_t indirectOffset,
bool useNumWorkgroups = true) { bool useNumWorkgroups = true) {
// TODO(dawn:1791): fix indirect dispatch on D3D11
DAWN_SUPPRESS_TEST_IF(IsD3D11());
// Set up dst storage buffer to contain dispatch x, y, z // Set up dst storage buffer to contain dispatch x, y, z
wgpu::Buffer dst = utils::CreateBufferFromData<uint32_t>( wgpu::Buffer dst = utils::CreateBufferFromData<uint32_t>(
device, device,
@ -118,7 +115,7 @@ class ComputeDispatchTests : public DawnTest {
wgpu::Buffer indirectBuffer = utils::CreateBufferFromData( wgpu::Buffer indirectBuffer = utils::CreateBufferFromData(
device, &indirectBufferData[0], indirectBufferData.size() * sizeof(uint32_t), device, &indirectBufferData[0], indirectBufferData.size() * sizeof(uint32_t),
wgpu::BufferUsage::Indirect); wgpu::BufferUsage::Indirect | wgpu::BufferUsage::CopySrc);
uint32_t indirectStart = indirectOffset / sizeof(uint32_t); uint32_t indirectStart = indirectOffset / sizeof(uint32_t);
@ -174,6 +171,8 @@ class ComputeDispatchTests : public DawnTest {
indirectBufferData.begin() + indirectStart + 3); indirectBufferData.begin() + indirectStart + 3);
} }
// Verify the indirect buffer is not modified
EXPECT_BUFFER_U32_RANGE_EQ(&indirectBufferData[0], indirectBuffer, 0, 3);
// Verify the dispatch got called with group counts in indirect buffer if all group counts // Verify the dispatch got called with group counts in indirect buffer if all group counts
// are not zero // are not zero
EXPECT_BUFFER_U32_RANGE_EQ(&expected[0], dst, 0, 3); EXPECT_BUFFER_U32_RANGE_EQ(&expected[0], dst, 0, 3);

View File

@ -303,6 +303,9 @@ TEST_P(DrawIndexedIndirectTest, ValidateMultipleDraws) {
// TODO(dawn:1549) Fails on Qualcomm-based Android devices. // TODO(dawn:1549) Fails on Qualcomm-based Android devices.
DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsQualcomm()); DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsQualcomm());
// TODO(dawn:1791): Test fails with D3D11.
DAWN_SUPPRESS_TEST_IF(IsD3D11());
// It doesn't make sense to test invalid inputs when validation is disabled. // It doesn't make sense to test invalid inputs when validation is disabled.
DAWN_SUPPRESS_TEST_IF(HasToggleEnabled("skip_validation")); DAWN_SUPPRESS_TEST_IF(HasToggleEnabled("skip_validation"));
@ -710,6 +713,7 @@ TEST_P(DrawIndexedIndirectTest, ValidateReusedBundleWithChangingParams) {
} }
DAWN_INSTANTIATE_TEST(DrawIndexedIndirectTest, DAWN_INSTANTIATE_TEST(DrawIndexedIndirectTest,
D3D11Backend(),
D3D12Backend(), D3D12Backend(),
MetalBackend(), MetalBackend(),
OpenGLBackend(), OpenGLBackend(),