diff --git a/src/common/settings.h b/src/common/settings.h index ce1bc647d9..8ad320aed1 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -330,6 +330,7 @@ struct Values { Setting use_nvdec_emulation{true, "use_nvdec_emulation"}; Setting accelerate_astc{true, "accelerate_astc"}; Setting use_vsync{true, "use_vsync"}; + BasicSetting fps_cap{1000, "fps_cap"}; BasicSetting disable_fps_limit{false, "disable_fps_limit"}; Setting use_assembly_shaders{false, "use_assembly_shaders"}; Setting use_asynchronous_shaders{false, "use_asynchronous_shaders"}; diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index 1d810562ff..9417489705 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp @@ -307,11 +307,12 @@ void NVFlinger::Compose() { } s64 NVFlinger::GetNextTicks() const { - if (Settings::values.disable_fps_limit.GetValue()) { - return 0; - } - constexpr s64 max_hertz = 120LL; - return (1000000000 * (1LL << swap_interval)) / max_hertz; + static constexpr s64 max_hertz = 120LL; + + const auto& settings = Settings::values; + const bool unlocked_fps = settings.disable_fps_limit.GetValue(); + const s64 fps_cap = unlocked_fps ? static_cast(settings.fps_cap.GetValue()) : 1; + return (1000000000 * (1LL << swap_interval)) / (max_hertz * fps_cap); } } // namespace Service::NVFlinger diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index a5e032959a..52bb07d160 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -823,6 +823,7 @@ void Config::ReadRendererValues() { ReadGlobalSetting(Settings::values.bg_blue); if (global) { + ReadBasicSetting(Settings::values.fps_cap); ReadBasicSetting(Settings::values.renderer_debug); } @@ -1352,6 +1353,7 @@ void Config::SaveRendererValues() { WriteGlobalSetting(Settings::values.bg_blue); if (global) { + WriteBasicSetting(Settings::values.fps_cap); WriteBasicSetting(Settings::values.renderer_debug); } diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp index 18f25def62..d79d2e23e3 100644 --- a/src/yuzu/configuration/configure_general.cpp +++ b/src/yuzu/configuration/configure_general.cpp @@ -48,6 +48,8 @@ void ConfigureGeneral::SetConfiguration() { ui->toggle_frame_limit->setChecked(Settings::values.use_frame_limit.GetValue()); ui->frame_limit->setValue(Settings::values.frame_limit.GetValue()); + ui->fps_cap->setValue(Settings::values.fps_cap.GetValue()); + ui->button_reset_defaults->setEnabled(runtime_lock); if (Settings::IsConfiguringGlobal()) { @@ -87,6 +89,8 @@ void ConfigureGeneral::ApplyConfiguration() { UISettings::values.pause_when_in_background = ui->toggle_background_pause->isChecked(); UISettings::values.hide_mouse = ui->toggle_hide_mouse->isChecked(); + Settings::values.fps_cap.SetValue(ui->fps_cap->value()); + // Guard if during game and set to game-specific value if (Settings::values.use_frame_limit.UsingGlobal()) { Settings::values.use_frame_limit.SetValue(ui->toggle_frame_limit->checkState() == diff --git a/src/yuzu/configuration/configure_general.ui b/src/yuzu/configuration/configure_general.ui index bc70410900..bc3c4b481c 100644 --- a/src/yuzu/configuration/configure_general.ui +++ b/src/yuzu/configuration/configure_general.ui @@ -51,6 +51,36 @@ + + + + + + Framerate Cap + + + Requires the use of the FPS Limiter Toggle hotkey to take effect. + + + + + + + x + + + 1 + + + 1000 + + + 500 + + + + + diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 03a909d17d..ce74155927 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -2921,7 +2921,7 @@ void GMainWindow::UpdateStatusBar() { } if (Settings::values.disable_fps_limit) { game_fps_label->setText( - tr("Game: %1 FPS (Limit off)").arg(results.average_game_fps, 0, 'f', 0)); + tr("Game: %1 FPS (Unlocked)").arg(results.average_game_fps, 0, 'f', 0)); } else { game_fps_label->setText(tr("Game: %1 FPS").arg(results.average_game_fps, 0, 'f', 0)); } diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 3e22fee379..12a61fc43d 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp @@ -455,6 +455,7 @@ void Config::ReadValues() { ReadSetting("Renderer", Settings::values.gpu_accuracy); ReadSetting("Renderer", Settings::values.use_asynchronous_gpu_emulation); ReadSetting("Renderer", Settings::values.use_vsync); + ReadSetting("Renderer", Settings::values.fps_cap); ReadSetting("Renderer", Settings::values.disable_fps_limit); ReadSetting("Renderer", Settings::values.use_assembly_shaders); ReadSetting("Renderer", Settings::values.use_asynchronous_shaders); diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h index 88d33ecabd..833c346bca 100644 --- a/src/yuzu_cmd/default_ini.h +++ b/src/yuzu_cmd/default_ini.h @@ -290,6 +290,10 @@ bg_red = bg_blue = bg_green = +# Caps the unlocked framerate to a multiple of the title's target FPS. +# 1 - 1000: Target FPS multiple cap. 1000 (default) +fps_cap = + [Audio] # Which audio output engine to use. # auto (default): Auto-select