From f8aaa599907cff765efdaa6f9875cb4c42746870 Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Sun, 26 Jun 2022 13:58:06 -0700
Subject: [PATCH 1/3] hle: service: nvflinger: Factor speed limit into frame
 time calculation.

- This allows the %-based "Limit Speed Percent" setting to work with MC emulation.
- This is already supported for SC emulation.
---
 src/core/hle/service/nvflinger/nvflinger.cpp | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index 5f69c8c2c2..f92d6beb5d 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -289,7 +289,14 @@ s64 NVFlinger::GetNextTicks() const {
     const auto& settings = Settings::values;
     const bool unlocked_fps = settings.disable_fps_limit.GetValue();
     const s64 fps_cap = unlocked_fps ? static_cast<s64>(settings.fps_cap.GetValue()) : 1;
-    return (1000000000 * (1LL << swap_interval)) / (max_hertz * fps_cap);
+    auto speed_scale = 1.f;
+    if (settings.use_speed_limit.GetValue() && settings.use_multi_core.GetValue()) {
+        // Scales the speed based on speed_limit setting on MC. SC is handled by
+        // SpeedLimiter::DoSpeedLimiting.
+        speed_scale = 100.f / settings.speed_limit.GetValue();
+    }
+    return static_cast<s64>(((1000000000 * (1LL << swap_interval)) / (max_hertz * fps_cap)) *
+                            speed_scale);
 }
 
 } // namespace Service::NVFlinger

From 02282477e739c8db64a13ecb0d1128098b0b0035 Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Fri, 15 Jul 2022 22:14:00 -0700
Subject: [PATCH 2/3] yuzu: settings: Remove framerate cap and merge unlocked
 framerate setting.

- These were all somewhat redundant.
---
 src/common/settings.cpp                       |  1 -
 src/common/settings.h                         |  2 -
 src/core/hle/service/nvflinger/nvflinger.cpp  | 18 +++--
 .../renderer_vulkan/vk_swapchain.cpp          |  6 +-
 src/yuzu/configuration/config.cpp             |  2 -
 src/yuzu/configuration/configure_general.cpp  | 24 ------
 src/yuzu/configuration/configure_general.ui   | 81 -------------------
 src/yuzu/main.cpp                             |  7 +-
 src/yuzu_cmd/config.cpp                       |  2 -
 src/yuzu_cmd/default_ini.h                    |  7 --
 10 files changed, 15 insertions(+), 135 deletions(-)

