From acfe3cb0e3257d03481a3d9b7d5fbaf403281e9d Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sun, 16 Feb 2025 14:03:12 +0100 Subject: [PATCH] [d3d11] Use resource cookies for draw buffer tracking Avoids keeping draw buffers alive when the app stops using indirect draws. Unlikely to have caused issues in practice, but draw buffers are not part of the API state to begin with. --- src/d3d11/d3d11_context.cpp | 20 ++++++++++++-------- src/d3d11/d3d11_context_imm.cpp | 5 +++++ src/d3d11/d3d11_context_state.h | 10 +++++----- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index 0868ab9ed..97af10d3a 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -4644,10 +4644,6 @@ namespace dxvk { ApplyRasterizerSampleCount(); ApplyViewportState(); - BindDrawBuffers( - m_state.id.argBuffer.ptr(), - m_state.id.cntBuffer.ptr()); - BindIndexBuffer( m_state.ia.indexBuffer.buffer.ptr(), m_state.ia.indexBuffer.offset, @@ -4686,6 +4682,11 @@ namespace dxvk { RestoreSamplers(); RestoreSamplers(); RestoreSamplers(); + + // Draw buffer bindings aren't persistent at the API level, and + // we can't meaningfully track them. Just reset this state here + // and reapply on the next indirect draw. + SetDrawBuffers(nullptr, nullptr); } @@ -5012,10 +5013,13 @@ namespace dxvk { auto argBuffer = static_cast(pBufferForArgs); auto cntBuffer = static_cast(pBufferForCount); - if (m_state.id.argBuffer != argBuffer - || m_state.id.cntBuffer != cntBuffer) { - m_state.id.argBuffer = argBuffer; - m_state.id.cntBuffer = cntBuffer; + auto argBufferCookie = argBuffer ? argBuffer->GetCookie() : 0u; + auto cntBufferCookie = cntBuffer ? cntBuffer->GetCookie() : 0u; + + if (m_state.id.argBufferCookie != argBufferCookie + || m_state.id.cntBufferCookie != cntBufferCookie) { + m_state.id.argBufferCookie = argBufferCookie; + m_state.id.cntBufferCookie = cntBufferCookie; BindDrawBuffers(argBuffer, cntBuffer); } diff --git a/src/d3d11/d3d11_context_imm.cpp b/src/d3d11/d3d11_context_imm.cpp index e762dd9eb..e22201afa 100644 --- a/src/d3d11/d3d11_context_imm.cpp +++ b/src/d3d11/d3d11_context_imm.cpp @@ -865,6 +865,11 @@ namespace dxvk { Rc LatencyTracker) { D3D10DeviceLock lock = LockContext(); + // Don't keep draw buffers alive indefinitely. This cannot be + // done in ExecuteFlush because command recording itself might + // flush, so no state changes are allowed to happen there. + SetDrawBuffers(nullptr, nullptr); + EmitCs([ cTracker = std::move(LatencyTracker) ] (DxvkContext* ctx) { diff --git a/src/d3d11/d3d11_context_state.h b/src/d3d11/d3d11_context_state.h index fd48d8ee4..9dea34937 100644 --- a/src/d3d11/d3d11_context_state.h +++ b/src/d3d11/d3d11_context_state.h @@ -232,12 +232,12 @@ namespace dxvk { * argument and draw count buffer. */ struct D3D11ContextStateID { - Com argBuffer = nullptr; - Com cntBuffer = nullptr; + uint64_t argBufferCookie = 0u; + uint64_t cntBufferCookie = 0u; void reset() { - argBuffer = nullptr; - cntBuffer = nullptr; + argBufferCookie = 0u; + cntBufferCookie = 0u; } }; @@ -347,4 +347,4 @@ namespace dxvk { uint32_t soCount; }; -} \ No newline at end of file +}