diff --git a/Ryujinx.Graphics.Vulkan/PipelineFull.cs b/Ryujinx.Graphics.Vulkan/PipelineFull.cs index 0d461b213..e25f8bdf0 100644 --- a/Ryujinx.Graphics.Vulkan/PipelineFull.cs +++ b/Ryujinx.Graphics.Vulkan/PipelineFull.cs @@ -206,16 +206,25 @@ namespace Ryujinx.Graphics.Vulkan // The GPU will flush the queries to CPU and evaluate the condition there instead. - FlushCommandsImpl(); // The thread will be stalled manually flushing the counter, so flush GL commands now. + FlushPendingQuery(); // The thread will be stalled manually flushing the counter, so flush commands now. return false; } public bool TryHostConditionalRendering(ICounterEvent value, ICounterEvent compare, bool isEqual) { - FlushCommandsImpl(); // The thread will be stalled manually flushing the counter, so flush GL commands now. + FlushPendingQuery(); // The thread will be stalled manually flushing the counter, so flush commands now. return false; } + private void FlushPendingQuery() + { + if (_hasPendingQuery) + { + _hasPendingQuery = false; + FlushCommandsImpl(); + } + } + public void FlushCommandsImpl([System.Runtime.CompilerServices.CallerMemberName] string caller = "") { // System.Console.WriteLine("flush by " + caller); @@ -285,11 +294,7 @@ namespace Ryujinx.Graphics.Vulkan protected override void SignalProgramChange() { - if (_hasPendingQuery) - { - _hasPendingQuery = false; - FlushCommandsImpl(); - } + FlushPendingQuery(); } } } diff --git a/Ryujinx.Graphics.Vulkan/Queries/CounterQueue.cs b/Ryujinx.Graphics.Vulkan/Queries/CounterQueue.cs index 197cd5b5c..6f0b25c60 100644 --- a/Ryujinx.Graphics.Vulkan/Queries/CounterQueue.cs +++ b/Ryujinx.Graphics.Vulkan/Queries/CounterQueue.cs @@ -21,12 +21,14 @@ namespace Ryujinx.Graphics.Vulkan.Queries private CounterQueueEvent _current; private ulong _accumulatedCounter; + private int _waiterCount; private object _lock = new object(); private Queue _queryPool; private AutoResetEvent _queuedEvent = new AutoResetEvent(false); private AutoResetEvent _wakeSignal = new AutoResetEvent(false); + private AutoResetEvent _eventConsumed = new AutoResetEvent(false); private Thread _consumerThread; @@ -69,7 +71,13 @@ namespace Ryujinx.Graphics.Vulkan.Queries } else { - evt.TryConsume(ref _accumulatedCounter, true, _wakeSignal); + // Spin-wait rather than sleeping if there are any waiters, by passing null instead of the wake signal. + evt.TryConsume(ref _accumulatedCounter, true, _waiterCount == 0 ? _wakeSignal : null); + } + + if (_waiterCount > 0) + { + _eventConsumed.Set(); } } } @@ -175,32 +183,17 @@ namespace Ryujinx.Graphics.Vulkan.Queries public void FlushTo(CounterQueueEvent evt) { - lock (_lock) + // Flush the counter queue on the main thread. + Interlocked.Increment(ref _waiterCount); + + _wakeSignal.Set(); + + while (!evt.Disposed) { - if (evt.Disposed) - { - return; - } - - // Tell the queue to process all events up to this one. - while (_events.Count > 0) - { - CounterQueueEvent flush = _events.Peek(); - - if (flush.DrawIndex > evt.DrawIndex) - { - return; - } - - _events.Dequeue(); - flush.TryConsume(ref _accumulatedCounter, true); - - if (flush == evt) - { - return; - } - } + _eventConsumed.WaitOne(1); } + + Interlocked.Decrement(ref _waiterCount); } public void Dispose() @@ -227,6 +220,10 @@ namespace Ryujinx.Graphics.Vulkan.Queries { query.Dispose(); } + + _queuedEvent.Dispose(); + _wakeSignal.Dispose(); + _eventConsumed.Dispose(); } } }