From 348a76090bbfb601cae9f5f8d0c9ad5748cdc418 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Sat, 28 Mar 2026 01:14:41 +0100 Subject: [PATCH] permet escollir driver de gpu o no escollir-ne cap --- source/core/rendering/screen.cpp | 1 + source/core/rendering/screen.hpp | 1 + .../core/rendering/sdl3gpu/sdl3gpu_shader.cpp | 12 +++- .../core/rendering/sdl3gpu/sdl3gpu_shader.hpp | 4 ++ source/core/rendering/shader_backend.hpp | 6 ++ source/game/options.cpp | 9 +++ source/game/options.hpp | 1 + source/game/ui/console.cpp | 57 +++++++++++++++++++ 8 files changed, 90 insertions(+), 1 deletion(-) diff --git a/source/core/rendering/screen.cpp b/source/core/rendering/screen.cpp index 4d48208..01f3848 100644 --- a/source/core/rendering/screen.cpp +++ b/source/core/rendering/screen.cpp @@ -578,6 +578,7 @@ void Screen::initShaders() { if (!shader_backend_) { shader_backend_ = std::make_unique(); + shader_backend_->setPreferredDriver(Options::video.gpu_preferred_driver); } shader_backend_->init(window_, tex, "", ""); gpu_driver_ = shader_backend_->getDriverName(); diff --git a/source/core/rendering/screen.hpp b/source/core/rendering/screen.hpp index 605e4e7..6c388b7 100644 --- a/source/core/rendering/screen.hpp +++ b/source/core/rendering/screen.hpp @@ -74,6 +74,7 @@ class Screen { auto getBorderSurface() -> std::shared_ptr; [[nodiscard]] auto getText() const -> std::shared_ptr { return text_; } [[nodiscard]] auto getGameSurfaceDstRect() const -> SDL_FRect { return game_surface_dstrect_; } + [[nodiscard]] auto getGPUDriver() const -> const std::string& { return gpu_driver_; } private: // Estructuras diff --git a/source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp b/source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp index 1e3b3ef..cd140a7 100644 --- a/source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp +++ b/source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp @@ -269,13 +269,23 @@ namespace Rendering { // ---------------------------------------------------------------- // 1. Create GPU device (solo si no existe ya) // ---------------------------------------------------------------- + if (preferred_driver_ == "none") { + SDL_Log("SDL3GPUShader: GPU disabled by config, using SDL_Renderer fallback"); + driver_name_ = "none"; + return false; + } if (device_ == nullptr) { #ifdef __APPLE__ const SDL_GPUShaderFormat PREFERRED = SDL_GPU_SHADERFORMAT_MSL | SDL_GPU_SHADERFORMAT_METALLIB; #else const SDL_GPUShaderFormat PREFERRED = SDL_GPU_SHADERFORMAT_SPIRV; #endif - device_ = SDL_CreateGPUDevice(PREFERRED, false, nullptr); + const char* preferred = preferred_driver_.empty() ? nullptr : preferred_driver_.c_str(); + device_ = SDL_CreateGPUDevice(PREFERRED, false, preferred); + if (device_ == nullptr && preferred != nullptr) { + SDL_Log("SDL3GPUShader: driver '%s' not available, falling back to auto", preferred); + device_ = SDL_CreateGPUDevice(PREFERRED, false, nullptr); + } if (device_ == nullptr) { SDL_Log("SDL3GPUShader: SDL_CreateGPUDevice failed: %s", SDL_GetError()); return false; diff --git a/source/core/rendering/sdl3gpu/sdl3gpu_shader.hpp b/source/core/rendering/sdl3gpu/sdl3gpu_shader.hpp index 2527273..a8309af 100644 --- a/source/core/rendering/sdl3gpu/sdl3gpu_shader.hpp +++ b/source/core/rendering/sdl3gpu/sdl3gpu_shader.hpp @@ -58,6 +58,9 @@ namespace Rendering { [[nodiscard]] auto isHardwareAccelerated() const -> bool override { return is_initialized_; } [[nodiscard]] auto getDriverName() const -> std::string override { return driver_name_; } + // Establece el driver GPU preferido (vacío = auto). Debe llamarse antes de init(). + void setPreferredDriver(const std::string& driver) override { preferred_driver_ = driver; } + // Sube píxeles ARGB8888 desde CPU; llamado antes de render() void uploadPixels(const Uint32* pixels, int width, int height) override; @@ -121,6 +124,7 @@ namespace Rendering { int oversample_ = 1; // SS on/off (1 = off, >1 = on) int downscale_algo_ = 1; // 0 = bilinear legacy, 1 = Lanczos2, 2 = Lanczos3 std::string driver_name_; + std::string preferred_driver_; // Driver preferido; vacío = auto (SDL elige) bool is_initialized_ = false; bool vsync_ = true; bool integer_scale_ = false; diff --git a/source/core/rendering/shader_backend.hpp b/source/core/rendering/shader_backend.hpp index e6e33f5..2714be3 100644 --- a/source/core/rendering/shader_backend.hpp +++ b/source/core/rendering/shader_backend.hpp @@ -116,6 +116,12 @@ namespace Rendering { * @return Cadena vacía si no disponible */ [[nodiscard]] virtual auto getDriverName() const -> std::string { return {}; } + + /** + * @brief Establece el driver GPU preferido antes de init(). + * Vacío = selección automática de SDL. Implementado en SDL3GPUShader. + */ + virtual void setPreferredDriver(const std::string& /*driver*/) {} }; } // namespace Rendering diff --git a/source/game/options.cpp b/source/game/options.cpp index cdb098e..a059d0e 100644 --- a/source/game/options.cpp +++ b/source/game/options.cpp @@ -404,6 +404,14 @@ namespace Options { } } + if (vid.contains("gpu_preferred_driver")) { + try { + video.gpu_preferred_driver = vid["gpu_preferred_driver"].get_value(); + } catch (...) { + video.gpu_preferred_driver = ""; + } + } + loadPaletteFromYaml(vid); } @@ -662,6 +670,7 @@ namespace Options { file << " keep_aspect: " << (video.keep_aspect ? "true" : "false") << "\n"; file << " linear_upscale: " << (video.linear_upscale ? "true" : "false") << "\n"; file << " downscale_algo: " << video.downscale_algo << " # 0=bilinear, 1=Lanczos2, 2=Lanczos3\n"; + file << " gpu_preferred_driver: \"" << video.gpu_preferred_driver << "\" # GPU driver (empty = auto)\n"; file << " palette: " << video.palette << "\n"; file << " border:\n"; file << " enabled: " << (video.border.enabled ? "true" : "false") << "\n"; diff --git a/source/game/options.hpp b/source/game/options.hpp index d28b7a4..a3a50d4 100644 --- a/source/game/options.hpp +++ b/source/game/options.hpp @@ -89,6 +89,7 @@ namespace Options { Border border{}; // Borde de la pantalla std::string palette{Defaults::Video::PALETTE_NAME}; // Paleta de colores a usar en el juego std::string info; // Información sobre el modo de vídeo + std::string gpu_preferred_driver; // Driver GPU preferido; vacío = auto. Aplica en el próximo arranque. }; // Estructura para las opciones de musica diff --git a/source/game/ui/console.cpp b/source/game/ui/console.cpp index dcaad9a..48c525a 100644 --- a/source/game/ui/console.cpp +++ b/source/game/ui/console.cpp @@ -72,6 +72,7 @@ static void printHelp() { SDL_Log(" UPSCALE [NEAREST|LINEAR] SS upscale filter (toggle if no arg)"); SDL_Log(" DOWNSCALE [BILINEAR|LANCZOS2|LANCZOS3] SS downscale algorithm"); SDL_Log(" VSYNC [ON|OFF] Vertical sync"); + SDL_Log(" DRIVER [LIST|AUTO|NONE|] GPU driver (restart to apply)"); SDL_Log(" PALETTE [NEXT|PREV] Color palette (F5/F6)"); #ifdef _DEBUG SDL_Log(" DEBUG Toggle debug overlay (F12)"); @@ -215,6 +216,62 @@ static const std::vector COMMANDS = { Options::video.vertical_sync, Screen::get()->toggleVSync())}, + // DRIVER [LIST|AUTO|] — Driver GPU (aplica en el próximo arranque) + {.keyword = "DRIVER", .execute = [](const std::vector& args) -> std::string { + // Sin argumentos: muestra el driver activo (permitido en kiosk) + if (args.empty()) { + const auto& driver = Screen::get()->getGPUDriver(); + return "GPU: " + (driver.empty() ? std::string("sdl") : driver); + } + // LIST: lista drivers disponibles marcando el activo con * (permitido en kiosk) + if (args[0] == "LIST") { + const int COUNT = SDL_GetNumGPUDrivers(); + if (COUNT <= 0) { return "No GPU drivers found"; } + const std::string& active = Screen::get()->getGPUDriver(); + std::string result = "Drivers:"; + for (int i = 0; i < COUNT; ++i) { + const char* name = SDL_GetGPUDriver(i); + if (name != nullptr) { + result += ' '; + result += name; + if (active == name) { result += '*'; } + } + } + SDL_Log("SDL GPU drivers: %s", result.c_str()); + return result; + } + // Cambiar driver: bloqueado en kiosk salvo PLEASE + const bool HAS_PLEASE = std::ranges::find(args, std::string("PLEASE")) != args.end(); + if (Options::kiosk.enabled && !HAS_PLEASE) { + return "Not allowed in kiosk mode"; + } + if (args[0] == "AUTO") { + Options::video.gpu_preferred_driver.clear(); + Options::saveToFile(); + return "Driver: auto (restart)"; + } + if (args[0] == "NONE") { + Options::video.gpu_preferred_driver = "none"; + Options::saveToFile(); + return "Driver: none (SDL fallback, restart)"; + } + std::string driver_lower = args[0]; + std::ranges::transform(driver_lower, driver_lower.begin(), ::tolower); + // Validar que el nombre existe en la lista de drivers SDL + const int COUNT = SDL_GetNumGPUDrivers(); + bool found = false; + for (int i = 0; i < COUNT && !found; ++i) { + const char* name = SDL_GetGPUDriver(i); + if (name != nullptr && driver_lower == name) { found = true; } + } + if (!found) { + return "Unknown driver: " + driver_lower + ". Use DRIVER LIST or NONE"; + } + Options::video.gpu_preferred_driver = driver_lower; + Options::saveToFile(); + return "Driver: " + driver_lower + " (restart)"; + }}, + // PALETTE NEXT/PREV — Paleta de colores (F5/F6) {.keyword = "PALETTE", .execute = [](const std::vector& args) -> std::string { if (args.empty()) { return "Usage: PALETTE [NEXT|PREV]"; }