aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.HLE/OsHle/Services/Nv/NvHostCtrl/NvHostSyncPt.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.HLE/OsHle/Services/Nv/NvHostCtrl/NvHostSyncPt.cs')
-rw-r--r--Ryujinx.HLE/OsHle/Services/Nv/NvHostCtrl/NvHostSyncPt.cs107
1 files changed, 107 insertions, 0 deletions
diff --git a/Ryujinx.HLE/OsHle/Services/Nv/NvHostCtrl/NvHostSyncPt.cs b/Ryujinx.HLE/OsHle/Services/Nv/NvHostCtrl/NvHostSyncPt.cs
new file mode 100644
index 00000000..47d63f79
--- /dev/null
+++ b/Ryujinx.HLE/OsHle/Services/Nv/NvHostCtrl/NvHostSyncPt.cs
@@ -0,0 +1,107 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Threading;
+
+namespace Ryujinx.HLE.OsHle.Services.Nv.NvHostCtrl
+{
+ class NvHostSyncpt
+ {
+ public const int SyncptsCount = 192;
+
+ private int[] CounterMin;
+ private int[] CounterMax;
+
+ private long EventMask;
+
+ private ConcurrentDictionary<EventWaitHandle, int> Waiters;
+
+ public NvHostSyncpt()
+ {
+ CounterMin = new int[SyncptsCount];
+ CounterMax = new int[SyncptsCount];
+
+ Waiters = new ConcurrentDictionary<EventWaitHandle, int>();
+ }
+
+ public int GetMin(int Id)
+ {
+ return CounterMin[Id];
+ }
+
+ public int GetMax(int Id)
+ {
+ return CounterMax[Id];
+ }
+
+ public int Increment(int Id)
+ {
+ if (((EventMask >> Id) & 1) != 0)
+ {
+ Interlocked.Increment(ref CounterMax[Id]);
+ }
+
+ return IncrementMin(Id);
+ }
+
+ public int IncrementMin(int Id)
+ {
+ int Value = Interlocked.Increment(ref CounterMin[Id]);
+
+ WakeUpWaiters(Id, Value);
+
+ return Value;
+ }
+
+ public int IncrementMax(int Id)
+ {
+ return Interlocked.Increment(ref CounterMax[Id]);
+ }
+
+ public void AddWaiter(int Threshold, EventWaitHandle WaitEvent)
+ {
+ if (!Waiters.TryAdd(WaitEvent, Threshold))
+ {
+ throw new InvalidOperationException();
+ }
+ }
+
+ public bool RemoveWaiter(EventWaitHandle WaitEvent)
+ {
+ return Waiters.TryRemove(WaitEvent, out _);
+ }
+
+ private void WakeUpWaiters(int Id, int NewValue)
+ {
+ foreach (KeyValuePair<EventWaitHandle, int> KV in Waiters)
+ {
+ if (MinCompare(Id, NewValue, CounterMax[Id], KV.Value))
+ {
+ KV.Key.Set();
+
+ Waiters.TryRemove(KV.Key, out _);
+ }
+ }
+ }
+
+ public bool MinCompare(int Id, int Threshold)
+ {
+ return MinCompare(Id, CounterMin[Id], CounterMax[Id], Threshold);
+ }
+
+ private bool MinCompare(int Id, int Min, int Max, int Threshold)
+ {
+ int MinDiff = Min - Threshold;
+ int MaxDiff = Max - Threshold;
+
+ if (((EventMask >> Id) & 1) != 0)
+ {
+ return MinDiff >= 0;
+ }
+ else
+ {
+ return (uint)MaxDiff >= (uint)MinDiff;
+ }
+ }
+ }
+} \ No newline at end of file