mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2025-02-22 17:10:19 +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.
|
// 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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryHostConditionalRendering(ICounterEvent value, ICounterEvent compare, bool isEqual)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void FlushPendingQuery()
|
||||||
|
{
|
||||||
|
if (_hasPendingQuery)
|
||||||
|
{
|
||||||
|
_hasPendingQuery = false;
|
||||||
|
FlushCommandsImpl();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void FlushCommandsImpl([System.Runtime.CompilerServices.CallerMemberName] string caller = "")
|
public void FlushCommandsImpl([System.Runtime.CompilerServices.CallerMemberName] string caller = "")
|
||||||
{
|
{
|
||||||
// System.Console.WriteLine("flush by " + caller);
|
// System.Console.WriteLine("flush by " + caller);
|
||||||
|
@ -285,11 +294,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
|
|
||||||
protected override void SignalProgramChange()
|
protected override void SignalProgramChange()
|
||||||
{
|
{
|
||||||
if (_hasPendingQuery)
|
FlushPendingQuery();
|
||||||
{
|
|
||||||
_hasPendingQuery = false;
|
|
||||||
FlushCommandsImpl();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,12 +21,14 @@ namespace Ryujinx.Graphics.Vulkan.Queries
|
||||||
private CounterQueueEvent _current;
|
private CounterQueueEvent _current;
|
||||||
|
|
||||||
private ulong _accumulatedCounter;
|
private ulong _accumulatedCounter;
|
||||||
|
private int _waiterCount;
|
||||||
|
|
||||||
private object _lock = new object();
|
private object _lock = new object();
|
||||||
|
|
||||||
private Queue<BufferedQuery> _queryPool;
|
private Queue<BufferedQuery> _queryPool;
|
||||||
private AutoResetEvent _queuedEvent = new AutoResetEvent(false);
|
private AutoResetEvent _queuedEvent = new AutoResetEvent(false);
|
||||||
private AutoResetEvent _wakeSignal = new AutoResetEvent(false);
|
private AutoResetEvent _wakeSignal = new AutoResetEvent(false);
|
||||||
|
private AutoResetEvent _eventConsumed = new AutoResetEvent(false);
|
||||||
|
|
||||||
private Thread _consumerThread;
|
private Thread _consumerThread;
|
||||||
|
|
||||||
|
@ -69,7 +71,13 @@ namespace Ryujinx.Graphics.Vulkan.Queries
|
||||||
}
|
}
|
||||||
else
|
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)
|
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)
|
_eventConsumed.WaitOne(1);
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Interlocked.Decrement(ref _waiterCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
@ -227,6 +220,10 @@ namespace Ryujinx.Graphics.Vulkan.Queries
|
||||||
{
|
{
|
||||||
query.Dispose();
|
query.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_queuedEvent.Dispose();
|
||||||
|
_wakeSignal.Dispose();
|
||||||
|
_eventConsumed.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue