From 114cd4e70337e764f2724fc9d3efa1e8c5d8c8d5 Mon Sep 17 00:00:00 2001 From: MaranBr Date: Mon, 9 Feb 2026 11:03:25 -0400 Subject: [PATCH] Fix frame pacing when switching games --- src/android/app/src/main/res/values/arrays.xml | 2 +- src/android/app/src/main/res/values/strings.xml | 2 +- src/common/settings.h | 4 ++-- src/common/settings_enums.h | 2 +- src/qt_common/config/shared_translation.cpp | 2 +- src/video_core/renderer_vulkan/vk_scheduler.h | 16 ++++++++++++---- src/video_core/renderer_vulkan/vk_swapchain.cpp | 5 ++++- 7 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/android/app/src/main/res/values/arrays.xml b/src/android/app/src/main/res/values/arrays.xml index 1f45383a86..8b6ae5405c 100644 --- a/src/android/app/src/main/res/values/arrays.xml +++ b/src/android/app/src/main/res/values/arrays.xml @@ -531,7 +531,7 @@ - @string/frame_pacing_mode_default + @string/frame_pacing_mode_target_Auto @string/frame_pacing_mode_target_30 @string/frame_pacing_mode_target_60 @string/frame_pacing_mode_target_120 diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 99e225192f..1c8f009132 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -1026,7 +1026,7 @@ Safe - Default + Auto 30 FPS 60 FPS 120 FPS diff --git a/src/common/settings.h b/src/common/settings.h index 79028fcaa2..5dc2f30cf8 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -435,8 +435,8 @@ struct Values { Category::RendererAdvanced}; SwitchableSetting frame_pacing_mode{linkage, - FramePacingMode::Default, - FramePacingMode::Default, + FramePacingMode::Target_Auto, + FramePacingMode::Target_Auto, FramePacingMode::Target_120, "frame_pacing_mode", Category::RendererAdvanced}; diff --git a/src/common/settings_enums.h b/src/common/settings_enums.h index 509bd414ae..def99db21b 100644 --- a/src/common/settings_enums.h +++ b/src/common/settings_enums.h @@ -129,7 +129,7 @@ ENUM(TimeZone, Auto, Default, Cet, Cst6Cdt, Cuba, Eet, Egypt, Eire, Est, Est5Edt ENUM(AnisotropyMode, Automatic, Default, X2, X4, X8, X16, X32, X64, None); ENUM(AstcDecodeMode, Cpu, Gpu, CpuAsynchronous); ENUM(AstcRecompression, Uncompressed, Bc1, Bc3); -ENUM(FramePacingMode, Default, Target_30, Target_60, Target_120); +ENUM(FramePacingMode, Target_Auto, Target_30, Target_60, Target_120); ENUM(VSyncMode, Immediate, Mailbox, Fifo, FifoRelaxed); ENUM(VramUsageMode, Conservative, Aggressive); ENUM(RendererBackend, OpenGL_GLSL, Vulkan, Null, OpenGL_GLASM, OpenGL_SPIRV); diff --git a/src/qt_common/config/shared_translation.cpp b/src/qt_common/config/shared_translation.cpp index fdcfbea9e9..b5ad941cc5 100644 --- a/src/qt_common/config/shared_translation.cpp +++ b/src/qt_common/config/shared_translation.cpp @@ -501,7 +501,7 @@ std::unique_ptr ComboboxEnumeration(QObject* parent) }}); translations->insert({Settings::EnumMetadata::Index(), { - PAIR(FramePacingMode, Default, tr("Default")), + PAIR(FramePacingMode, Target_Auto, tr("Auto")), PAIR(FramePacingMode, Target_30, tr("30 FPS")), PAIR(FramePacingMode, Target_60, tr("60 FPS")), PAIR(FramePacingMode, Target_120, tr("120 FPS")), diff --git a/src/video_core/renderer_vulkan/vk_scheduler.h b/src/video_core/renderer_vulkan/vk_scheduler.h index 6de9b6b1ca..094607775c 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.h +++ b/src/video_core/renderer_vulkan/vk_scheduler.h @@ -125,10 +125,12 @@ public: if (master_semaphore->CurrentTick() >= tick) { return; } - static auto next_frame_time = std::chrono::steady_clock::now(); - auto frame_duration = std::chrono::duration(1.0 / target_fps); - next_frame_time += std::chrono::duration_cast(frame_duration); - auto now = std::chrono::steady_clock::now(); + const auto frame_duration = std::chrono::duration_cast(std::chrono::duration(1.0 / target_fps)); + const auto now = std::chrono::steady_clock::now(); + if (next_frame_time == std::chrono::steady_clock::time_point{}) { + next_frame_time = now; + } + next_frame_time += frame_duration; if (next_frame_time > now) { std::this_thread::sleep_until(next_frame_time); } else { @@ -136,6 +138,10 @@ public: } } + void ResetFramePacing() { + next_frame_time = std::chrono::steady_clock::now(); + } + /// Returns the master timeline semaphore. [[nodiscard]] MasterSemaphore& GetMasterSemaphore() const noexcept { return *master_semaphore; @@ -277,6 +283,8 @@ private: std::mutex queue_mutex; std::condition_variable_any event_cv; std::jthread worker_thread; + + std::chrono::steady_clock::time_point next_frame_time{}; }; } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index ce1c3b9442..3f56a950a3 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp @@ -146,6 +146,9 @@ void Swapchain::Create( { is_outdated = false; is_suboptimal = false; + + scheduler.ResetFramePacing(); + width = width_; height = height_; #ifdef ANDROID @@ -198,7 +201,7 @@ bool Swapchain::AcquireNextImage() { scheduler.Wait(resource_ticks[image_index]); } else { switch (Settings::values.frame_pacing_mode.GetValue()) { - case Settings::FramePacingMode::Default: + case Settings::FramePacingMode::Target_Auto: scheduler.Wait(resource_ticks[image_index]); break; case Settings::FramePacingMode::Target_30: