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.
This commit is contained in:
Unknown W. Brackets 2019-06-22 11:48:36 -07:00
parent df6c5f38dc
commit 504acf15de
5 changed files with 82 additions and 39 deletions

View File

@ -546,34 +546,43 @@ static int DefaultGPUBackend() {
int Config::NextValidBackend() { int Config::NextValidBackend() {
std::vector<std::string> split; std::vector<std::string> split;
std::set<int> failed; std::set<GPUBackend> failed;
SplitString(sFailedGPUBackends, ',', split); SplitString(sFailedGPUBackends, ',', split);
for (const auto &str : split) { for (const auto &str : split) {
if (!str.empty() && str != "ALL") { 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); ERROR_LOG(LOADER, "Graphics backend failed for %d, trying another", iGPUBackend);
#if (PPSSPP_PLATFORM(WINDOWS) || PPSSPP_PLATFORM(ANDROID)) && !PPSSPP_PLATFORM(UWP) #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; return (int)GPUBackend::VULKAN;
} }
#endif #endif
#if PPSSPP_PLATFORM(WINDOWS) #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; return (int)GPUBackend::DIRECT3D11;
} }
#endif #endif
#if PPSSPP_API(ANY_GL) #if PPSSPP_API(ANY_GL)
if (!failed.count((int)GPUBackend::OPENGL)) { if (!failed.count(GPUBackend::OPENGL)) {
return (int)GPUBackend::OPENGL; return (int)GPUBackend::OPENGL;
} }
#endif #endif
#if PPSSPP_API(D3D9) #if PPSSPP_API(D3D9)
if (!failed.count((int)GPUBackend::DIRECT3D9)) { if (!failed.count(GPUBackend::DIRECT3D9)) {
return (int)GPUBackend::DIRECT3D9; return (int)GPUBackend::DIRECT3D9;
} }
#endif #endif
@ -587,6 +596,48 @@ int Config::NextValidBackend() {
return iGPUBackend; return iGPUBackend;
} }
bool Config::IsBackendEnabled(GPUBackend backend, bool validate) {
std::vector<std::string> 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() { static bool DefaultVertexCache() {
return DefaultGPUBackend() == (int)GPUBackend::OPENGL; return DefaultGPUBackend() == (int)GPUBackend::OPENGL;
} }
@ -599,6 +650,7 @@ static ConfigSetting graphicsSettings[] = {
ConfigSetting("ShowFPSCounter", &g_Config.iShowFPSCounter, 0, true, true), ConfigSetting("ShowFPSCounter", &g_Config.iShowFPSCounter, 0, true, true),
ReportedConfigSetting("GraphicsBackend", &g_Config.iGPUBackend, &DefaultGPUBackend), ReportedConfigSetting("GraphicsBackend", &g_Config.iGPUBackend, &DefaultGPUBackend),
ConfigSetting("FailedGraphicsBackends", &g_Config.sFailedGPUBackends, ""), ConfigSetting("FailedGraphicsBackends", &g_Config.sFailedGPUBackends, ""),
ConfigSetting("DisabledGraphicsBackends", &g_Config.sDisabledGPUBackends, ""),
ConfigSetting("VulkanDevice", &g_Config.sVulkanDevice, "", true, false), ConfigSetting("VulkanDevice", &g_Config.sVulkanDevice, "", true, false),
#ifdef _WIN32 #ifdef _WIN32
ConfigSetting("D3D11Device", &g_Config.sD3D11Device, "", true, false), ConfigSetting("D3D11Device", &g_Config.sD3D11Device, "", true, false),

View File

@ -23,6 +23,7 @@
#include "ppsspp_config.h" #include "ppsspp_config.h"
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Core/ConfigValues.h"
extern const char *PPSSPP_GIT_VERSION; extern const char *PPSSPP_GIT_VERSION;
@ -124,6 +125,7 @@ public:
// GFX // GFX
int iGPUBackend; int iGPUBackend;
std::string sFailedGPUBackends; std::string sFailedGPUBackends;
std::string sDisabledGPUBackends;
// We have separate device parameters for each backend so it doesn't get erased if you switch backends. // 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. // If not set, will use the "best" device.
std::string sVulkanDevice; std::string sVulkanDevice;
@ -441,6 +443,7 @@ public:
bool IsPortrait() const; bool IsPortrait() const;
int NextValidBackend(); int NextValidBackend();
bool IsBackendEnabled(GPUBackend backend, bool validate = true);
protected: protected:
void LoadStandardControllerIni(); void LoadStandardControllerIni();

View File

@ -68,8 +68,6 @@
#include "Windows/W32Util/ShellUtil.h" #include "Windows/W32Util/ShellUtil.h"
#endif #endif
extern bool VulkanMayBeAvailable();
GameSettingsScreen::GameSettingsScreen(std::string gamePath, std::string gameID, bool editThenRestore) GameSettingsScreen::GameSettingsScreen(std::string gamePath, std::string gameID, bool editThenRestore)
: UIDialogScreenWithGameBackground(gamePath), gameID_(gameID), enableReports_(false), editThenRestore_(editThenRestore) { : UIDialogScreenWithGameBackground(gamePath), gameID_(gameID), enableReports_(false), editThenRestore_(editThenRestore) {
lastVertical_ = UseVerticalLayout(); lastVertical_ = UseVerticalLayout();
@ -199,26 +197,17 @@ void GameSettingsScreen::CreateViews() {
static const char *renderingBackend[] = { "OpenGL", "Direct3D 9", "Direct3D 11", "Vulkan" }; 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())); 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); renderingBackendChoice->OnChoice.Handle(this, &GameSettingsScreen::OnRenderingBackend);
#if !PPSSPP_PLATFORM(WINDOWS)
renderingBackendChoice->HideChoice(1); // D3D9 if (!g_Config.IsBackendEnabled(GPUBackend::OPENGL))
renderingBackendChoice->HideChoice(2); // D3D11 renderingBackendChoice->HideChoice((int)GPUBackend::OPENGL);
#else if (!g_Config.IsBackendEnabled(GPUBackend::DIRECT3D9))
#if !PPSSPP_API(ANY_GL) renderingBackendChoice->HideChoice((int)GPUBackend::DIRECT3D9);
renderingBackendChoice->HideChoice(0); // OpenGL if (!g_Config.IsBackendEnabled(GPUBackend::DIRECT3D11))
#endif renderingBackendChoice->HideChoice((int)GPUBackend::DIRECT3D11);
if (!DoesVersionMatchWindows(6, 0, 0, 0, true)) { if (!g_Config.IsBackendEnabled(GPUBackend::VULKAN))
// Hide the D3D11 choice if Windows version is older than Windows Vista. renderingBackendChoice->HideChoice((int)GPUBackend::VULKAN);
renderingBackendChoice->HideChoice(2); // D3D11
}
#endif
bool vulkanAvailable = false;
#ifndef IOS
vulkanAvailable = VulkanMayBeAvailable();
#endif
if (!vulkanAvailable) {
renderingBackendChoice->HideChoice(3);
}
#endif #endif
Draw::DrawContext *draw = screenManager()->getDrawContext(); Draw::DrawContext *draw = screenManager()->getDrawContext();
// Backends that don't allow a device choice will only expose one device. // Backends that don't allow a device choice will only expose one device.

View File

@ -1290,14 +1290,11 @@ namespace MainWindow {
CheckMenuItem(menu, savestateSlot[i], MF_BYCOMMAND | ((i == g_Config.iCurrentStateSlot) ? MF_CHECKED : MF_UNCHECKED)); CheckMenuItem(menu, savestateSlot[i], MF_BYCOMMAND | ((i == g_Config.iCurrentStateSlot) ? MF_CHECKED : MF_UNCHECKED));
} }
bool allowD3D11 = DoesVersionMatchWindows(6, 0, 0, 0, true); bool allowD3D9 = g_Config.IsBackendEnabled(GPUBackend::DIRECT3D9);
bool allowVulkan = VulkanMayBeAvailable(); 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()) { switch (GetGPUBackend()) {
case GPUBackend::DIRECT3D9: case GPUBackend::DIRECT3D9:
EnableMenuItem(menu, ID_OPTIONS_DIRECT3D9, MF_GRAYED); EnableMenuItem(menu, ID_OPTIONS_DIRECT3D9, MF_GRAYED);
@ -1310,7 +1307,7 @@ namespace MainWindow {
CheckMenuItem(menu, ID_OPTIONS_VULKAN, MF_UNCHECKED); CheckMenuItem(menu, ID_OPTIONS_VULKAN, MF_UNCHECKED);
break; break;
case GPUBackend::OPENGL: 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_DIRECT3D11, allowD3D11 ? MF_ENABLED : MF_GRAYED);
EnableMenuItem(menu, ID_OPTIONS_OPENGL, MF_GRAYED); EnableMenuItem(menu, ID_OPTIONS_OPENGL, MF_GRAYED);
EnableMenuItem(menu, ID_OPTIONS_VULKAN, allowVulkan ? MF_ENABLED : 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); CheckMenuItem(menu, ID_OPTIONS_VULKAN, MF_UNCHECKED);
break; break;
case GPUBackend::VULKAN: 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_DIRECT3D11, allowD3D11 ? MF_ENABLED : MF_GRAYED);
EnableMenuItem(menu, ID_OPTIONS_OPENGL, allowOpenGL ? MF_ENABLED : MF_GRAYED); EnableMenuItem(menu, ID_OPTIONS_OPENGL, allowOpenGL ? MF_ENABLED : MF_GRAYED);
EnableMenuItem(menu, ID_OPTIONS_VULKAN, MF_GRAYED); EnableMenuItem(menu, ID_OPTIONS_VULKAN, MF_GRAYED);
@ -1330,7 +1327,7 @@ namespace MainWindow {
CheckMenuItem(menu, ID_OPTIONS_VULKAN, MF_CHECKED); CheckMenuItem(menu, ID_OPTIONS_VULKAN, MF_CHECKED);
break; break;
case GPUBackend::DIRECT3D11: 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_DIRECT3D11, MF_GRAYED);
EnableMenuItem(menu, ID_OPTIONS_OPENGL, allowOpenGL ? MF_ENABLED : MF_GRAYED); EnableMenuItem(menu, ID_OPTIONS_OPENGL, allowOpenGL ? MF_ENABLED : MF_GRAYED);
EnableMenuItem(menu, ID_OPTIONS_VULKAN, allowVulkan ? MF_ENABLED : MF_GRAYED); EnableMenuItem(menu, ID_OPTIONS_VULKAN, allowVulkan ? MF_ENABLED : MF_GRAYED);

View File

@ -572,7 +572,9 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
#ifndef _DEBUG #ifndef _DEBUG
// See #11719 - too many Vulkan drivers crash on basic init. // See #11719 - too many Vulkan drivers crash on basic init.
VulkanSetAvailable(DetectVulkanInExternalProcess()); if (g_Config.IsBackendEnabled(GPUBackend::VULKAN)) {
VulkanSetAvailable(DetectVulkanInExternalProcess());
}
#endif #endif
if (iCmdShow == SW_MAXIMIZE) { if (iCmdShow == SW_MAXIMIZE) {