From cd48576f5846aa89a36bfc833e9de5dde9627aed Mon Sep 17 00:00:00 2001
From: riperiperi <rhy3756547@hotmail.com>
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.
---
 .../Queries/CounterQueueEvent.cs                   | 100 +++++++++++++++++++++
 1 file changed, 100 insertions(+)
 create mode 100644 Ryujinx.Graphics.OpenGL/Queries/CounterQueueEvent.cs

(limited to 'Ryujinx.Graphics.OpenGL/Queries/CounterQueueEvent.cs')

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);
+        }
+    }
+}
-- 
cgit v1.2.3-70-g09d2