SyncManager.cs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. using Ryujinx.Common.Logging;
  2. using Silk.NET.Vulkan;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. namespace Ryujinx.Graphics.Vulkan
  6. {
  7. class SyncManager
  8. {
  9. private class SyncHandle
  10. {
  11. public ulong ID;
  12. public MultiFenceHolder Waitable;
  13. }
  14. private ulong _firstHandle = 0;
  15. private readonly VulkanRenderer _gd;
  16. private readonly Device _device;
  17. private List<SyncHandle> _handles;
  18. public SyncManager(VulkanRenderer gd, Device device)
  19. {
  20. _gd = gd;
  21. _device = device;
  22. _handles = new List<SyncHandle>();
  23. }
  24. public void Create(ulong id)
  25. {
  26. MultiFenceHolder waitable = new MultiFenceHolder();
  27. _gd.FlushAllCommands();
  28. _gd.CommandBufferPool.AddWaitable(waitable);
  29. SyncHandle handle = new SyncHandle
  30. {
  31. ID = id,
  32. Waitable = waitable
  33. };
  34. lock (_handles)
  35. {
  36. _handles.Add(handle);
  37. }
  38. }
  39. public void Wait(ulong id)
  40. {
  41. SyncHandle result = null;
  42. lock (_handles)
  43. {
  44. if ((long)(_firstHandle - id) > 0)
  45. {
  46. return; // The handle has already been signalled or deleted.
  47. }
  48. foreach (SyncHandle handle in _handles)
  49. {
  50. if (handle.ID == id)
  51. {
  52. result = handle;
  53. break;
  54. }
  55. }
  56. }
  57. if (result != null)
  58. {
  59. lock (result)
  60. {
  61. if (result.Waitable == null)
  62. {
  63. return;
  64. }
  65. bool signaled = result.Waitable.WaitForFences(_gd.Api, _device, 1000000000);
  66. if (!signaled)
  67. {
  68. Logger.Error?.PrintMsg(LogClass.Gpu, $"VK Sync Object {result.ID} failed to signal within 1000ms. Continuing...");
  69. }
  70. }
  71. }
  72. }
  73. public void Cleanup()
  74. {
  75. // Iterate through handles and remove any that have already been signalled.
  76. while (true)
  77. {
  78. SyncHandle first = null;
  79. lock (_handles)
  80. {
  81. first = _handles.FirstOrDefault();
  82. }
  83. if (first == null) break;
  84. bool signaled = first.Waitable.WaitForFences(_gd.Api, _device, 0);
  85. if (signaled)
  86. {
  87. // Delete the sync object.
  88. lock (_handles)
  89. {
  90. lock (first)
  91. {
  92. _firstHandle = first.ID + 1;
  93. _handles.RemoveAt(0);
  94. first.Waitable = null;
  95. }
  96. }
  97. } else
  98. {
  99. // This sync handle and any following have not been reached yet.
  100. break;
  101. }
  102. }
  103. }
  104. }
  105. }