From c7d9201303c373a3c30ba4401d55d6af5008108d Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Thu, 4 Aug 2022 14:21:27 +0200 Subject: [PATCH] [d3d11] Change state clearing behaviour around deferred contexts Resetting command list state at the end of each D3D11 command list, as well as before ExecuteCommandList, will allow us to track which state needs to be reset, which may save us a significant amount of CPU work. --- src/d3d11/d3d11_context_def.cpp | 33 ++++++++++++++++++++++++++++----- src/d3d11/d3d11_context_imm.cpp | 8 +++++++- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/src/d3d11/d3d11_context_def.cpp b/src/d3d11/d3d11_context_def.cpp index 211c7aaed..b12f5b858 100644 --- a/src/d3d11/d3d11_context_def.cpp +++ b/src/d3d11/d3d11_context_def.cpp @@ -9,7 +9,7 @@ namespace dxvk { UINT ContextFlags) : D3D11CommonContext(pParent, Device, ContextFlags, GetCsChunkFlags(pParent)), m_commandList (CreateCommandList()) { - ClearState(); + ResetContextState(); } @@ -135,14 +135,25 @@ namespace dxvk { BOOL RestoreContextState) { D3D10DeviceLock lock = LockContext(); + // Clear state so that the command list can't observe any + // current context state. The command list itself will clean + // up after execution to ensure that no state changes done + // by the command list are visible to the immediate context. + ResetCommandListState(); + + // Flush any outstanding commands so that + // we don't mess up the execution order FlushCsChunk(); - static_cast(pCommandList)->EmitToCommandList(m_commandList.ptr()); + // Record any chunks from the given command list into the + // current command list and deal with context state + auto commandList = static_cast(pCommandList); + commandList->EmitToCommandList(m_commandList.ptr()); if (RestoreContextState) RestoreCommandListState(); else - ClearState(); + ResetContextState(); } @@ -151,17 +162,29 @@ namespace dxvk { ID3D11CommandList **ppCommandList) { D3D10DeviceLock lock = LockContext(); + // End all queries that were left active by the app FinalizeQueries(); + + // Clean up command list state so that the any state changed + // by this command list does not affect the calling context + ResetCommandListState(); + + // Make sure all commands are visible to the command list FlushCsChunk(); - if (ppCommandList != nullptr) + if (ppCommandList) *ppCommandList = m_commandList.ref(); + + // Create a clean command list, and if requested, restore all + // previously set context state. Otherwise, reset the context. + // Any use of ExecuteCommandList will reset command list state + // before the command list is actually executed. m_commandList = CreateCommandList(); if (RestoreDeferredContextState) RestoreCommandListState(); else - ClearState(); + ResetContextState(); m_mappedResources.clear(); ResetStagingBuffer(); diff --git a/src/d3d11/d3d11_context_imm.cpp b/src/d3d11/d3d11_context_imm.cpp index e0fe09cca..2f827d4d6 100644 --- a/src/d3d11/d3d11_context_imm.cpp +++ b/src/d3d11/d3d11_context_imm.cpp @@ -226,6 +226,12 @@ namespace dxvk { auto commandList = static_cast(pCommandList); + // Clear state so that the command list can't observe any + // current context state. The command list itself will clean + // up after execution to ensure that no state changes done + // by the command list are visible to the immediate context. + ResetCommandListState(); + // Flush any outstanding commands so that // we don't mess up the execution order FlushCsChunk(); @@ -242,7 +248,7 @@ namespace dxvk { if (RestoreContextState) RestoreCommandListState(); else - ClearState(); + ResetContextState(); // Mark CS thread as busy so that subsequent // flush operations get executed correctly.