From 99a65f3a0ab2ccdc49bdb4f531b8f86f7dc73e13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 16 Sep 2024 12:28:38 +0200 Subject: [PATCH] Implement the fallback path from OpenGL to Vulkan --- Common/File/FileUtil.cpp | 2 ++ Core/HLE/sceAtrac.cpp | 6 +++++- SDL/SDLGLGraphicsContext.cpp | 5 +++-- SDL/SDLGLGraphicsContext.h | 4 +++- SDL/SDLMain.cpp | 42 ++++++++++++++++++++++++++++-------- 5 files changed, 46 insertions(+), 13 deletions(-) diff --git a/Common/File/FileUtil.cpp b/Common/File/FileUtil.cpp index c750aec1f9..ee1969577b 100644 --- a/Common/File/FileUtil.cpp +++ b/Common/File/FileUtil.cpp @@ -1289,6 +1289,8 @@ bool IsProbablyInDownloadsFolder(const Path &filename) { } break; } + default: + break; } return filename.FilePathContainsNoCase("download"); } diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 4dcf94e441..7ac530bc5b 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -528,7 +528,11 @@ static u32 sceAtracGetStreamDataInfo(int atracID, u32 writePtrAddr, u32 writable static u32 sceAtracReleaseAtracID(int atracID) { int result = deleteAtrac(atracID); if (result < 0) { - return hleLogError(Log::ME, result, "did not exist"); + if (atracID >= 0) { + return hleLogError(Log::ME, result, "did not exist"); + } else { + return hleLogWarning(Log::ME, result, "did not exist"); + } } return hleLogSuccessInfoI(Log::ME, result); } diff --git a/SDL/SDLGLGraphicsContext.cpp b/SDL/SDLGLGraphicsContext.cpp index 651e544d63..db53a72507 100644 --- a/SDL/SDLGLGraphicsContext.cpp +++ b/SDL/SDLGLGraphicsContext.cpp @@ -299,8 +299,8 @@ void EGL_Close() { #endif // USING_EGL -bool SDLGLGraphicsContext::InitFromRenderThread() { - bool retval = GraphicsContext::InitFromRenderThread(); +bool SDLGLGraphicsContext::InitFromRenderThread(std::string *errorMessage) { + bool retval = GraphicsContext::InitFromRenderThread(errorMessage); // HACK: Ensure that the swap interval is set after context creation (needed for kmsdrm) SDL_GL_SetSwapInterval(1); return retval; @@ -375,6 +375,7 @@ int SDLGLGraphicsContext::Init(SDL_Window *&window, int x, int y, int w, int h, glContext = SDL_GL_CreateContext(window); if (glContext == nullptr) { + // OK, now we really have tried everything. NativeShutdown(); fprintf(stderr, "SDL_GL_CreateContext failed: %s\n", SDL_GetError()); SDL_Quit(); diff --git a/SDL/SDLGLGraphicsContext.h b/SDL/SDLGLGraphicsContext.h index ca16380571..c2d046a243 100644 --- a/SDL/SDLGLGraphicsContext.h +++ b/SDL/SDLGLGraphicsContext.h @@ -7,6 +7,8 @@ #include "SDL_syswm.h" #endif +#include + #include "Common/GPU/OpenGL/GLRenderManager.h" #include "Common/GPU/OpenGL/GLCommon.h" #include "Common/GraphicsContext.h" @@ -16,7 +18,7 @@ public: // Returns 0 on success. int Init(SDL_Window *&window, int x, int y, int w, int h, int mode, std::string *error_message); - bool InitFromRenderThread() override; + bool InitFromRenderThread(std::string *errorMessage) override; void Shutdown() override {} void ShutdownFromRenderThread() override; diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index e934fb8bfd..53a2160440 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -1336,24 +1336,44 @@ int main(int argc, char *argv[]) { std::string error_message; if (g_Config.iGPUBackend == (int)GPUBackend::OPENGL) { - SDLGLGraphicsContext *ctx = new SDLGLGraphicsContext(); - if (ctx->Init(window, x, y, w, h, mode, &error_message) != 0) { - printf("GL init error '%s'\n", error_message.c_str()); + SDLGLGraphicsContext *glctx = new SDLGLGraphicsContext(); + if (glctx->Init(window, x, y, w, h, mode, &error_message) != 0) { + // Let's try the fallback once per process run. + printf("GL init error '%s' - falling back to Vulkan\n", error_message.c_str()); + g_Config.iGPUBackend = (int)GPUBackend::VULKAN; + SetGPUBackend((GPUBackend)g_Config.iGPUBackend); + delete glctx; + + // NOTE : This should match the lines below in the Vulkan case. + SDLVulkanGraphicsContext *vkctx = new SDLVulkanGraphicsContext(); + if (!vkctx->Init(window, x, y, w, h, mode | SDL_WINDOW_VULKAN, &error_message)) { + printf("Vulkan fallback failed: %s\n", error_message.c_str()); + return 1; + } + graphicsContext = vkctx; + } else { + graphicsContext = glctx; } - graphicsContext = ctx; #if !PPSSPP_PLATFORM(SWITCH) } else if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN) { - SDLVulkanGraphicsContext *ctx = new SDLVulkanGraphicsContext(); - if (!ctx->Init(window, x, y, w, h, mode | SDL_WINDOW_VULKAN, &error_message)) { + SDLVulkanGraphicsContext *vkctx = new SDLVulkanGraphicsContext(); + if (!vkctx->Init(window, x, y, w, h, mode | SDL_WINDOW_VULKAN, &error_message)) { + // Let's try the fallback once per process run. + printf("Vulkan init error '%s' - falling back to GL\n", error_message.c_str()); g_Config.iGPUBackend = (int)GPUBackend::OPENGL; SetGPUBackend((GPUBackend)g_Config.iGPUBackend); - delete ctx; + delete vkctx; + + // NOTE : This should match the three lines above in the OpenGL case. SDLGLGraphicsContext *glctx = new SDLGLGraphicsContext(); - glctx->Init(window, x, y, w, h, mode, &error_message); + if (glctx->Init(window, x, y, w, h, mode, &error_message) != 0) { + printf("GL fallback failed: %s\n", error_message.c_str()); + return 1; + } graphicsContext = glctx; } else { - graphicsContext = ctx; + graphicsContext = vkctx; } #endif } @@ -1396,8 +1416,12 @@ int main(int argc, char *argv[]) { // Since we render from the main thread, there's nothing done here, but we call it to avoid confusion. if (!graphicsContext->InitFromRenderThread(&error_message)) { printf("Init from thread error: '%s'\n", error_message.c_str()); + return 1; } + // OK, we have a valid graphics backend selected. Let's clear the failures. + g_Config.sFailedGPUBackends.clear(); + #ifdef MOBILE_DEVICE SDL_ShowCursor(SDL_DISABLE); #endif