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 }