aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.GAL/Multithreading
diff options
context:
space:
mode:
authorriperiperi <rhy3756547@hotmail.com>2023-05-31 22:43:20 +0100
committerGitHub <noreply@github.com>2023-05-31 21:43:20 +0000
commitc6676007bfdc65724afebac27990c47a5d6aa3dd (patch)
tree83196584e20c31b405db2f801a01c0204bc588bf /src/Ryujinx.Graphics.GAL/Multithreading
parent92b0b7d753a07b9865386881524838fe42f3668a (diff)
GPU: Dispose Renderer after running deferred actions (#5144)
* GAL: Dispose Renderer after running deferred actions Deferred actions from disposing physical memory instances always dispose the resources in their caches. The renderer can't be disposed before these resources get disposed, otherwise the dispose actions will not actually run, and the ThreadedRenderer may get stuck trying to enqueue too many commands when there is nothing consuming them. This should fix most instances of the emulator freezing on close. * Wait for main render commands to finish, but keep RenderThread alive til dispose * Address some feedback. * No parameterize needed * Set thread name as part of constructor * Port to Ava and SDL2
Diffstat (limited to 'src/Ryujinx.Graphics.GAL/Multithreading')
-rw-r--r--src/Ryujinx.Graphics.GAL/Multithreading/ThreadedRenderer.cs28
1 files changed, 18 insertions, 10 deletions
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedRenderer.cs b/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedRenderer.cs
index 3e179621..e6169d89 100644
--- a/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedRenderer.cs
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedRenderer.cs
@@ -30,7 +30,6 @@ namespace Ryujinx.Graphics.GAL.Multithreading
private IRenderer _baseRenderer;
private Thread _gpuThread;
private Thread _backendThread;
- private bool _disposed;
private bool _running;
private AutoResetEvent _frameComplete = new AutoResetEvent(true);
@@ -98,19 +97,17 @@ namespace Ryujinx.Graphics.GAL.Multithreading
_refQueue = new object[MaxRefsPerCommand * QueueCount];
}
- public void RunLoop(Action gpuLoop)
+ public void RunLoop(ThreadStart gpuLoop)
{
_running = true;
_backendThread = Thread.CurrentThread;
- _gpuThread = new Thread(() => {
- gpuLoop();
- _running = false;
- _galWorkAvailable.Set();
- });
+ _gpuThread = new Thread(gpuLoop)
+ {
+ Name = "GPU.MainThread"
+ };
- _gpuThread.Name = "GPU.MainThread";
_gpuThread.Start();
RenderLoop();
@@ -120,7 +117,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
{
// Power through the render queue until the Gpu thread work is done.
- while (_running && !_disposed)
+ while (_running)
{
_galWorkAvailable.Wait();
_galWorkAvailable.Reset();
@@ -488,12 +485,23 @@ namespace Ryujinx.Graphics.GAL.Multithreading
return _baseRenderer.PrepareHostMapping(address, size);
}
+ public void FlushThreadedCommands()
+ {
+ SpinWait wait = new();
+
+ while (Volatile.Read(ref _commandCount) > 0)
+ {
+ wait.SpinOnce();
+ }
+ }
+
public void Dispose()
{
// Dispose must happen from the render thread, after all commands have completed.
// Stop the GPU thread.
- _disposed = true;
+ _running = false;
+ _galWorkAvailable.Set();
if (_gpuThread != null && _gpuThread.IsAlive)
{