System: Add 'Reduce Input Latency' option

i.e. pre-frame sleep.
This commit is contained in:
Stenzek
2024-04-13 19:56:08 +10:00
parent 6258cb9e0e
commit c149d66d4d
12 changed files with 320 additions and 114 deletions

View File

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "emulationsettingswidget.h"
@ -19,6 +19,9 @@ EmulationSettingsWidget::EmulationSettingsWidget(SettingsWindow* dialog, QWidget
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.vsync, "Display", "VSync", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.syncToHostRefreshRate, "Main", "SyncToHostRefreshRate", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.optimalFramePacing, "Display", "OptimalFramePacing", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.preFrameSleep, "Display", "PreFrameSleep", false);
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.preFrameSleepBuffer, "Display", "PreFrameSleepBuffer",
Settings::DEFAULT_DISPLAY_PRE_FRAME_SLEEP_BUFFER);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.rewindEnable, "Main", "RewindEnable", false);
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.rewindSaveFrequency, "Main", "RewindFrequency", 10.0f);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.rewindSaveSlots, "Main", "RewindSaveSlots", 10);
@ -69,6 +72,9 @@ EmulationSettingsWidget::EmulationSettingsWidget(SettingsWindow* dialog, QWidget
connect(m_ui.turboSpeed, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&EmulationSettingsWidget::onTurboSpeedIndexChanged);
connect(m_ui.vsync, &QCheckBox::checkStateChanged, this, &EmulationSettingsWidget::onVSyncChanged);
connect(m_ui.optimalFramePacing, &QCheckBox::checkStateChanged, this,
&EmulationSettingsWidget::onOptimalFramePacingChanged);
connect(m_ui.preFrameSleep, &QCheckBox::checkStateChanged, this, &EmulationSettingsWidget::onPreFrameSleepChanged);
connect(m_ui.rewindEnable, &QCheckBox::checkStateChanged, this, &EmulationSettingsWidget::updateRewind);
connect(m_ui.rewindSaveFrequency, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this,
@ -96,16 +102,25 @@ EmulationSettingsWidget::EmulationSettingsWidget(SettingsWindow* dialog, QWidget
"instead.</strong>"));
dialog->registerWidgetHelp(
m_ui.syncToHostRefreshRate, tr("Sync To Host Refresh Rate"), tr("Unchecked"),
tr("Adjusts the emulation speed so the console's refresh rate matches the host's refresh rate when both VSync and "
"Audio Resampling settings are enabled. This results in the smoothest animations possible, at the cost of "
"potentially increasing the emulation speed by less than 1%. Sync To Host Refresh Rate will not take effect if "
"the console's refresh rate is too far from the host's refresh rate. Users with variable refresh rate displays "
"should disable this option."));
tr(
"Adjusts the emulation speed so the console's refresh rate matches the host's refresh rate when VSync is "
"enabled. This results in the smoothest animations possible, at the cost of potentially increasing the emulation "
"speed by less than 1%. Sync To Host Refresh Rate will not take effect if the console's refresh rate is too far "
"from the host's refresh rate. Users with variable refresh rate displays should disable this option."));
dialog->registerWidgetHelp(
m_ui.optimalFramePacing, tr("Optimal Frame Pacing"), tr("Unchecked"),
tr("Enabling this option will ensure every frame the console renders is displayed to the screen, at a consistent "
"rate, for optimal frame pacing. If you have a GSync/FreeSync display, enable this option. If you are having "
"difficulties maintaining full speed, or are getting audio glitches, try disabling this option."));
dialog->registerWidgetHelp(
m_ui.preFrameSleep, tr("Reduce Input Latency"), tr("Unchecked"),
tr("Reduces input latency by delaying the start of frame until closer to the presentation time. This may cause "
"dropped frames on slower systems with higher frame time variance, if the buffer size is not sufficient."));
dialog->registerWidgetHelp(m_ui.preFrameSleepBuffer, tr("Frame Time Buffer"),
tr("%1 ms").arg(Settings::DEFAULT_DISPLAY_PRE_FRAME_SLEEP_BUFFER),
tr("Specifies the amount of buffer time added, which reduces the additional sleep time "
"introduced. Higher values increase input latency, but decrease the risk of overrun, "
"or missed frames. Lower values require faster hardware."));
dialog->registerWidgetHelp(
m_ui.rewindEnable, tr("Rewinding"), tr("Unchecked"),
tr("<b>Enable Rewinding:</b> Saves state periodically so you can rewind any mistakes while playing.<br> "
@ -119,6 +134,7 @@ EmulationSettingsWidget::EmulationSettingsWidget(SettingsWindow* dialog, QWidget
"Simulates the system ahead of time and rolls back/replays to reduce input lag. Very high system requirements."));
onVSyncChanged();
onOptimalFramePacingChanged();
updateRewind();
}
@ -190,6 +206,21 @@ void EmulationSettingsWidget::onVSyncChanged()
m_ui.syncToHostRefreshRate->setEnabled(vsync);
}
void EmulationSettingsWidget::onOptimalFramePacingChanged()
{
const bool optimal_frame_pacing_enabled = m_dialog->getEffectiveBoolValue("Display", "OptimalFramePacing", false);
m_ui.preFrameSleep->setEnabled(optimal_frame_pacing_enabled);
onPreFrameSleepChanged();
}
void EmulationSettingsWidget::onPreFrameSleepChanged()
{
const bool pre_frame_sleep_enabled = m_dialog->getEffectiveBoolValue("Display", "PreFrameSleep", false);
const bool show_buffer_size = (m_ui.preFrameSleep->isEnabled() && pre_frame_sleep_enabled);
m_ui.preFrameSleepBuffer->setVisible(show_buffer_size);
m_ui.preFrameSleepBufferLabel->setVisible(show_buffer_size);
}
void EmulationSettingsWidget::updateRewind()
{
const bool rewind_enabled = m_dialog->getEffectiveBoolValue("Main", "RewindEnable", false);

View File

@ -22,6 +22,8 @@ private Q_SLOTS:
void onFastForwardSpeedIndexChanged(int index);
void onTurboSpeedIndexChanged(int index);
void onVSyncChanged();
void onOptimalFramePacingChanged();
void onPreFrameSleepChanged();
void updateRewind();
private:

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>568</width>
<height>369</height>
<width>618</width>
<height>440</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
@ -59,26 +59,62 @@
<item row="2" column="1">
<widget class="QComboBox" name="turboSpeed"/>
</item>
<item row="3" column="0" colspan="2">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QCheckBox" name="vsync">
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Latency Control</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QCheckBox" name="vsync">
<property name="text">
<string>Vertical Sync (VSync)</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="syncToHostRefreshRate">
<property name="text">
<string>Sync To Host Refresh Rate</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="optimalFramePacing">
<property name="text">
<string>Optimal Frame Pacing</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="preFrameSleep">
<property name="text">
<string>Reduce Input Latency</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<layout class="QHBoxLayout" name="preFrameSleepBufferLayout" stretch="0,1">
<item>
<widget class="QLabel" name="preFrameSleepBufferLabel">
<property name="text">
<string>Vertical Sync (VSync)</string>
<string>Frame Time Buffer:</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QCheckBox" name="syncToHostRefreshRate">
<property name="text">
<string>Sync To Host Refresh Rate</string>
<item>
<widget class="QDoubleSpinBox" name="preFrameSleepBuffer">
<property name="suffix">
<string> Milliseconds</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="optimalFramePacing">
<property name="text">
<string>Optimal Frame Pacing</string>
<property name="decimals">
<number>1</number>
</property>
<property name="singleStep">
<double>0.500000000000000</double>
</property>
</widget>
</item>

View File

@ -174,6 +174,8 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.showGPU, "Display", "ShowGPU", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.showInput, "Display", "ShowInputs", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.showGPUStatistics, "Display", "ShowGPUStatistics", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.showLatencyStatistics, "Display", "ShowLatencyStatistics",
false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.showStatusIndicators, "Display", "ShowStatusIndicators", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.showFrameTimes, "Display", "ShowFrameTimes", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.showSettings, "Display", "ShowEnhancements", false);
@ -426,6 +428,9 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
tr("Shows the host's GPU usage in the top-right corner of the display."));
dialog->registerWidgetHelp(m_ui.showGPUStatistics, tr("Show GPU Statistics"), tr("Unchecked"),
tr("Shows information about the emulated GPU in the top-right corner of the display."));
dialog->registerWidgetHelp(
m_ui.showLatencyStatistics, tr("Show Latency Statistics"), tr("Unchecked"),
tr("Shows information about input and audio latency in the top-right corner of the display."));
dialog->registerWidgetHelp(
m_ui.showFrameTimes, tr("Show Frame Times"), tr("Unchecked"),
tr("Shows the history of frame rendering times as a graph in the top-right corner of the display."));

