From 78902911e90bafa22ce930154c834da75010083d Mon Sep 17 00:00:00 2001 From: ParantezTech <12572227+par274@users.noreply.github.com> Date: Tue, 6 Oct 2026 17:47:34 +0300 Subject: [PATCH] [GPU] Run relay work after accepted command streams Co-authored-by: Sekai <140012992+igettingit@users.noreply.github.com> --- .../Gpu/Scheduling/GpuWorkerRelay.cs | 46 ++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/src/SharpEmu.Libs/Gpu/Scheduling/GpuWorkerRelay.cs b/src/SharpEmu.Libs/Gpu/Scheduling/GpuWorkerRelay.cs index 19e67f0..028e46b 100644 --- a/src/SharpEmu.Libs/Gpu/Scheduling/GpuWorkerRelay.cs +++ b/src/SharpEmu.Libs/Gpu/Scheduling/GpuWorkerRelay.cs @@ -14,16 +14,60 @@ public sealed class GpuWorkerRelay : IGpuQueueRelay private readonly object _gate = new(); private readonly Queue _commands = new(); private readonly Action _wake; + private readonly Func? _tryEnqueueAfterPendingWork; private int _pendingCount; private bool _accepting = true; - public GpuWorkerRelay(Action wake) + public GpuWorkerRelay(Action wake, Func? tryEnqueueAfterPendingWork = null) { _wake = wake; + _tryEnqueueAfterPendingWork = tryEnqueueAfterPendingWork; } public bool TryRunAfterPendingWork(Action work) => TryRunOnGpuQueue(work); + public bool TryRunAfterAcceptedCommandStreams(Action work) + { + ArgumentNullException.ThrowIfNull(work); + if (IsGpuQueueThread || _tryEnqueueAfterPendingWork is null) + { + return TryRunOnGpuQueue(work); + } + + using var done = new SemaphoreSlim(0); + System.Runtime.ExceptionServices.ExceptionDispatchInfo? failure = null; + if (!_tryEnqueueAfterPendingWork( + () => + { + try + { + work(); + } + catch (Exception exception) + { + failure = System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(exception); + } + finally + { + done.Release(); + } + }, + () => + { + failure = System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture( + new OperationCanceledException( + "The command stream stopped before the ordered GPU worker action could run.")); + done.Release(); + })) + { + return false; + } + + done.Wait(); + failure?.Throw(); + return true; + } + public bool IsGpuQueueThread => _boundWorker == this; public bool HasPendingCommands => Volatile.Read(ref _pendingCount) != 0;