From c8220c0c112cd0df85e19e8485732f4ff93a4f50 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 5 Oct 2026 13:33:43 +0000 Subject: [PATCH] Report graphics startup failures instead of aborting When no backend could create a window and a WebGPU device, aurora hit an ASSERT and the process aborted with only SDL's last error in the log. Keep the first adapter, device or window error, return it from aurora_initialize with a new initializationStatus, and have the runtime throw it so the existing fatal popup and fatal log record the reason. ImGui shutdown now skips backends that never initialized, so the shutdown that follows a failed start does not crash. From upstream patchzyy/Wiicompiled 6f14bde (#244, KartPad batch). Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01Wg7mB8ogCWmp9GH19Uc82B --- aurora-main/include/aurora/aurora.h | 8 ++++++++ aurora-main/lib/aurora.cpp | 20 +++++++++++++++++++- aurora-main/lib/imgui.cpp | 24 ++++++++++++++++++------ aurora-main/lib/webgpu/gpu.cpp | 9 +++++++++ runtime/src/main.cpp | 4 ++++ 5 files changed, 58 insertions(+), 7 deletions(-) diff --git a/aurora-main/include/aurora/aurora.h b/aurora-main/include/aurora/aurora.h index ff9120f..237bfbf 100644 --- a/aurora-main/include/aurora/aurora.h +++ b/aurora-main/include/aurora/aurora.h @@ -295,12 +295,20 @@ typedef struct { bool xrHeadsetOnly; } AuroraConfig; +typedef enum { + AURORA_INITIALIZATION_SUCCESS = 0, + AURORA_INITIALIZATION_GRAPHICS_UNAVAILABLE = 1, +} AuroraInitializationStatus; + typedef struct { AuroraBackend backend; const char* userPath; const char* cachePath; SDL_Window* window; AuroraWindowSize windowSize; + AuroraInitializationStatus initializationStatus; + // On failure, owned by SDL on the calling thread. Copy before another SDL call. + const char* initializationError; } AuroraInfo; AuroraInfo aurora_initialize(int argc, char* argv[], const AuroraConfig* config); diff --git a/aurora-main/lib/aurora.cpp b/aurora-main/lib/aurora.cpp index 5a12c9f..52c5a34 100644 --- a/aurora-main/lib/aurora.cpp +++ b/aurora-main/lib/aurora.cpp @@ -1229,15 +1229,23 @@ AuroraInfo initialize(int argc, char* argv[], const AuroraConfig& config) noexce const AuroraBackend requestedBackend = config.desiredBackend; AuroraBackend selectedBackend = requestedBackend; bool windowCreated = false; + std::string firstGraphicsError; + const auto rememberGraphicsError = [&] { + if (firstGraphicsError.empty() && SDL_GetError()[0] != '\0') { + firstGraphicsError = SDL_GetError(); + } + }; if (selectedBackend != BACKEND_AUTO) { Log.info("Requested graphics backend: {}", backend_name(selectedBackend)); if (window::create_window(selectedBackend)) { if (webgpu::initialize(selectedBackend)) { windowCreated = true; } else { + rememberGraphicsError(); window::destroy_window(); } } else { + rememberGraphicsError(); Log.error("Failed to create a window for backend {}: {}", backend_name(selectedBackend), SDL_GetError()); } if (!windowCreated) { @@ -1254,18 +1262,28 @@ AuroraInfo initialize(int argc, char* argv[], const AuroraConfig& config) noexce for (const auto backendType : PreferredBackendOrder) { selectedBackend = backendType; if (!window::create_window(selectedBackend)) { + rememberGraphicsError(); continue; } if (webgpu::initialize(selectedBackend)) { windowCreated = true; break; } else { + rememberGraphicsError(); window::destroy_window(); } } } - ASSERT(windowCreated, "Error creating window: {}", SDL_GetError()); + if (!windowCreated) { + if (firstGraphicsError.empty()) firstGraphicsError = "No supported graphics backend is available"; + SDL_SetError("%s", firstGraphicsError.c_str()); + Log.error("Graphics initialization failed: {}", firstGraphicsError); + return { + .initializationStatus = AURORA_INITIALIZATION_GRAPHICS_UNAVAILABLE, + .initializationError = SDL_GetError(), + }; + } if (requestedBackend != BACKEND_AUTO && selectedBackend != requestedBackend) { Log.error( "Graphics backend fallback in effect: video.graphics_api requested {}, " diff --git a/aurora-main/lib/imgui.cpp b/aurora-main/lib/imgui.cpp index f3854d4..0cdd07b 100644 --- a/aurora-main/lib/imgui.cpp +++ b/aurora-main/lib/imgui.cpp @@ -85,18 +85,30 @@ void initialize() noexcept { void shutdown() noexcept { ZoneScoped; - if (g_useSdlRenderer) { - ImGui_ImplSDLRenderer3_Shutdown(); - } else { - ImGui_ImplWGPU_Shutdown(); + // Startup can fail before either backend initializes. A context alone does + // not mean its renderer/platform backend owns resources to release. + if (ImGui::GetCurrentContext() != nullptr) { + ImGuiIO& io = ImGui::GetIO(); + if (io.BackendRendererUserData != nullptr) { + if (g_useSdlRenderer) { + ImGui_ImplSDLRenderer3_Shutdown(); + } else { + ImGui_ImplWGPU_Shutdown(); + } + } + if (io.BackendPlatformUserData != nullptr) { + ImGui_ImplSDL3_Shutdown(); + } + ImGui::DestroyContext(); } - ImGui_ImplSDL3_Shutdown(); - ImGui::DestroyContext(); for (const auto& texture : g_sdlTextures) { SDL_DestroyTexture(texture); } g_sdlTextures.clear(); g_wgpuTextures.clear(); + g_useSdlRenderer = false; + g_scale = 0.f; + g_frameDataBuilt = true; } void process_event(const SDL_Event& event) noexcept { diff --git a/aurora-main/lib/webgpu/gpu.cpp b/aurora-main/lib/webgpu/gpu.cpp index 0876bb6..6b015aa 100644 --- a/aurora-main/lib/webgpu/gpu.cpp +++ b/aurora-main/lib/webgpu/gpu.cpp @@ -627,12 +627,16 @@ bool initialize(AuroraBackend auroraBackend) { g_adapter = std::move(adapter); } else { Log.warn("Adapter request failed: {}", message); + const std::string_view reason{message}; + SDL_SetError("Graphics adapter unavailable: %.*s", + static_cast(std::min(reason.size(), 512)), reason.data()); } }); const auto status = g_instance.WaitAny(future, 5000000000); if (status != wgpu::WaitStatus::Success) { Log.error("Failed to create {} adapter: {}", magic_enum::enum_name(backend), magic_enum::enum_name(status)); + SDL_SetError("Graphics adapter request did not complete within its startup deadline"); return false; } if (!g_adapter) { @@ -845,11 +849,16 @@ bool initialize(AuroraBackend auroraBackend) { g_device = std::move(device); } else { Log.warn("Device request failed: {}", message); + const std::string_view reason{message}; + SDL_SetError("Graphics device unavailable: %.*s", + static_cast(std::min(reason.size(), 512)), + reason.data()); } }); const auto status = g_instance.WaitAny(future, 5000000000); if (status != wgpu::WaitStatus::Success) { Log.error("Failed to create device: {}", magic_enum::enum_name(status)); + SDL_SetError("Graphics device request did not complete within its startup deadline"); return false; } if (!g_device) { diff --git a/runtime/src/main.cpp b/runtime/src/main.cpp index abc2e9b..539cd4a 100644 --- a/runtime/src/main.cpp +++ b/runtime/src/main.cpp @@ -1551,6 +1551,10 @@ int RuntimeMain(int argc, char** argv) { WiiRemoteInput::ConfigureSdlHints(RuntimeConfigFile::WiiRemotesEnabled(true)); const AuroraInfo auroraInfo = aurora_initialize(0, nullptr, &auroraConfig); + if (auroraInfo.initializationStatus != AURORA_INITIALIZATION_SUCCESS) { + throw std::runtime_error(auroraInfo.initializationError != nullptr + ? auroraInfo.initializationError : "No supported graphics backend is available"); + } if (requestedBackend != BACKEND_AUTO && auroraInfo.backend != requestedBackend) { RT_LOG(RT_TAG_RUNTIME) << "graphics_api=\"" << backend << "\" is not available on this system; aurora fell back to \""