configure_graphics.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. // Copyright 2016 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. // Include this early to include Vulkan headers how we want to
  5. #include "video_core/vulkan_common/vulkan_wrapper.h"
  6. #include <QColorDialog>
  7. #include <QComboBox>
  8. #include <QVulkanInstance>
  9. #include "common/common_types.h"
  10. #include "common/logging/log.h"
  11. #include "common/settings.h"
  12. #include "core/core.h"
  13. #include "ui_configure_graphics.h"
  14. #include "video_core/vulkan_common/vulkan_instance.h"
  15. #include "video_core/vulkan_common/vulkan_library.h"
  16. #include "yuzu/configuration/configuration_shared.h"
  17. #include "yuzu/configuration/configure_graphics.h"
  18. ConfigureGraphics::ConfigureGraphics(QWidget* parent)
  19. : QWidget(parent), ui(new Ui::ConfigureGraphics) {
  20. vulkan_device = Settings::values.vulkan_device.GetValue();
  21. RetrieveVulkanDevices();
  22. ui->setupUi(this);
  23. SetupPerGameUI();
  24. SetConfiguration();
  25. connect(ui->api, qOverload<int>(&QComboBox::currentIndexChanged), this, [this] {
  26. UpdateDeviceComboBox();
  27. if (!Settings::IsConfiguringGlobal()) {
  28. ConfigurationShared::SetHighlight(
  29. ui->api_layout, ui->api->currentIndex() != ConfigurationShared::USE_GLOBAL_INDEX);
  30. }
  31. });
  32. connect(ui->device, qOverload<int>(&QComboBox::activated), this,
  33. [this](int device) { UpdateDeviceSelection(device); });
  34. connect(ui->bg_button, &QPushButton::clicked, this, [this] {
  35. const QColor new_bg_color = QColorDialog::getColor(bg_color);
  36. if (!new_bg_color.isValid()) {
  37. return;
  38. }
  39. UpdateBackgroundColorButton(new_bg_color);
  40. });
  41. ui->bg_label->setVisible(Settings::IsConfiguringGlobal());
  42. ui->bg_combobox->setVisible(!Settings::IsConfiguringGlobal());
  43. }
  44. void ConfigureGraphics::UpdateDeviceSelection(int device) {
  45. if (device == -1) {
  46. return;
  47. }
  48. if (GetCurrentGraphicsBackend() == Settings::RendererBackend::Vulkan) {
  49. vulkan_device = device;
  50. }
  51. }
  52. ConfigureGraphics::~ConfigureGraphics() = default;
  53. void ConfigureGraphics::SetConfiguration() {
  54. const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn();
  55. ui->api->setEnabled(runtime_lock);
  56. ui->use_asynchronous_gpu_emulation->setEnabled(runtime_lock);
  57. ui->use_disk_shader_cache->setEnabled(runtime_lock);
  58. ui->use_nvdec_emulation->setEnabled(runtime_lock);
  59. ui->accelerate_astc->setEnabled(runtime_lock);
  60. ui->use_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache.GetValue());
  61. ui->use_asynchronous_gpu_emulation->setChecked(
  62. Settings::values.use_asynchronous_gpu_emulation.GetValue());
  63. ui->use_nvdec_emulation->setChecked(Settings::values.use_nvdec_emulation.GetValue());
  64. ui->accelerate_astc->setChecked(Settings::values.accelerate_astc.GetValue());
  65. if (Settings::IsConfiguringGlobal()) {
  66. ui->api->setCurrentIndex(static_cast<int>(Settings::values.renderer_backend.GetValue()));
  67. ui->fullscreen_mode_combobox->setCurrentIndex(Settings::values.fullscreen_mode.GetValue());
  68. ui->aspect_ratio_combobox->setCurrentIndex(Settings::values.aspect_ratio.GetValue());
  69. } else {
  70. ConfigurationShared::SetPerGameSetting(ui->api, &Settings::values.renderer_backend);
  71. ConfigurationShared::SetHighlight(ui->api_layout,
  72. !Settings::values.renderer_backend.UsingGlobal());
  73. ConfigurationShared::SetPerGameSetting(ui->fullscreen_mode_combobox,
  74. &Settings::values.fullscreen_mode);
  75. ConfigurationShared::SetHighlight(ui->fullscreen_mode_label,
  76. !Settings::values.fullscreen_mode.UsingGlobal());
  77. ConfigurationShared::SetPerGameSetting(ui->aspect_ratio_combobox,
  78. &Settings::values.aspect_ratio);
  79. ConfigurationShared::SetHighlight(ui->ar_label,
  80. !Settings::values.aspect_ratio.UsingGlobal());
  81. ui->bg_combobox->setCurrentIndex(Settings::values.bg_red.UsingGlobal() ? 0 : 1);
  82. ui->bg_button->setEnabled(!Settings::values.bg_red.UsingGlobal());
  83. ConfigurationShared::SetHighlight(ui->bg_layout, !Settings::values.bg_red.UsingGlobal());
  84. }
  85. UpdateBackgroundColorButton(QColor::fromRgb(Settings::values.bg_red.GetValue(),
  86. Settings::values.bg_green.GetValue(),
  87. Settings::values.bg_blue.GetValue()));
  88. UpdateDeviceComboBox();
  89. }
  90. void ConfigureGraphics::ApplyConfiguration() {
  91. ConfigurationShared::ApplyPerGameSetting(&Settings::values.fullscreen_mode,
  92. ui->fullscreen_mode_combobox);
  93. ConfigurationShared::ApplyPerGameSetting(&Settings::values.aspect_ratio,
  94. ui->aspect_ratio_combobox);
  95. ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_disk_shader_cache,
  96. ui->use_disk_shader_cache, use_disk_shader_cache);
  97. ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_gpu_emulation,
  98. ui->use_asynchronous_gpu_emulation,
  99. use_asynchronous_gpu_emulation);
  100. ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_nvdec_emulation,
  101. ui->use_nvdec_emulation, use_nvdec_emulation);
  102. ConfigurationShared::ApplyPerGameSetting(&Settings::values.accelerate_astc, ui->accelerate_astc,
  103. accelerate_astc);
  104. if (Settings::IsConfiguringGlobal()) {
  105. // Guard if during game and set to game-specific value
  106. if (Settings::values.renderer_backend.UsingGlobal()) {
  107. Settings::values.renderer_backend.SetValue(GetCurrentGraphicsBackend());
  108. }
  109. if (Settings::values.vulkan_device.UsingGlobal()) {
  110. Settings::values.vulkan_device.SetValue(vulkan_device);
  111. }
  112. if (Settings::values.bg_red.UsingGlobal()) {
  113. Settings::values.bg_red.SetValue(static_cast<u8>(bg_color.red()));
  114. Settings::values.bg_green.SetValue(static_cast<u8>(bg_color.green()));
  115. Settings::values.bg_blue.SetValue(static_cast<u8>(bg_color.blue()));
  116. }
  117. } else {
  118. if (ui->api->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) {
  119. Settings::values.renderer_backend.SetGlobal(true);
  120. Settings::values.vulkan_device.SetGlobal(true);
  121. } else {
  122. Settings::values.renderer_backend.SetGlobal(false);
  123. Settings::values.renderer_backend.SetValue(GetCurrentGraphicsBackend());
  124. if (GetCurrentGraphicsBackend() == Settings::RendererBackend::Vulkan) {
  125. Settings::values.vulkan_device.SetGlobal(false);
  126. Settings::values.vulkan_device.SetValue(vulkan_device);
  127. } else {
  128. Settings::values.vulkan_device.SetGlobal(true);
  129. }
  130. }
  131. if (ui->bg_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) {
  132. Settings::values.bg_red.SetGlobal(true);
  133. Settings::values.bg_green.SetGlobal(true);
  134. Settings::values.bg_blue.SetGlobal(true);
  135. } else {
  136. Settings::values.bg_red.SetGlobal(false);
  137. Settings::values.bg_green.SetGlobal(false);
  138. Settings::values.bg_blue.SetGlobal(false);
  139. Settings::values.bg_red.SetValue(static_cast<u8>(bg_color.red()));
  140. Settings::values.bg_green.SetValue(static_cast<u8>(bg_color.green()));
  141. Settings::values.bg_blue.SetValue(static_cast<u8>(bg_color.blue()));
  142. }
  143. }
  144. }
  145. void ConfigureGraphics::changeEvent(QEvent* event) {
  146. if (event->type() == QEvent::LanguageChange) {
  147. RetranslateUI();
  148. }
  149. QWidget::changeEvent(event);
  150. }
  151. void ConfigureGraphics::RetranslateUI() {
  152. ui->retranslateUi(this);
  153. }
  154. void ConfigureGraphics::UpdateBackgroundColorButton(QColor color) {
  155. bg_color = color;
  156. QPixmap pixmap(ui->bg_button->size());
  157. pixmap.fill(bg_color);
  158. const QIcon color_icon(pixmap);
  159. ui->bg_button->setIcon(color_icon);
  160. }
  161. void ConfigureGraphics::UpdateDeviceComboBox() {
  162. ui->device->clear();
  163. bool enabled = false;
  164. if (!Settings::IsConfiguringGlobal() &&
  165. ui->api->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) {
  166. vulkan_device = Settings::values.vulkan_device.GetValue();
  167. }
  168. switch (GetCurrentGraphicsBackend()) {
  169. case Settings::RendererBackend::OpenGL:
  170. ui->device->addItem(tr("OpenGL Graphics Device"));
  171. enabled = false;
  172. break;
  173. case Settings::RendererBackend::Vulkan:
  174. for (const auto& device : vulkan_devices) {
  175. ui->device->addItem(device);
  176. }
  177. ui->device->setCurrentIndex(vulkan_device);
  178. enabled = !vulkan_devices.empty();
  179. break;
  180. }
  181. // If in per-game config and use global is selected, don't enable.
  182. enabled &= !(!Settings::IsConfiguringGlobal() &&
  183. ui->api->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX);
  184. ui->device->setEnabled(enabled && !Core::System::GetInstance().IsPoweredOn());
  185. }
  186. void ConfigureGraphics::RetrieveVulkanDevices() try {
  187. using namespace Vulkan;
  188. vk::InstanceDispatch dld;
  189. const Common::DynamicLibrary library = OpenLibrary();
  190. const vk::Instance instance = CreateInstance(library, dld, VK_API_VERSION_1_0);
  191. const std::vector<VkPhysicalDevice> physical_devices = instance.EnumeratePhysicalDevices();
  192. vulkan_devices.clear();
  193. vulkan_devices.reserve(physical_devices.size());
  194. for (const VkPhysicalDevice device : physical_devices) {
  195. const std::string name = vk::PhysicalDevice(device, dld).GetProperties().deviceName;
  196. vulkan_devices.push_back(QString::fromStdString(name));
  197. }
  198. } catch (const Vulkan::vk::Exception& exception) {
  199. LOG_ERROR(Frontend, "Failed to enumerate devices with error: {}", exception.what());
  200. }
  201. Settings::RendererBackend ConfigureGraphics::GetCurrentGraphicsBackend() const {
  202. if (Settings::IsConfiguringGlobal()) {
  203. return static_cast<Settings::RendererBackend>(ui->api->currentIndex());
  204. }
  205. if (ui->api->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) {
  206. Settings::values.renderer_backend.SetGlobal(true);
  207. return Settings::values.renderer_backend.GetValue();
  208. }
  209. Settings::values.renderer_backend.SetGlobal(false);
  210. return static_cast<Settings::RendererBackend>(ui->api->currentIndex() -
  211. ConfigurationShared::USE_GLOBAL_OFFSET);
  212. }
  213. void ConfigureGraphics::SetupPerGameUI() {
  214. if (Settings::IsConfiguringGlobal()) {
  215. ui->api->setEnabled(Settings::values.renderer_backend.UsingGlobal());
  216. ui->device->setEnabled(Settings::values.renderer_backend.UsingGlobal());
  217. ui->fullscreen_mode_combobox->setEnabled(Settings::values.fullscreen_mode.UsingGlobal());
  218. ui->aspect_ratio_combobox->setEnabled(Settings::values.aspect_ratio.UsingGlobal());
  219. ui->use_asynchronous_gpu_emulation->setEnabled(
  220. Settings::values.use_asynchronous_gpu_emulation.UsingGlobal());
  221. ui->use_nvdec_emulation->setEnabled(Settings::values.use_nvdec_emulation.UsingGlobal());
  222. ui->accelerate_astc->setEnabled(Settings::values.accelerate_astc.UsingGlobal());
  223. ui->use_disk_shader_cache->setEnabled(Settings::values.use_disk_shader_cache.UsingGlobal());
  224. ui->bg_button->setEnabled(Settings::values.bg_red.UsingGlobal());
  225. return;
  226. }
  227. connect(ui->bg_combobox, qOverload<int>(&QComboBox::activated), this, [this](int index) {
  228. ui->bg_button->setEnabled(index == 1);
  229. ConfigurationShared::SetHighlight(ui->bg_layout, index == 1);
  230. });
  231. ConfigurationShared::SetColoredTristate(
  232. ui->use_disk_shader_cache, Settings::values.use_disk_shader_cache, use_disk_shader_cache);
  233. ConfigurationShared::SetColoredTristate(
  234. ui->use_nvdec_emulation, Settings::values.use_nvdec_emulation, use_nvdec_emulation);
  235. ConfigurationShared::SetColoredTristate(ui->accelerate_astc, Settings::values.accelerate_astc,
  236. accelerate_astc);
  237. ConfigurationShared::SetColoredTristate(ui->use_asynchronous_gpu_emulation,
  238. Settings::values.use_asynchronous_gpu_emulation,
  239. use_asynchronous_gpu_emulation);
  240. ConfigurationShared::SetColoredComboBox(ui->aspect_ratio_combobox, ui->ar_label,
  241. Settings::values.aspect_ratio.GetValue(true));
  242. ConfigurationShared::SetColoredComboBox(ui->fullscreen_mode_combobox, ui->fullscreen_mode_label,
  243. Settings::values.fullscreen_mode.GetValue(true));
  244. ConfigurationShared::InsertGlobalItem(
  245. ui->api, static_cast<int>(Settings::values.renderer_backend.GetValue(true)));
  246. }