View File

@ -704,20 +704,6 @@
</item>
<item row="1" column="0" colspan="2">
<layout class="QGridLayout" name="gridLayout_3">
<item row="4" column="0">
<widget class="QCheckBox" name="showInput">
<property name="text">
<string>Show Controller Input</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="showStatusIndicators">
<property name="text">
<string>Show Status Indicators</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="showFPS">
<property name="text">
@ -732,20 +718,6 @@
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="showResolution">
<property name="text">
<string>Show Resolution</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QCheckBox" name="showSettings">
<property name="text">
<string>Show Settings</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="showCPU">
<property name="text">
@ -767,17 +739,52 @@
</property>
</widget>
</item>
<item row="3" column="1">
<item row="2" column="1">
<widget class="QCheckBox" name="showGPU">
<property name="text">
<string>Show GPU Usage</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QCheckBox" name="showSettings">
<property name="text">
<string>Show Settings</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="showStatusIndicators">
<property name="text">
<string>Show Status Indicators</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="showInput">
<property name="text">
<string>Show Controller Input</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="showFrameTimes">
<property name="text">
<string>Show Frame Times</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="showGPU">
<item row="3" column="1">
<widget class="QCheckBox" name="showResolution">
<property name="text">
<string>Show GPU Usage</string>
<string>Show Resolution</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QCheckBox" name="showLatencyStatistics">
<property name="text">
<string>Show Latency Statistics</string>
</property>
</widget>
</item>