SynchronizationManager.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. using System;
  2. using System.Threading;
  3. namespace Ryujinx.Graphics.Gpu.Synchronization
  4. {
  5. /// <summary>
  6. /// GPU synchronization manager.
  7. /// </summary>
  8. public class SynchronizationManager
  9. {
  10. /// <summary>
  11. /// The maximum number of syncpoints supported by the GM20B.
  12. /// </summary>
  13. public const int MaxHardwareSyncpoints = 192;
  14. /// <summary>
  15. /// Array containing all hardware syncpoints.
  16. /// </summary>
  17. private Syncpoint[] _syncpoints;
  18. public SynchronizationManager()
  19. {
  20. _syncpoints = new Syncpoint[MaxHardwareSyncpoints];
  21. for (uint i = 0; i < _syncpoints.Length; i++)
  22. {
  23. _syncpoints[i] = new Syncpoint(i);
  24. }
  25. }
  26. /// <summary>
  27. /// Increment the value of a syncpoint with a given id.
  28. /// </summary>
  29. /// <param name="id">The id of the syncpoint</param>
  30. /// <exception cref="System.ArgumentOutOfRangeException">Thrown when id >= MaxHardwareSyncpoints</exception>
  31. /// <returns>The incremented value of the syncpoint</returns>
  32. public uint IncrementSyncpoint(uint id)
  33. {
  34. if (id >= MaxHardwareSyncpoints)
  35. {
  36. throw new ArgumentOutOfRangeException(nameof(id));
  37. }
  38. return _syncpoints[id].Increment();
  39. }
  40. /// <summary>
  41. /// Get the value of a syncpoint with a given id.
  42. /// </summary>
  43. /// <param name="id">The id of the syncpoint</param>
  44. /// <exception cref="System.ArgumentOutOfRangeException">Thrown when id >= MaxHardwareSyncpoints</exception>
  45. /// <returns>The value of the syncpoint</returns>
  46. public uint GetSyncpointValue(uint id)
  47. {
  48. if (id >= MaxHardwareSyncpoints)
  49. {
  50. throw new ArgumentOutOfRangeException(nameof(id));
  51. }
  52. return _syncpoints[id].Value;
  53. }
  54. /// <summary>
  55. /// Register a new callback on a syncpoint with a given id at a target threshold.
  56. /// The callback will be called once the threshold is reached and will automatically be unregistered.
  57. /// </summary>
  58. /// <param name="id">The id of the syncpoint</param>
  59. /// <param name="threshold">The target threshold</param>
  60. /// <param name="callback">The callback to call when the threshold is reached</param>
  61. /// <exception cref="System.ArgumentOutOfRangeException">Thrown when id >= MaxHardwareSyncpoints</exception>
  62. /// <returns>The created SyncpointWaiterHandle object or null if already past threshold</returns>
  63. public SyncpointWaiterHandle RegisterCallbackOnSyncpoint(uint id, uint threshold, Action callback)
  64. {
  65. if (id >= MaxHardwareSyncpoints)
  66. {
  67. throw new ArgumentOutOfRangeException(nameof(id));
  68. }
  69. return _syncpoints[id].RegisterCallback(threshold, callback);
  70. }
  71. /// <summary>
  72. /// Unregister a callback on a given syncpoint.
  73. /// </summary>
  74. /// <param name="id">The id of the syncpoint</param>
  75. /// <param name="waiterInformation">The waiter information to unregister</param>
  76. /// <exception cref="System.ArgumentOutOfRangeException">Thrown when id >= MaxHardwareSyncpoints</exception>
  77. public void UnregisterCallback(uint id, SyncpointWaiterHandle waiterInformation)
  78. {
  79. if (id >= MaxHardwareSyncpoints)
  80. {
  81. throw new ArgumentOutOfRangeException(nameof(id));
  82. }
  83. _syncpoints[id].UnregisterCallback(waiterInformation);
  84. }
  85. /// <summary>
  86. /// Wait on a syncpoint with a given id at a target threshold.
  87. /// The callback will be called once the threshold is reached and will automatically be unregistered.
  88. /// </summary>
  89. /// <param name="id">The id of the syncpoint</param>
  90. /// <param name="threshold">The target threshold</param>
  91. /// <param name="timeout">The timeout</param>
  92. /// <exception cref="System.ArgumentOutOfRangeException">Thrown when id >= MaxHardwareSyncpoints</exception>
  93. /// <returns>True if timed out</returns>
  94. public bool WaitOnSyncpoint(uint id, uint threshold, TimeSpan timeout)
  95. {
  96. if (id >= MaxHardwareSyncpoints)
  97. {
  98. throw new ArgumentOutOfRangeException(nameof(id));
  99. }
  100. using (ManualResetEvent waitEvent = new ManualResetEvent(false))
  101. {
  102. var info = _syncpoints[id].RegisterCallback(threshold, () => waitEvent.Set());
  103. if (info == null)
  104. {
  105. return false;
  106. }
  107. bool signaled = waitEvent.WaitOne(timeout);
  108. if (!signaled && info != null)
  109. {
  110. _syncpoints[id].UnregisterCallback(info);
  111. }
  112. return !signaled;
  113. }
  114. }
  115. }
  116. }