FenceHolder.cs 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. using SharpMetal.Metal;
  2. using System;
  3. using System.Runtime.Versioning;
  4. using System.Threading;
  5. namespace Ryujinx.Graphics.Metal
  6. {
  7. [SupportedOSPlatform("macos")]
  8. class FenceHolder : IDisposable
  9. {
  10. private MTLCommandBuffer _fence;
  11. private int _referenceCount;
  12. private bool _disposed;
  13. public FenceHolder(MTLCommandBuffer fence)
  14. {
  15. _fence = fence;
  16. _referenceCount = 1;
  17. }
  18. public MTLCommandBuffer GetUnsafe()
  19. {
  20. return _fence;
  21. }
  22. public bool TryGet(out MTLCommandBuffer fence)
  23. {
  24. int lastValue;
  25. do
  26. {
  27. lastValue = _referenceCount;
  28. if (lastValue == 0)
  29. {
  30. fence = default;
  31. return false;
  32. }
  33. } while (Interlocked.CompareExchange(ref _referenceCount, lastValue + 1, lastValue) != lastValue);
  34. fence = _fence;
  35. return true;
  36. }
  37. public MTLCommandBuffer Get()
  38. {
  39. Interlocked.Increment(ref _referenceCount);
  40. return _fence;
  41. }
  42. public void Put()
  43. {
  44. if (Interlocked.Decrement(ref _referenceCount) == 0)
  45. {
  46. _fence = default;
  47. }
  48. }
  49. public void Wait()
  50. {
  51. _fence.WaitUntilCompleted();
  52. }
  53. public bool IsSignaled()
  54. {
  55. return _fence.Status == MTLCommandBufferStatus.Completed;
  56. }
  57. public void Dispose()
  58. {
  59. if (!_disposed)
  60. {
  61. Put();
  62. _disposed = true;
  63. }
  64. }
  65. }
  66. }