[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.
This commit is contained in:
netborg 2025-02-23 23:07:52 +01:00
parent 3720d3e0e8
commit bee72c27c8
5 changed files with 21 additions and 11 deletions

View file

@ -987,7 +987,7 @@ namespace dxvk {
entry->second.presenter = CreatePresenter(m_window, entry->second.frameLatencySignal); entry->second.presenter = CreatePresenter(m_window, entry->second.frameLatencySignal);
if (m_presentParams.hDeviceWindow == m_window && m_latencyTracking) 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; m_wctx = &entry->second;

View file

@ -309,15 +309,16 @@ namespace dxvk {
Rc<DxvkLatencyTracker> DxvkDevice::createLatencyTracker( Rc<DxvkLatencyTracker> DxvkDevice::createLatencyTracker(
const Rc<Presenter>& presenter) { const Rc<Presenter>& presenter,
uint64_t firstFrameId ) {
if (m_options.latencySleep == Tristate::False) 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_options.latencySleep == Tristate::Auto) {
if (m_features.nvLowLatency2) if (m_features.nvLowLatency2)
return new DxvkReflexLatencyTrackerNv(presenter); return new DxvkReflexLatencyTrackerNv(presenter);
else else
return new FramePacer(m_options); return new FramePacer(m_options, firstFrameId);
} }
return new DxvkBuiltInLatencyTracker(presenter, return new DxvkBuiltInLatencyTracker(presenter,

View file

@ -489,7 +489,8 @@ namespace dxvk {
* \param [in] presenter Presenter instance * \param [in] presenter Presenter instance
*/ */
Rc<DxvkLatencyTracker> createLatencyTracker( Rc<DxvkLatencyTracker> createLatencyTracker(
const Rc<Presenter>& presenter); const Rc<Presenter>& presenter,
uint64_t firstFrameId = 17);
/** /**
* \brief Presents a swap chain image * \brief Presents a swap chain image

View file

@ -8,7 +8,7 @@
namespace dxvk { 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, // 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. // 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, // although MAX_FRAME_LATENCY has advantages in many games and is likely the better default,
@ -53,11 +53,19 @@ namespace dxvk {
gpuStart.store(0); gpuStart.store(0);
} }
// be consistent that every frame has a gpuReady event from the previous frame // be consistent that every frame has a gpuReady event from finishing the previous frame
uint64_t firstFrameId = DXGI_MAX_SWAP_CHAIN_BUFFERS+1; LatencyMarkers* m = m_latencyMarkersStorage.getMarkers( firstFrameId );
LatencyMarkers* m = m_latencyMarkersStorage.getMarkers(firstFrameId); m->gpuReady.push_back( high_resolution_clock::now() );
m->gpuReady.push_back(high_resolution_clock::now());
m_gpuStarts[ firstFrameId % m_gpuStarts.size() ] = gpuReadyBit; 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 );
} }

View file

@ -23,7 +23,7 @@ namespace dxvk {
using microseconds = std::chrono::microseconds; using microseconds = std::chrono::microseconds;
public: public:
FramePacer( const DxvkOptions& options ); FramePacer( const DxvkOptions& options, uint64_t firstFrameId );
~FramePacer(); ~FramePacer();
void sleepAndBeginFrame( void sleepAndBeginFrame(