diff --git a/src/common/settings.cpp b/src/common/settings.cpp
index 751549583e..d4c52989a9 100644
--- a/src/common/settings.cpp
+++ b/src/common/settings.cpp
@@ -185,7 +185,6 @@ void RestoreGlobalState(bool is_powered_on) {
     values.max_anisotropy.SetGlobal(true);
     values.use_speed_limit.SetGlobal(true);
     values.speed_limit.SetGlobal(true);
-    values.fps_cap.SetGlobal(true);
     values.use_disk_shader_cache.SetGlobal(true);
     values.gpu_accuracy.SetGlobal(true);
     values.use_asynchronous_gpu_emulation.SetGlobal(true);
diff --git a/src/common/settings.h b/src/common/settings.h
index 368046e871..2bccb8642c 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -440,8 +440,6 @@ struct Values {
     SwitchableSetting<NvdecEmulation> nvdec_emulation{NvdecEmulation::GPU, "nvdec_emulation"};
     SwitchableSetting<bool> accelerate_astc{true, "accelerate_astc"};
     SwitchableSetting<bool> use_vsync{true, "use_vsync"};
-    SwitchableSetting<u16, true> fps_cap{1000, 1, 1000, "fps_cap"};
-    Setting<bool> disable_fps_limit{false, "disable_fps_limit"};
     SwitchableSetting<ShaderBackend, true> shader_backend{ShaderBackend::GLASM, ShaderBackend::GLSL,
                                                           ShaderBackend::SPIRV, "shader_backend"};
     SwitchableSetting<bool> 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 f92d6beb5d..798c4d3a7f 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -287,16 +287,18 @@ s64 NVFlinger::GetNextTicks() const {
     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<s64>(settings.fps_cap.GetValue()) : 1;
     auto speed_scale = 1.f;
-    if (settings.use_speed_limit.GetValue() && settings.use_multi_core.GetValue()) {
-        // Scales the speed based on speed_limit setting on MC. SC is handled by
-        // SpeedLimiter::DoSpeedLimiting.
-        speed_scale = 100.f / settings.speed_limit.GetValue();
+    if (settings.use_multi_core.GetValue()) {
+        if (settings.use_speed_limit.GetValue()) {
+            // Scales the speed based on speed_limit setting on MC. SC is handled by
+            // SpeedLimiter::DoSpeedLimiting.
+            speed_scale = 100.f / settings.speed_limit.GetValue();
+        } else {
+            // Run at unlocked framerate.
+            speed_scale = 0.01f;
+        }
     }
-    return static_cast<s64>(((1000000000 * (1LL << swap_interval)) / (max_hertz * fps_cap)) *
-                            speed_scale);
+    return static_cast<s64>(((1000000000 * (1LL << swap_interval)) / max_hertz) * speed_scale);
 }
 
 } // namespace Service::NVFlinger
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp
index a0c26a72a0..fa8efd22ec 100644
--- a/src/video_core/renderer_vulkan/vk_swapchain.cpp
+++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp
@@ -38,7 +38,7 @@ VkPresentModeKHR ChooseSwapPresentMode(vk::Span<VkPresentModeKHR> modes) {
     if (found_mailbox != modes.end()) {
         return VK_PRESENT_MODE_MAILBOX_KHR;
     }
-    if (Settings::values.disable_fps_limit.GetValue()) {
+    if (!Settings::values.use_speed_limit.GetValue()) {
         // FIFO present mode locks the framerate to the monitor's refresh rate,
         // Find an alternative to surpass this limitation if FPS is unlocked.
         const auto found_imm = std::find(modes.begin(), modes.end(), VK_PRESENT_MODE_IMMEDIATE_KHR);
@@ -205,7 +205,7 @@ void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, u3
 
     extent = swapchain_ci.imageExtent;
     current_srgb = srgb;
-    current_fps_unlocked = Settings::values.disable_fps_limit.GetValue();
+    current_fps_unlocked = !Settings::values.use_speed_limit.GetValue();
 
     images = swapchain.GetImages();
     image_count = static_cast<u32>(images.size());
@@ -259,7 +259,7 @@ void Swapchain::Destroy() {
 }
 
 bool Swapchain::HasFpsUnlockChanged() const {
-    return current_fps_unlocked != Settings::values.disable_fps_limit.GetValue();
+    return current_fps_unlocked != !Settings::values.use_speed_limit.GetValue();
 }
 
 bool Swapchain::NeedsPresentModeUpdate() const {
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index a57b2e019d..0a61839da9 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -668,7 +668,6 @@ void Config::ReadRendererValues() {
     ReadGlobalSetting(Settings::values.max_anisotropy);
     ReadGlobalSetting(Settings::values.use_speed_limit);
     ReadGlobalSetting(Settings::values.speed_limit);
-    ReadGlobalSetting(Settings::values.fps_cap);
     ReadGlobalSetting(Settings::values.use_disk_shader_cache);
     ReadGlobalSetting(Settings::values.gpu_accuracy);
     ReadGlobalSetting(Settings::values.use_asynchronous_gpu_emulation);
@@ -1237,7 +1236,6 @@ void Config::SaveRendererValues() {
     WriteGlobalSetting(Settings::values.max_anisotropy);
     WriteGlobalSetting(Settings::values.use_speed_limit);
     WriteGlobalSetting(Settings::values.speed_limit);
-    WriteGlobalSetting(Settings::values.fps_cap);
     WriteGlobalSetting(Settings::values.use_disk_shader_cache);
     WriteSetting(QString::fromStdString(Settings::values.gpu_accuracy.GetLabel()),
                  static_cast<u32>(Settings::values.gpu_accuracy.GetValue(global)),
diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp
index a31fabd3ff..2a446205b8 100644
--- a/src/yuzu/configuration/configure_general.cpp
+++ b/src/yuzu/configuration/configure_general.cpp
@@ -27,9 +27,6 @@ ConfigureGeneral::ConfigureGeneral(const Core::System& system_, QWidget* parent)
 
     connect(ui->button_reset_defaults, &QPushButton::clicked, this,
             &ConfigureGeneral::ResetDefaults);
-
-    ui->fps_cap_label->setVisible(Settings::IsConfiguringGlobal());
-    ui->fps_cap_combobox->setVisible(!Settings::IsConfiguringGlobal());
 }
 
 ConfigureGeneral::~ConfigureGeneral() = default;
@@ -52,8 +49,6 @@ void ConfigureGeneral::SetConfiguration() {
     ui->toggle_speed_limit->setChecked(Settings::values.use_speed_limit.GetValue());
     ui->speed_limit->setValue(Settings::values.speed_limit.GetValue());
 
-    ui->fps_cap->setValue(Settings::values.fps_cap.GetValue());
-
     ui->button_reset_defaults->setEnabled(runtime_lock);
 
     if (Settings::IsConfiguringGlobal()) {
@@ -61,11 +56,6 @@ void ConfigureGeneral::SetConfiguration() {
     } else {
         ui->speed_limit->setEnabled(Settings::values.use_speed_limit.GetValue() &&
                                     use_speed_limit != ConfigurationShared::CheckState::Global);
-
-        ui->fps_cap_combobox->setCurrentIndex(Settings::values.fps_cap.UsingGlobal() ? 0 : 1);
-        ui->fps_cap->setEnabled(!Settings::values.fps_cap.UsingGlobal());
-        ConfigurationShared::SetHighlight(ui->fps_cap_layout,
-                                          !Settings::values.fps_cap.UsingGlobal());
     }
 }
 
@@ -102,8 +92,6 @@ void ConfigureGeneral::ApplyConfiguration() {
         UISettings::values.mute_when_in_background = ui->toggle_background_mute->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_speed_limit.UsingGlobal()) {
             Settings::values.use_speed_limit.SetValue(ui->toggle_speed_limit->checkState() ==
@@ -119,13 +107,6 @@ void ConfigureGeneral::ApplyConfiguration() {
                                                       Qt::Checked);
             Settings::values.speed_limit.SetValue(ui->speed_limit->value());
         }
-
-        if (ui->fps_cap_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) {
-            Settings::values.fps_cap.SetGlobal(true);
-        } else {
-            Settings::values.fps_cap.SetGlobal(false);
-            Settings::values.fps_cap.SetValue(ui->fps_cap->value());
-        }
     }
 }
 
@@ -171,9 +152,4 @@ void ConfigureGeneral::SetupPerGameUI() {
         ui->speed_limit->setEnabled(ui->toggle_speed_limit->isChecked() &&
                                     (use_speed_limit != ConfigurationShared::CheckState::Global));
     });
-
-    connect(ui->fps_cap_combobox, qOverload<int>(&QComboBox::activated), this, [this](int index) {
-        ui->fps_cap->setEnabled(index == 1);
-        ConfigurationShared::SetHighlight(ui->fps_cap_layout, index == 1);
-    });
 }
diff --git a/src/yuzu/configuration/configure_general.ui b/src/yuzu/configuration/configure_general.ui
index c6ef2ab705..5b90b11094 100644
--- a/src/yuzu/configuration/configure_general.ui
+++ b/src/yuzu/configuration/configure_general.ui
@@ -27,87 +27,6 @@
        <layout class="QHBoxLayout" name="GeneralHorizontalLayout">
         <item>
          <layout class="QVBoxLayout" name="GeneralVerticalLayout">
-          <item>
-           <widget class="QWidget" name="fps_cap_layout" native="true">
-            <layout class="QHBoxLayout" name="horizontalLayout" stretch="1,1">
-             <property name="leftMargin">
-              <number>0</number>
-             </property>
-             <property name="topMargin">
-              <number>0</number>
-             </property>
-             <property name="rightMargin">
-              <number>0</number>
-             </property>
-             <property name="bottomMargin">
-              <number>0</number>
-             </property>
-             <item>
-              <layout class="QHBoxLayout" name="horizontalLayout_4">
-               <item>
-                <widget class="QComboBox" name="fps_cap_combobox">
-                 <property name="currentText">
-                  <string>Use global framerate cap</string>
-                 </property>
-                 <property name="currentIndex">
-                  <number>0</number>
-                 </property>
-                 <item>
-                  <property name="text">
-                   <string>Use global framerate cap</string>
-                  </property>
-                 </item>
-                 <item>
-                  <property name="text">
-                   <string>Set framerate cap:</string>
-                  </property>
-                 </item>
-                </widget>
-               </item>
-               <item>
-                <widget class="QLabel" name="fps_cap_label">
-                 <property name="toolTip">
-                  <string>Requires the use of the FPS Limiter Toggle hotkey to take effect.</string>
-                 </property>
-                 <property name="text">
-                  <string>Framerate Cap</string>
-                 </property>
-                </widget>
-               </item>
-               <item>
-                <spacer name="horizontalSpacer">
-                 <property name="orientation">
-                  <enum>Qt::Horizontal</enum>
-                 </property>
-                 <property name="sizeHint" stdset="0">
-                  <size>
-                   <width>40</width>
-                   <height>20</height>
-                  </size>
-                 </property>
-                </spacer>
-               </item>
-              </layout>
-             </item>
-             <item>
-              <widget class="QSpinBox" name="fps_cap">
-               <property name="suffix">
-                <string>x</string>
-               </property>
-               <property name="minimum">
-                <number>1</number>
-               </property>
-               <property name="maximum">
-                <number>1000</number>
-               </property>
-               <property name="value">
-                <number>500</number>
-               </property>
-              </widget>
-             </item>
-            </layout>
-           </widget>
-          </item>
           <item>
            <layout class="QHBoxLayout" name="horizontalLayout_2">
             <item>
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index b460020b16..ed802d3290 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -1059,7 +1059,7 @@ void GMainWindow::InitializeHotkeys() {
         Settings::values.volume.SetValue(static_cast<u8>(new_volume));
     });
     connect_shortcut(QStringLiteral("Toggle Framerate Limit"), [] {
-        Settings::values.disable_fps_limit.SetValue(!Settings::values.disable_fps_limit.GetValue());
+        Settings::values.use_speed_limit.SetValue(!Settings::values.use_speed_limit.GetValue());
     });
     connect_shortcut(QStringLiteral("Toggle Mouse Panning"), [&] {
         Settings::values.mouse_panning = !Settings::values.mouse_panning;
@@ -1483,9 +1483,6 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
         Config per_game_config(*system, config_file_name, Config::ConfigType::PerGameConfig);
     }
 
-    // Disable fps limit toggle when booting a new title
-    Settings::values.disable_fps_limit.SetValue(false);
-
     // Save configurations
     UpdateUISettings();
     game_list->SaveInterfaceLayout();
@@ -3277,7 +3274,7 @@ void GMainWindow::UpdateStatusBar() {
     } else {
         emu_speed_label->setText(tr("Speed: %1%").arg(results.emulation_speed * 100.0, 0, 'f', 0));
     }
-    if (Settings::values.disable_fps_limit) {
+    if (!Settings::values.use_speed_limit) {
         game_fps_label->setText(
             tr("Game: %1 FPS (Unlocked)").arg(results.average_game_fps, 0, 'f', 0));
     } else {
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index 9db7115a20..5576fb7954 100644
--- a/src/yuzu_cmd/config.cpp
+++ b/src/yuzu_cmd/config.cpp
@@ -310,8 +310,6 @@ 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.shader_backend);
     ReadSetting("Renderer", Settings::values.use_asynchronous_shaders);
     ReadSetting("Renderer", Settings::values.nvdec_emulation);
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h
index a3b8432f51..d9a2a460c2 100644
--- a/src/yuzu_cmd/default_ini.h
+++ b/src/yuzu_cmd/default_ini.h
@@ -330,10 +330,6 @@ 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
@@ -434,9 +430,6 @@ use_debug_asserts =
 use_auto_stub =
 # Enables/Disables the macro JIT compiler
 disable_macro_jit=false
-# Presents guest frames as they become available. Experimental.
-# false: Disabled (default), true: Enabled
-disable_fps_limit=false
 # Determines whether to enable the GDB stub and wait for the debugger to attach before running.
 # false: Disabled (default), true: Enabled
 use_gdbstub=false

From 6d160873c4c6a963057da5c3dca5c5f26e810052 Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Sat, 16 Jul 2022 13:26:47 -0700
Subject: [PATCH 3/3] hle: service: nvflinger: Fix implicit conversion.

---
 src/core/hle/service/nvflinger/nvflinger.cpp | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index 798c4d3a7f..5574269eb2 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -298,7 +298,10 @@ s64 NVFlinger::GetNextTicks() const {
             speed_scale = 0.01f;
         }
     }
-    return static_cast<s64>(((1000000000 * (1LL << swap_interval)) / max_hertz) * speed_scale);
+
+    const auto next_ticks = ((1000000000 * (1LL << swap_interval)) / max_hertz);
+
+    return static_cast<s64>(speed_scale * static_cast<float>(next_ticks));
 }
 
 } // namespace Service::NVFlinger