diff --git a/src/Ryujinx.Graphics.Vulkan/Auto.cs b/src/Ryujinx.Graphics.Vulkan/Auto.cs index 7ce309a5d..9c8c7ff4b 100644 --- a/src/Ryujinx.Graphics.Vulkan/Auto.cs +++ b/src/Ryujinx.Graphics.Vulkan/Auto.cs @@ -1,3 +1,4 @@ +using Ryujinx.Common.Logging; using System; using System.Diagnostics; using System.Threading; @@ -114,7 +115,7 @@ namespace Ryujinx.Graphics.Vulkan cbs.AddDependant(this); // We need to add a dependency on the command buffer to all objects this object - // references aswell. + // references as well. if (_referencedObjs != null) { for (int i = 0; i < _referencedObjs.Length; i++) @@ -176,6 +177,8 @@ namespace Ryujinx.Graphics.Vulkan } } + // This can somehow become -1. + // Logger.Info?.PrintMsg(LogClass.Gpu, $"_referenceCount: {_referenceCount}"); Debug.Assert(_referenceCount >= 0); } diff --git a/src/Ryujinx/Systems/AppHost.cs b/src/Ryujinx/Systems/AppHost.cs index b5f40a4dc..4000f370a 100644 --- a/src/Ryujinx/Systems/AppHost.cs +++ b/src/Ryujinx/Systems/AppHost.cs @@ -617,10 +617,18 @@ namespace Ryujinx.Ava.Systems Device.Dispose(); // NOTE: The render loop is allowed to stay alive until the renderer itself is disposed, as it may handle resource dispose. - // We only need to wait for all commands submitted during the main gpu loop to be processed, unless the GPU event is cancelled. + // We only need to wait for all commands submitted during the main gpu loop to be processed. + // If the GPU has no work and is cancelled, we need to handle that as well. - WaitHandle.WaitAny(new []{_gpuDoneEvent, _gpuCancellationTokenSource.Token.WaitHandle}); + WaitHandle.WaitAny(new[] { _gpuDoneEvent, _gpuCancellationTokenSource.Token.WaitHandle }); _gpuCancellationTokenSource.Dispose(); + + // Waiting for work to be finished before we dispose. + if (_renderingStarted) + { + Device.Gpu.WaitUntilGpuReady(); + } + _gpuDoneEvent.Dispose(); DisposeGpu(); @@ -632,10 +640,16 @@ namespace Ryujinx.Ava.Systems { if (Device.Processes != null) { - // If the ActiveApplication is null, then the ProgramIdText should be - // so that we aren't arbitrarily applying metadata to something that doesn't exist. - MainWindowViewModel.UpdateGameMetadata(Device.Processes.ActiveApplication?.ProgramIdText ?? "", - _playTimer.Elapsed); + // If the ActiveApplication is null, then the ProgramIdText is invalid. + if (Device.Processes.ActiveApplication is not null) + { + MainWindowViewModel.UpdateGameMetadata(Device.Processes.ActiveApplication.ProgramIdText, + _playTimer.Elapsed); + } + else + { + Logger.Error?.PrintMsg(LogClass.Application, "Cannot save metadata because title ID is invalid."); + } } ConfigurationState.Instance.System.IgnoreMissingServices.Event -= UpdateIgnoreMissingServicesState; @@ -677,6 +691,12 @@ namespace Ryujinx.Ava.Systems } else { + // No use waiting on something that never started work + if (_renderingStarted) + { + Device.Gpu.WaitUntilGpuReady(); + } + Device.DisposeGpu(); } } @@ -1115,7 +1135,9 @@ namespace Ryujinx.Ava.Systems // Make sure all commands in the run loop are fully executed before leaving the loop. if (Device.Gpu.Renderer is ThreadedRenderer threaded) { + Logger.Info?.PrintMsg(LogClass.Gpu, "Flushing threaded commands..."); threaded.FlushThreadedCommands(); + Logger.Info?.PrintMsg(LogClass.Gpu, "Flushed!"); } _gpuDoneEvent.Set(); diff --git a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs index c537b7ad8..d720568b7 100644 --- a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs @@ -1717,7 +1717,6 @@ namespace Ryujinx.Ava.UI.ViewModels this, TopLevel); - // Needs a new name to better fit code styling CancellationTokenSource cts = new CancellationTokenSource(); try