From 504acf15de33e6312965c17a11ddb33c8c258b78 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 22 Jun 2019 11:48:36 -0700 Subject: [PATCH] Core: Allow for disabling graphics backends. Mainly for Vulkan, since sometimes even mobile drivers crash when we ask. This at least provides options. Also centralizes support checks. --- Core/Config.cpp | 66 ++++++++++++++++++++++++++++++++++---- Core/Config.h | 3 ++ UI/GameSettingsScreen.cpp | 31 ++++++------------ Windows/MainWindowMenu.cpp | 17 ++++------ Windows/main.cpp | 4 ++- 5 files changed, 82 insertions(+), 39 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index a80735f6f8..8c52116987 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -546,34 +546,43 @@ static int DefaultGPUBackend() { int Config::NextValidBackend() { std::vector split; - std::set failed; + std::set failed; + SplitString(sFailedGPUBackends, ',', split); for (const auto &str : split) { if (!str.empty() && str != "ALL") { - failed.insert((int)GPUBackendFromString(str)); + failed.insert(GPUBackendFromString(str)); } } - if (failed.count(iGPUBackend)) { + // Count these as "failed" too so we don't pick them. + SplitString(sDisabledGPUBackends, ',', split); + for (const auto &str : split) { + if (!str.empty()) { + failed.insert(GPUBackendFromString(str)); + } + } + + if (failed.count((GPUBackend)iGPUBackend)) { ERROR_LOG(LOADER, "Graphics backend failed for %d, trying another", iGPUBackend); #if (PPSSPP_PLATFORM(WINDOWS) || PPSSPP_PLATFORM(ANDROID)) && !PPSSPP_PLATFORM(UWP) - if (VulkanMayBeAvailable() && !failed.count((int)GPUBackend::VULKAN)) { + if (!failed.count(GPUBackend::VULKAN) && VulkanMayBeAvailable()) { return (int)GPUBackend::VULKAN; } #endif #if PPSSPP_PLATFORM(WINDOWS) - if (DoesVersionMatchWindows(6, 1, 0, 0, true) && !failed.count((int)GPUBackend::DIRECT3D11)) { + if (!failed.count(GPUBackend::DIRECT3D11) && DoesVersionMatchWindows(6, 1, 0, 0, true)) { return (int)GPUBackend::DIRECT3D11; } #endif #if PPSSPP_API(ANY_GL) - if (!failed.count((int)GPUBackend::OPENGL)) { + if (!failed.count(GPUBackend::OPENGL)) { return (int)GPUBackend::OPENGL; } #endif #if PPSSPP_API(D3D9) - if (!failed.count((int)GPUBackend::DIRECT3D9)) { + if (!failed.count(GPUBackend::DIRECT3D9)) { return (int)GPUBackend::DIRECT3D9; } #endif @@ -587,6 +596,48 @@ int Config::NextValidBackend() { return iGPUBackend; } +bool Config::IsBackendEnabled(GPUBackend backend, bool validate) { + std::vector split; + + SplitString(sDisabledGPUBackends, ',', split); + for (const auto &str : split) { + if (str.empty()) + continue; + auto match = GPUBackendFromString(str); + if (match == backend) + return false; + } + +#if PPSSPP_PLATFORM(IOS) + if (backend != GPUBackend::OPENGL) + return false; +#elif PPSSPP_PLATFORM(UWP) + if (backend != GPUBackend::DIRECT3D11) + return false; +#elif PPSSPP_PLATFORM(WINDOWS) + if (validate) { + if (backend == GPUBackend::DIRECT3D11 && !DoesVersionMatchWindows(6, 0, 0, 0, true)) + return false; + } +#else + if (backend == GPUBackend::DIRECT3D11 || backend == GPUBackend::DIRECT3D9) + return false; +#endif + +#if !PPSSPP_API(ANY_GL) + if (backend == GPUBackend::OPENGL) + return false; +#endif +#if !PPSSPP_PLATFORM(IOS) + if (validate) { + if (backend == GPUBackend::VULKAN && !VulkanMayBeAvailable()) + return false; + } +#endif + + return true; +} + static bool DefaultVertexCache() { return DefaultGPUBackend() == (int)GPUBackend::OPENGL; } @@ -599,6 +650,7 @@ static ConfigSetting graphicsSettings[] = { ConfigSetting("ShowFPSCounter", &g_Config.iShowFPSCounter, 0, true, true), ReportedConfigSetting("GraphicsBackend", &g_Config.iGPUBackend, &DefaultGPUBackend), ConfigSetting("FailedGraphicsBackends", &g_Config.sFailedGPUBackends, ""), + ConfigSetting("DisabledGraphicsBackends", &g_Config.sDisabledGPUBackends, ""), ConfigSetting("VulkanDevice", &g_Config.sVulkanDevice, "", true, false), #ifdef _WIN32 ConfigSetting("D3D11Device", &g_Config.sD3D11Device, "", true, false), diff --git a/Core/Config.h b/Core/Config.h index 1c1f4c4bc9..61199c2c24 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -23,6 +23,7 @@ #include "ppsspp_config.h" #include "Common/CommonTypes.h" +#include "Core/ConfigValues.h" extern const char *PPSSPP_GIT_VERSION; @@ -124,6 +125,7 @@ public: // GFX int iGPUBackend; std::string sFailedGPUBackends; + std::string sDisabledGPUBackends; // We have separate device parameters for each backend so it doesn't get erased if you switch backends. // If not set, will use the "best" device. std::string sVulkanDevice; @@ -441,6 +443,7 @@ public: bool IsPortrait() const; int NextValidBackend(); + bool IsBackendEnabled(GPUBackend backend, bool validate = true); protected: void LoadStandardControllerIni(); diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index ae5916b2e6..c2f4182f05 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -68,8 +68,6 @@ #include "Windows/W32Util/ShellUtil.h" #endif -extern bool VulkanMayBeAvailable(); - GameSettingsScreen::GameSettingsScreen(std::string gamePath, std::string gameID, bool editThenRestore) : UIDialogScreenWithGameBackground(gamePath), gameID_(gameID), enableReports_(false), editThenRestore_(editThenRestore) { lastVertical_ = UseVerticalLayout(); @@ -199,26 +197,17 @@ void GameSettingsScreen::CreateViews() { static const char *renderingBackend[] = { "OpenGL", "Direct3D 9", "Direct3D 11", "Vulkan" }; PopupMultiChoice *renderingBackendChoice = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iGPUBackend, gr->T("Backend"), renderingBackend, (int)GPUBackend::OPENGL, ARRAY_SIZE(renderingBackend), gr->GetName(), screenManager())); renderingBackendChoice->OnChoice.Handle(this, &GameSettingsScreen::OnRenderingBackend); -#if !PPSSPP_PLATFORM(WINDOWS) - renderingBackendChoice->HideChoice(1); // D3D9 - renderingBackendChoice->HideChoice(2); // D3D11 -#else -#if !PPSSPP_API(ANY_GL) - renderingBackendChoice->HideChoice(0); // OpenGL -#endif - if (!DoesVersionMatchWindows(6, 0, 0, 0, true)) { - // Hide the D3D11 choice if Windows version is older than Windows Vista. - renderingBackendChoice->HideChoice(2); // D3D11 - } -#endif - bool vulkanAvailable = false; -#ifndef IOS - vulkanAvailable = VulkanMayBeAvailable(); -#endif - if (!vulkanAvailable) { - renderingBackendChoice->HideChoice(3); - } + + if (!g_Config.IsBackendEnabled(GPUBackend::OPENGL)) + renderingBackendChoice->HideChoice((int)GPUBackend::OPENGL); + if (!g_Config.IsBackendEnabled(GPUBackend::DIRECT3D9)) + renderingBackendChoice->HideChoice((int)GPUBackend::DIRECT3D9); + if (!g_Config.IsBackendEnabled(GPUBackend::DIRECT3D11)) + renderingBackendChoice->HideChoice((int)GPUBackend::DIRECT3D11); + if (!g_Config.IsBackendEnabled(GPUBackend::VULKAN)) + renderingBackendChoice->HideChoice((int)GPUBackend::VULKAN); #endif + Draw::DrawContext *draw = screenManager()->getDrawContext(); // Backends that don't allow a device choice will only expose one device. diff --git a/Windows/MainWindowMenu.cpp b/Windows/MainWindowMenu.cpp index d1f29b5ce8..a53ecdaad5 100644 --- a/Windows/MainWindowMenu.cpp +++ b/Windows/MainWindowMenu.cpp @@ -1290,14 +1290,11 @@ namespace MainWindow { CheckMenuItem(menu, savestateSlot[i], MF_BYCOMMAND | ((i == g_Config.iCurrentStateSlot) ? MF_CHECKED : MF_UNCHECKED)); } - bool allowD3D11 = DoesVersionMatchWindows(6, 0, 0, 0, true); - bool allowVulkan = VulkanMayBeAvailable(); + bool allowD3D9 = g_Config.IsBackendEnabled(GPUBackend::DIRECT3D9); + bool allowD3D11 = g_Config.IsBackendEnabled(GPUBackend::DIRECT3D11); + bool allowOpenGL = g_Config.IsBackendEnabled(GPUBackend::OPENGL); + bool allowVulkan = g_Config.IsBackendEnabled(GPUBackend::VULKAN); -#if PPSSPP_API(ANY_GL) - bool allowOpenGL = true; -#else - bool allowOpenGL = false; -#endif switch (GetGPUBackend()) { case GPUBackend::DIRECT3D9: EnableMenuItem(menu, ID_OPTIONS_DIRECT3D9, MF_GRAYED); @@ -1310,7 +1307,7 @@ namespace MainWindow { CheckMenuItem(menu, ID_OPTIONS_VULKAN, MF_UNCHECKED); break; case GPUBackend::OPENGL: - EnableMenuItem(menu, ID_OPTIONS_DIRECT3D9, MF_ENABLED); + EnableMenuItem(menu, ID_OPTIONS_DIRECT3D9, allowD3D9 ? MF_ENABLED : MF_GRAYED); EnableMenuItem(menu, ID_OPTIONS_DIRECT3D11, allowD3D11 ? MF_ENABLED : MF_GRAYED); EnableMenuItem(menu, ID_OPTIONS_OPENGL, MF_GRAYED); EnableMenuItem(menu, ID_OPTIONS_VULKAN, allowVulkan ? MF_ENABLED : MF_GRAYED); @@ -1320,7 +1317,7 @@ namespace MainWindow { CheckMenuItem(menu, ID_OPTIONS_VULKAN, MF_UNCHECKED); break; case GPUBackend::VULKAN: - EnableMenuItem(menu, ID_OPTIONS_DIRECT3D9, MF_ENABLED); + EnableMenuItem(menu, ID_OPTIONS_DIRECT3D9, allowD3D9 ? MF_ENABLED : MF_GRAYED); EnableMenuItem(menu, ID_OPTIONS_DIRECT3D11, allowD3D11 ? MF_ENABLED : MF_GRAYED); EnableMenuItem(menu, ID_OPTIONS_OPENGL, allowOpenGL ? MF_ENABLED : MF_GRAYED); EnableMenuItem(menu, ID_OPTIONS_VULKAN, MF_GRAYED); @@ -1330,7 +1327,7 @@ namespace MainWindow { CheckMenuItem(menu, ID_OPTIONS_VULKAN, MF_CHECKED); break; case GPUBackend::DIRECT3D11: - EnableMenuItem(menu, ID_OPTIONS_DIRECT3D9, MF_ENABLED); + EnableMenuItem(menu, ID_OPTIONS_DIRECT3D9, allowD3D9 ? MF_ENABLED : MF_GRAYED); EnableMenuItem(menu, ID_OPTIONS_DIRECT3D11, MF_GRAYED); EnableMenuItem(menu, ID_OPTIONS_OPENGL, allowOpenGL ? MF_ENABLED : MF_GRAYED); EnableMenuItem(menu, ID_OPTIONS_VULKAN, allowVulkan ? MF_ENABLED : MF_GRAYED); diff --git a/Windows/main.cpp b/Windows/main.cpp index b7052c13b1..ddc6561a46 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -572,7 +572,9 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin #ifndef _DEBUG // See #11719 - too many Vulkan drivers crash on basic init. - VulkanSetAvailable(DetectVulkanInExternalProcess()); + if (g_Config.IsBackendEnabled(GPUBackend::VULKAN)) { + VulkanSetAvailable(DetectVulkanInExternalProcess()); + } #endif if (iCmdShow == SW_MAXIMIZE) {