From bee72c27c86baa2fdd231a4b1350cb0c2d73bbf8 Mon Sep 17 00:00:00 2001 From: netborg <137700136+netborg-afps@users.noreply.github.com> Date: Sun, 23 Feb 2025 23:07:52 +0100 Subject: [PATCH] [dxvk] Improve robustness of frame pacer initialization In d3d9 there were situations where the first frameId was 22, although in d3d11 it always started at 17. This did cause issues especially when waiting for fences which didn't get signaled for these frameIds. --- src/d3d9/d3d9_swapchain.cpp | 2 +- src/dxvk/dxvk_device.cpp | 7 ++++--- src/dxvk/dxvk_device.h | 3 ++- src/dxvk/framepacer/dxvk_framepacer.cpp | 18 +++++++++++++----- src/dxvk/framepacer/dxvk_framepacer.h | 2 +- 5 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/d3d9/d3d9_swapchain.cpp b/src/d3d9/d3d9_swapchain.cpp index 4ab616ed7..b858df2af 100644 --- a/src/d3d9/d3d9_swapchain.cpp +++ b/src/d3d9/d3d9_swapchain.cpp @@ -987,7 +987,7 @@ namespace dxvk { entry->second.presenter = CreatePresenter(m_window, entry->second.frameLatencySignal); if (m_presentParams.hDeviceWindow == m_window && m_latencyTracking) - m_latencyTracker = m_device->createLatencyTracker(entry->second.presenter); + m_latencyTracker = m_device->createLatencyTracker(entry->second.presenter, entry->second.frameId+1); } m_wctx = &entry->second; diff --git a/src/dxvk/dxvk_device.cpp b/src/dxvk/dxvk_device.cpp index cdb59e6c7..b05acf034 100644 --- a/src/dxvk/dxvk_device.cpp +++ b/src/dxvk/dxvk_device.cpp @@ -309,15 +309,16 @@ namespace dxvk { Rc DxvkDevice::createLatencyTracker( - const Rc& presenter) { + const Rc& presenter, + uint64_t firstFrameId ) { if (m_options.latencySleep == Tristate::False) - return new FramePacer(m_options); + return new FramePacer(m_options, firstFrameId); if (m_options.latencySleep == Tristate::Auto) { if (m_features.nvLowLatency2) return new DxvkReflexLatencyTrackerNv(presenter); else - return new FramePacer(m_options); + return new FramePacer(m_options, firstFrameId); } return new DxvkBuiltInLatencyTracker(presenter, diff --git a/src/dxvk/dxvk_device.h b/src/dxvk/dxvk_device.h index 2ec517c2e..859b30297 100644 --- a/src/dxvk/dxvk_device.h +++ b/src/dxvk/dxvk_device.h @@ -489,7 +489,8 @@ namespace dxvk { * \param [in] presenter Presenter instance */ Rc createLatencyTracker( - const Rc& presenter); + const Rc& presenter, + uint64_t firstFrameId = 17); /** * \brief Presents a swap chain image diff --git a/src/dxvk/framepacer/dxvk_framepacer.cpp b/src/dxvk/framepacer/dxvk_framepacer.cpp index c520d854d..a71b2d31d 100644 --- a/src/dxvk/framepacer/dxvk_framepacer.cpp +++ b/src/dxvk/framepacer/dxvk_framepacer.cpp @@ -8,7 +8,7 @@ namespace dxvk { - FramePacer::FramePacer( const DxvkOptions& options ) { + FramePacer::FramePacer( const DxvkOptions& options, uint64_t firstFrameId ) { // we'll default to LOW_LATENCY in the draft-PR for now, for demonstration purposes, // highlighting the generally much better input lag and medium-term time consistency. // although MAX_FRAME_LATENCY has advantages in many games and is likely the better default, @@ -53,11 +53,19 @@ namespace dxvk { gpuStart.store(0); } - // be consistent that every frame has a gpuReady event from the previous frame - uint64_t firstFrameId = DXGI_MAX_SWAP_CHAIN_BUFFERS+1; - LatencyMarkers* m = m_latencyMarkersStorage.getMarkers(firstFrameId); - m->gpuReady.push_back(high_resolution_clock::now()); + // be consistent that every frame has a gpuReady event from finishing the previous frame + LatencyMarkers* m = m_latencyMarkersStorage.getMarkers( firstFrameId ); + m->gpuReady.push_back( high_resolution_clock::now() ); m_gpuStarts[ firstFrameId % m_gpuStarts.size() ] = gpuReadyBit; + + LatencyMarkersTimeline& timeline = m_latencyMarkersStorage.m_timeline; + timeline.cpuFinished.store ( firstFrameId-1 ); + timeline.gpuStart.store ( firstFrameId-1 ); + timeline.gpuFinished.store ( firstFrameId-1 ); + timeline.frameFinished.store ( firstFrameId-1 ); + + m_mode->signalGpuStart ( firstFrameId-1 ); + m_mode->signalRenderFinished ( firstFrameId-1 ); } diff --git a/src/dxvk/framepacer/dxvk_framepacer.h b/src/dxvk/framepacer/dxvk_framepacer.h index 1a8cf63f3..38d740d1a 100644 --- a/src/dxvk/framepacer/dxvk_framepacer.h +++ b/src/dxvk/framepacer/dxvk_framepacer.h @@ -23,7 +23,7 @@ namespace dxvk { using microseconds = std::chrono::microseconds; public: - FramePacer( const DxvkOptions& options ); + FramePacer( const DxvkOptions& options, uint64_t firstFrameId ); ~FramePacer(); void sleepAndBeginFrame(