diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 77ff211283..92794f4a27 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -60,7 +60,7 @@ void LogSettings() { log_setting("Renderer_NvdecEmulation", values.nvdec_emulation.GetValue()); log_setting("Renderer_AccelerateASTC", values.accelerate_astc.GetValue()); log_setting("Renderer_AsyncASTC", values.async_astc.GetValue()); - log_setting("Renderer_UseVsync", values.use_vsync.GetValue()); + log_setting("Renderer_UseVsync", values.vsync_mode.GetValue()); log_setting("Renderer_ShaderBackend", values.shader_backend.GetValue()); log_setting("Renderer_UseAsynchronousShaders", values.use_asynchronous_shaders.GetValue()); log_setting("Renderer_AnisotropicFilteringLevel", values.max_anisotropy.GetValue()); @@ -222,7 +222,6 @@ void RestoreGlobalState(bool is_powered_on) { values.nvdec_emulation.SetGlobal(true); values.accelerate_astc.SetGlobal(true); values.async_astc.SetGlobal(true); - values.use_vsync.SetGlobal(true); values.shader_backend.SetGlobal(true); values.use_asynchronous_shaders.SetGlobal(true); values.use_fast_gpu_time.SetGlobal(true); diff --git a/src/common/settings.h b/src/common/settings.h index 5379d0dd52..2371495e42 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -16,6 +16,12 @@ namespace Settings { +enum class VSyncMode : u32 { + Immediate, + FIFO, + Mailbox, +}; + enum class RendererBackend : u32 { OpenGL = 0, Vulkan = 1, @@ -455,7 +461,8 @@ struct Values { SwitchableSetting nvdec_emulation{NvdecEmulation::GPU, "nvdec_emulation"}; SwitchableSetting accelerate_astc{true, "accelerate_astc"}; SwitchableSetting async_astc{false, "async_astc"}; - SwitchableSetting use_vsync{true, "use_vsync"}; + Setting vsync_mode{VSyncMode::FIFO, VSyncMode::Immediate, VSyncMode::Mailbox, + "use_vsync"}; SwitchableSetting shader_backend{ShaderBackend::GLSL, ShaderBackend::GLSL, ShaderBackend::SPIRV, "shader_backend"}; SwitchableSetting use_asynchronous_shaders{false, "use_asynchronous_shaders"}; diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp index 9178b00ca6..6ec8e440c4 100644 --- a/src/core/telemetry_session.cpp +++ b/src/core/telemetry_session.cpp @@ -85,6 +85,18 @@ static const char* TranslateNvdecEmulation(Settings::NvdecEmulation backend) { return "Unknown"; } +constexpr const char* TranslateVSyncMode(Settings::VSyncMode mode) { + switch (mode) { + case Settings::VSyncMode::Immediate: + return "Immediate"; + case Settings::VSyncMode::FIFO: + return "FIFO"; + case Settings::VSyncMode::Mailbox: + return "Mailbox"; + } + return "Unknown"; +} + u64 GetTelemetryId() { u64 telemetry_id{}; const auto filename = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir) / "telemetry_id"; @@ -241,7 +253,8 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader, AddField(field_type, "Renderer_NvdecEmulation", TranslateNvdecEmulation(Settings::values.nvdec_emulation.GetValue())); AddField(field_type, "Renderer_AccelerateASTC", Settings::values.accelerate_astc.GetValue()); - AddField(field_type, "Renderer_UseVsync", Settings::values.use_vsync.GetValue()); + AddField(field_type, "Renderer_UseVsync", + TranslateVSyncMode(Settings::values.vsync_mode.GetValue())); AddField(field_type, "Renderer_ShaderBackend", static_cast(Settings::values.shader_backend.GetValue())); AddField(field_type, "Renderer_UseAsynchronousShaders", diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index 23bbea7f10..08d82769c2 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp @@ -34,21 +34,22 @@ VkSurfaceFormatKHR ChooseSwapSurfaceFormat(vk::Span formats) } VkPresentModeKHR ChooseSwapPresentMode(vk::Span modes) { - // Mailbox (triple buffering) doesn't lock the application like fifo (vsync), - // prefer it if vsync option is not selected - const auto found_mailbox = std::find(modes.begin(), modes.end(), VK_PRESENT_MODE_MAILBOX_KHR); - if (Settings::values.fullscreen_mode.GetValue() == Settings::FullscreenMode::Borderless && - found_mailbox != modes.end() && !Settings::values.use_vsync.GetValue()) { + // Mailbox (triple buffering) doesn't lock the application like FIFO (vsync) + // FIFO present mode locks the framerate to the monitor's refresh rate + const bool has_mailbox = + std::find(modes.begin(), modes.end(), VK_PRESENT_MODE_MAILBOX_KHR) != modes.end(); + const bool has_imm = + std::find(modes.begin(), modes.end(), VK_PRESENT_MODE_IMMEDIATE_KHR) != modes.end(); + const Settings::VSyncMode mode = Settings::values.vsync_mode.GetValue(); + + if (mode == Settings::VSyncMode::Immediate && has_imm) { + LOG_INFO(Render_Vulkan, "Using swap present mode Immediate"); + return VK_PRESENT_MODE_IMMEDIATE_KHR; + } else if (mode == Settings::VSyncMode::Mailbox && has_mailbox) { + LOG_INFO(Render_Vulkan, "Using swap present mode Mailbox"); return VK_PRESENT_MODE_MAILBOX_KHR; } - if (!Settings::values.use_speed_limit.GetValue()) { - // FIFO present mode locks the framerate to the monitor's refresh rate, - // 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); - if (found_imm != modes.end()) { - return VK_PRESENT_MODE_IMMEDIATE_KHR; - } - } + LOG_INFO(Render_Vulkan, "Using swap present mode FIFO"); return VK_PRESENT_MODE_FIFO_KHR; } diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 4c7bf28d80..01dc51cffc 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -154,7 +154,18 @@ public: // disable vsync for any shared contexts auto format = share_context->format(); - format.setSwapInterval(main_surface ? Settings::values.use_vsync.GetValue() : 0); + const int swap_interval = [&]() { + switch (Settings::values.vsync_mode.GetValue()) { + case Settings::VSyncMode::Immediate: + return 0; + case Settings::VSyncMode::FIFO: + return 1; + case Settings::VSyncMode::Mailbox: + return 2; + } + }(); + + format.setSwapInterval(main_surface ? swap_interval : 0); context = std::make_unique(); context->setShareContext(share_context); diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 305891d18f..4a8436e5c1 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -6,6 +6,7 @@ #include #include "common/fs/fs.h" #include "common/fs/path_util.h" +#include "common/settings.h" #include "core/core.h" #include "core/hle/service/acc/profile_manager.h" #include "core/hle/service/hid/controllers/npad.h" @@ -709,7 +710,6 @@ void Config::ReadRendererValues() { ReadGlobalSetting(Settings::values.nvdec_emulation); ReadGlobalSetting(Settings::values.accelerate_astc); ReadGlobalSetting(Settings::values.async_astc); - ReadGlobalSetting(Settings::values.use_vsync); ReadGlobalSetting(Settings::values.shader_backend); ReadGlobalSetting(Settings::values.use_asynchronous_shaders); ReadGlobalSetting(Settings::values.use_fast_gpu_time); @@ -720,6 +720,10 @@ void Config::ReadRendererValues() { ReadGlobalSetting(Settings::values.bg_blue); if (global) { + Settings::values.vsync_mode.SetValue(static_cast( + ReadSetting(QString::fromStdString(Settings::values.vsync_mode.GetLabel()), + static_cast(Settings::values.vsync_mode.GetDefault())) + .value())); ReadBasicSetting(Settings::values.renderer_debug); ReadBasicSetting(Settings::values.renderer_shader_feedback); ReadBasicSetting(Settings::values.enable_nsight_aftermath); @@ -1352,7 +1356,6 @@ void Config::SaveRendererValues() { Settings::values.nvdec_emulation.UsingGlobal()); WriteGlobalSetting(Settings::values.accelerate_astc); WriteGlobalSetting(Settings::values.async_astc); - WriteGlobalSetting(Settings::values.use_vsync); WriteSetting(QString::fromStdString(Settings::values.shader_backend.GetLabel()), static_cast(Settings::values.shader_backend.GetValue(global)), static_cast(Settings::values.shader_backend.GetDefault()), @@ -1366,6 +1369,9 @@ void Config::SaveRendererValues() { WriteGlobalSetting(Settings::values.bg_blue); if (global) { + WriteSetting(QString::fromStdString(Settings::values.vsync_mode.GetLabel()), + static_cast(Settings::values.vsync_mode.GetValue()), + static_cast(Settings::values.vsync_mode.GetDefault())); WriteBasicSetting(Settings::values.renderer_debug); WriteBasicSetting(Settings::values.renderer_shader_feedback); WriteBasicSetting(Settings::values.enable_nsight_aftermath); diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index e9388daadb..17a54f0f4a 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp @@ -99,6 +99,7 @@ void ConfigureGraphics::SetConfiguration() { ui->nvdec_emulation_widget->setEnabled(runtime_lock); ui->resolution_combobox->setEnabled(runtime_lock); ui->accelerate_astc->setEnabled(runtime_lock); + ui->vsync_mode_combobox->setEnabled(runtime_lock); ui->use_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache.GetValue()); ui->use_asynchronous_gpu_emulation->setChecked( Settings::values.use_asynchronous_gpu_emulation.GetValue()); @@ -118,6 +119,9 @@ void ConfigureGraphics::SetConfiguration() { ui->fsr_sharpening_slider->setValue(Settings::values.fsr_sharpening_slider.GetValue()); ui->anti_aliasing_combobox->setCurrentIndex( static_cast(Settings::values.anti_aliasing.GetValue())); + + ui->vsync_mode_combobox->setCurrentIndex( + static_cast(Settings::values.vsync_mode.GetValue())); } else { ConfigurationShared::SetPerGameSetting(ui->api, &Settings::values.renderer_backend); ConfigurationShared::SetHighlight(ui->api_widget, @@ -232,6 +236,9 @@ void ConfigureGraphics::ApplyConfiguration() { Settings::values.anti_aliasing.SetValue(anti_aliasing); } Settings::values.fsr_sharpening_slider.SetValue(ui->fsr_sharpening_slider->value()); + + Settings::values.vsync_mode.SetValue( + static_cast(ui->vsync_mode_combobox->currentIndex())); } else { if (ui->resolution_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { Settings::values.resolution_setup.SetGlobal(true); @@ -465,4 +472,6 @@ void ConfigureGraphics::SetupPerGameUI() { ui->api, static_cast(Settings::values.renderer_backend.GetValue(true))); ConfigurationShared::InsertGlobalItem( ui->nvdec_emulation, static_cast(Settings::values.nvdec_emulation.GetValue(true))); + + ui->vsync_mode_layout->setVisible(false); } diff --git a/src/yuzu/configuration/configure_graphics.ui b/src/yuzu/configuration/configure_graphics.ui index a45ec69ecf..4c241e2471 100644 --- a/src/yuzu/configuration/configure_graphics.ui +++ b/src/yuzu/configuration/configure_graphics.ui @@ -188,6 +188,53 @@ + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + VSync Mode + + + + + + + Off (Immediate) + + + + Off (Immediate) + + + + + Double Buffering (FIFO) + + + + + Triple Buffering (Mailbox) + + + + + + + @@ -366,7 +413,7 @@ - 1.5X (1080p/1620p) [EXPERIMENTAL] + 1.5X (1080p/1620p) [EXPERIMENTAL] diff --git a/src/yuzu/configuration/configure_graphics_advanced.cpp b/src/yuzu/configuration/configure_graphics_advanced.cpp index 7f7bf0e4d0..4072ce145a 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.cpp +++ b/src/yuzu/configuration/configure_graphics_advanced.cpp @@ -21,7 +21,6 @@ ConfigureGraphicsAdvanced::~ConfigureGraphicsAdvanced() = default; void ConfigureGraphicsAdvanced::SetConfiguration() { const bool runtime_lock = !system.IsPoweredOn(); - ui->use_vsync->setEnabled(runtime_lock); ui->async_present->setEnabled(runtime_lock); ui->renderer_force_max_clock->setEnabled(runtime_lock); ui->async_astc->setEnabled(runtime_lock); @@ -30,7 +29,6 @@ void ConfigureGraphicsAdvanced::SetConfiguration() { ui->async_present->setChecked(Settings::values.async_presentation.GetValue()); ui->renderer_force_max_clock->setChecked(Settings::values.renderer_force_max_clock.GetValue()); - ui->use_vsync->setChecked(Settings::values.use_vsync.GetValue()); ui->async_astc->setChecked(Settings::values.async_astc.GetValue()); ui->use_asynchronous_shaders->setChecked(Settings::values.use_asynchronous_shaders.GetValue()); ui->use_fast_gpu_time->setChecked(Settings::values.use_fast_gpu_time.GetValue()); @@ -63,7 +61,6 @@ void ConfigureGraphicsAdvanced::ApplyConfiguration() { renderer_force_max_clock); ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy, ui->anisotropic_filtering_combobox); - ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync, ui->use_vsync, use_vsync); ConfigurationShared::ApplyPerGameSetting(&Settings::values.async_astc, ui->async_astc, async_astc); ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_shaders, @@ -97,7 +94,6 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() { ui->async_present->setEnabled(Settings::values.async_presentation.UsingGlobal()); ui->renderer_force_max_clock->setEnabled( Settings::values.renderer_force_max_clock.UsingGlobal()); - ui->use_vsync->setEnabled(Settings::values.use_vsync.UsingGlobal()); ui->async_astc->setEnabled(Settings::values.async_astc.UsingGlobal()); ui->use_asynchronous_shaders->setEnabled( Settings::values.use_asynchronous_shaders.UsingGlobal()); @@ -117,7 +113,6 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() { ConfigurationShared::SetColoredTristate(ui->renderer_force_max_clock, Settings::values.renderer_force_max_clock, renderer_force_max_clock); - ConfigurationShared::SetColoredTristate(ui->use_vsync, Settings::values.use_vsync, use_vsync); ConfigurationShared::SetColoredTristate(ui->async_astc, Settings::values.async_astc, async_astc); ConfigurationShared::SetColoredTristate(ui->use_asynchronous_shaders, diff --git a/src/yuzu/configuration/configure_graphics_advanced.ui b/src/yuzu/configuration/configure_graphics_advanced.ui index d7ec189395..134023032e 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.ui +++ b/src/yuzu/configuration/configure_graphics_advanced.ui @@ -86,16 +86,6 @@ - - - - VSync prevents the screen from tearing, but some graphics cards have lower performance with VSync enabled. Keep it enabled if you don't notice a performance difference. - - - Use VSync - - - diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index fa347fb8cb..a692ef809d 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp @@ -320,7 +320,7 @@ void Config::ReadValues() { ReadSetting("Renderer", Settings::values.use_disk_shader_cache); ReadSetting("Renderer", Settings::values.gpu_accuracy); ReadSetting("Renderer", Settings::values.use_asynchronous_gpu_emulation); - ReadSetting("Renderer", Settings::values.use_vsync); + ReadSetting("Renderer", Settings::values.vsync_mode); ReadSetting("Renderer", Settings::values.shader_backend); ReadSetting("Renderer", Settings::values.use_asynchronous_shaders); ReadSetting("Renderer", Settings::values.nvdec_emulation);