From cd48576f5846aa89a36bfc833e9de5dde9627aed Mon Sep 17 00:00:00 2001 From: riperiperi Date: Mon, 4 May 2020 03:24:59 +0100 Subject: Implement Counter Queue and Partial Host Conditional Rendering (#1167) * Implementation of query queue and host conditional rendering * Resolve some comments. * Use overloads instead of passing object. * Wake the consumer threads when incrementing syncpoints. Also, do a busy loop when awaiting the counter for a blocking flush, rather than potentially sleeping the thread. * Ensure there's a command between begin and end query. --- .../Engine/MethodConditionalRendering.cs | 86 +++++++++++++++++----- 1 file changed, 66 insertions(+), 20 deletions(-) (limited to 'Ryujinx.Graphics.Gpu/Engine/MethodConditionalRendering.cs') diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodConditionalRendering.cs b/Ryujinx.Graphics.Gpu/Engine/MethodConditionalRendering.cs index 4775de02..c8d47b9f 100644 --- a/Ryujinx.Graphics.Gpu/Engine/MethodConditionalRendering.cs +++ b/Ryujinx.Graphics.Gpu/Engine/MethodConditionalRendering.cs @@ -1,26 +1,34 @@ using Ryujinx.Common.Logging; +using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Gpu.State; namespace Ryujinx.Graphics.Gpu.Engine { partial class Methods { + enum ConditionalRenderEnabled + { + False, + True, + Host + } + /// /// Checks if draws and clears should be performed, according /// to currently set conditional rendering conditions. /// /// GPU state /// True if rendering is enabled, false otherwise - private bool GetRenderEnable(GpuState state) + private ConditionalRenderEnabled GetRenderEnable(GpuState state) { ConditionState condState = state.Get(MethodOffset.ConditionState); switch (condState.Condition) { case Condition.Always: - return true; + return ConditionalRenderEnabled.True; case Condition.Never: - return false; + return ConditionalRenderEnabled.False; case Condition.ResultNonZero: return CounterNonZero(condState.Address.Pack()); case Condition.Equal: @@ -31,22 +39,32 @@ namespace Ryujinx.Graphics.Gpu.Engine Logger.PrintWarning(LogClass.Gpu, $"Invalid conditional render condition \"{condState.Condition}\"."); - return true; + return ConditionalRenderEnabled.True; } /// /// Checks if the counter value at a given GPU memory address is non-zero. /// /// GPU virtual address of the counter value - /// True if the value is not zero, false otherwise - private bool CounterNonZero(ulong gpuVa) + /// True if the value is not zero, false otherwise. Returns host if handling with host conditional rendering + private ConditionalRenderEnabled CounterNonZero(ulong gpuVa) { - if (!FindAndFlush(gpuVa)) + ICounterEvent evt = _counterCache.FindEvent(gpuVa); + + if (evt == null) { - return false; + return ConditionalRenderEnabled.False; } - return _context.MemoryAccessor.ReadUInt64(gpuVa) != 0; + if (_context.Renderer.Pipeline.TryHostConditionalRendering(evt, 0L, false)) + { + return ConditionalRenderEnabled.Host; + } + else + { + evt.Flush(); + return (_context.MemoryAccessor.ReadUInt64(gpuVa) != 0) ? ConditionalRenderEnabled.True : ConditionalRenderEnabled.False; + } } /// @@ -54,29 +72,57 @@ namespace Ryujinx.Graphics.Gpu.Engine /// /// GPU virtual address /// True to check if the values are equal, false to check if they are not equal - /// True if the condition is met, false otherwise - private bool CounterCompare(ulong gpuVa, bool isEqual) + /// True if the condition is met, false otherwise. Returns host if handling with host conditional rendering + private ConditionalRenderEnabled CounterCompare(ulong gpuVa, bool isEqual) { - if (!FindAndFlush(gpuVa) && !FindAndFlush(gpuVa + 16)) + ICounterEvent evt = FindEvent(gpuVa); + ICounterEvent evt2 = FindEvent(gpuVa + 16); + + if (evt == null && evt2 == null) + { + return ConditionalRenderEnabled.False; + } + + bool useHost; + + if (evt != null && evt2 == null) + { + useHost = _context.Renderer.Pipeline.TryHostConditionalRendering(evt, _context.MemoryAccessor.ReadUInt64(gpuVa + 16), isEqual); + } + else if (evt == null && evt2 != null) + { + useHost = _context.Renderer.Pipeline.TryHostConditionalRendering(evt2, _context.MemoryAccessor.ReadUInt64(gpuVa), isEqual); + } + else { - return false; + useHost = _context.Renderer.Pipeline.TryHostConditionalRendering(evt, evt2, isEqual); } - ulong x = _context.MemoryAccessor.ReadUInt64(gpuVa); - ulong y = _context.MemoryAccessor.ReadUInt64(gpuVa + 16); + if (useHost) + { + return ConditionalRenderEnabled.Host; + } + else + { + evt?.Flush(); + evt2?.Flush(); - return isEqual ? x == y : x != y; + ulong x = _context.MemoryAccessor.ReadUInt64(gpuVa); + ulong y = _context.MemoryAccessor.ReadUInt64(gpuVa + 16); + + return (isEqual ? x == y : x != y) ? ConditionalRenderEnabled.True : ConditionalRenderEnabled.False; + } } /// /// Tries to find a counter that is supposed to be written at the specified address, - /// flushing if necessary. + /// returning the related event. /// /// GPU virtual address where the counter is supposed to be written - /// True if a counter value is found at the specified address, false otherwise - private bool FindAndFlush(ulong gpuVa) + /// The counter event, or null if not present + private ICounterEvent FindEvent(ulong gpuVa) { - return _counterCache.Contains(gpuVa); + return _counterCache.FindEvent(gpuVa); } } } -- cgit v1.2.3