From 6f0929df82be77f116988cf16cde4ebbc5f978dc Mon Sep 17 00:00:00 2001 From: lat9nq <22451773+lat9nq@users.noreply.github.com> Date: Sun, 30 Apr 2023 15:39:00 -0400 Subject: configuration: Expose separate swap present modes Previously, yuzu would try and guess which vsync mode to use given different scenarios, but apparently we didn't always get it right. This exposes the separate modes in a drop-down the user can select. If a mode isn't available in Vulkan, it defaults to FIFO. --- src/yuzu/configuration/configure_graphics.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/yuzu/configuration/configure_graphics.cpp') diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index e9388daad..17a54f0f4 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); } -- cgit v1.2.3 From a546ecbb1241a28b808d3a9ebe1a55f001c267ed Mon Sep 17 00:00:00 2001 From: lat9nq <22451773+lat9nq@users.noreply.github.com> Date: Mon, 1 May 2023 20:36:23 -0400 Subject: configure_graphics: Actively find present modes When Vulkan devices are enumerated, this also determines the available present modes for each device, maps them to a vector, and gives those options to the user. OpenGL options are limited to On/Off. Required creating a VkSurfaceKHR during device enumeration, which may or may not be desireable. For the sake of a less confusing UI. Also fixes a bug where if a graphics device disappears on the host, we don't try and select the non-existant devices. configure_graphics: Remove vsync runtime lock for Vulkan configure_graphics: Recommend Mailbox present mode configure_graphics: Fix type-limits warning configure_graphics: Clean up includes configure_graphics: Add tooltip --- src/yuzu/configuration/configure_graphics.cpp | 155 ++++++++++++++++++++++++-- 1 file changed, 144 insertions(+), 11 deletions(-) (limited to 'src/yuzu/configuration/configure_graphics.cpp') diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index 17a54f0f4..3e3398f42 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp @@ -4,20 +4,62 @@ // Include this early to include Vulkan headers how we want to #include "video_core/vulkan_common/vulkan_wrapper.h" +#include #include +#include #include +#include +#include +#include "bootmanager.h" #include "common/common_types.h" #include "common/logging/log.h" #include "common/settings.h" #include "core/core.h" +#include "core/frontend/emu_window.h" #include "ui_configure_graphics.h" #include "video_core/vulkan_common/vulkan_instance.h" #include "video_core/vulkan_common/vulkan_library.h" +#include "video_core/vulkan_common/vulkan_surface.h" #include "yuzu/configuration/configuration_shared.h" #include "yuzu/configuration/configure_graphics.h" +#include "yuzu/qt_common.h" #include "yuzu/uisettings.h" +static const std::vector default_present_modes{VK_PRESENT_MODE_IMMEDIATE_KHR, + VK_PRESENT_MODE_FIFO_KHR}; + +// Converts a setting to a present mode (or vice versa) +static constexpr VkPresentModeKHR VSyncSettingToMode(Settings::VSyncMode mode) { + switch (mode) { + case Settings::VSyncMode::Immediate: + return VK_PRESENT_MODE_IMMEDIATE_KHR; + case Settings::VSyncMode::Mailbox: + return VK_PRESENT_MODE_MAILBOX_KHR; + case Settings::VSyncMode::FIFO: + return VK_PRESENT_MODE_FIFO_KHR; + case Settings::VSyncMode::FIFORelaxed: + return VK_PRESENT_MODE_FIFO_RELAXED_KHR; + default: + return VK_PRESENT_MODE_FIFO_KHR; + } +} + +static constexpr Settings::VSyncMode PresentModeToSetting(VkPresentModeKHR mode) { + switch (mode) { + case VK_PRESENT_MODE_IMMEDIATE_KHR: + return Settings::VSyncMode::Immediate; + case VK_PRESENT_MODE_MAILBOX_KHR: + return Settings::VSyncMode::Mailbox; + case VK_PRESENT_MODE_FIFO_KHR: + return Settings::VSyncMode::FIFO; + case VK_PRESENT_MODE_FIFO_RELAXED_KHR: + return Settings::VSyncMode::FIFORelaxed; + default: + return Settings::VSyncMode::FIFO; + } +} + ConfigureGraphics::ConfigureGraphics(const Core::System& system_, QWidget* parent) : QWidget(parent), ui{std::make_unique()}, system{system_} { vulkan_device = Settings::values.vulkan_device.GetValue(); @@ -39,13 +81,16 @@ ConfigureGraphics::ConfigureGraphics(const Core::System& system_, QWidget* paren connect(ui->api, qOverload(&QComboBox::currentIndexChanged), this, [this] { UpdateAPILayout(); + PopulateVSyncModeSelection(); if (!Settings::IsConfiguringGlobal()) { ConfigurationShared::SetHighlight( ui->api_widget, ui->api->currentIndex() != ConfigurationShared::USE_GLOBAL_INDEX); } }); - connect(ui->device, qOverload(&QComboBox::activated), this, - [this](int device) { UpdateDeviceSelection(device); }); + connect(ui->device, qOverload(&QComboBox::activated), this, [this](int device) { + UpdateDeviceSelection(device); + PopulateVSyncModeSelection(); + }); connect(ui->backend, qOverload(&QComboBox::activated), this, [this](int backend) { UpdateShaderBackendSelection(backend); }); @@ -70,6 +115,43 @@ ConfigureGraphics::ConfigureGraphics(const Core::System& system_, QWidget* paren ui->fsr_sharpening_label->setVisible(Settings::IsConfiguringGlobal()); } +void ConfigureGraphics::PopulateVSyncModeSelection() { + const Settings::RendererBackend backend{GetCurrentGraphicsBackend()}; + if (backend == Settings::RendererBackend::Null) { + ui->vsync_mode_combobox->setEnabled(false); + return; + } + ui->vsync_mode_combobox->setEnabled(true); + + const int current_index = //< current selected vsync mode from combobox + ui->vsync_mode_combobox->currentIndex(); + const auto current_mode = //< current selected vsync mode as a VkPresentModeKHR + current_index == -1 ? VSyncSettingToMode(Settings::values.vsync_mode.GetValue()) + : vsync_mode_combobox_enum_map[current_index]; + int index{}; + const int device{ui->device->currentIndex()}; //< current selected Vulkan device + const auto& present_modes = //< relevant vector of present modes for the selected device or API + backend == Settings::RendererBackend::Vulkan ? device_present_modes[device] + : default_present_modes; + + ui->vsync_mode_combobox->clear(); + vsync_mode_combobox_enum_map.clear(); + vsync_mode_combobox_enum_map.reserve(present_modes.size()); + for (const auto present_mode : present_modes) { + const auto mode_name = TranslateVSyncMode(present_mode, backend); + if (mode_name.isEmpty()) { + continue; + } + + ui->vsync_mode_combobox->insertItem(index, mode_name); + vsync_mode_combobox_enum_map.push_back(present_mode); + if (present_mode == current_mode) { + ui->vsync_mode_combobox->setCurrentIndex(index); + } + index++; + } +} + void ConfigureGraphics::UpdateDeviceSelection(int device) { if (device == -1) { return; @@ -99,7 +181,9 @@ 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->vsync_mode_layout->setEnabled(runtime_lock || + Settings::values.renderer_backend.GetValue() == + Settings::RendererBackend::Vulkan); 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()); @@ -119,9 +203,6 @@ 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, @@ -174,7 +255,24 @@ void ConfigureGraphics::SetConfiguration() { Settings::values.bg_green.GetValue(), Settings::values.bg_blue.GetValue())); UpdateAPILayout(); + PopulateVSyncModeSelection(); //< must happen after UpdateAPILayout SetFSRIndicatorText(ui->fsr_sharpening_slider->sliderPosition()); + + // V-Sync setting needs to be determined after populating the V-Sync combobox + if (Settings::IsConfiguringGlobal()) { + const auto vsync_mode_setting = Settings::values.vsync_mode.GetValue(); + const auto vsync_mode = VSyncSettingToMode(vsync_mode_setting); + int index{}; + for (const auto mode : vsync_mode_combobox_enum_map) { + if (mode == vsync_mode) { + break; + } + index++; + } + if (static_cast(index) < vsync_mode_combobox_enum_map.size()) { + ui->vsync_mode_combobox->setCurrentIndex(index); + } + } } void ConfigureGraphics::SetFSRIndicatorText(int percentage) { @@ -182,6 +280,27 @@ void ConfigureGraphics::SetFSRIndicatorText(int percentage) { tr("%1%", "FSR sharpening percentage (e.g. 50%)").arg(100 - (percentage / 2))); } +const QString ConfigureGraphics::TranslateVSyncMode(VkPresentModeKHR mode, + Settings::RendererBackend backend) const { + switch (mode) { + case VK_PRESENT_MODE_IMMEDIATE_KHR: + return backend == Settings::RendererBackend::OpenGL + ? tr("Off") + : QStringLiteral("Immediate (%1)").arg(tr("V-Sync Off")); + case VK_PRESENT_MODE_MAILBOX_KHR: + return QStringLiteral("Mailbox (%1)").arg(tr("Recommended")); + case VK_PRESENT_MODE_FIFO_KHR: + return backend == Settings::RendererBackend::OpenGL + ? tr("On") + : QStringLiteral("FIFO (%1)").arg(tr("V-Sync On")); + case VK_PRESENT_MODE_FIFO_RELAXED_KHR: + return QStringLiteral("FIFO Relaxed"); + default: + return {}; + break; + } +} + void ConfigureGraphics::ApplyConfiguration() { const auto resolution_setup = static_cast( ui->resolution_combobox->currentIndex() - @@ -237,8 +356,9 @@ void ConfigureGraphics::ApplyConfiguration() { } Settings::values.fsr_sharpening_slider.SetValue(ui->fsr_sharpening_slider->value()); - Settings::values.vsync_mode.SetValue( - static_cast(ui->vsync_mode_combobox->currentIndex())); + const auto mode = vsync_mode_combobox_enum_map[ui->vsync_mode_combobox->currentIndex()]; + const auto vsync_mode = PresentModeToSetting(mode); + Settings::values.vsync_mode.SetValue(vsync_mode); } else { if (ui->resolution_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { Settings::values.resolution_setup.SetGlobal(true); @@ -352,7 +472,9 @@ void ConfigureGraphics::UpdateAPILayout() { ui->backend_widget->setVisible(true); break; case Settings::RendererBackend::Vulkan: - ui->device->setCurrentIndex(vulkan_device); + if (static_cast(vulkan_device) < ui->device->count()) { + ui->device->setCurrentIndex(vulkan_device); + } ui->device_widget->setVisible(true); ui->backend_widget->setVisible(false); break; @@ -370,16 +492,27 @@ void ConfigureGraphics::RetrieveVulkanDevices() try { using namespace Vulkan; + auto* window = this->window()->windowHandle(); + auto wsi = YuzuQtCommon::GetWindowSystemInfo(window); + vk::InstanceDispatch dld; const Common::DynamicLibrary library = OpenLibrary(); - const vk::Instance instance = CreateInstance(library, dld, VK_API_VERSION_1_1); + const vk::Instance instance = CreateInstance(library, dld, VK_API_VERSION_1_1, wsi.type); const std::vector physical_devices = instance.EnumeratePhysicalDevices(); + vk::SurfaceKHR surface = //< needed to view present modes for a device + CreateSurface(instance, wsi); vulkan_devices.clear(); vulkan_devices.reserve(physical_devices.size()); + device_present_modes.clear(); + device_present_modes.reserve(physical_devices.size()); for (const VkPhysicalDevice device : physical_devices) { - const std::string name = vk::PhysicalDevice(device, dld).GetProperties().deviceName; + const auto physical_device = vk::PhysicalDevice(device, dld); + const std::string name = physical_device.GetProperties().deviceName; + const std::vector present_modes = + physical_device.GetSurfacePresentModesKHR(*surface); vulkan_devices.push_back(QString::fromStdString(name)); + device_present_modes.push_back(present_modes); } } catch (const Vulkan::vk::Exception& exception) { LOG_ERROR(Frontend, "Failed to enumerate devices with error: {}", exception.what()); -- cgit v1.2.3 From cd2981ee125bb4fac48b8acd31a3bd921cc362c4 Mon Sep 17 00:00:00 2001 From: lat9nq <22451773+lat9nq@users.noreply.github.com> Date: Tue, 2 May 2023 16:54:32 -0400 Subject: configure_graphics: Clean up includes [IWYU] --- src/yuzu/configuration/configure_graphics.cpp | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'src/yuzu/configuration/configure_graphics.cpp') diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index 3e3398f42..4a4a7bb0b 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp @@ -4,19 +4,33 @@ // Include this early to include Vulkan headers how we want to #include "video_core/vulkan_common/vulkan_wrapper.h" +#include +#include +#include +#include +#include +#include #include +#include +#include #include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include "bootmanager.h" #include "common/common_types.h" +#include "common/dynamic_library.h" #include "common/logging/log.h" #include "common/settings.h" #include "core/core.h" -#include "core/frontend/emu_window.h" #include "ui_configure_graphics.h" #include "video_core/vulkan_common/vulkan_instance.h" #include "video_core/vulkan_common/vulkan_library.h" -- cgit v1.2.3 From 35e7f36a39775c48ba2c8ed6b5a52dcbbe381a19 Mon Sep 17 00:00:00 2001 From: lat9nq <22451773+lat9nq@users.noreply.github.com> Date: Tue, 2 May 2023 19:22:54 -0400 Subject: configure_graphics: No there isn't a hyphen in VSync Most sources seem to suggest VSync and not V-Sync --- src/yuzu/configuration/configure_graphics.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/yuzu/configuration/configure_graphics.cpp') diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index 4a4a7bb0b..6f5bc8d90 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp @@ -272,7 +272,7 @@ void ConfigureGraphics::SetConfiguration() { PopulateVSyncModeSelection(); //< must happen after UpdateAPILayout SetFSRIndicatorText(ui->fsr_sharpening_slider->sliderPosition()); - // V-Sync setting needs to be determined after populating the V-Sync combobox + // VSync setting needs to be determined after populating the VSync combobox if (Settings::IsConfiguringGlobal()) { const auto vsync_mode_setting = Settings::values.vsync_mode.GetValue(); const auto vsync_mode = VSyncSettingToMode(vsync_mode_setting); @@ -300,13 +300,13 @@ const QString ConfigureGraphics::TranslateVSyncMode(VkPresentModeKHR mode, case VK_PRESENT_MODE_IMMEDIATE_KHR: return backend == Settings::RendererBackend::OpenGL ? tr("Off") - : QStringLiteral("Immediate (%1)").arg(tr("V-Sync Off")); + : QStringLiteral("Immediate (%1)").arg(tr("VSync Off")); case VK_PRESENT_MODE_MAILBOX_KHR: return QStringLiteral("Mailbox (%1)").arg(tr("Recommended")); case VK_PRESENT_MODE_FIFO_KHR: return backend == Settings::RendererBackend::OpenGL ? tr("On") - : QStringLiteral("FIFO (%1)").arg(tr("V-Sync On")); + : QStringLiteral("FIFO (%1)").arg(tr("VSync On")); case VK_PRESENT_MODE_FIFO_RELAXED_KHR: return QStringLiteral("FIFO Relaxed"); default: -- cgit v1.2.3 From a71498d163029c29285e5bef7098f2fe265196fa Mon Sep 17 00:00:00 2001 From: lat9nq <22451773+lat9nq@users.noreply.github.com> Date: Wed, 3 May 2023 18:11:34 -0400 Subject: qt_common: Remove yuzu prefix --- src/yuzu/configuration/configure_graphics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/yuzu/configuration/configure_graphics.cpp') diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index 6f5bc8d90..76e5b7499 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp @@ -507,7 +507,7 @@ void ConfigureGraphics::RetrieveVulkanDevices() try { using namespace Vulkan; auto* window = this->window()->windowHandle(); - auto wsi = YuzuQtCommon::GetWindowSystemInfo(window); + auto wsi = QtCommon::GetWindowSystemInfo(window); vk::InstanceDispatch dld; const Common::DynamicLibrary library = OpenLibrary(); -- cgit v1.2.3