System: Combine VRR and Optimal Frame Pacing

GSync/FreeSync display users should:
 - DISABLE VSync.
 - ENABLE Optimal Frame Pacing.
This commit is contained in:
Stenzek
2024-04-11 21:26:50 +10:00
parent 2ad67ad3ee
commit 88270771da
26 changed files with 224 additions and 289 deletions

View File

@ -16,8 +16,9 @@ EmulationSettingsWidget::EmulationSettingsWidget(SettingsWindow* dialog, QWidget
m_ui.setupUi(this);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.vsync, "Display", "VSync", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.syncToHostRefreshRate, "Main", "SyncToHostRefreshRate", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.displayAllFrames, "Display", "DisplayAllFrames", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.optimalFramePacing, "Display", "OptimalFramePacing", false);
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);
@ -67,6 +68,7 @@ EmulationSettingsWidget::EmulationSettingsWidget(SettingsWindow* dialog, QWidget
}
connect(m_ui.turboSpeed, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&EmulationSettingsWidget::onTurboSpeedIndexChanged);
connect(m_ui.vsync, &QCheckBox::stateChanged, this, &EmulationSettingsWidget::onVSyncChanged);
connect(m_ui.rewindEnable, &QCheckBox::stateChanged, this, &EmulationSettingsWidget::updateRewind);
connect(m_ui.rewindSaveFrequency, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this,
@ -87,6 +89,11 @@ EmulationSettingsWidget::EmulationSettingsWidget(SettingsWindow* dialog, QWidget
m_ui.turboSpeed, tr("Turbo Speed"), tr("User Preference"),
tr("Sets the turbo speed. This speed will be used when the turbo hotkey is pressed/toggled. Turboing will take "
"priority over fast forwarding if both hotkeys are pressed/toggled."));
dialog->registerWidgetHelp(
m_ui.vsync, tr("Display Vertical Sync (VSync)"), tr("Unchecked"),
tr("Synchronizes presentation of the console's frames to the host. Enabling may result in smoother animations, at "
"the cost of increased input lag. <strong>GSync/FreeSync users should enable Optimal Frame Pacing "
"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 "
@ -94,10 +101,11 @@ EmulationSettingsWidget::EmulationSettingsWidget(SettingsWindow* dialog, QWidget
"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.displayAllFrames, tr("Optimal Frame Pacing"), tr("Unchecked"),
tr("Enabling this option will ensure every frame the console renders is displayed to the "
"screen, for optimal frame pacing. If you are having difficulties maintaining full "
"speed, or are getting audio glitches, try disabling 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.rewindEnable, tr("Rewinding"), tr("Unchecked"),
tr("<b>Enable Rewinding:</b> Saves state periodically so you can rewind any mistakes while playing.<br> "
@ -110,6 +118,7 @@ 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();
updateRewind();
}
@ -175,6 +184,12 @@ 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::updateRewind()
{
const bool rewind_enabled = m_dialog->getEffectiveBoolValue("Main", "RewindEnable", false);

View File

@ -21,6 +21,7 @@ private Q_SLOTS:
void onEmulationSpeedIndexChanged(int index);
void onFastForwardSpeedIndexChanged(int index);
void onTurboSpeedIndexChanged(int index);
void onVSyncChanged();
void updateRewind();
private:

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>672</width>
<height>518</height>
<width>568</width>
<height>369</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
@ -61,15 +61,22 @@
</item>
<item row="3" column="0" colspan="2">
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="1">
<item row="0" column="0">
<widget class="QCheckBox" name="vsync">
<property name="text">
<string>Display Vertical Sync (VSync)</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QCheckBox" name="syncToHostRefreshRate">
<property name="text">
<string>Sync To Host Refresh Rate</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QCheckBox" name="displayAllFrames">
<item row="1" column="0">
<widget class="QCheckBox" name="optimalFramePacing">
<property name="text">
<string>Optimal Frame Pacing</string>
</property>
@ -215,7 +222,7 @@
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>

View File

@ -75,9 +75,6 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
SettingWidgetBinder::BindWidgetToEnumSetting(sif, m_ui.displayScaling, "Display", "Scaling",
&Settings::ParseDisplayScaling, &Settings::GetDisplayScalingName,
Settings::DEFAULT_DISPLAY_SCALING);
SettingWidgetBinder::BindWidgetToEnumSetting(sif, m_ui.displaySyncMode, "Display", "SyncMode",
&Settings::ParseDisplaySyncMode, &Settings::GetDisplaySyncModeName,
Settings::DEFAULT_DISPLAY_SYNC_MODE);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.gpuDownsampleScale, "GPU", "DownsampleScale", 1);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.trueColor, "GPU", "TrueColor", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.disableInterlacing, "GPU", "DisableInterlacing", true);
@ -284,10 +281,6 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
dialog->registerWidgetHelp(
m_ui.displayScaling, tr("Scaling"), tr("Bilinear (Smooth)"),
tr("Determines how the emulated console's output is upscaled or downscaled to your monitor's resolution."));
dialog->registerWidgetHelp(
m_ui.displaySyncMode, tr("VSync"), tr("Unchecked"),
tr("Enable this option to match DuckStation's refresh rate with your current monitor or screen. "
"VSync is automatically disabled when it is not possible (e.g. running at non-100% speed)."));
dialog->registerWidgetHelp(
m_ui.trueColor, tr("True Color Rendering"), tr("Checked"),
tr("Forces the precision of colours output to the console's framebuffer to use the full 8 bits of precision per "
@ -550,12 +543,6 @@ void GraphicsSettingsWidget::setupAdditionalUi()
QString::fromUtf8(Settings::GetDisplayScalingDisplayName(static_cast<DisplayScalingMode>(i))));
}
for (u32 i = 0; i < static_cast<u32>(DisplaySyncMode::Count); i++)
{
m_ui.displaySyncMode->addItem(
QString::fromUtf8(Settings::GetDisplaySyncModeDisplayName(static_cast<DisplaySyncMode>(i))));
}
// Advanced Tab
for (u32 i = 0; i < static_cast<u32>(DisplayExclusiveFullscreenControl::Count); i++)

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>584</width>
<height>450</height>
<height>430</height>
</rect>
</property>
<property name="windowTitle">
@ -260,6 +260,16 @@
</item>
</layout>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Deinterlacing:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="displayDeinterlacing"/>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
@ -280,32 +290,8 @@
<item row="6" column="1">
<widget class="QComboBox" name="displayScaling"/>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>VSync:</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QComboBox" name="displaySyncMode"/>
</item>
<item row="8" column="0" colspan="2">
<item row="7" column="0" colspan="2">
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="0">
<widget class="QCheckBox" name="pgxpEnable">
<property name="text">
<string>PGXP Geometry Correction</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="trueColor">
<property name="text">
<string>True Color Rendering</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="pgxpDepthBuffer">
<property name="text">
@ -313,20 +299,6 @@
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="force43For24Bit">
<property name="text">
<string>Force 4:3 For FMVs</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="chromaSmoothingFor24Bit">
<property name="text">
<string>FMV Chroma Smoothing</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="disableInterlacing">
<property name="text">
@ -334,13 +306,6 @@
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="widescreenHack">
<property name="text">
<string>Widescreen Rendering</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="forceNTSCTimings">
<property name="text">
@ -348,25 +313,50 @@
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="force43For24Bit">
<property name="text">
<string>Force 4:3 For FMVs</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="trueColor">
<property name="text">
<string>True Color Rendering</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="chromaSmoothingFor24Bit">
<property name="text">
<string>FMV Chroma Smoothing</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="widescreenHack">
<property name="text">
<string>Widescreen Rendering</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="pgxpEnable">
<property name="text">
<string>PGXP Geometry Correction</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Deinterlacing:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="displayDeinterlacing"/>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@ -437,20 +427,6 @@
</item>
<item row="3" column="0" colspan="2">
<layout class="QGridLayout" name="advancedDisplayOptionsLayout">
<item row="0" column="0">
<widget class="QCheckBox" name="gpuThread">
<property name="text">
<string>Threaded Rendering</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="threadedPresentation">
<property name="text">
<string>Threaded Presentation</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="blitSwapChain">
<property name="text">
@ -465,6 +441,20 @@
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="threadedPresentation">
<property name="text">
<string>Threaded Presentation</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="gpuThread">
<property name="text">
<string>Threaded Rendering</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
@ -488,13 +478,6 @@
</item>
<item row="2" column="0" colspan="2">
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="1">
<widget class="QCheckBox" name="scaledDithering">
<property name="text">
<string>Scaled Dithering</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="debanding">
<property name="text">
@ -502,6 +485,13 @@
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="scaledDithering">
<property name="text">
<string>Scaled Dithering</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="useSoftwareRendererForReadbacks">
<property name="text">
@ -527,7 +517,7 @@
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@ -657,7 +647,7 @@
<item>
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@ -799,7 +789,7 @@
<item>
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@ -874,7 +864,7 @@
<item>
<spacer name="verticalSpacer_7">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@ -1008,7 +998,7 @@
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@ -1111,7 +1101,7 @@
<item>
<spacer name="verticalSpacer_6">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>

View File

@ -92,6 +92,7 @@ static void SetResourcesDirectory();
static bool SetDataDirectory();
static bool SetCriticalFolders();
static void SetDefaultSettings(SettingsInterface& si, bool system, bool controller);
static void MigrateSettings();
static void SaveSettings();
static bool RunSetupWizard();
static std::string GetResourcePath(std::string_view name, bool allow_override);
@ -379,6 +380,7 @@ bool QtHost::InitializeConfig(std::string settings_filename)
EmuFolders::LoadConfig(*s_base_settings_interface.get());
EmuFolders::EnsureFoldersExist();
MigrateSettings();
// We need to create the console window early, otherwise it appears behind the main window.
if (!Log::IsConsoleOutputEnabled() &&
@ -596,6 +598,21 @@ void QtHost::SetDefaultSettings(SettingsInterface& si, bool system, bool control
}
}
void QtHost::MigrateSettings()
{
SmallString value;
if (s_base_settings_interface->GetStringValue("Display", "SyncMode", &value))
{
s_base_settings_interface->SetBoolValue("Display", "VSync", (value == "VSync" || value == "VSyncRelaxed"));
s_base_settings_interface->SetBoolValue(
"Display", "OptimalFramePacing",
(value == "VRR" || s_base_settings_interface->GetBoolValue("Display", "DisplayAllFrames", false)));
s_base_settings_interface->DeleteValue("Display", "SyncMode");
s_base_settings_interface->DeleteValue("Display", "DisplayAllFrames");
s_base_settings_interface->Save();
}
}
bool EmuThread::shouldRenderToMain() const
{
return !Host::GetBoolSettingValue("Main", "RenderToSeparateWindow", false) && !QtHost::InNoGUIMode();
@ -1551,7 +1568,7 @@ void EmuThread::run()
if (g_gpu_device)
{
System::PresentDisplay(false);
if (!g_gpu_device->IsVSyncActive())
if (!g_gpu_device->IsVSyncEnabled())
g_gpu_device->ThrottlePresentation();
}
}