From f083783f7e4d0fe67d46e671a8464842cdbdd99b Mon Sep 17 00:00:00 2001 From: jchen10 Date: Tue, 9 May 2023 02:22:42 +0000 Subject: [PATCH] d3d11: VertexBufferTracker This introduces VertexBufferTracker to correctly track pipeline's vertex buffer state. Bug: dawn:1799 Bug: dawn:1705 Change-Id: I06f32b501a3637b22318ec201b1953eba6ed0cf2 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/131700 Reviewed-by: Peng Huang Kokoro: Kokoro Reviewed-by: Austin Eng Commit-Queue: Jie A Chen --- src/dawn/native/d3d11/CommandBufferD3D11.cpp | 58 +++++++++++++++---- .../tests/end2end/BufferZeroInitTests.cpp | 2 - 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/src/dawn/native/d3d11/CommandBufferD3D11.cpp b/src/dawn/native/d3d11/CommandBufferD3D11.cpp index 38bf0eb7cc..4db4f9bc7c 100644 --- a/src/dawn/native/d3d11/CommandBufferD3D11.cpp +++ b/src/dawn/native/d3d11/CommandBufferD3D11.cpp @@ -50,6 +50,48 @@ DXGI_FORMAT DXGIIndexFormat(wgpu::IndexFormat format) { } } +class VertexBufferTracker { + public: + explicit VertexBufferTracker(CommandRecordingContext* commandContext) + : mCommandContext(commandContext) {} + + ~VertexBufferTracker() { + mD3D11Buffers = {}; + mStrides = {}; + mOffsets = {}; + mCommandContext->GetD3D11DeviceContext()->IASetVertexBuffers( + 0, kMaxVertexBuffers, mD3D11Buffers.data(), mStrides.data(), mOffsets.data()); + } + + void OnSetVertexBuffer(VertexBufferSlot slot, ID3D11Buffer* buffer, uint64_t offset) { + mD3D11Buffers[slot] = buffer; + mOffsets[slot] = offset; + } + + void Apply(const RenderPipeline* renderPipeline) { + ASSERT(renderPipeline != nullptr); + + // If the vertex state has changed, we need to update the strides. + if (mLastAppliedRenderPipeline != renderPipeline) { + mLastAppliedRenderPipeline = renderPipeline; + for (VertexBufferSlot slot : + IterateBitSet(renderPipeline->GetVertexBufferSlotsUsed())) { + mStrides[slot] = renderPipeline->GetVertexBuffer(slot).arrayStride; + } + } + + mCommandContext->GetD3D11DeviceContext()->IASetVertexBuffers( + 0, kMaxVertexBuffers, mD3D11Buffers.data(), mStrides.data(), mOffsets.data()); + } + + private: + CommandRecordingContext* const mCommandContext; + const RenderPipeline* mLastAppliedRenderPipeline = nullptr; + ityp::array mD3D11Buffers = {}; + ityp::array mStrides = {}; + ityp::array mOffsets = {}; +}; + } // namespace // Create CommandBuffer @@ -437,6 +479,7 @@ MaybeError CommandBuffer::ExecuteRenderPass(BeginRenderPassCmd* renderPass, RenderPipeline* lastPipeline = nullptr; BindGroupTracker bindGroupTracker(commandContext); + VertexBufferTracker vertexBufferTracker(commandContext); std::array blendColor = {0.0f, 0.0f, 0.0f, 0.0f}; uint32_t stencilReference = 0; @@ -446,6 +489,7 @@ MaybeError CommandBuffer::ExecuteRenderPass(BeginRenderPassCmd* renderPass, DrawCmd* draw = iter->NextCommand(); DAWN_TRY(bindGroupTracker.Apply()); + vertexBufferTracker.Apply(lastPipeline); DAWN_TRY(RecordFirstIndexOffset(lastPipeline, commandContext, draw->firstVertex, draw->firstInstance)); commandContext->GetD3D11DeviceContext()->DrawInstanced( @@ -458,6 +502,7 @@ MaybeError CommandBuffer::ExecuteRenderPass(BeginRenderPassCmd* renderPass, DrawIndexedCmd* draw = iter->NextCommand(); DAWN_TRY(bindGroupTracker.Apply()); + vertexBufferTracker.Apply(lastPipeline); DAWN_TRY(RecordFirstIndexOffset(lastPipeline, commandContext, draw->baseVertex, draw->firstInstance)); commandContext->GetD3D11DeviceContext()->DrawIndexedInstanced( @@ -474,6 +519,7 @@ MaybeError CommandBuffer::ExecuteRenderPass(BeginRenderPassCmd* renderPass, ASSERT(indirectBuffer != nullptr); DAWN_TRY(bindGroupTracker.Apply()); + vertexBufferTracker.Apply(lastPipeline); if (lastPipeline->GetUsesVertexOrInstanceIndex()) { // Copy StartVertexLocation and StartInstanceLocation into the uniform buffer @@ -499,6 +545,7 @@ MaybeError CommandBuffer::ExecuteRenderPass(BeginRenderPassCmd* renderPass, ASSERT(indirectBuffer != nullptr); DAWN_TRY(bindGroupTracker.Apply()); + vertexBufferTracker.Apply(lastPipeline); if (lastPipeline->GetUsesVertexOrInstanceIndex()) { // Copy StartVertexLocation and StartInstanceLocation into the uniform buffer @@ -555,17 +602,8 @@ MaybeError CommandBuffer::ExecuteRenderPass(BeginRenderPassCmd* renderPass, case Command::SetVertexBuffer: { SetVertexBufferCmd* cmd = iter->NextCommand(); - ASSERT(lastPipeline); - const VertexBufferInfo& info = lastPipeline->GetVertexBuffer(cmd->slot); - - // TODO(dawn:1705): should we set vertex back to nullptr after the draw call? - UINT slot = static_cast(cmd->slot); ID3D11Buffer* buffer = ToBackend(cmd->buffer)->GetD3D11Buffer(); - UINT arrayStride = info.arrayStride; - UINT offset = cmd->offset; - commandContext->GetD3D11DeviceContext()->IASetVertexBuffers(slot, 1, &buffer, - &arrayStride, &offset); - + vertexBufferTracker.OnSetVertexBuffer(cmd->slot, buffer, cmd->offset); break; } diff --git a/src/dawn/tests/end2end/BufferZeroInitTests.cpp b/src/dawn/tests/end2end/BufferZeroInitTests.cpp index faf3d7d5d6..05982faf18 100644 --- a/src/dawn/tests/end2end/BufferZeroInitTests.cpp +++ b/src/dawn/tests/end2end/BufferZeroInitTests.cpp @@ -1122,8 +1122,6 @@ TEST_P(BufferZeroInitTest, BoundAsStorageBuffer) { // Test the buffer will be lazily initialized correctly when its first use is in SetVertexBuffer. TEST_P(BufferZeroInitTest, SetVertexBuffer) { - // TODO(dawn:1799): Figure this out. - DAWN_SUPPRESS_TEST_IF(IsD3D11()); // Bind the whole buffer as a vertex buffer. { constexpr uint64_t kVertexBufferOffset = 0u;