diff --git a/src/Ryujinx.Graphics.GAL/IPipeline.cs b/src/Ryujinx.Graphics.GAL/IPipeline.cs index 3ba084aa5..e196cf4ad 100644 --- a/src/Ryujinx.Graphics.GAL/IPipeline.cs +++ b/src/Ryujinx.Graphics.GAL/IPipeline.cs @@ -103,7 +103,7 @@ namespace Ryujinx.Graphics.GAL void TextureBarrier(); void TextureBarrierTiled(); - bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual); + bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual, bool forwarded = false); bool TryHostConditionalRendering(ICounterEvent value, ICounterEvent compare, bool isEqual); void EndHostConditionalRendering(); } diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/TryHostConditionalRenderingCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/TryHostConditionalRenderingCommand.cs index 21e3a0d12..99d24c211 100644 --- a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/TryHostConditionalRenderingCommand.cs +++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/TryHostConditionalRenderingCommand.cs @@ -19,7 +19,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands public static void Run(ref TryHostConditionalRenderingCommand command, ThreadedRenderer threaded, IRenderer renderer) { - renderer.Pipeline.TryHostConditionalRendering(command._value.Get(threaded)?.Base, command._compare, command._isEqual); + renderer.Pipeline.TryHostConditionalRendering(command._value.Get(threaded)?.Base, command._compare, command._isEqual, true); } } } diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs b/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs index ad50bddf4..88064cf1b 100644 --- a/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs +++ b/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs @@ -333,7 +333,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading _renderer.QueueCommand(); } - public bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual) + public bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual, bool forwarded = false) { var evt = value as ThreadedCounterEvent; if (evt != null) diff --git a/src/Ryujinx.Graphics.OpenGL/Pipeline.cs b/src/Ryujinx.Graphics.OpenGL/Pipeline.cs index a31a0ad12..a821b6e6a 100644 --- a/src/Ryujinx.Graphics.OpenGL/Pipeline.cs +++ b/src/Ryujinx.Graphics.OpenGL/Pipeline.cs @@ -1629,7 +1629,7 @@ namespace Ryujinx.Graphics.OpenGL } } - public bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual) + public bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual, bool forwarded = false) { // Compare an event and a constant value. if (value is CounterQueueEvent evt) @@ -1642,7 +1642,8 @@ namespace Ryujinx.Graphics.OpenGL if (compare == 0 && evt.Type == QueryTarget.SamplesPassed && evt.ClearCounter) { - if (!value.ReserveForHostAccess()) + // If the call is forwarded from backend threading, then we have already reserved host access. + if (!forwarded && !value.ReserveForHostAccess()) { // If the event has been flushed, then just use the values on the CPU. // The query object may already be repurposed for another draw (eg. begin + end). diff --git a/src/Ryujinx.Graphics.OpenGL/Queries/CounterQueueEvent.cs b/src/Ryujinx.Graphics.OpenGL/Queries/CounterQueueEvent.cs index a67d868e8..9e8919adc 100644 --- a/src/Ryujinx.Graphics.OpenGL/Queries/CounterQueueEvent.cs +++ b/src/Ryujinx.Graphics.OpenGL/Queries/CounterQueueEvent.cs @@ -21,7 +21,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries private readonly CounterQueue _queue; private readonly BufferedQuery _counter; - private bool _hostAccessReserved = false; + private int _hostAccessReserved = 0; private int _refCount = 1; // Starts with a reference from the counter queue. private readonly object _lock = new(); @@ -115,8 +115,9 @@ namespace Ryujinx.Graphics.OpenGL.Queries public bool ReserveForHostAccess() { - if (_hostAccessReserved) + if (_hostAccessReserved > 0) { + Interlocked.Increment(ref _hostAccessReserved); return true; } @@ -132,14 +133,14 @@ namespace Ryujinx.Graphics.OpenGL.Queries return false; } - _hostAccessReserved = true; + _hostAccessReserved = Interlocked.Increment(ref _hostAccessReserved); return true; } public void ReleaseHostAccess() { - _hostAccessReserved = false; + Interlocked.Decrement(ref _hostAccessReserved); DecrementRefCount(); } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineFull.cs b/src/Ryujinx.Graphics.Vulkan/PipelineFull.cs index 4987548cd..b0bda2648 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineFull.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineFull.cs @@ -131,7 +131,7 @@ namespace Ryujinx.Graphics.Vulkan _activeConditionalRender = null; } - public bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual) + public bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual, bool forwarded = false) { // Compare an event and a constant value. if (value is CounterQueueEvent evt) @@ -144,7 +144,8 @@ namespace Ryujinx.Graphics.Vulkan if (compare == 0 && evt.Type == CounterType.SamplesPassed && evt.ClearCounter) { - if (!value.ReserveForHostAccess()) + // If the call is forwarded from backend threading, then we have already reserved host access. + if (!forwarded && !value.ReserveForHostAccess()) { // If the event has been flushed, then just use the values on the CPU. // The query object may already be repurposed for another draw (eg. begin + end). diff --git a/src/Ryujinx.Graphics.Vulkan/Queries/CounterQueueEvent.cs b/src/Ryujinx.Graphics.Vulkan/Queries/CounterQueueEvent.cs index 14d3050bf..e30bb3ecc 100644 --- a/src/Ryujinx.Graphics.Vulkan/Queries/CounterQueueEvent.cs +++ b/src/Ryujinx.Graphics.Vulkan/Queries/CounterQueueEvent.cs @@ -19,7 +19,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries private readonly CounterQueue _queue; private readonly BufferedQuery _counter; - private bool _hostAccessReserved; + private int _hostAccessReserved; private int _refCount = 1; // Starts with a reference from the counter queue. private readonly object _lock = new(); @@ -121,8 +121,9 @@ namespace Ryujinx.Graphics.Vulkan.Queries public bool ReserveForHostAccess() { - if (_hostAccessReserved) + if (_hostAccessReserved > 0) { + Interlocked.Increment(ref _hostAccessReserved); return true; } @@ -138,14 +139,14 @@ namespace Ryujinx.Graphics.Vulkan.Queries return false; } - _hostAccessReserved = true; + Interlocked.Increment(ref _hostAccessReserved); return true; } public void ReleaseHostAccess() { - _hostAccessReserved = false; + Interlocked.Decrement(ref _hostAccessReserved); DecrementRefCount(); }