summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/yuzu/configuration/configure_graphics.cpp155
-rw-r--r--src/yuzu/configuration/configure_graphics.h10
-rw-r--r--src/yuzu/configuration/configure_graphics.ui23
3 files changed, 161 insertions, 27 deletions
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 @@
4// Include this early to include Vulkan headers how we want to 4// Include this early to include Vulkan headers how we want to
5#include "video_core/vulkan_common/vulkan_wrapper.h" 5#include "video_core/vulkan_common/vulkan_wrapper.h"
6 6
7#include <vector>
7#include <QColorDialog> 8#include <QColorDialog>
9#include <QGuiApplication>
8#include <QVulkanInstance> 10#include <QVulkanInstance>
11#include <QWindow>
12#include <vulkan/vulkan_core.h>
9 13
14#include "bootmanager.h"
10#include "common/common_types.h" 15#include "common/common_types.h"
11#include "common/logging/log.h" 16#include "common/logging/log.h"
12#include "common/settings.h" 17#include "common/settings.h"
13#include "core/core.h" 18#include "core/core.h"
19#include "core/frontend/emu_window.h"
14#include "ui_configure_graphics.h" 20#include "ui_configure_graphics.h"
15#include "video_core/vulkan_common/vulkan_instance.h" 21#include "video_core/vulkan_common/vulkan_instance.h"
16#include "video_core/vulkan_common/vulkan_library.h" 22#include "video_core/vulkan_common/vulkan_library.h"
23#include "video_core/vulkan_common/vulkan_surface.h"
17#include "yuzu/configuration/configuration_shared.h" 24#include "yuzu/configuration/configuration_shared.h"
18#include "yuzu/configuration/configure_graphics.h" 25#include "yuzu/configuration/configure_graphics.h"
26#include "yuzu/qt_common.h"
19#include "yuzu/uisettings.h" 27#include "yuzu/uisettings.h"
20 28
29static const std::vector<VkPresentModeKHR> default_present_modes{VK_PRESENT_MODE_IMMEDIATE_KHR,
30 VK_PRESENT_MODE_FIFO_KHR};
31
32// Converts a setting to a present mode (or vice versa)
33static constexpr VkPresentModeKHR VSyncSettingToMode(Settings::VSyncMode mode) {
34 switch (mode) {
35 case Settings::VSyncMode::Immediate:
36 return VK_PRESENT_MODE_IMMEDIATE_KHR;
37 case Settings::VSyncMode::Mailbox:
38 return VK_PRESENT_MODE_MAILBOX_KHR;
39 case Settings::VSyncMode::FIFO:
40 return VK_PRESENT_MODE_FIFO_KHR;
41 case Settings::VSyncMode::FIFORelaxed:
42 return VK_PRESENT_MODE_FIFO_RELAXED_KHR;
43 default:
44 return VK_PRESENT_MODE_FIFO_KHR;
45 }
46}
47
48static constexpr Settings::VSyncMode PresentModeToSetting(VkPresentModeKHR mode) {
49 switch (mode) {
50 case VK_PRESENT_MODE_IMMEDIATE_KHR:
51 return Settings::VSyncMode::Immediate;
52 case VK_PRESENT_MODE_MAILBOX_KHR:
53 return Settings::VSyncMode::Mailbox;
54 case VK_PRESENT_MODE_FIFO_KHR:
55 return Settings::VSyncMode::FIFO;
56 case VK_PRESENT_MODE_FIFO_RELAXED_KHR:
57 return Settings::VSyncMode::FIFORelaxed;
58 default:
59 return Settings::VSyncMode::FIFO;
60 }
61}
62
21ConfigureGraphics::ConfigureGraphics(const Core::System& system_, QWidget* parent) 63ConfigureGraphics::ConfigureGraphics(const Core::System& system_, QWidget* parent)
22 : QWidget(parent), ui{std::make_unique<Ui::ConfigureGraphics>()}, system{system_} { 64 : QWidget(parent), ui{std::make_unique<Ui::ConfigureGraphics>()}, system{system_} {
23 vulkan_device = Settings::values.vulkan_device.GetValue(); 65 vulkan_device = Settings::values.vulkan_device.GetValue();
@@ -39,13 +81,16 @@ ConfigureGraphics::ConfigureGraphics(const Core::System& system_, QWidget* paren
39 81
40 connect(ui->api, qOverload<int>(&QComboBox::currentIndexChanged), this, [this] { 82 connect(ui->api, qOverload<int>(&QComboBox::currentIndexChanged), this, [this] {
41 UpdateAPILayout(); 83 UpdateAPILayout();
84 PopulateVSyncModeSelection();
42 if (!Settings::IsConfiguringGlobal()) { 85 if (!Settings::IsConfiguringGlobal()) {
43 ConfigurationShared::SetHighlight( 86 ConfigurationShared::SetHighlight(
44 ui->api_widget, ui->api->currentIndex() != ConfigurationShared::USE_GLOBAL_INDEX); 87 ui->api_widget, ui->api->currentIndex() != ConfigurationShared::USE_GLOBAL_INDEX);
45 } 88 }
46 }); 89 });
47 connect(ui->device, qOverload<int>(&QComboBox::activated), this, 90 connect(ui->device, qOverload<int>(&QComboBox::activated), this, [this](int device) {
48 [this](int device) { UpdateDeviceSelection(device); }); 91 UpdateDeviceSelection(device);
92 PopulateVSyncModeSelection();
93 });
49 connect(ui->backend, qOverload<int>(&QComboBox::activated), this, 94 connect(ui->backend, qOverload<int>(&QComboBox::activated), this,
50 [this](int backend) { UpdateShaderBackendSelection(backend); }); 95 [this](int backend) { UpdateShaderBackendSelection(backend); });
51 96
@@ -70,6 +115,43 @@ ConfigureGraphics::ConfigureGraphics(const Core::System& system_, QWidget* paren
70 ui->fsr_sharpening_label->setVisible(Settings::IsConfiguringGlobal()); 115 ui->fsr_sharpening_label->setVisible(Settings::IsConfiguringGlobal());
71} 116}
72 117
118void ConfigureGraphics::PopulateVSyncModeSelection() {
119 const Settings::RendererBackend backend{GetCurrentGraphicsBackend()};
120 if (backend == Settings::RendererBackend::Null) {
121 ui->vsync_mode_combobox->setEnabled(false);
122 return;
123 }
124 ui->vsync_mode_combobox->setEnabled(true);
125
126 const int current_index = //< current selected vsync mode from combobox
127 ui->vsync_mode_combobox->currentIndex();
128 const auto current_mode = //< current selected vsync mode as a VkPresentModeKHR
129 current_index == -1 ? VSyncSettingToMode(Settings::values.vsync_mode.GetValue())
130 : vsync_mode_combobox_enum_map[current_index];
131 int index{};
132 const int device{ui->device->currentIndex()}; //< current selected Vulkan device
133 const auto& present_modes = //< relevant vector of present modes for the selected device or API
134 backend == Settings::RendererBackend::Vulkan ? device_present_modes[device]
135 : default_present_modes;
136
137 ui->vsync_mode_combobox->clear();
138 vsync_mode_combobox_enum_map.clear();
139 vsync_mode_combobox_enum_map.reserve(present_modes.size());
140 for (const auto present_mode : present_modes) {
141 const auto mode_name = TranslateVSyncMode(present_mode, backend);
142 if (mode_name.isEmpty()) {
143 continue;
144 }
145
146 ui->vsync_mode_combobox->insertItem(index, mode_name);
147 vsync_mode_combobox_enum_map.push_back(present_mode);
148 if (present_mode == current_mode) {
149 ui->vsync_mode_combobox->setCurrentIndex(index);
150 }
151 index++;
152 }
153}
154
73void ConfigureGraphics::UpdateDeviceSelection(int device) { 155void ConfigureGraphics::UpdateDeviceSelection(int device) {
74 if (device == -1) { 156 if (device == -1) {
75 return; 157 return;
@@ -99,7 +181,9 @@ void ConfigureGraphics::SetConfiguration() {
99 ui->nvdec_emulation_widget->setEnabled(runtime_lock); 181 ui->nvdec_emulation_widget->setEnabled(runtime_lock);
100 ui->resolution_combobox->setEnabled(runtime_lock); 182 ui->resolution_combobox->setEnabled(runtime_lock);
101 ui->accelerate_astc->setEnabled(runtime_lock); 183 ui->accelerate_astc->setEnabled(runtime_lock);
102 ui->vsync_mode_combobox->setEnabled(runtime_lock); 184 ui->vsync_mode_layout->setEnabled(runtime_lock ||
185 Settings::values.renderer_backend.GetValue() ==
186 Settings::RendererBackend::Vulkan);
103 ui->use_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache.GetValue()); 187 ui->use_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache.GetValue());
104 ui->use_asynchronous_gpu_emulation->setChecked( 188 ui->use_asynchronous_gpu_emulation->setChecked(
105 Settings::values.use_asynchronous_gpu_emulation.GetValue()); 189 Settings::values.use_asynchronous_gpu_emulation.GetValue());
@@ -119,9 +203,6 @@ void ConfigureGraphics::SetConfiguration() {
119 ui->fsr_sharpening_slider->setValue(Settings::values.fsr_sharpening_slider.GetValue()); 203 ui->fsr_sharpening_slider->setValue(Settings::values.fsr_sharpening_slider.GetValue());
120 ui->anti_aliasing_combobox->setCurrentIndex( 204 ui->anti_aliasing_combobox->setCurrentIndex(
121 static_cast<int>(Settings::values.anti_aliasing.GetValue())); 205 static_cast<int>(Settings::values.anti_aliasing.GetValue()));
122
123 ui->vsync_mode_combobox->setCurrentIndex(
124 static_cast<int>(Settings::values.vsync_mode.GetValue()));
125 } else { 206 } else {
126 ConfigurationShared::SetPerGameSetting(ui->api, &Settings::values.renderer_backend); 207 ConfigurationShared::SetPerGameSetting(ui->api, &Settings::values.renderer_backend);
127 ConfigurationShared::SetHighlight(ui->api_widget, 208 ConfigurationShared::SetHighlight(ui->api_widget,
@@ -174,7 +255,24 @@ void ConfigureGraphics::SetConfiguration() {
174 Settings::values.bg_green.GetValue(), 255 Settings::values.bg_green.GetValue(),
175 Settings::values.bg_blue.GetValue())); 256 Settings::values.bg_blue.GetValue()));
176 UpdateAPILayout(); 257 UpdateAPILayout();
258 PopulateVSyncModeSelection(); //< must happen after UpdateAPILayout
177 SetFSRIndicatorText(ui->fsr_sharpening_slider->sliderPosition()); 259 SetFSRIndicatorText(ui->fsr_sharpening_slider->sliderPosition());
260
261 // V-Sync setting needs to be determined after populating the V-Sync combobox
262 if (Settings::IsConfiguringGlobal()) {
263 const auto vsync_mode_setting = Settings::values.vsync_mode.GetValue();
264 const auto vsync_mode = VSyncSettingToMode(vsync_mode_setting);
265 int index{};
266 for (const auto mode : vsync_mode_combobox_enum_map) {
267 if (mode == vsync_mode) {
268 break;
269 }
270 index++;
271 }
272 if (static_cast<unsigned long>(index) < vsync_mode_combobox_enum_map.size()) {
273 ui->vsync_mode_combobox->setCurrentIndex(index);
274 }
275 }
178} 276}
179 277
180void ConfigureGraphics::SetFSRIndicatorText(int percentage) { 278void ConfigureGraphics::SetFSRIndicatorText(int percentage) {
@@ -182,6 +280,27 @@ void ConfigureGraphics::SetFSRIndicatorText(int percentage) {
182 tr("%1%", "FSR sharpening percentage (e.g. 50%)").arg(100 - (percentage / 2))); 280 tr("%1%", "FSR sharpening percentage (e.g. 50%)").arg(100 - (percentage / 2)));
183} 281}
184 282
283const QString ConfigureGraphics::TranslateVSyncMode(VkPresentModeKHR mode,
284 Settings::RendererBackend backend) const {
285 switch (mode) {
286 case VK_PRESENT_MODE_IMMEDIATE_KHR:
287 return backend == Settings::RendererBackend::OpenGL
288 ? tr("Off")
289 : QStringLiteral("Immediate (%1)").arg(tr("V-Sync Off"));
290 case VK_PRESENT_MODE_MAILBOX_KHR:
291 return QStringLiteral("Mailbox (%1)").arg(tr("Recommended"));
292 case VK_PRESENT_MODE_FIFO_KHR:
293 return backend == Settings::RendererBackend::OpenGL
294 ? tr("On")
295 : QStringLiteral("FIFO (%1)").arg(tr("V-Sync On"));
296 case VK_PRESENT_MODE_FIFO_RELAXED_KHR:
297 return QStringLiteral("FIFO Relaxed");
298 default:
299 return {};
300 break;
301 }
302}
303
185void ConfigureGraphics::ApplyConfiguration() { 304void ConfigureGraphics::ApplyConfiguration() {
186 const auto resolution_setup = static_cast<Settings::ResolutionSetup>( 305 const auto resolution_setup = static_cast<Settings::ResolutionSetup>(
187 ui->resolution_combobox->currentIndex() - 306 ui->resolution_combobox->currentIndex() -
@@ -237,8 +356,9 @@ void ConfigureGraphics::ApplyConfiguration() {
237 } 356 }
238 Settings::values.fsr_sharpening_slider.SetValue(ui->fsr_sharpening_slider->value()); 357 Settings::values.fsr_sharpening_slider.SetValue(ui->fsr_sharpening_slider->value());
239 358
240 Settings::values.vsync_mode.SetValue( 359 const auto mode = vsync_mode_combobox_enum_map[ui->vsync_mode_combobox->currentIndex()];
241 static_cast<Settings::VSyncMode>(ui->vsync_mode_combobox->currentIndex())); 360 const auto vsync_mode = PresentModeToSetting(mode);
361 Settings::values.vsync_mode.SetValue(vsync_mode);
242 } else { 362 } else {
243 if (ui->resolution_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { 363 if (ui->resolution_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) {
244 Settings::values.resolution_setup.SetGlobal(true); 364 Settings::values.resolution_setup.SetGlobal(true);
@@ -352,7 +472,9 @@ void ConfigureGraphics::UpdateAPILayout() {
352 ui->backend_widget->setVisible(true); 472 ui->backend_widget->setVisible(true);
353 break; 473 break;
354 case Settings::RendererBackend::Vulkan: 474 case Settings::RendererBackend::Vulkan:
355 ui->device->setCurrentIndex(vulkan_device); 475 if (static_cast<int>(vulkan_device) < ui->device->count()) {
476 ui->device->setCurrentIndex(vulkan_device);
477 }
356 ui->device_widget->setVisible(true); 478 ui->device_widget->setVisible(true);
357 ui->backend_widget->setVisible(false); 479 ui->backend_widget->setVisible(false);
358 break; 480 break;
@@ -370,16 +492,27 @@ void ConfigureGraphics::RetrieveVulkanDevices() try {
370 492
371 using namespace Vulkan; 493 using namespace Vulkan;
372 494
495 auto* window = this->window()->windowHandle();
496 auto wsi = YuzuQtCommon::GetWindowSystemInfo(window);
497
373 vk::InstanceDispatch dld; 498 vk::InstanceDispatch dld;
374 const Common::DynamicLibrary library = OpenLibrary(); 499 const Common::DynamicLibrary library = OpenLibrary();
375 const vk::Instance instance = CreateInstance(library, dld, VK_API_VERSION_1_1); 500 const vk::Instance instance = CreateInstance(library, dld, VK_API_VERSION_1_1, wsi.type);
376 const std::vector<VkPhysicalDevice> physical_devices = instance.EnumeratePhysicalDevices(); 501 const std::vector<VkPhysicalDevice> physical_devices = instance.EnumeratePhysicalDevices();
502 vk::SurfaceKHR surface = //< needed to view present modes for a device
503 CreateSurface(instance, wsi);
377 504
378 vulkan_devices.clear(); 505 vulkan_devices.clear();
379 vulkan_devices.reserve(physical_devices.size()); 506 vulkan_devices.reserve(physical_devices.size());
507 device_present_modes.clear();
508 device_present_modes.reserve(physical_devices.size());
380 for (const VkPhysicalDevice device : physical_devices) { 509 for (const VkPhysicalDevice device : physical_devices) {
381 const std::string name = vk::PhysicalDevice(device, dld).GetProperties().deviceName; 510 const auto physical_device = vk::PhysicalDevice(device, dld);
511 const std::string name = physical_device.GetProperties().deviceName;
512 const std::vector<VkPresentModeKHR> present_modes =
513 physical_device.GetSurfacePresentModesKHR(*surface);
382 vulkan_devices.push_back(QString::fromStdString(name)); 514 vulkan_devices.push_back(QString::fromStdString(name));
515 device_present_modes.push_back(present_modes);
383 } 516 }
384} catch (const Vulkan::vk::Exception& exception) { 517} catch (const Vulkan::vk::Exception& exception) {
385 LOG_ERROR(Frontend, "Failed to enumerate devices with error: {}", exception.what()); 518 LOG_ERROR(Frontend, "Failed to enumerate devices with error: {}", exception.what());
diff --git a/src/yuzu/configuration/configure_graphics.h b/src/yuzu/configuration/configure_graphics.h
index d98d6624e..6d8002de2 100644
--- a/src/yuzu/configuration/configure_graphics.h
+++ b/src/yuzu/configuration/configure_graphics.h
@@ -7,6 +7,7 @@
7#include <vector> 7#include <vector>
8#include <QString> 8#include <QString>
9#include <QWidget> 9#include <QWidget>
10#include <vulkan/vulkan_core.h>
10#include "common/settings.h" 11#include "common/settings.h"
11 12
12namespace Core { 13namespace Core {
@@ -35,6 +36,7 @@ private:
35 void changeEvent(QEvent* event) override; 36 void changeEvent(QEvent* event) override;
36 void RetranslateUI(); 37 void RetranslateUI();
37 38
39 void PopulateVSyncModeSelection();
38 void UpdateBackgroundColorButton(QColor color); 40 void UpdateBackgroundColorButton(QColor color);
39 void UpdateAPILayout(); 41 void UpdateAPILayout();
40 void UpdateDeviceSelection(int device); 42 void UpdateDeviceSelection(int device);
@@ -43,6 +45,10 @@ private:
43 void RetrieveVulkanDevices(); 45 void RetrieveVulkanDevices();
44 46
45 void SetFSRIndicatorText(int percentage); 47 void SetFSRIndicatorText(int percentage);
48 /* Turns a Vulkan present mode into a textual string for a UI
49 * (and eventually for a human to read) */
50 const QString TranslateVSyncMode(VkPresentModeKHR mode,
51 Settings::RendererBackend backend) const;
46 52
47 void SetupPerGameUI(); 53 void SetupPerGameUI();
48 54
@@ -58,6 +64,10 @@ private:
58 ConfigurationShared::CheckState use_asynchronous_gpu_emulation; 64 ConfigurationShared::CheckState use_asynchronous_gpu_emulation;
59 65
60 std::vector<QString> vulkan_devices; 66 std::vector<QString> vulkan_devices;
67 std::vector<std::vector<VkPresentModeKHR>> device_present_modes;
68 std::vector<VkPresentModeKHR>
69 vsync_mode_combobox_enum_map; //< Keeps track of which present mode corresponds to which
70 // selection in the combobox
61 u32 vulkan_device{}; 71 u32 vulkan_device{};
62 Settings::ShaderBackend shader_backend{}; 72 Settings::ShaderBackend shader_backend{};
63 73
diff --git a/src/yuzu/configuration/configure_graphics.ui b/src/yuzu/configuration/configure_graphics.ui
index 9ad1c88a7..94eba6c7e 100644
--- a/src/yuzu/configuration/configure_graphics.ui
+++ b/src/yuzu/configuration/configure_graphics.ui
@@ -212,24 +212,15 @@
212 </item> 212 </item>
213 <item> 213 <item>
214 <widget class="QComboBox" name="vsync_mode_combobox"> 214 <widget class="QComboBox" name="vsync_mode_combobox">
215 <property name="toolTip">
216 <string>FIFO (V-Sync) does not drop frames or exhibit tearing but is limited by the screen refresh rate.
217FIFO Relaxed is similar to FIFO but allows tearing as it recovers from a slow down.
218Mailbox can have lower latency than FIFO and does not tear but may drop frames.
219Immediate (no synchronization) just presents whatever is available and can exhibit tearing.</string>
220 </property>
215 <property name="currentText"> 221 <property name="currentText">
216 <string>Off (Immediate)</string> 222 <string/>
217 </property> 223 </property>
218 <item>
219 <property name="text">
220 <string>Off (Immediate)</string>
221 </property>
222 </item>
223 <item>
224 <property name="text">
225 <string>Double Buffering (FIFO)</string>
226 </property>
227 </item>
228 <item>
229 <property name="text">
230 <string>Triple Buffering (Mailbox)</string>
231 </property>
232 </item>
233 </widget> 224 </widget>
234 </item> 225 </item>
235 </layout> 226 </layout>