diff options
author | riperiperi <rhy3756547@hotmail.com> | 2020-05-04 03:24:59 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-04 12:24:59 +1000 |
commit | cd48576f5846aa89a36bfc833e9de5dde9627aed (patch) | |
tree | 5bf04a43725cf7fdc098cde59856798a67b839e0 /Ryujinx.Graphics.OpenGL/Queries/CounterQueueEvent.cs | |
parent | 651a07c6c2a3e89c059d56e916c45e1881d56abc (diff) |
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.
Diffstat (limited to 'Ryujinx.Graphics.OpenGL/Queries/CounterQueueEvent.cs')
-rw-r--r-- | Ryujinx.Graphics.OpenGL/Queries/CounterQueueEvent.cs | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/Ryujinx.Graphics.OpenGL/Queries/CounterQueueEvent.cs b/Ryujinx.Graphics.OpenGL/Queries/CounterQueueEvent.cs new file mode 100644 index 00000000..0fba24a1 --- /dev/null +++ b/Ryujinx.Graphics.OpenGL/Queries/CounterQueueEvent.cs @@ -0,0 +1,100 @@ +using OpenTK.Graphics.OpenGL; +using Ryujinx.Graphics.GAL; +using System; +using System.Threading; + +namespace Ryujinx.Graphics.OpenGL.Queries +{ + class CounterQueueEvent : ICounterEvent + { + public event EventHandler<ulong> OnResult; + + public QueryTarget Type { get; } + public bool ClearCounter { get; private set; } + public int Query => _counter.Query; + + public bool Disposed { get; private set; } + public bool Invalid { get; set; } + + private CounterQueue _queue; + private BufferedQuery _counter; + + private object _lock = new object(); + + public CounterQueueEvent(CounterQueue queue, QueryTarget type) + { + _queue = queue; + + _counter = queue.GetQueryObject(); + Type = type; + + _counter.Begin(); + } + + internal void Clear() + { + _counter.Reset(); + ClearCounter = true; + } + + internal void Complete() + { + _counter.End(); + } + + internal bool TryConsume(ref ulong result, bool block, AutoResetEvent wakeSignal = null) + { + lock (_lock) + { + if (Disposed) + { + return true; + } + + if (ClearCounter || Type == QueryTarget.Timestamp) + { + result = 0; + } + + long queryResult; + + if (block) + { + queryResult = _counter.AwaitResult(wakeSignal); + } + else + { + if (!_counter.TryGetResult(out queryResult)) + { + return false; + } + } + + result += (ulong)queryResult; + + OnResult?.Invoke(this, result); + + Dispose(); // Return the our resources to the pool. + + return true; + } + } + + public void Flush() + { + if (Disposed) + { + return; + } + + // Tell the queue to process all events up to this one. + _queue.FlushTo(this); + } + + public void Dispose() + { + Disposed = true; + _queue.ReturnQueryObject(_counter); + } + } +} |