From 43d01776dc031d268755bc38216c4d3f29a6f161 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Mon, 11 Jan 2021 03:50:44 +1000 Subject: [PATCH] HostInterface: Add "Sync To Host Refresh Rate" option --- src/core/host_interface.cpp | 1 + src/core/settings.cpp | 2 ++ src/core/settings.h | 1 + src/duckstation-qt/consolesettingswidget.cpp | 6 ++++ src/duckstation-qt/consolesettingswidget.ui | 7 +++++ src/frontend-common/common_host_interface.cpp | 29 +++++++++++++++---- 6 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/core/host_interface.cpp b/src/core/host_interface.cpp index 9142f3e38..c8fe8b9cc 100644 --- a/src/core/host_interface.cpp +++ b/src/core/host_interface.cpp @@ -473,6 +473,7 @@ void HostInterface::SetDefaultSettings(SettingsInterface& si) si.SetFloatValue("Main", "EmulationSpeed", 1.0f); si.SetFloatValue("Main", "FastForwardSpeed", 0.0f); si.SetFloatValue("Main", "TurboSpeed", 0.0f); + si.SetBoolValue("Main", "SyncToHostRefreshRate", true); si.SetBoolValue("Main", "IncreaseTimerResolution", true); si.SetBoolValue("Main", "StartPaused", false); si.SetBoolValue("Main", "StartFullscreen", false); diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 27534d7ce..bcfd02b2e 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -112,6 +112,7 @@ void Settings::Load(SettingsInterface& si) emulation_speed = si.GetFloatValue("Main", "EmulationSpeed", 1.0f); fast_forward_speed = si.GetFloatValue("Main", "FastForwardSpeed", 0.0f); turbo_speed = si.GetFloatValue("Main", "TurboSpeed", 0.0f); + sync_to_host_refresh_rate = si.GetBoolValue("Main", "SyncToHostRefreshRate", true); increase_timer_resolution = si.GetBoolValue("Main", "IncreaseTimerResolution", true); start_paused = si.GetBoolValue("Main", "StartPaused", false); start_fullscreen = si.GetBoolValue("Main", "StartFullscreen", false); @@ -283,6 +284,7 @@ void Settings::Save(SettingsInterface& si) const si.SetFloatValue("Main", "EmulationSpeed", emulation_speed); si.SetFloatValue("Main", "FastForwardSpeed", fast_forward_speed); si.SetFloatValue("Main", "TurboSpeed", turbo_speed); + si.SetBoolValue("Main", "SyncToHostRefreshRate", sync_to_host_refresh_rate); si.SetBoolValue("Main", "IncreaseTimerResolution", increase_timer_resolution); si.SetBoolValue("Main", "StartPaused", start_paused); si.SetBoolValue("Main", "StartFullscreen", start_fullscreen); diff --git a/src/core/settings.h b/src/core/settings.h index c58f30995..64756595f 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -82,6 +82,7 @@ struct Settings float emulation_speed = 1.0f; float fast_forward_speed = 0.0f; float turbo_speed = 0.0f; + bool sync_to_host_refresh_rate = true; bool increase_timer_resolution = true; bool start_paused = false; bool start_fullscreen = false; diff --git a/src/duckstation-qt/consolesettingswidget.cpp b/src/duckstation-qt/consolesettingswidget.cpp index f241878d0..8d66a9823 100644 --- a/src/duckstation-qt/consolesettingswidget.cpp +++ b/src/duckstation-qt/consolesettingswidget.cpp @@ -25,6 +25,8 @@ ConsoleSettingsWidget::ConsoleSettingsWidget(QtHostInterface* host_interface, QW SettingWidgetBinder::BindWidgetToEnumSetting(m_host_interface, m_ui.region, "Console", "Region", &Settings::ParseConsoleRegionName, &Settings::GetConsoleRegionName, Settings::DEFAULT_CONSOLE_REGION); + SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.syncToHostRefreshRate, "Main", + "SyncToHostRefreshRate", true); SettingWidgetBinder::BindWidgetToEnumSetting(m_host_interface, m_ui.cpuExecutionMode, "CPU", "ExecutionMode", &Settings::ParseCPUExecutionMode, &Settings::GetCPUExecutionModeName, Settings::DEFAULT_CPU_EXECUTION_MODE); @@ -75,6 +77,10 @@ ConsoleSettingsWidget::ConsoleSettingsWidget(QtHostInterface* host_interface, QW dialog->registerWidgetHelp( m_ui.turboSpeed, tr("Turbo Speed"), "100%", tr("Sets the turbo speed. This speed will be used when the turbo hotkey is pressed/toggled.")); + dialog->registerWidgetHelp(m_ui.syncToHostRefreshRate, tr("Sync To Host Refresh Rate"), "100%", + 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%.")); m_ui.cpuClockSpeed->setEnabled(m_ui.enableCPUClockSpeedControl->checkState() == Qt::Checked); m_ui.cdromReadSpeedup->setCurrentIndex(m_host_interface->GetIntSettingValue("CDROM", "ReadSpeedup", 1) - 1); diff --git a/src/duckstation-qt/consolesettingswidget.ui b/src/duckstation-qt/consolesettingswidget.ui index 51044c53e..a2da17111 100644 --- a/src/duckstation-qt/consolesettingswidget.ui +++ b/src/duckstation-qt/consolesettingswidget.ui @@ -81,6 +81,13 @@ + + + + Sync To Host Refresh Rate + + + diff --git a/src/frontend-common/common_host_interface.cpp b/src/frontend-common/common_host_interface.cpp index e612f694c..9d02e126d 100644 --- a/src/frontend-common/common_host_interface.cpp +++ b/src/frontend-common/common_host_interface.cpp @@ -604,26 +604,44 @@ bool CommonHostInterface::ResumeSystemFromMostRecentState() void CommonHostInterface::UpdateSpeedLimiterState() { - const float target_speed = m_turbo_enabled ? - g_settings.turbo_speed : - (m_fast_forward_enabled ? g_settings.fast_forward_speed : g_settings.emulation_speed); + float target_speed = m_turbo_enabled ? + g_settings.turbo_speed : + (m_fast_forward_enabled ? g_settings.fast_forward_speed : g_settings.emulation_speed); m_speed_limiter_enabled = (target_speed != 0.0f); + if (g_settings.sync_to_host_refresh_rate && target_speed == 1.0f && g_settings.video_sync_enabled && m_display && + System::IsRunning()) + { + float host_refresh_rate; + if (m_display->GetHostRefreshRate(&host_refresh_rate)) + { + const float ratio = host_refresh_rate / System::GetThrottleFrequency(); + const bool can_sync = (ratio >= 0.95f && ratio <= 1.05f); + Log_InfoPrintf("Refresh rate: Host=%fhz Guest=%fhz Ratio=%f - %s", host_refresh_rate, + System::GetThrottleFrequency(), ratio, can_sync ? "can sync" : "can't sync"); + if (can_sync) + target_speed *= ratio; + } + } + const bool is_non_standard_speed = (std::abs(target_speed - 1.0f) > 0.05f); const bool audio_sync_enabled = !System::IsRunning() || (m_speed_limiter_enabled && g_settings.audio_sync_enabled && !is_non_standard_speed); const bool video_sync_enabled = !System::IsRunning() || (m_speed_limiter_enabled && g_settings.video_sync_enabled && !is_non_standard_speed); const float max_display_fps = m_speed_limiter_enabled ? 0.0f : g_settings.display_max_fps; + Log_InfoPrintf("Target speed: %f%%", target_speed * 100.0f); Log_InfoPrintf("Syncing to %s%s", audio_sync_enabled ? "audio" : "", (audio_sync_enabled && video_sync_enabled) ? " and video" : (video_sync_enabled ? "video" : "")); Log_InfoPrintf("Max display fps: %f", max_display_fps); if (m_audio_stream) { - const u32 input_sample_rate = (!is_non_standard_speed || target_speed == 0.0f || !g_settings.audio_resampling) ? + const u32 input_sample_rate = (target_speed == 0.0f || !g_settings.audio_resampling) ? AUDIO_SAMPLE_RATE : static_cast(static_cast(AUDIO_SAMPLE_RATE) * target_speed); + Log_InfoPrintf("Audio input sample rate: %u hz", input_sample_rate); + m_audio_stream->SetInputSampleRate(input_sample_rate); m_audio_stream->SetOutputVolume(GetAudioOutputVolume()); m_audio_stream->SetSync(audio_sync_enabled); @@ -2221,7 +2239,8 @@ void CommonHostInterface::CheckForSettingsChanges(const Settings& old_settings) g_settings.emulation_speed != old_settings.emulation_speed || g_settings.fast_forward_speed != old_settings.fast_forward_speed || g_settings.display_max_fps != old_settings.display_max_fps || - g_settings.audio_resampling != old_settings.audio_resampling) + g_settings.audio_resampling != old_settings.audio_resampling || + g_settings.sync_to_host_refresh_rate != old_settings.sync_to_host_refresh_rate) { UpdateSpeedLimiterState(); }