From 3dbe8ad43c578d2436e4ba5a1092f49096727066 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Wed, 15 Jan 2025 19:02:50 +0100 Subject: [PATCH] [d3d9] Rework device reset detection More robust. --- src/d3d9/d3d9_device.cpp | 2 +- src/d3d9/d3d9_device.h | 8 ++++---- src/d3d9/d3d9_swapchain.cpp | 14 +++++++++++++- src/d3d9/d3d9_swapchain.h | 4 ++++ 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/d3d9/d3d9_device.cpp b/src/d3d9/d3d9_device.cpp index 5679c1a3d..80bdcf88f 100644 --- a/src/d3d9/d3d9_device.cpp +++ b/src/d3d9/d3d9_device.cpp @@ -539,7 +539,7 @@ namespace dxvk { SynchronizeCsThread(DxvkCsThread::SynchronizeAll); if (m_d3d9Options.deferSurfaceCreation) - m_deviceHasBeenReset = true; + m_resetCtr++; return D3D_OK; } diff --git a/src/d3d9/d3d9_device.h b/src/d3d9/d3d9_device.h index c307036a4..7fd4ab70a 100644 --- a/src/d3d9/d3d9_device.h +++ b/src/d3d9/d3d9_device.h @@ -1143,12 +1143,12 @@ namespace dxvk { } /** - * \brief Returns whether the device has been reset and marks it as true. + * \brief Queries current reset counter * Used for the deferred surface creation workaround. * (Device Reset detection for D3D9SwapChainEx::Present) */ - bool IsDeviceReset() { - return std::exchange(m_deviceHasBeenReset, false); + uint32_t GetResetCounter() { + return m_resetCtr; } template @@ -1513,7 +1513,7 @@ namespace dxvk { VkImageLayout m_hazardLayout = VK_IMAGE_LAYOUT_GENERAL; bool m_usingGraphicsPipelines = false; - bool m_deviceHasBeenReset = false; + uint32_t m_resetCtr = 0u; DxvkDepthBiasRepresentation m_depthBiasRepresentation = { VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORMAT_EXT, false }; float m_depthBiasScale = 0.0f; diff --git a/src/d3d9/d3d9_swapchain.cpp b/src/d3d9/d3d9_swapchain.cpp index db590d725..0c47db2a0 100644 --- a/src/d3d9/d3d9_swapchain.cpp +++ b/src/d3d9/d3d9_swapchain.cpp @@ -151,7 +151,7 @@ namespace dxvk { if (!UpdateWindowCtx()) return D3D_OK; - if (options->deferSurfaceCreation && m_parent->IsDeviceReset()) + if (options->deferSurfaceCreation && IsDeviceReset(m_wctx)) m_wctx->presenter->invalidateSurface(); m_wctx->presenter->setSyncInterval(presentInterval); @@ -1272,6 +1272,18 @@ namespace dxvk { return this->GetParent()->IsExtended() ? "D3D9Ex" : "D3D9"; } + + bool D3D9SwapChainEx::IsDeviceReset(D3D9WindowContext* wctx) { + uint32_t counter = m_parent->GetResetCounter(); + + if (counter == wctx->deviceResetCounter) + return false; + + wctx->deviceResetCounter = counter; + return true; + } + + D3D9VkExtSwapchain::D3D9VkExtSwapchain(D3D9SwapChainEx *pSwapChain) : m_swapchain(pSwapChain) { diff --git a/src/d3d9/d3d9_swapchain.h b/src/d3d9/d3d9_swapchain.h index fd08508f3..9ab394975 100644 --- a/src/d3d9/d3d9_swapchain.h +++ b/src/d3d9/d3d9_swapchain.h @@ -55,6 +55,8 @@ namespace dxvk { uint64_t frameId = D3D9DeviceEx::MaxFrameLatency; Rc frameLatencySignal; + + uint32_t deviceResetCounter = 0u; }; using D3D9SwapChainExBase = D3D9DeviceChild; @@ -228,6 +230,8 @@ namespace dxvk { std::string GetApiName(); + bool IsDeviceReset(D3D9WindowContext* wctx); + const Com& GetFrontBuffer() const { return m_backBuffers.back(); }