Merge pull request #8508 from yuzu-emu/mc-speed-limit
hle: service: nvflinger: Factor speed limit into frame time calculation.
This commit is contained in:
commit
ba8ea95624
|
@ -185,7 +185,6 @@ void RestoreGlobalState(bool is_powered_on) {
|
||||||
values.max_anisotropy.SetGlobal(true);
|
values.max_anisotropy.SetGlobal(true);
|
||||||
values.use_speed_limit.SetGlobal(true);
|
values.use_speed_limit.SetGlobal(true);
|
||||||
values.speed_limit.SetGlobal(true);
|
values.speed_limit.SetGlobal(true);
|
||||||
values.fps_cap.SetGlobal(true);
|
|
||||||
values.use_disk_shader_cache.SetGlobal(true);
|
values.use_disk_shader_cache.SetGlobal(true);
|
||||||
values.gpu_accuracy.SetGlobal(true);
|
values.gpu_accuracy.SetGlobal(true);
|
||||||
values.use_asynchronous_gpu_emulation.SetGlobal(true);
|
values.use_asynchronous_gpu_emulation.SetGlobal(true);
|
||||||
|
|
|
@ -440,8 +440,6 @@ struct Values {
|
||||||
SwitchableSetting<NvdecEmulation> nvdec_emulation{NvdecEmulation::GPU, "nvdec_emulation"};
|
SwitchableSetting<NvdecEmulation> nvdec_emulation{NvdecEmulation::GPU, "nvdec_emulation"};
|
||||||
SwitchableSetting<bool> accelerate_astc{true, "accelerate_astc"};
|
SwitchableSetting<bool> accelerate_astc{true, "accelerate_astc"};
|
||||||
SwitchableSetting<bool> use_vsync{true, "use_vsync"};
|
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,
|
SwitchableSetting<ShaderBackend, true> shader_backend{ShaderBackend::GLASM, ShaderBackend::GLSL,
|
||||||
ShaderBackend::SPIRV, "shader_backend"};
|
ShaderBackend::SPIRV, "shader_backend"};
|
||||||
SwitchableSetting<bool> use_asynchronous_shaders{false, "use_asynchronous_shaders"};
|
SwitchableSetting<bool> use_asynchronous_shaders{false, "use_asynchronous_shaders"};
|
||||||
|
|
|
@ -287,9 +287,21 @@ s64 NVFlinger::GetNextTicks() const {
|
||||||
static constexpr s64 max_hertz = 120LL;
|
static constexpr s64 max_hertz = 120LL;
|
||||||
|
|
||||||
const auto& settings = Settings::values;
|
const auto& settings = Settings::values;
|
||||||
const bool unlocked_fps = settings.disable_fps_limit.GetValue();
|
auto speed_scale = 1.f;
|
||||||
const s64 fps_cap = unlocked_fps ? static_cast<s64>(settings.fps_cap.GetValue()) : 1;
|
if (settings.use_multi_core.GetValue()) {
|
||||||
return (1000000000 * (1LL << swap_interval)) / (max_hertz * fps_cap);
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto next_ticks = ((1000000000 * (1LL << swap_interval)) / max_hertz);
|
||||||
|
|
||||||
|
return static_cast<s64>(speed_scale * static_cast<float>(next_ticks));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::NVFlinger
|
} // namespace Service::NVFlinger
|
||||||
|
|
|
@ -38,7 +38,7 @@ VkPresentModeKHR ChooseSwapPresentMode(vk::Span<VkPresentModeKHR> modes) {
|
||||||
if (found_mailbox != modes.end()) {
|
if (found_mailbox != modes.end()) {
|
||||||
return VK_PRESENT_MODE_MAILBOX_KHR;
|
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,
|
// FIFO present mode locks the framerate to the monitor's refresh rate,
|
||||||
// Find an alternative to surpass this limitation if FPS is unlocked.
|
// 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);
|
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;
|
extent = swapchain_ci.imageExtent;
|
||||||
current_srgb = srgb;
|
current_srgb = srgb;
|
||||||
current_fps_unlocked = Settings::values.disable_fps_limit.GetValue();
|
current_fps_unlocked = !Settings::values.use_speed_limit.GetValue();
|
||||||
|
|
||||||
images = swapchain.GetImages();
|
images = swapchain.GetImages();
|
||||||
image_count = static_cast<u32>(images.size());
|
image_count = static_cast<u32>(images.size());
|
||||||
|
@ -259,7 +259,7 @@ void Swapchain::Destroy() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Swapchain::HasFpsUnlockChanged() const {
|
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 {
|
bool Swapchain::NeedsPresentModeUpdate() const {
|
||||||
|
|
|
@ -668,7 +668,6 @@ void Config::ReadRendererValues() {
|
||||||
ReadGlobalSetting(Settings::values.max_anisotropy);
|
ReadGlobalSetting(Settings::values.max_anisotropy);
|
||||||
ReadGlobalSetting(Settings::values.use_speed_limit);
|
ReadGlobalSetting(Settings::values.use_speed_limit);
|
||||||
ReadGlobalSetting(Settings::values.speed_limit);
|
ReadGlobalSetting(Settings::values.speed_limit);
|
||||||
ReadGlobalSetting(Settings::values.fps_cap);
|
|
||||||
ReadGlobalSetting(Settings::values.use_disk_shader_cache);
|
ReadGlobalSetting(Settings::values.use_disk_shader_cache);
|
||||||
ReadGlobalSetting(Settings::values.gpu_accuracy);
|
ReadGlobalSetting(Settings::values.gpu_accuracy);
|
||||||
ReadGlobalSetting(Settings::values.use_asynchronous_gpu_emulation);
|
ReadGlobalSetting(Settings::values.use_asynchronous_gpu_emulation);
|
||||||
|
@ -1237,7 +1236,6 @@ void Config::SaveRendererValues() {
|
||||||
WriteGlobalSetting(Settings::values.max_anisotropy);
|
WriteGlobalSetting(Settings::values.max_anisotropy);
|
||||||
WriteGlobalSetting(Settings::values.use_speed_limit);
|
WriteGlobalSetting(Settings::values.use_speed_limit);
|
||||||
WriteGlobalSetting(Settings::values.speed_limit);
|
WriteGlobalSetting(Settings::values.speed_limit);
|
||||||
WriteGlobalSetting(Settings::values.fps_cap);
|
|
||||||
WriteGlobalSetting(Settings::values.use_disk_shader_cache);
|
WriteGlobalSetting(Settings::values.use_disk_shader_cache);
|
||||||
WriteSetting(QString::fromStdString(Settings::values.gpu_accuracy.GetLabel()),
|
WriteSetting(QString::fromStdString(Settings::values.gpu_accuracy.GetLabel()),
|
||||||
static_cast<u32>(Settings::values.gpu_accuracy.GetValue(global)),
|
static_cast<u32>(Settings::values.gpu_accuracy.GetValue(global)),
|
||||||
|
|
|
@ -27,9 +27,6 @@ ConfigureGeneral::ConfigureGeneral(const Core::System& system_, QWidget* parent)
|
||||||
|
|
||||||
connect(ui->button_reset_defaults, &QPushButton::clicked, this,
|
connect(ui->button_reset_defaults, &QPushButton::clicked, this,
|
||||||
&ConfigureGeneral::ResetDefaults);
|
&ConfigureGeneral::ResetDefaults);
|
||||||
|
|
||||||
ui->fps_cap_label->setVisible(Settings::IsConfiguringGlobal());
|
|
||||||
ui->fps_cap_combobox->setVisible(!Settings::IsConfiguringGlobal());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigureGeneral::~ConfigureGeneral() = default;
|
ConfigureGeneral::~ConfigureGeneral() = default;
|
||||||
|
@ -52,8 +49,6 @@ void ConfigureGeneral::SetConfiguration() {
|
||||||
ui->toggle_speed_limit->setChecked(Settings::values.use_speed_limit.GetValue());
|
ui->toggle_speed_limit->setChecked(Settings::values.use_speed_limit.GetValue());
|
||||||
ui->speed_limit->setValue(Settings::values.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);
|
ui->button_reset_defaults->setEnabled(runtime_lock);
|
||||||
|
|
||||||
if (Settings::IsConfiguringGlobal()) {
|
if (Settings::IsConfiguringGlobal()) {
|
||||||
|
@ -61,11 +56,6 @@ void ConfigureGeneral::SetConfiguration() {
|
||||||
} else {
|
} else {
|
||||||
ui->speed_limit->setEnabled(Settings::values.use_speed_limit.GetValue() &&
|
ui->speed_limit->setEnabled(Settings::values.use_speed_limit.GetValue() &&
|
||||||
use_speed_limit != ConfigurationShared::CheckState::Global);
|
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.mute_when_in_background = ui->toggle_background_mute->isChecked();
|
||||||
UISettings::values.hide_mouse = ui->toggle_hide_mouse->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
|
// Guard if during game and set to game-specific value
|
||||||
if (Settings::values.use_speed_limit.UsingGlobal()) {
|
if (Settings::values.use_speed_limit.UsingGlobal()) {
|
||||||
Settings::values.use_speed_limit.SetValue(ui->toggle_speed_limit->checkState() ==
|
Settings::values.use_speed_limit.SetValue(ui->toggle_speed_limit->checkState() ==
|
||||||
|
@ -119,13 +107,6 @@ void ConfigureGeneral::ApplyConfiguration() {
|
||||||
Qt::Checked);
|
Qt::Checked);
|
||||||
Settings::values.speed_limit.SetValue(ui->speed_limit->value());
|
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() &&
|
ui->speed_limit->setEnabled(ui->toggle_speed_limit->isChecked() &&
|
||||||
(use_speed_limit != ConfigurationShared::CheckState::Global));
|
(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);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,87 +27,6 @@
|
||||||
<layout class="QHBoxLayout" name="GeneralHorizontalLayout">
|
<layout class="QHBoxLayout" name="GeneralHorizontalLayout">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QVBoxLayout" name="GeneralVerticalLayout">
|
<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>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
|
|
|
@ -1059,7 +1059,7 @@ void GMainWindow::InitializeHotkeys() {
|
||||||
Settings::values.volume.SetValue(static_cast<u8>(new_volume));
|
Settings::values.volume.SetValue(static_cast<u8>(new_volume));
|
||||||
});
|
});
|
||||||
connect_shortcut(QStringLiteral("Toggle Framerate Limit"), [] {
|
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"), [&] {
|
connect_shortcut(QStringLiteral("Toggle Mouse Panning"), [&] {
|
||||||
Settings::values.mouse_panning = !Settings::values.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);
|
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
|
// Save configurations
|
||||||
UpdateUISettings();
|
UpdateUISettings();
|
||||||
game_list->SaveInterfaceLayout();
|
game_list->SaveInterfaceLayout();
|
||||||
|
@ -3277,7 +3274,7 @@ void GMainWindow::UpdateStatusBar() {
|
||||||
} else {
|
} else {
|
||||||
emu_speed_label->setText(tr("Speed: %1%").arg(results.emulation_speed * 100.0, 0, 'f', 0));
|
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(
|
game_fps_label->setText(
|
||||||
tr("Game: %1 FPS (Unlocked)").arg(results.average_game_fps, 0, 'f', 0));
|
tr("Game: %1 FPS (Unlocked)").arg(results.average_game_fps, 0, 'f', 0));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -310,8 +310,6 @@ void Config::ReadValues() {
|
||||||
ReadSetting("Renderer", Settings::values.gpu_accuracy);
|
ReadSetting("Renderer", Settings::values.gpu_accuracy);
|
||||||
ReadSetting("Renderer", Settings::values.use_asynchronous_gpu_emulation);
|
ReadSetting("Renderer", Settings::values.use_asynchronous_gpu_emulation);
|
||||||
ReadSetting("Renderer", Settings::values.use_vsync);
|
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.shader_backend);
|
||||||
ReadSetting("Renderer", Settings::values.use_asynchronous_shaders);
|
ReadSetting("Renderer", Settings::values.use_asynchronous_shaders);
|
||||||
ReadSetting("Renderer", Settings::values.nvdec_emulation);
|
ReadSetting("Renderer", Settings::values.nvdec_emulation);
|
||||||
|
|
|
@ -330,10 +330,6 @@ bg_red =
|
||||||
bg_blue =
|
bg_blue =
|
||||||
bg_green =
|
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]
|
[Audio]
|
||||||
# Which audio output engine to use.
|
# Which audio output engine to use.
|
||||||
# auto (default): Auto-select
|
# auto (default): Auto-select
|
||||||
|
@ -434,9 +430,6 @@ use_debug_asserts =
|
||||||
use_auto_stub =
|
use_auto_stub =
|
||||||
# Enables/Disables the macro JIT compiler
|
# Enables/Disables the macro JIT compiler
|
||||||
disable_macro_jit=false
|
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.
|
# Determines whether to enable the GDB stub and wait for the debugger to attach before running.
|
||||||
# false: Disabled (default), true: Enabled
|
# false: Disabled (default), true: Enabled
|
||||||
use_gdbstub=false
|
use_gdbstub=false
|
||||||
|
|
Reference in New Issue