System: Add "Skip Duplicate Frame Display" option

Skips the presentation/display of frames that are not unique.
Can be combined with driver-level frame generation to increase
perceptible frame rate. Can result in worse frame pacing, and is
not compatible with syncing to host refresh.
This commit is contained in:
Stenzek
2024-05-19 18:15:01 +10:00
parent 7b8f9506c9
commit 5b4f74122c
8 changed files with 97 additions and 51 deletions

View File

@ -20,6 +20,8 @@ EmulationSettingsWidget::EmulationSettingsWidget(SettingsWindow* dialog, QWidget
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::BindWidgetToBoolSetting(sif, m_ui.skipPresentingDuplicateFrames, "Display",
"SkipPresentingDuplicateFrames", 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);
@ -71,7 +73,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.vsync, &QCheckBox::checkStateChanged, this, &EmulationSettingsWidget::updateSkipDuplicateFramesEnabled);
connect(m_ui.syncToHostRefreshRate, &QCheckBox::checkStateChanged, this,
&EmulationSettingsWidget::updateSkipDuplicateFramesEnabled);
connect(m_ui.optimalFramePacing, &QCheckBox::checkStateChanged, this,
&EmulationSettingsWidget::onOptimalFramePacingChanged);
connect(m_ui.preFrameSleep, &QCheckBox::checkStateChanged, this, &EmulationSettingsWidget::onPreFrameSleepChanged);
@ -121,6 +125,11 @@ EmulationSettingsWidget::EmulationSettingsWidget(SettingsWindow* dialog, QWidget
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.skipPresentingDuplicateFrames, tr("Skip Duplicate Frame Display"), tr("Unchecked"),
tr("Skips the presentation/display of frames that are not unique. Can be combined with driver-level frame "
"generation to increase perceptible frame rate. Can result in worse frame pacing, and is not compatible with "
"syncing to host refresh."));
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> "
@ -133,8 +142,8 @@ EmulationSettingsWidget::EmulationSettingsWidget(SettingsWindow* dialog, QWidget
tr(
"Simulates the system ahead of time and rolls back/replays to reduce input lag. Very high system requirements."));
onVSyncChanged();
onOptimalFramePacingChanged();
updateSkipDuplicateFramesEnabled();
updateRewind();
}
@ -200,12 +209,6 @@ void EmulationSettingsWidget::onTurboSpeedIndexChanged(int index)
m_dialog->setFloatSettingValue("Main", "TurboSpeed", okay ? value : 0.0f);
}
void EmulationSettingsWidget::onVSyncChanged()
{
const bool vsync = m_dialog->getEffectiveBoolValue("Display", "VSync", false);
m_ui.syncToHostRefreshRate->setEnabled(vsync);
}
void EmulationSettingsWidget::onOptimalFramePacingChanged()
{
const bool optimal_frame_pacing_enabled = m_dialog->getEffectiveBoolValue("Display", "OptimalFramePacing", false);
@ -221,6 +224,13 @@ void EmulationSettingsWidget::onPreFrameSleepChanged()
m_ui.preFrameSleepBufferLabel->setVisible(show_buffer_size);
}
void EmulationSettingsWidget::updateSkipDuplicateFramesEnabled()
{
const bool vsync = m_dialog->getEffectiveBoolValue("Display", "VSync", false);
const bool sync_to_host = m_dialog->getEffectiveBoolValue("Main", "SyncToHostRefreshRate", false) && vsync;
m_ui.skipPresentingDuplicateFrames->setEnabled(!sync_to_host);
}
void EmulationSettingsWidget::updateRewind()
{
const bool rewind_enabled = m_dialog->getEffectiveBoolValue("Main", "RewindEnable", false);

View File

@ -21,9 +21,9 @@ private Q_SLOTS:
void onEmulationSpeedIndexChanged(int index);
void onFastForwardSpeedIndexChanged(int index);
void onTurboSpeedIndexChanged(int index);
void onVSyncChanged();
void onOptimalFramePacingChanged();
void onPreFrameSleepChanged();
void updateSkipDuplicateFramesEnabled();
void updateRewind();
private:

View File

@ -68,10 +68,10 @@
<string>Latency Control</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QCheckBox" name="vsync">
<item row="1" column="1">
<widget class="QCheckBox" name="preFrameSleep">
<property name="text">
<string>Vertical Sync (VSync)</string>
<string>Reduce Input Latency</string>
</property>
</widget>
</item>
@ -82,6 +82,13 @@
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="vsync">
<property name="text">
<string>Vertical Sync (VSync)</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="optimalFramePacing">
<property name="text">
@ -89,23 +96,23 @@
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="preFrameSleep">
<item row="2" column="0">
<widget class="QCheckBox" name="skipPresentingDuplicateFrames">
<property name="text">
<string>Reduce Input Latency</string>
<string>Skip Duplicate Frame Display</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<layout class="QHBoxLayout" name="preFrameSleepBufferLayout" stretch="0,1">
<item>
<item row="2" column="1">
<layout class="QFormLayout" name="formLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="preFrameSleepBufferLabel">
<property name="text">
<string>Frame Time Buffer:</string>
</property>
</widget>
</item>
<item>
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="preFrameSleepBuffer">
<property name="suffix">
<string> Milliseconds</string>