/ src / Ryujinx.Graphics.Host1x / SyncptIncrManager.cs
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  }