mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2025-02-21 16:43:35 +00:00
Update counter queue to be similar to the OGL one
Fixes softlocks when games had to flush counters.
This commit is contained in:
parent
d55f664908
commit
23b8bd8642
2 changed files with 34 additions and 32 deletions
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<BufferedQuery> _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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue