/ src / Ryujinx.Graphics.GAL / Multithreading / Resources / ThreadedCounterEvent.cs
ThreadedCounterEvent.cs
 1  using Ryujinx.Graphics.GAL.Multithreading.Commands.CounterEvent;
 2  using Ryujinx.Graphics.GAL.Multithreading.Model;
 3  using System.Threading;
 4  
 5  namespace Ryujinx.Graphics.GAL.Multithreading.Resources
 6  {
 7      class ThreadedCounterEvent : ICounterEvent
 8      {
 9          private readonly ThreadedRenderer _renderer;
10          public ICounterEvent Base;
11  
12          public bool Invalid { get; set; }
13  
14          public CounterType Type { get; }
15          public bool ClearCounter { get; }
16  
17          private bool _reserved;
18          private int _createLock;
19  
20          public ThreadedCounterEvent(ThreadedRenderer renderer, CounterType type, bool clearCounter)
21          {
22              _renderer = renderer;
23              Type = type;
24              ClearCounter = clearCounter;
25          }
26  
27          private TableRef<T> Ref<T>(T reference)
28          {
29              return new TableRef<T>(_renderer, reference);
30          }
31  
32          public void Dispose()
33          {
34              _renderer.New<CounterEventDisposeCommand>().Set(Ref(this));
35              _renderer.QueueCommand();
36          }
37  
38          public void Flush()
39          {
40              ThreadedHelpers.SpinUntilNonNull(ref Base);
41  
42              Base.Flush();
43          }
44  
45          public bool ReserveForHostAccess()
46          {
47              if (Base != null)
48              {
49                  return Base.ReserveForHostAccess();
50              }
51              else
52              {
53                  bool result = true;
54  
55                  // A very light lock, as this case is uncommon.
56                  ThreadedHelpers.SpinUntilExchange(ref _createLock, 1, 0);
57  
58                  if (Base != null)
59                  {
60                      result = Base.ReserveForHostAccess();
61                  }
62                  else
63                  {
64                      _reserved = true;
65                  }
66  
67                  Volatile.Write(ref _createLock, 0);
68  
69                  return result;
70              }
71          }
72  
73          public void Create(IRenderer renderer, CounterType type, System.EventHandler<ulong> eventHandler, float divisor, bool hostReserved)
74          {
75              ThreadedHelpers.SpinUntilExchange(ref _createLock, 1, 0);
76              Base = renderer.ReportCounter(type, eventHandler, divisor, hostReserved || _reserved);
77              Volatile.Write(ref _createLock, 0);
78          }
79      }
80  }