SyncptIncrManager.cs
1 using Ryujinx.Graphics.Device; 2 using System.Collections.Generic; 3 4 namespace Ryujinx.Graphics.Host1x 5 { 6 class SyncptIncrManager 7 { 8 private readonly ISynchronizationManager _syncMgr; 9 10 private readonly struct SyncptIncr 11 { 12 public uint Id { get; } 13 public ClassId ClassId { get; } 14 public uint SyncptId { get; } 15 public bool Done { get; } 16 17 public SyncptIncr(uint id, ClassId classId, uint syncptId, bool done = false) 18 { 19 Id = id; 20 ClassId = classId; 21 SyncptId = syncptId; 22 Done = done; 23 } 24 } 25 26 private readonly List<SyncptIncr> _incrs = new(); 27 28 private uint _currentId; 29 30 public SyncptIncrManager(ISynchronizationManager syncMgr) 31 { 32 _syncMgr = syncMgr; 33 } 34 35 public void Increment(uint id) 36 { 37 lock (_incrs) 38 { 39 _incrs.Add(new SyncptIncr(0, 0, id, true)); 40 41 IncrementAllDone(); 42 } 43 } 44 45 public uint IncrementWhenDone(ClassId classId, uint id) 46 { 47 lock (_incrs) 48 { 49 uint handle = _currentId++; 50 51 _incrs.Add(new SyncptIncr(handle, classId, id)); 52 53 return handle; 54 } 55 } 56 57 public void SignalDone(uint handle) 58 { 59 lock (_incrs) 60 { 61 // Set pending increment with the given handle to "done". 62 for (int i = 0; i < _incrs.Count; i++) 63 { 64 SyncptIncr incr = _incrs[i]; 65 66 if (_incrs[i].Id == handle) 67 { 68 _incrs[i] = new SyncptIncr(incr.Id, incr.ClassId, incr.SyncptId, true); 69 70 break; 71 } 72 } 73 74 IncrementAllDone(); 75 } 76 } 77 78 private void IncrementAllDone() 79 { 80 lock (_incrs) 81 { 82 // Increment all sequential pending increments that are already done. 83 int doneCount = 0; 84 85 for (; doneCount < _incrs.Count; doneCount++) 86 { 87 if (!_incrs[doneCount].Done) 88 { 89 break; 90 } 91 92 _syncMgr.IncrementSyncpoint(_incrs[doneCount].SyncptId); 93 } 94 95 _incrs.RemoveRange(0, doneCount); 96 } 97 } 98 } 99 }