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:
parent
283b3a042f
commit
300ec34c72
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
Loading…
Reference in New Issue