From 4f3c3a7b5d292daf64ebaeb7236734944f8e6f19 Mon Sep 17 00:00:00 2001 From: avan Date: Sat, 1 Aug 2026 22:50:35 +0800 Subject: [PATCH] Fix OpenGL program relaunch The Enhanced and Classic versions of FFT are different program indices within the same application. When the Classic version is launched, the game uses ExecuteProgram to stop the current program, trigger DisposeGpu, create a new renderer and OpenGL context, and then launch the requested program. Previously, when AppHost executed DisposeGpu, it attempted to bind the old OpenGL context and then called Device.DisposeGpu to destroy GPU resources. During the program relaunch flow, however, the old RendererHost may already have been removed from the visual tree, causing its native window to become detached. If the old OpenGL context can no longer be bound, a ContextException is thrown, preventing the subsequent AppExit and program relaunch flow from continuing. The updated implementation handles this case by detecting a ContextException while binding the OpenGL context when ShouldRestart is true. It then skips the destruction of GPU resources that depend on the old OpenGL context, allowing the old context to be released together with the old window. The AppExit and program relaunch flow can then continue without being interrupted. (cherry picked from commit cfc7c6039f75ad76ef00f7b6585da14f6be01f91) --- src/Ryujinx/AppHost.cs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/Ryujinx/AppHost.cs b/src/Ryujinx/AppHost.cs index 909cd20aa..45d5a45eb 100644 --- a/src/Ryujinx/AppHost.cs +++ b/src/Ryujinx/AppHost.cs @@ -43,6 +43,7 @@ using Ryujinx.UI.Common.Configuration; using Ryujinx.UI.Common.Helper; using Silk.NET.Vulkan; using SkiaSharp; +using SPB.Graphics.Exceptions; using SPB.Graphics.Vulkan; using System; using System.Collections.Generic; @@ -640,8 +641,22 @@ namespace Ryujinx.Ava if (RendererHost.EmbeddedWindow is EmbeddedWindowOpenGL openGlWindow) { - // Try to bind the OpenGL context before calling the shutdown event. - openGlWindow.MakeCurrent(false, false); + try + { + // Try to bind the OpenGL context before disposing GPU resources. + openGlWindow.MakeCurrent(); + } + catch (ContextException e) when (_userChannelPersistence.ShouldRestart) + { + // ExecuteProgram may detach the old native window before GPU + // disposal. Allow the old context to be released with the window + // and continue the requested program relaunch. + Logger.Warning?.Print( + LogClass.UI, + $"Failed to bind OpenGL context during program relaunch: {e}"); + + return; + } Device.DisposeGpu();