summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/yuzu/configuration/config.cpp8
-rw-r--r--src/yuzu/configuration/configure_graphics.cpp37
-rw-r--r--src/yuzu/configuration/configure_graphics.h2
-rw-r--r--src/yuzu/configuration/configure_graphics.ui9
-rw-r--r--src/yuzu/main.cpp30
-rw-r--r--src/yuzu/main.h2
-rw-r--r--src/yuzu/startup_checks.cpp78
-rw-r--r--src/yuzu/startup_checks.h12
-rw-r--r--src/yuzu/uisettings.h2
9 files changed, 65 insertions, 115 deletions
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 9686412d0..ca10e9f23 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -682,12 +682,6 @@ void Config::ReadRendererValues() {
682 ReadGlobalSetting(Settings::values.bg_green); 682 ReadGlobalSetting(Settings::values.bg_green);
683 ReadGlobalSetting(Settings::values.bg_blue); 683 ReadGlobalSetting(Settings::values.bg_blue);
684 684
685 if (!global && UISettings::values.has_broken_vulkan &&
686 Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::Vulkan &&
687 !Settings::values.renderer_backend.UsingGlobal()) {
688 Settings::values.renderer_backend.SetGlobal(true);
689 }
690
691 if (global) { 685 if (global) {
692 ReadBasicSetting(Settings::values.renderer_debug); 686 ReadBasicSetting(Settings::values.renderer_debug);
693 ReadBasicSetting(Settings::values.renderer_shader_feedback); 687 ReadBasicSetting(Settings::values.renderer_shader_feedback);
@@ -807,7 +801,6 @@ void Config::ReadUIValues() {
807 ReadBasicSetting(UISettings::values.pause_when_in_background); 801 ReadBasicSetting(UISettings::values.pause_when_in_background);
808 ReadBasicSetting(UISettings::values.mute_when_in_background); 802 ReadBasicSetting(UISettings::values.mute_when_in_background);
809 ReadBasicSetting(UISettings::values.hide_mouse); 803 ReadBasicSetting(UISettings::values.hide_mouse);
810 ReadBasicSetting(UISettings::values.has_broken_vulkan);
811 ReadBasicSetting(UISettings::values.disable_web_applet); 804 ReadBasicSetting(UISettings::values.disable_web_applet);
812 805
813 qt_config->endGroup(); 806 qt_config->endGroup();
@@ -1355,7 +1348,6 @@ void Config::SaveUIValues() {
1355 WriteBasicSetting(UISettings::values.pause_when_in_background); 1348 WriteBasicSetting(UISettings::values.pause_when_in_background);
1356 WriteBasicSetting(UISettings::values.mute_when_in_background); 1349 WriteBasicSetting(UISettings::values.mute_when_in_background);
1357 WriteBasicSetting(UISettings::values.hide_mouse); 1350 WriteBasicSetting(UISettings::values.hide_mouse);
1358 WriteBasicSetting(UISettings::values.has_broken_vulkan);
1359 WriteBasicSetting(UISettings::values.disable_web_applet); 1351 WriteBasicSetting(UISettings::values.disable_web_applet);
1360 1352
1361 qt_config->endGroup(); 1353 qt_config->endGroup();
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp
index 85f34dc35..6b33c4535 100644
--- a/src/yuzu/configuration/configure_graphics.cpp
+++ b/src/yuzu/configuration/configure_graphics.cpp
@@ -58,24 +58,9 @@ ConfigureGraphics::ConfigureGraphics(const Core::System& system_, QWidget* paren
58 UpdateBackgroundColorButton(new_bg_color); 58 UpdateBackgroundColorButton(new_bg_color);
59 }); 59 });
60 60
61 connect(ui->button_check_vulkan, &QAbstractButton::clicked, this, [this] { 61 ui->api->setEnabled(!UISettings::values.has_broken_vulkan);
62 UISettings::values.has_broken_vulkan = false; 62 ui->api_widget->setEnabled(!UISettings::values.has_broken_vulkan ||
63 63 Settings::IsConfiguringGlobal());
64 if (RetrieveVulkanDevices()) {
65 ui->api->setEnabled(true);
66 ui->button_check_vulkan->hide();
67
68 for (const auto& device : vulkan_devices) {
69 ui->device->addItem(device);
70 }
71 } else {
72 UISettings::values.has_broken_vulkan = true;
73 }
74 });
75
76 ui->api->setEnabled(!UISettings::values.has_broken_vulkan.GetValue());
77 ui->button_check_vulkan->setVisible(UISettings::values.has_broken_vulkan.GetValue());
78
79 ui->bg_label->setVisible(Settings::IsConfiguringGlobal()); 64 ui->bg_label->setVisible(Settings::IsConfiguringGlobal());
80 ui->bg_combobox->setVisible(!Settings::IsConfiguringGlobal()); 65 ui->bg_combobox->setVisible(!Settings::IsConfiguringGlobal());
81} 66}
@@ -315,7 +300,7 @@ void ConfigureGraphics::UpdateAPILayout() {
315 vulkan_device = Settings::values.vulkan_device.GetValue(true); 300 vulkan_device = Settings::values.vulkan_device.GetValue(true);
316 shader_backend = Settings::values.shader_backend.GetValue(true); 301 shader_backend = Settings::values.shader_backend.GetValue(true);
317 ui->device_widget->setEnabled(false); 302 ui->device_widget->setEnabled(false);
318 ui->backend_widget->setEnabled(UISettings::values.has_broken_vulkan.GetValue()); 303 ui->backend_widget->setEnabled(false);
319 } else { 304 } else {
320 vulkan_device = Settings::values.vulkan_device.GetValue(); 305 vulkan_device = Settings::values.vulkan_device.GetValue();
321 shader_backend = Settings::values.shader_backend.GetValue(); 306 shader_backend = Settings::values.shader_backend.GetValue();
@@ -337,9 +322,9 @@ void ConfigureGraphics::UpdateAPILayout() {
337 } 322 }
338} 323}
339 324
340bool ConfigureGraphics::RetrieveVulkanDevices() try { 325void ConfigureGraphics::RetrieveVulkanDevices() try {
341 if (UISettings::values.has_broken_vulkan) { 326 if (UISettings::values.has_broken_vulkan) {
342 return false; 327 return;
343 } 328 }
344 329
345 using namespace Vulkan; 330 using namespace Vulkan;
@@ -355,11 +340,8 @@ bool ConfigureGraphics::RetrieveVulkanDevices() try {
355 const std::string name = vk::PhysicalDevice(device, dld).GetProperties().deviceName; 340 const std::string name = vk::PhysicalDevice(device, dld).GetProperties().deviceName;
356 vulkan_devices.push_back(QString::fromStdString(name)); 341 vulkan_devices.push_back(QString::fromStdString(name));
357 } 342 }
358
359 return true;
360} catch (const Vulkan::vk::Exception& exception) { 343} catch (const Vulkan::vk::Exception& exception) {
361 LOG_ERROR(Frontend, "Failed to enumerate devices with error: {}", exception.what()); 344 LOG_ERROR(Frontend, "Failed to enumerate devices with error: {}", exception.what());
362 return false;
363} 345}
364 346
365Settings::RendererBackend ConfigureGraphics::GetCurrentGraphicsBackend() const { 347Settings::RendererBackend ConfigureGraphics::GetCurrentGraphicsBackend() const {
@@ -440,11 +422,4 @@ void ConfigureGraphics::SetupPerGameUI() {
440 ui->api, static_cast<int>(Settings::values.renderer_backend.GetValue(true))); 422 ui->api, static_cast<int>(Settings::values.renderer_backend.GetValue(true)));
441 ConfigurationShared::InsertGlobalItem( 423 ConfigurationShared::InsertGlobalItem(
442 ui->nvdec_emulation, static_cast<int>(Settings::values.nvdec_emulation.GetValue(true))); 424 ui->nvdec_emulation, static_cast<int>(Settings::values.nvdec_emulation.GetValue(true)));
443
444 if (UISettings::values.has_broken_vulkan) {
445 ui->backend_widget->setEnabled(true);
446 ConfigurationShared::SetColoredComboBox(
447 ui->backend, ui->backend_widget,
448 static_cast<int>(Settings::values.shader_backend.GetValue(true)));
449 }
450} 425}
diff --git a/src/yuzu/configuration/configure_graphics.h b/src/yuzu/configuration/configure_graphics.h
index 8438f0187..1b101c940 100644
--- a/src/yuzu/configuration/configure_graphics.h
+++ b/src/yuzu/configuration/configure_graphics.h
@@ -41,7 +41,7 @@ private:
41 void UpdateDeviceSelection(int device); 41 void UpdateDeviceSelection(int device);
42 void UpdateShaderBackendSelection(int backend); 42 void UpdateShaderBackendSelection(int backend);
43 43
44 bool RetrieveVulkanDevices(); 44 void RetrieveVulkanDevices();
45 45
46 void SetupPerGameUI(); 46 void SetupPerGameUI();
47 47
diff --git a/src/yuzu/configuration/configure_graphics.ui b/src/yuzu/configuration/configure_graphics.ui
index 2f94c94bc..1e4f74704 100644
--- a/src/yuzu/configuration/configure_graphics.ui
+++ b/src/yuzu/configuration/configure_graphics.ui
@@ -6,7 +6,7 @@
6 <rect> 6 <rect>
7 <x>0</x> 7 <x>0</x>
8 <y>0</y> 8 <y>0</y>
9 <width>471</width> 9 <width>541</width>
10 <height>759</height> 10 <height>759</height>
11 </rect> 11 </rect>
12 </property> 12 </property>
@@ -574,13 +574,6 @@
574 </property> 574 </property>
575 </spacer> 575 </spacer>
576 </item> 576 </item>
577 <item>
578 <widget class="QPushButton" name="button_check_vulkan">
579 <property name="text">
580 <string>Check for Working Vulkan</string>
581 </property>
582 </widget>
583 </item>
584 </layout> 577 </layout>
585 </widget> 578 </widget>
586 <resources/> 579 <resources/>
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index f2e449560..a2b11fdbf 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -252,7 +252,7 @@ static QString PrettyProductName() {
252 return QSysInfo::prettyProductName(); 252 return QSysInfo::prettyProductName();
253} 253}
254 254
255GMainWindow::GMainWindow() 255GMainWindow::GMainWindow(bool has_broken_vulkan)
256 : ui{std::make_unique<Ui::MainWindow>()}, system{std::make_unique<Core::System>()}, 256 : ui{std::make_unique<Ui::MainWindow>()}, system{std::make_unique<Core::System>()},
257 input_subsystem{std::make_shared<InputCommon::InputSubsystem>()}, 257 input_subsystem{std::make_shared<InputCommon::InputSubsystem>()},
258 config{std::make_unique<Config>(*system)}, 258 config{std::make_unique<Config>(*system)},
@@ -352,17 +352,15 @@ GMainWindow::GMainWindow()
352 352
353 MigrateConfigFiles(); 353 MigrateConfigFiles();
354 354
355 if (!CheckVulkan()) { 355 if (has_broken_vulkan) {
356 config->Save(); 356 UISettings::values.has_broken_vulkan = true;
357
358 QMessageBox::warning(this, tr("Broken Vulkan Installation Detected"),
359 tr("Vulkan initialization failed during boot.<br><br>Click <a "
360 "href='https://yuzu-emu.org/wiki/faq/"
361 "#yuzu-starts-with-the-error-broken-vulkan-installation-detected'>"
362 "here for instructions to fix the issue</a>."));
357 363
358 QMessageBox::warning(
359 this, tr("Broken Vulkan Installation Detected"),
360 tr("Vulkan initialization failed on the previous boot.<br><br>Click <a "
361 "href='https://yuzu-emu.org/wiki/faq/"
362 "#yuzu-starts-with-the-error-broken-vulkan-installation-detected'>here for "
363 "instructions to fix the issue</a>."));
364 }
365 if (UISettings::values.has_broken_vulkan) {
366 Settings::values.renderer_backend = Settings::RendererBackend::OpenGL; 364 Settings::values.renderer_backend = Settings::RendererBackend::OpenGL;
367 365
368 renderer_status_button->setDisabled(true); 366 renderer_status_button->setDisabled(true);
@@ -3853,17 +3851,17 @@ void GMainWindow::SetDiscordEnabled([[maybe_unused]] bool state) {
3853#endif 3851#endif
3854 3852
3855int main(int argc, char* argv[]) { 3853int main(int argc, char* argv[]) {
3854 bool has_broken_vulkan = false;
3856#ifdef _WIN32 3855#ifdef _WIN32
3857 char variable_contents[32]; 3856 char variable_contents[32];
3858 const DWORD startup_check_var = 3857 const DWORD startup_check_var =
3859 GetEnvironmentVariable(STARTUP_CHECK_ENV_VAR, variable_contents, 32); 3858 GetEnvironmentVariable(STARTUP_CHECK_ENV_VAR, variable_contents, 32);
3860 if (startup_check_var != 0) { 3859 const std::string variable_contents_s{variable_contents};
3861 std::fprintf(stderr, "perform statup checks\n"); 3860 if (startup_check_var > 0 && variable_contents_s == "ON") {
3862 CheckVulkan(); 3861 CheckVulkan();
3863 return 0; 3862 return 0;
3864 } else {
3865 std::fprintf(stderr, "%d\n", StartupChecks());
3866 } 3863 }
3864 StartupChecks(argv[0], &has_broken_vulkan);
3867#elif YUZU_UNIX 3865#elif YUZU_UNIX
3868#error "Unimplemented" 3866#error "Unimplemented"
3869#endif 3867#endif
@@ -3907,7 +3905,7 @@ int main(int argc, char* argv[]) {
3907 // generating shaders 3905 // generating shaders
3908 setlocale(LC_ALL, "C"); 3906 setlocale(LC_ALL, "C");
3909 3907
3910 GMainWindow main_window{}; 3908 GMainWindow main_window{has_broken_vulkan};
3911 // After settings have been loaded by GMainWindow, apply the filter 3909 // After settings have been loaded by GMainWindow, apply the filter
3912 main_window.show(); 3910 main_window.show();
3913 3911
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 8cf224c9c..7df656002 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -118,7 +118,7 @@ class GMainWindow : public QMainWindow {
118public: 118public:
119 void filterBarSetChecked(bool state); 119 void filterBarSetChecked(bool state);
120 void UpdateUITheme(); 120 void UpdateUITheme();
121 explicit GMainWindow(); 121 explicit GMainWindow(bool has_broken_vulkan);
122 ~GMainWindow() override; 122 ~GMainWindow() override;
123 123
124 bool DropAction(QDropEvent* event); 124 bool DropAction(QDropEvent* event);
diff --git a/src/yuzu/startup_checks.cpp b/src/yuzu/startup_checks.cpp
index cfd14a6d5..c860f0aa0 100644
--- a/src/yuzu/startup_checks.cpp
+++ b/src/yuzu/startup_checks.cpp
@@ -22,29 +22,7 @@
22#include "yuzu/startup_checks.h" 22#include "yuzu/startup_checks.h"
23#include "yuzu/uisettings.h" 23#include "yuzu/uisettings.h"
24 24
25constexpr char TEMP_FILE_NAME[] = "vulkan_check"; 25void CheckVulkan() {
26
27bool CheckVulkan() {
28 if (UISettings::values.has_broken_vulkan) {
29 return true;
30 }
31
32 LOG_DEBUG(Frontend, "Checking presence of Vulkan");
33
34 const auto fs_config_loc = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir);
35 const auto temp_file_loc = fs_config_loc / TEMP_FILE_NAME;
36
37 if (std::filesystem::exists(temp_file_loc)) {
38 LOG_WARNING(Frontend, "Detected recovery from previous failed Vulkan initialization");
39
40 UISettings::values.has_broken_vulkan = true;
41 std::filesystem::remove(temp_file_loc);
42 return false;
43 }
44
45 std::ofstream temp_file_handle(temp_file_loc);
46 temp_file_handle.close();
47
48 try { 26 try {
49 Vulkan::vk::InstanceDispatch dld; 27 Vulkan::vk::InstanceDispatch dld;
50 const Common::DynamicLibrary library = Vulkan::OpenLibrary(); 28 const Common::DynamicLibrary library = Vulkan::OpenLibrary();
@@ -53,32 +31,48 @@ bool CheckVulkan() {
53 31
54 } catch (const Vulkan::vk::Exception& exception) { 32 } catch (const Vulkan::vk::Exception& exception) {
55 LOG_ERROR(Frontend, "Failed to initialize Vulkan: {}", exception.what()); 33 LOG_ERROR(Frontend, "Failed to initialize Vulkan: {}", exception.what());
56 // Don't set has_broken_vulkan to true here: we care when loading Vulkan crashes the
57 // application, not when we can handle it.
58 } 34 }
59
60 std::filesystem::remove(temp_file_loc);
61 return true;
62} 35}
63 36
64bool StartupChecks() { 37bool StartupChecks(const char* arg0, bool* has_broken_vulkan) {
65#ifdef _WIN32 38#ifdef _WIN32
66 const bool env_var_set = SetEnvironmentVariableA(STARTUP_CHECK_ENV_VAR, "ON"); 39 const bool env_var_set = SetEnvironmentVariableA(STARTUP_CHECK_ENV_VAR, "ON");
67 if (!env_var_set) { 40 if (!env_var_set) {
68 LOG_ERROR(Frontend, "SetEnvironmentVariableA failed to set {}, {}", STARTUP_CHECK_ENV_VAR, 41 std::fprintf(stderr, "SetEnvironmentVariableA failed to set %s, %d\n",
69 GetLastError()); 42 STARTUP_CHECK_ENV_VAR, GetLastError());
70 return false; 43 return false;
71 } 44 }
72 45
73 STARTUPINFOA startup_info;
74 PROCESS_INFORMATION process_info; 46 PROCESS_INFORMATION process_info;
47 std::memset(&process_info, '\0', sizeof(process_info));
48
49 if (!SpawnChild(arg0, &process_info)) {
50 return false;
51 }
52
53 // wait until the processs exits
54 DWORD exit_code = STILL_ACTIVE;
55 while (exit_code == STILL_ACTIVE) {
56 GetExitCodeProcess(process_info.hProcess, &exit_code);
57 }
58
59 *has_broken_vulkan = (exit_code != 0);
60
61 CloseHandle(process_info.hProcess);
62 CloseHandle(process_info.hThread);
63#endif
64 return true;
65}
66
67#ifdef _WIN32
68bool SpawnChild(const char* arg0, PROCESS_INFORMATION* pi) {
69 STARTUPINFOA startup_info;
75 70
76 std::memset(&startup_info, '\0', sizeof(startup_info)); 71 std::memset(&startup_info, '\0', sizeof(startup_info));
77 std::memset(&process_info, '\0', sizeof(process_info));
78 startup_info.cb = sizeof(startup_info); 72 startup_info.cb = sizeof(startup_info);
79 73
80 char p_name[255]; 74 char p_name[255];
81 std::strncpy(p_name, "yuzu.exe", 255); 75 std::strncpy(p_name, arg0, 255);
82 76
83 // TODO: use argv[0] instead of yuzu.exe 77 // TODO: use argv[0] instead of yuzu.exe
84 const bool process_created = CreateProcessA(nullptr, // lpApplicationName 78 const bool process_created = CreateProcessA(nullptr, // lpApplicationName
@@ -90,23 +84,13 @@ bool StartupChecks() {
90 nullptr, // lpEnvironment 84 nullptr, // lpEnvironment
91 nullptr, // lpCurrentDirectory 85 nullptr, // lpCurrentDirectory
92 &startup_info, // lpStartupInfo 86 &startup_info, // lpStartupInfo
93 &process_info // lpProcessInformation 87 pi // lpProcessInformation
94 ); 88 );
95 if (!process_created) { 89 if (!process_created) {
96 LOG_ERROR(Frontend, "CreateProcessA failed, {}", GetLastError()); 90 std::fprintf(stderr, "CreateProcessA failed, %d\n", GetLastError());
97 return false; 91 return false;
98 } 92 }
99 93
100 // wait until the processs exits
101 DWORD exit_code = STILL_ACTIVE;
102 while (exit_code == STILL_ACTIVE) {
103 GetExitCodeProcess(process_info.hProcess, &exit_code);
104 }
105
106 std::fprintf(stderr, "exit code: %d\n", exit_code);
107
108 CloseHandle(process_info.hProcess);
109 CloseHandle(process_info.hThread);
110#endif
111 return true; 94 return true;
112} 95}
96#endif
diff --git a/src/yuzu/startup_checks.h b/src/yuzu/startup_checks.h
index 98bd5f4bf..096dd54a8 100644
--- a/src/yuzu/startup_checks.h
+++ b/src/yuzu/startup_checks.h
@@ -3,7 +3,15 @@
3 3
4#pragma once 4#pragma once
5 5
6#ifdef _WIN32
7#include <windows.h>
8#endif
9
6constexpr char STARTUP_CHECK_ENV_VAR[] = "YUZU_DO_STARTUP_CHECKS"; 10constexpr char STARTUP_CHECK_ENV_VAR[] = "YUZU_DO_STARTUP_CHECKS";
7 11
8bool CheckVulkan(); 12void CheckVulkan();
9bool StartupChecks(); 13bool StartupChecks(const char* arg0, bool* has_broken_vulkan);
14
15#ifdef _WIN32
16bool SpawnChild(const char* arg0, PROCESS_INFORMATION* pi);
17#endif
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h
index 044d88ca6..2f6948243 100644
--- a/src/yuzu/uisettings.h
+++ b/src/yuzu/uisettings.h
@@ -78,7 +78,7 @@ struct Values {
78 Settings::Setting<bool> mute_when_in_background{false, "muteWhenInBackground"}; 78 Settings::Setting<bool> mute_when_in_background{false, "muteWhenInBackground"};
79 Settings::Setting<bool> hide_mouse{true, "hideInactiveMouse"}; 79 Settings::Setting<bool> hide_mouse{true, "hideInactiveMouse"};
80 // Set when Vulkan is known to crash the application 80 // Set when Vulkan is known to crash the application
81 Settings::Setting<bool> has_broken_vulkan{false, "has_broken_vulkan"}; 81 bool has_broken_vulkan = false;
82 82
83 Settings::Setting<bool> select_user_on_boot{false, "select_user_on_boot"}; 83 Settings::Setting<bool> select_user_on_boot{false, "select_user_on_boot"};
84 84