diff --git a/Ryujinx.Graphics.Gpu/Engine/Threed/SemaphoreUpdater.cs b/Ryujinx.Graphics.Gpu/Engine/Threed/SemaphoreUpdater.cs index f52f9f8140..63a2c841cc 100644 --- a/Ryujinx.Graphics.Gpu/Engine/Threed/SemaphoreUpdater.cs +++ b/Ryujinx.Graphics.Gpu/Engine/Threed/SemaphoreUpdater.cs @@ -152,21 +152,10 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed ulong ticks = _context.GetTimestamp(); - float divisor = type switch - { - ReportCounterType.SamplesPassed => _channel.TextureManager.RenderTargetScale * _channel.TextureManager.RenderTargetScale, - _ => 1f - }; - ICounterEvent counter = null; void resultHandler(object evt, ulong result) { - if (divisor != 1f) - { - result = (ulong)MathF.Ceiling(result / divisor); - } - CounterData counterData = new CounterData { Counter = result, diff --git a/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs b/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs index 9490684cd7..c79700fc24 100644 --- a/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs +++ b/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs @@ -178,7 +178,7 @@ namespace Ryujinx.Graphics.OpenGL } _pipeline.Initialize(this); - _counters.Initialize(); + _counters.Initialize(_pipeline); // This is required to disable [0, 1] clamping for SNorm outputs on compatibility profiles. // This call is expected to fail if we're running with a core profile, diff --git a/Ryujinx.Graphics.OpenGL/Pipeline.cs b/Ryujinx.Graphics.OpenGL/Pipeline.cs index 970feea0cc..62996bd0a1 100644 --- a/Ryujinx.Graphics.OpenGL/Pipeline.cs +++ b/Ryujinx.Graphics.OpenGL/Pipeline.cs @@ -773,6 +773,16 @@ namespace Ryujinx.Graphics.OpenGL _tfEnabled = false; } + public double GetCounterDivisor(CounterType type) + { + if (type == CounterType.SamplesPassed) + { + return _renderScale[0].X * _renderScale[0].X; + } + + return 1; + } + public void SetAlphaTest(bool enable, float reference, CompareOp op) { if (!enable) diff --git a/Ryujinx.Graphics.OpenGL/Queries/BufferedQuery.cs b/Ryujinx.Graphics.OpenGL/Queries/BufferedQuery.cs index 027495cdd5..99ea6a5c71 100644 --- a/Ryujinx.Graphics.OpenGL/Queries/BufferedQuery.cs +++ b/Ryujinx.Graphics.OpenGL/Queries/BufferedQuery.cs @@ -10,6 +10,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries { private const int MaxQueryRetries = 5000; private const long DefaultValue = -1; + private const ulong HighMask = 0xFFFFFFFF00000000; public int Query { get; } @@ -63,11 +64,17 @@ namespace Ryujinx.Graphics.OpenGL.Queries } } + private bool WaitingForValue(long data) + { + return data == DefaultValue || + ((ulong)data & HighMask) == (unchecked((ulong)DefaultValue) & HighMask); + } + public bool TryGetResult(out long result) { result = Marshal.ReadInt64(_bufferMap); - return result != DefaultValue; + return WaitingForValue(result); } public long AwaitResult(AutoResetEvent wakeSignal = null) @@ -76,7 +83,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries if (wakeSignal == null) { - while (data == DefaultValue) + while (WaitingForValue(data)) { data = Marshal.ReadInt64(_bufferMap); } @@ -84,10 +91,10 @@ namespace Ryujinx.Graphics.OpenGL.Queries else { int iterations = 0; - while (data == DefaultValue && iterations++ < MaxQueryRetries) + while (WaitingForValue(data) && iterations++ < MaxQueryRetries) { data = Marshal.ReadInt64(_bufferMap); - if (data == DefaultValue) + if (WaitingForValue(data)) { wakeSignal.WaitOne(1); } diff --git a/Ryujinx.Graphics.OpenGL/Queries/CounterQueue.cs b/Ryujinx.Graphics.OpenGL/Queries/CounterQueue.cs index 84b2bfdc90..e0aafa6faf 100644 --- a/Ryujinx.Graphics.OpenGL/Queries/CounterQueue.cs +++ b/Ryujinx.Graphics.OpenGL/Queries/CounterQueue.cs @@ -13,6 +13,8 @@ namespace Ryujinx.Graphics.OpenGL.Queries public CounterType Type { get; } public bool Disposed { get; private set; } + private readonly Pipeline _pipeline; + private Queue _events = new Queue(); private CounterQueueEvent _current; @@ -28,10 +30,12 @@ namespace Ryujinx.Graphics.OpenGL.Queries private Thread _consumerThread; - internal CounterQueue(CounterType type) + internal CounterQueue(Pipeline pipeline, CounterType type) { Type = type; + _pipeline = pipeline; + QueryTarget glType = GetTarget(Type); _queryPool = new Queue(QueryPoolInitialSize); @@ -119,7 +123,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries _current.ReserveForHostAccess(); } - _current.Complete(draws > 0); + _current.Complete(draws > 0, _pipeline.GetCounterDivisor(Type)); _events.Enqueue(_current); _current.OnResult += resultHandler; diff --git a/Ryujinx.Graphics.OpenGL/Queries/CounterQueueEvent.cs b/Ryujinx.Graphics.OpenGL/Queries/CounterQueueEvent.cs index 81451389c8..7297baab5b 100644 --- a/Ryujinx.Graphics.OpenGL/Queries/CounterQueueEvent.cs +++ b/Ryujinx.Graphics.OpenGL/Queries/CounterQueueEvent.cs @@ -26,6 +26,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries private object _lock = new object(); private ulong _result = ulong.MaxValue; + private double _divisor = 1f; public CounterQueueEvent(CounterQueue queue, QueryTarget type, ulong drawIndex) { @@ -45,9 +46,11 @@ namespace Ryujinx.Graphics.OpenGL.Queries ClearCounter = true; } - internal void Complete(bool withResult) + internal void Complete(bool withResult, double divisor) { _counter.End(withResult); + + _divisor = divisor; } internal bool TryConsume(ref ulong result, bool block, AutoResetEvent wakeSignal = null) @@ -78,7 +81,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries } } - result += (ulong)queryResult; + result += _divisor == 1 ? (ulong)queryResult : (ulong)Math.Ceiling(queryResult / _divisor); _result = result; diff --git a/Ryujinx.Graphics.OpenGL/Queries/Counters.cs b/Ryujinx.Graphics.OpenGL/Queries/Counters.cs index ebfd899c5d..e6c7ab2bde 100644 --- a/Ryujinx.Graphics.OpenGL/Queries/Counters.cs +++ b/Ryujinx.Graphics.OpenGL/Queries/Counters.cs @@ -14,12 +14,12 @@ namespace Ryujinx.Graphics.OpenGL.Queries _counterQueues = new CounterQueue[count]; } - public void Initialize() + public void Initialize(Pipeline pipeline) { for (int index = 0; index < _counterQueues.Length; index++) { CounterType type = (CounterType)index; - _counterQueues[index] = new CounterQueue(type); + _counterQueues[index] = new CounterQueue(pipeline, type); } } diff --git a/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 583bb9539a..3abab06579 100644 --- a/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -684,6 +684,16 @@ namespace Ryujinx.Graphics.Vulkan _tfEnabled = false; } + public double GetCounterDivisor(CounterType type) + { + if (type == CounterType.SamplesPassed) + { + return _renderScale[0].X * _renderScale[0].X; + } + + return 1; + } + public bool IsCommandBufferActive(CommandBuffer cb) { return CommandBuffer.Handle == cb.Handle; diff --git a/Ryujinx.Graphics.Vulkan/Queries/BufferedQuery.cs b/Ryujinx.Graphics.Vulkan/Queries/BufferedQuery.cs index 29efd8e74d..861155a30c 100644 --- a/Ryujinx.Graphics.Vulkan/Queries/BufferedQuery.cs +++ b/Ryujinx.Graphics.Vulkan/Queries/BufferedQuery.cs @@ -12,6 +12,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries private const int MaxQueryRetries = 5000; private const long DefaultValue = -1; private const long DefaultValueInt = 0xFFFFFFFF; + private const ulong HighMask = 0xFFFFFFFF00000000; private readonly Vk _api; private readonly Device _device; @@ -125,6 +126,12 @@ namespace Ryujinx.Graphics.Vulkan.Queries } } + private bool WaitingForValue(long data) + { + return data == _defaultValue || + (!_result32Bit && ((ulong)data & HighMask) == ((ulong)_defaultValue & HighMask)); + } + public bool TryGetResult(out long result) { result = Marshal.ReadInt64(_bufferMap); @@ -138,7 +145,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries if (wakeSignal == null) { - while (data == _defaultValue) + while (WaitingForValue(data)) { data = Marshal.ReadInt64(_bufferMap); } @@ -146,10 +153,10 @@ namespace Ryujinx.Graphics.Vulkan.Queries else { int iterations = 0; - while (data == _defaultValue && iterations++ < MaxQueryRetries) + while (WaitingForValue(data) && iterations++ < MaxQueryRetries) { data = Marshal.ReadInt64(_bufferMap); - if (data == _defaultValue) + if (WaitingForValue(data)) { wakeSignal.WaitOne(1); } diff --git a/Ryujinx.Graphics.Vulkan/Queries/CounterQueue.cs b/Ryujinx.Graphics.Vulkan/Queries/CounterQueue.cs index 7293b74f98..c30d91c42b 100644 --- a/Ryujinx.Graphics.Vulkan/Queries/CounterQueue.cs +++ b/Ryujinx.Graphics.Vulkan/Queries/CounterQueue.cs @@ -148,7 +148,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries _current.ReserveForHostAccess(); } - _current.Complete(draws > 0 && Type != CounterType.TransformFeedbackPrimitivesWritten); + _current.Complete(draws > 0 && Type != CounterType.TransformFeedbackPrimitivesWritten, _pipeline.GetCounterDivisor(Type)); _events.Enqueue(_current); _current.OnResult += resultHandler; diff --git a/Ryujinx.Graphics.Vulkan/Queries/CounterQueueEvent.cs b/Ryujinx.Graphics.Vulkan/Queries/CounterQueueEvent.cs index 6b780ba34a..d3aedb2f38 100644 --- a/Ryujinx.Graphics.Vulkan/Queries/CounterQueueEvent.cs +++ b/Ryujinx.Graphics.Vulkan/Queries/CounterQueueEvent.cs @@ -24,6 +24,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries private object _lock = new object(); private ulong _result = ulong.MaxValue; + private double _divisor = 1f; public CounterQueueEvent(CounterQueue queue, CounterType type, ulong drawIndex) { @@ -52,9 +53,11 @@ namespace Ryujinx.Graphics.Vulkan.Queries ClearCounter = true; } - internal void Complete(bool withResult) + internal void Complete(bool withResult, double divisor) { _counter.End(withResult); + + _divisor = divisor; } internal bool TryConsume(ref ulong result, bool block, AutoResetEvent wakeSignal = null) @@ -85,7 +88,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries } } - result += (ulong)queryResult; + result += _divisor == 1 ? (ulong)queryResult : (ulong)Math.Ceiling(queryResult / _divisor); _result = result;