From 32d2d41ecbe325968a935d00f6ccc1d7a4e8506a Mon Sep 17 00:00:00 2001 From: MaranBr Date: Tue, 10 Feb 2026 15:05:42 -0400 Subject: [PATCH] Avoid accumulating timing errors between frames --- src/video_core/renderer_vulkan/vk_scheduler.h | 20 ++++--------------- .../renderer_vulkan/vk_swapchain.cpp | 3 --- 2 files changed, 4 insertions(+), 19 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_scheduler.h b/src/video_core/renderer_vulkan/vk_scheduler.h index e762aa1019..09cdd41529 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.h +++ b/src/video_core/renderer_vulkan/vk_scheduler.h @@ -120,16 +120,11 @@ public: /// Waits for the given GPU tick, optionally pacing frames. void Wait(u64 tick, double target_fps = 0.0) { if (Settings::values.use_speed_limit.GetValue() && target_fps > 0.0) { - const auto frame_duration = std::chrono::duration(1.0 / target_fps); - auto now = std::chrono::steady_clock::now(); - if (next_frame_time == std::chrono::steady_clock::time_point{}) { - next_frame_time = now + std::chrono::duration_cast(frame_duration); - } - while (now > next_frame_time) { - next_frame_time += std::chrono::duration_cast(frame_duration); - } + const std::chrono::duration frame_duration_sec(1.0 / target_fps); + const auto now = std::chrono::steady_clock::now(); + const auto frames_elapsed = static_cast(std::chrono::duration_cast(now.time_since_epoch()).count() / std::chrono::duration_cast(frame_duration_sec).count()); + const auto next_frame_time = std::chrono::steady_clock::time_point(std::chrono::nanoseconds((frames_elapsed + 1) * std::chrono::duration_cast(frame_duration_sec).count())); std::this_thread::sleep_until(next_frame_time); - next_frame_time += std::chrono::duration_cast(frame_duration); } if (tick >= master_semaphore->CurrentTick()) { Flush(); @@ -137,11 +132,6 @@ public: master_semaphore->Wait(tick); } - /// Resets the frame pacing state by updating the next frame time to now. - void ResetFramePacing() { - next_frame_time = std::chrono::steady_clock::now(); - } - /// Returns the master timeline semaphore. [[nodiscard]] MasterSemaphore& GetMasterSemaphore() const noexcept { return *master_semaphore; @@ -296,8 +286,6 @@ private: std::condition_variable_any event_cv; std::jthread worker_thread; - std::chrono::steady_clock::time_point next_frame_time{}; - #ifdef _WIN32 std::unique_ptr high_res_timer; #endif diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index 1f31c8d5a1..0370e02fa7 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp @@ -146,9 +146,6 @@ void Swapchain::Create( { is_outdated = false; is_suboptimal = false; - - scheduler.ResetFramePacing(); - width = width_; height = height_; #ifdef ANDROID