diff --git a/Ryujinx.Ava/AppHost.cs b/Ryujinx.Ava/AppHost.cs index 3d4c6cde..a016ebd5 100644 --- a/Ryujinx.Ava/AppHost.cs +++ b/Ryujinx.Ava/AppHost.cs @@ -60,7 +60,7 @@ namespace Ryujinx.Ava private const float VolumeDelta = 0.05f; - private static readonly Cursor InvisibleCursor = new Cursor(StandardCursorType.None); + private static readonly Cursor InvisibleCursor = new Cursor(StandardCursorType.None); private readonly long _ticksPerFrame; private readonly Stopwatch _chrono; @@ -349,7 +349,10 @@ namespace Ryujinx.Ava _isActive = false; - _renderingThread.Join(); + if (_renderingThread.IsAlive) + { + _renderingThread.Join(); + } DisplaySleep.Restore(); @@ -378,7 +381,7 @@ namespace Ryujinx.Ava _gpuCancellationTokenSource.Cancel(); _gpuCancellationTokenSource.Dispose(); - + _chrono.Stop(); } @@ -393,7 +396,7 @@ namespace Ryujinx.Ava Renderer?.MakeCurrent(); Device.DisposeGpu(); - + Renderer?.MakeCurrent(null); } @@ -417,7 +420,6 @@ namespace Ryujinx.Ava public async Task LoadGuestApplication() { InitializeSwitchInstance(); - MainWindow.UpdateGraphicsConfig(); SystemVersion firmwareVersion = ContentManager.GetCurrentFirmwareVersion(); @@ -428,17 +430,16 @@ namespace Ryujinx.Ava { if (userError == UserError.NoFirmware) { - string message = string.Format(LocaleManager.Instance["DialogFirmwareInstallEmbeddedMessage"], - firmwareVersion.VersionString); - UserResult result = await ContentDialogHelper.CreateConfirmationDialog( - LocaleManager.Instance["DialogFirmwareNoFirmwareInstalledMessage"], message, - LocaleManager.Instance["InputDialogYes"], LocaleManager.Instance["InputDialogNo"], ""); + LocaleManager.Instance["DialogFirmwareNoFirmwareInstalledMessage"], + string.Format(LocaleManager.Instance["DialogFirmwareInstallEmbeddedMessage"], firmwareVersion.VersionString), + LocaleManager.Instance["InputDialogYes"], + LocaleManager.Instance["InputDialogNo"], + ""); if (result != UserResult.Yes) { - Dispatcher.UIThread.Post(async () => await - UserErrorDialog.ShowUserErrorDialog(userError, _parent)); + await UserErrorDialog.ShowUserErrorDialog(userError, _parent); Device.Dispose(); return false; @@ -447,8 +448,7 @@ namespace Ryujinx.Ava if (!SetupValidator.TryFixStartApplication(ContentManager, ApplicationPath, userError, out _)) { - Dispatcher.UIThread.Post(async () => await - UserErrorDialog.ShowUserErrorDialog(userError, _parent)); + await UserErrorDialog.ShowUserErrorDialog(userError, _parent); Device.Dispose(); return false; @@ -461,11 +461,9 @@ namespace Ryujinx.Ava _parent.RefreshFirmwareStatus(); - string message = string.Format(LocaleManager.Instance["DialogFirmwareInstallEmbeddedSuccessMessage"], firmwareVersion.VersionString); - await ContentDialogHelper.CreateInfoDialog( string.Format(LocaleManager.Instance["DialogFirmwareInstalledMessage"], firmwareVersion.VersionString), - message, + string.Format(LocaleManager.Instance["DialogFirmwareInstallEmbeddedSuccessMessage"], firmwareVersion.VersionString), LocaleManager.Instance["InputDialogOk"], "", LocaleManager.Instance["RyujinxInfo"]); @@ -473,9 +471,7 @@ namespace Ryujinx.Ava } else { - Dispatcher.UIThread.Post(async () => await - UserErrorDialog.ShowUserErrorDialog(userError, _parent)); - + await UserErrorDialog.ShowUserErrorDialog(userError, _parent); Device.Dispose(); return false; @@ -514,7 +510,7 @@ namespace Ryujinx.Ava } else if (File.Exists(ApplicationPath)) { - switch (System.IO.Path.GetExtension(ApplicationPath).ToLowerInvariant()) + switch (Path.GetExtension(ApplicationPath).ToLowerInvariant()) { case ".xci": { @@ -602,7 +598,7 @@ namespace Ryujinx.Ava if (Renderer.IsVulkan) { string preferredGpu = ConfigurationState.Instance.Graphics.PreferredGpu.Value; - + renderer = new VulkanRenderer(Renderer.CreateVulkanSurface, VulkanHelper.GetRequiredInstanceExtensions, preferredGpu); } else diff --git a/Ryujinx.Ava/Ui/Controls/OpenGLEmbeddedWindow.cs b/Ryujinx.Ava/Ui/Controls/OpenGLEmbeddedWindow.cs index ce579fdf..f32bf041 100644 --- a/Ryujinx.Ava/Ui/Controls/OpenGLEmbeddedWindow.cs +++ b/Ryujinx.Ava/Ui/Controls/OpenGLEmbeddedWindow.cs @@ -49,7 +49,7 @@ namespace Ryujinx.Ava.Ui.Controls { throw new PlatformNotSupportedException(); } - + var flags = OpenGLContextFlags.Compat; if (_graphicsDebugLevel != GraphicsDebugLevel.None) { @@ -69,12 +69,12 @@ namespace Ryujinx.Ava.Ui.Controls public void MakeCurrent() { - Context.MakeCurrent(_window); + Context?.MakeCurrent(_window); } public void MakeCurrent(NativeWindowBase window) { - Context.MakeCurrent(window); + Context?.MakeCurrent(window); } public void SwapBuffers() diff --git a/Ryujinx.Ava/Ui/Windows/MainWindow.axaml.cs b/Ryujinx.Ava/Ui/Windows/MainWindow.axaml.cs index 0e03803b..be4517c8 100644 --- a/Ryujinx.Ava/Ui/Windows/MainWindow.axaml.cs +++ b/Ryujinx.Ava/Ui/Windows/MainWindow.axaml.cs @@ -251,24 +251,29 @@ namespace Ryujinx.Ava.Ui.Windows AppHost = new AppHost(RendererControl, InputManager, path, VirtualFileSystem, ContentManager, AccountManager, _userChannelPersistence, this); - if (!AppHost.LoadGuestApplication().Result) + Dispatcher.UIThread.Post(async () => { - AppHost.DisposeContext(); + if (!await AppHost.LoadGuestApplication()) + { + AppHost.DisposeContext(); + AppHost = null; - return; - } + return; + } - ViewModel.LoadHeading = string.IsNullOrWhiteSpace(titleName) ? string.Format(LocaleManager.Instance["LoadingHeading"], AppHost.Device.Application.TitleName) : titleName; - ViewModel.TitleName = string.IsNullOrWhiteSpace(titleName) ? AppHost.Device.Application.TitleName : titleName; + ViewModel.LoadHeading = string.IsNullOrWhiteSpace(titleName) ? string.Format(LocaleManager.Instance["LoadingHeading"], AppHost.Device.Application.TitleName) : titleName; + ViewModel.TitleName = string.IsNullOrWhiteSpace(titleName) ? AppHost.Device.Application.TitleName : titleName; - SwitchToGameControl(startFullscreen); + SwitchToGameControl(startFullscreen); - _currentEmulatedGamePath = path; - Thread gameThread = new Thread(InitializeGame) - { - Name = "GUI.WindowThread" - }; - gameThread.Start(); + _currentEmulatedGamePath = path; + + Thread gameThread = new(InitializeGame) + { + Name = "GUI.WindowThread" + }; + gameThread.Start(); + }); } private void InitializeGame() @@ -546,10 +551,12 @@ namespace Ryujinx.Ava.Ui.Windows { ApplicationLibrary.LoadAndSaveMetaData(titleId, appMetadata => { - DateTime lastPlayedDateTime = DateTime.Parse(appMetadata.LastPlayed); - double sessionTimePlayed = DateTime.UtcNow.Subtract(lastPlayedDateTime).TotalSeconds; + if (DateTime.TryParse(appMetadata.LastPlayed, out DateTime lastPlayedDateTime)) + { + double sessionTimePlayed = DateTime.UtcNow.Subtract(lastPlayedDateTime).TotalSeconds; - appMetadata.TimePlayed += Math.Round(sessionTimePlayed, MidpointRounding.AwayFromZero); + appMetadata.TimePlayed += Math.Round(sessionTimePlayed, MidpointRounding.AwayFromZero); + } }); } diff --git a/Ryujinx.Graphics.GAL/Multithreading/ThreadedRenderer.cs b/Ryujinx.Graphics.GAL/Multithreading/ThreadedRenderer.cs index e105a092..7a625af3 100644 --- a/Ryujinx.Graphics.GAL/Multithreading/ThreadedRenderer.cs +++ b/Ryujinx.Graphics.GAL/Multithreading/ThreadedRenderer.cs @@ -422,7 +422,11 @@ namespace Ryujinx.Graphics.GAL.Multithreading // Stop the GPU thread. _disposed = true; - _gpuThread.Join(); + + if (_gpuThread != null && _gpuThread.IsAlive) + { + _gpuThread.Join(); + } // Dispose the renderer. _baseRenderer.Dispose(); @@ -435,4 +439,4 @@ namespace Ryujinx.Graphics.GAL.Multithreading Sync.Dispose(); } } -} +} \ No newline at end of file diff --git a/Ryujinx.Graphics.OpenGL/Queries/Counters.cs b/Ryujinx.Graphics.OpenGL/Queries/Counters.cs index 582800c8..ebfd899c 100644 --- a/Ryujinx.Graphics.OpenGL/Queries/Counters.cs +++ b/Ryujinx.Graphics.OpenGL/Queries/Counters.cs @@ -54,4 +54,4 @@ namespace Ryujinx.Graphics.OpenGL.Queries } } } -} +} \ No newline at end of file diff --git a/Ryujinx.Graphics.OpenGL/Window.cs b/Ryujinx.Graphics.OpenGL/Window.cs index 61b739b1..8f7917f9 100644 --- a/Ryujinx.Graphics.OpenGL/Window.cs +++ b/Ryujinx.Graphics.OpenGL/Window.cs @@ -10,6 +10,8 @@ namespace Ryujinx.Graphics.OpenGL private const int TextureCount = 3; private readonly OpenGLRenderer _renderer; + private bool _initialized; + private int _width; private int _height; private int _copyFramebufferHandle; @@ -179,6 +181,7 @@ namespace Ryujinx.Graphics.OpenGL public void InitializeBackgroundContext(IOpenGLContext baseContext) { BackgroundContext = new BackgroundContextWorker(baseContext); + _initialized = true; } public void CaptureFrame(int x, int y, int width, int height, bool isBgra, bool flipX, bool flipY) @@ -193,6 +196,11 @@ namespace Ryujinx.Graphics.OpenGL public void Dispose() { + if (!_initialized) + { + return; + } + BackgroundContext.Dispose(); if (_copyFramebufferHandle != 0) @@ -203,4 +211,4 @@ namespace Ryujinx.Graphics.OpenGL } } } -} +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs index 3f8ebe67..22e30329 100644 --- a/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs +++ b/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs @@ -22,6 +22,8 @@ namespace Ryujinx.Graphics.Vulkan private Device _device; private WindowBase _window; + private bool _initialized; + internal FormatCapabilities FormatCapabilities { get; private set; } internal HardwareCapabilities Capabilities; @@ -266,6 +268,8 @@ namespace Ryujinx.Graphics.Vulkan LoadFeatures(supportedExtensions, maxQueueCount, queueFamilyIndex); _window = new Window(this, _surface, _physicalDevice, _device); + + _initialized = true; } public BufferHandle CreateBuffer(int size) @@ -573,6 +577,11 @@ namespace Ryujinx.Graphics.Vulkan public unsafe void Dispose() { + if (!_initialized) + { + return; + } + CommandBufferPool.Dispose(); BackgroundResources.Dispose(); _counters.Dispose(); @@ -613,4 +622,4 @@ namespace Ryujinx.Graphics.Vulkan Api.DestroyInstance(_instance, null); } } -} +} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Horizon.cs b/Ryujinx.HLE/HOS/Horizon.cs index d2716beb..288c308a 100644 --- a/Ryujinx.HLE/HOS/Horizon.cs +++ b/Ryujinx.HLE/HOS/Horizon.cs @@ -479,7 +479,10 @@ namespace Ryujinx.HLE.HOS AudioRendererManager.Dispose(); - LibHacHorizonManager.PmClient.Fs.UnregisterProgram(LibHacHorizonManager.ApplicationClient.Os.GetCurrentProcessId().Value).ThrowIfFailure(); + if (LibHacHorizonManager.ApplicationClient != null) + { + LibHacHorizonManager.PmClient.Fs.UnregisterProgram(LibHacHorizonManager.ApplicationClient.Os.GetCurrentProcessId().Value).ThrowIfFailure(); + } KernelContext.Dispose(); } diff --git a/Ryujinx/Ui/MainWindow.cs b/Ryujinx/Ui/MainWindow.cs index 3f261f4d..9f9016b9 100644 --- a/Ryujinx/Ui/MainWindow.cs +++ b/Ryujinx/Ui/MainWindow.cs @@ -735,7 +735,6 @@ namespace Ryujinx.Ui _emulationContext.Dispose(); SwitchToGameTable(); - RendererWidget.Dispose(); return; } @@ -747,7 +746,6 @@ namespace Ryujinx.Ui _emulationContext.Dispose(); SwitchToGameTable(); - RendererWidget.Dispose(); return; } @@ -770,7 +768,6 @@ namespace Ryujinx.Ui _emulationContext.Dispose(); SwitchToGameTable(); - RendererWidget.Dispose(); return; } diff --git a/Ryujinx/Ui/RendererWidgetBase.cs b/Ryujinx/Ui/RendererWidgetBase.cs index 7e25ba2d..576d2d12 100644 --- a/Ryujinx/Ui/RendererWidgetBase.cs +++ b/Ryujinx/Ui/RendererWidgetBase.cs @@ -519,10 +519,14 @@ namespace Ryujinx.Ui _gpuCancellationTokenSource.Cancel(); _isStopped = true; - _isActive = false; + + if (_isActive) + { + _isActive = false; - _exitEvent.WaitOne(); - _exitEvent.Dispose(); + _exitEvent.WaitOne(); + _exitEvent.Dispose(); + } } private void NVStutterWorkaround() diff --git a/Ryujinx/Ui/VKRenderer.cs b/Ryujinx/Ui/VKRenderer.cs index 49578d2a..7e02c689 100644 --- a/Ryujinx/Ui/VKRenderer.cs +++ b/Ryujinx/Ui/VKRenderer.cs @@ -72,7 +72,8 @@ namespace Ryujinx.Ui protected override void Dispose(bool disposing) { - Device.DisposeGpu(); + Device?.DisposeGpu(); + NpadManager.Dispose(); } }