configure_graphics.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. // Copyright 2016 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <QColorDialog>
  5. #include <QComboBox>
  6. #ifdef HAS_VULKAN
  7. #include <QVulkanInstance>
  8. #endif
  9. #include "common/common_types.h"
  10. #include "common/logging/log.h"
  11. #include "core/core.h"
  12. #include "core/settings.h"
  13. #include "ui_configure_graphics.h"
  14. #include "yuzu/configuration/configure_graphics.h"
  15. namespace {
  16. enum class Resolution : int {
  17. Auto,
  18. Scale1x,
  19. Scale2x,
  20. Scale3x,
  21. Scale4x,
  22. };
  23. float ToResolutionFactor(Resolution option) {
  24. switch (option) {
  25. case Resolution::Auto:
  26. return 0.f;
  27. case Resolution::Scale1x:
  28. return 1.f;
  29. case Resolution::Scale2x:
  30. return 2.f;
  31. case Resolution::Scale3x:
  32. return 3.f;
  33. case Resolution::Scale4x:
  34. return 4.f;
  35. }
  36. return 0.f;
  37. }
  38. Resolution FromResolutionFactor(float factor) {
  39. if (factor == 0.f) {
  40. return Resolution::Auto;
  41. } else if (factor == 1.f) {
  42. return Resolution::Scale1x;
  43. } else if (factor == 2.f) {
  44. return Resolution::Scale2x;
  45. } else if (factor == 3.f) {
  46. return Resolution::Scale3x;
  47. } else if (factor == 4.f) {
  48. return Resolution::Scale4x;
  49. }
  50. return Resolution::Auto;
  51. }
  52. } // Anonymous namespace
  53. ConfigureGraphics::ConfigureGraphics(QWidget* parent)
  54. : QWidget(parent), ui(new Ui::ConfigureGraphics) {
  55. vulkan_device = Settings::values.vulkan_device;
  56. RetrieveVulkanDevices();
  57. ui->setupUi(this);
  58. SetConfiguration();
  59. connect(ui->api, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
  60. [this] { UpdateDeviceComboBox(); });
  61. connect(ui->device, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this,
  62. [this](int device) { UpdateDeviceSelection(device); });
  63. connect(ui->bg_button, &QPushButton::clicked, this, [this] {
  64. const QColor new_bg_color = QColorDialog::getColor(bg_color);
  65. if (!new_bg_color.isValid()) {
  66. return;
  67. }
  68. UpdateBackgroundColorButton(new_bg_color);
  69. });
  70. }
  71. void ConfigureGraphics::UpdateDeviceSelection(int device) {
  72. if (device == -1) {
  73. return;
  74. }
  75. if (GetCurrentGraphicsBackend() == Settings::RendererBackend::Vulkan) {
  76. vulkan_device = device;
  77. }
  78. }
  79. ConfigureGraphics::~ConfigureGraphics() = default;
  80. void ConfigureGraphics::SetConfiguration() {
  81. const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn();
  82. ui->api->setEnabled(runtime_lock);
  83. ui->api->setCurrentIndex(static_cast<int>(Settings::values.renderer_backend));
  84. ui->resolution_factor_combobox->setCurrentIndex(
  85. static_cast<int>(FromResolutionFactor(Settings::values.resolution_factor)));
  86. ui->use_disk_shader_cache->setEnabled(runtime_lock);
  87. ui->use_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache);
  88. ui->use_accurate_gpu_emulation->setChecked(Settings::values.use_accurate_gpu_emulation);
  89. ui->use_asynchronous_gpu_emulation->setEnabled(runtime_lock);
  90. ui->use_asynchronous_gpu_emulation->setChecked(Settings::values.use_asynchronous_gpu_emulation);
  91. ui->force_30fps_mode->setEnabled(runtime_lock);
  92. ui->force_30fps_mode->setChecked(Settings::values.force_30fps_mode);
  93. UpdateBackgroundColorButton(QColor::fromRgbF(Settings::values.bg_red, Settings::values.bg_green,
  94. Settings::values.bg_blue));
  95. UpdateDeviceComboBox();
  96. }
  97. void ConfigureGraphics::ApplyConfiguration() {
  98. Settings::values.renderer_backend = GetCurrentGraphicsBackend();
  99. Settings::values.vulkan_device = vulkan_device;
  100. Settings::values.resolution_factor =
  101. ToResolutionFactor(static_cast<Resolution>(ui->resolution_factor_combobox->currentIndex()));
  102. Settings::values.use_disk_shader_cache = ui->use_disk_shader_cache->isChecked();
  103. Settings::values.use_accurate_gpu_emulation = ui->use_accurate_gpu_emulation->isChecked();
  104. Settings::values.use_asynchronous_gpu_emulation =
  105. ui->use_asynchronous_gpu_emulation->isChecked();
  106. Settings::values.force_30fps_mode = ui->force_30fps_mode->isChecked();
  107. Settings::values.bg_red = static_cast<float>(bg_color.redF());
  108. Settings::values.bg_green = static_cast<float>(bg_color.greenF());
  109. Settings::values.bg_blue = static_cast<float>(bg_color.blueF());
  110. }
  111. void ConfigureGraphics::changeEvent(QEvent* event) {
  112. if (event->type() == QEvent::LanguageChange) {
  113. RetranslateUI();
  114. }
  115. QWidget::changeEvent(event);
  116. }
  117. void ConfigureGraphics::RetranslateUI() {
  118. ui->retranslateUi(this);
  119. }
  120. void ConfigureGraphics::UpdateBackgroundColorButton(QColor color) {
  121. bg_color = color;
  122. QPixmap pixmap(ui->bg_button->size());
  123. pixmap.fill(bg_color);
  124. const QIcon color_icon(pixmap);
  125. ui->bg_button->setIcon(color_icon);
  126. }
  127. void ConfigureGraphics::UpdateDeviceComboBox() {
  128. ui->device->clear();
  129. bool enabled = false;
  130. switch (GetCurrentGraphicsBackend()) {
  131. case Settings::RendererBackend::OpenGL:
  132. ui->device->addItem(tr("OpenGL Graphics Device"));
  133. enabled = false;
  134. break;
  135. case Settings::RendererBackend::Vulkan:
  136. for (const auto device : vulkan_devices) {
  137. ui->device->addItem(device);
  138. }
  139. ui->device->setCurrentIndex(vulkan_device);
  140. enabled = !vulkan_devices.empty();
  141. break;
  142. }
  143. ui->device->setEnabled(enabled && !Core::System::GetInstance().IsPoweredOn());
  144. }
  145. void ConfigureGraphics::RetrieveVulkanDevices() {
  146. #ifdef HAS_VULKAN
  147. QVulkanInstance instance;
  148. instance.setApiVersion(QVersionNumber(1, 1, 0));
  149. if (!instance.create()) {
  150. LOG_INFO(Frontend, "Vulkan 1.1 not available");
  151. return;
  152. }
  153. const auto vkEnumeratePhysicalDevices{reinterpret_cast<PFN_vkEnumeratePhysicalDevices>(
  154. instance.getInstanceProcAddr("vkEnumeratePhysicalDevices"))};
  155. if (vkEnumeratePhysicalDevices == nullptr) {
  156. LOG_INFO(Frontend, "Failed to get pointer to vkEnumeratePhysicalDevices");
  157. return;
  158. }
  159. u32 physical_device_count;
  160. if (vkEnumeratePhysicalDevices(instance.vkInstance(), &physical_device_count, nullptr) !=
  161. VK_SUCCESS) {
  162. LOG_INFO(Frontend, "Failed to get physical devices count");
  163. return;
  164. }
  165. std::vector<VkPhysicalDevice> physical_devices(physical_device_count);
  166. if (vkEnumeratePhysicalDevices(instance.vkInstance(), &physical_device_count,
  167. physical_devices.data()) != VK_SUCCESS) {
  168. LOG_INFO(Frontend, "Failed to get physical devices");
  169. return;
  170. }
  171. const auto vkGetPhysicalDeviceProperties{reinterpret_cast<PFN_vkGetPhysicalDeviceProperties>(
  172. instance.getInstanceProcAddr("vkGetPhysicalDeviceProperties"))};
  173. if (vkGetPhysicalDeviceProperties == nullptr) {
  174. LOG_INFO(Frontend, "Failed to get pointer to vkGetPhysicalDeviceProperties");
  175. return;
  176. }
  177. for (const auto physical_device : physical_devices) {
  178. VkPhysicalDeviceProperties properties;
  179. vkGetPhysicalDeviceProperties(physical_device, &properties);
  180. vulkan_devices.push_back(QString::fromUtf8(properties.deviceName));
  181. }
  182. #endif
  183. }
  184. Settings::RendererBackend ConfigureGraphics::GetCurrentGraphicsBackend() const {
  185. return static_cast<Settings::RendererBackend>(ui->api->currentIndex());
  186. }