UnityAsyncExtensions.AsyncGPUReadback.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1.  #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
  2. using System;
  3. using System.Threading;
  4. using UnityEngine.Rendering;
  5. namespace Cysharp.Threading.Tasks
  6. {
  7. public static partial class UnityAsyncExtensions
  8. {
  9. #region AsyncGPUReadbackRequest
  10. public static UniTask<AsyncGPUReadbackRequest>.Awaiter GetAwaiter(this AsyncGPUReadbackRequest asyncOperation)
  11. {
  12. return ToUniTask(asyncOperation).GetAwaiter();
  13. }
  14. public static UniTask<AsyncGPUReadbackRequest> WithCancellation(this AsyncGPUReadbackRequest asyncOperation, CancellationToken cancellationToken)
  15. {
  16. return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
  17. }
  18. public static UniTask<AsyncGPUReadbackRequest> ToUniTask(this AsyncGPUReadbackRequest asyncOperation, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
  19. {
  20. if (asyncOperation.done) return UniTask.FromResult(asyncOperation);
  21. return new UniTask<AsyncGPUReadbackRequest>(AsyncGPUReadbackRequestAwaiterConfiguredSource.Create(asyncOperation, timing, cancellationToken, out var token), token);
  22. }
  23. sealed class AsyncGPUReadbackRequestAwaiterConfiguredSource : IUniTaskSource<AsyncGPUReadbackRequest>, IPlayerLoopItem, ITaskPoolNode<AsyncGPUReadbackRequestAwaiterConfiguredSource>
  24. {
  25. static TaskPool<AsyncGPUReadbackRequestAwaiterConfiguredSource> pool;
  26. AsyncGPUReadbackRequestAwaiterConfiguredSource nextNode;
  27. public ref AsyncGPUReadbackRequestAwaiterConfiguredSource NextNode => ref nextNode;
  28. static AsyncGPUReadbackRequestAwaiterConfiguredSource()
  29. {
  30. TaskPool.RegisterSizeGetter(typeof(AsyncGPUReadbackRequestAwaiterConfiguredSource), () => pool.Size);
  31. }
  32. AsyncGPUReadbackRequest asyncOperation;
  33. CancellationToken cancellationToken;
  34. UniTaskCompletionSourceCore<AsyncGPUReadbackRequest> core;
  35. AsyncGPUReadbackRequestAwaiterConfiguredSource()
  36. {
  37. }
  38. public static IUniTaskSource<AsyncGPUReadbackRequest> Create(AsyncGPUReadbackRequest asyncOperation, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
  39. {
  40. if (cancellationToken.IsCancellationRequested)
  41. {
  42. return AutoResetUniTaskCompletionSource<AsyncGPUReadbackRequest>.CreateFromCanceled(cancellationToken, out token);
  43. }
  44. if (!pool.TryPop(out var result))
  45. {
  46. result = new AsyncGPUReadbackRequestAwaiterConfiguredSource();
  47. }
  48. result.asyncOperation = asyncOperation;
  49. result.cancellationToken = cancellationToken;
  50. TaskTracker.TrackActiveTask(result, 3);
  51. PlayerLoopHelper.AddAction(timing, result);
  52. token = result.core.Version;
  53. return result;
  54. }
  55. public AsyncGPUReadbackRequest GetResult(short token)
  56. {
  57. try
  58. {
  59. return core.GetResult(token);
  60. }
  61. finally
  62. {
  63. TryReturn();
  64. }
  65. }
  66. void IUniTaskSource.GetResult(short token)
  67. {
  68. GetResult(token);
  69. }
  70. public UniTaskStatus GetStatus(short token)
  71. {
  72. return core.GetStatus(token);
  73. }
  74. public UniTaskStatus UnsafeGetStatus()
  75. {
  76. return core.UnsafeGetStatus();
  77. }
  78. public void OnCompleted(Action<object> continuation, object state, short token)
  79. {
  80. core.OnCompleted(continuation, state, token);
  81. }
  82. public bool MoveNext()
  83. {
  84. if (cancellationToken.IsCancellationRequested)
  85. {
  86. core.TrySetCanceled(cancellationToken);
  87. return false;
  88. }
  89. if (asyncOperation.hasError)
  90. {
  91. core.TrySetException(new Exception("AsyncGPUReadbackRequest.hasError = true"));
  92. return false;
  93. }
  94. if (asyncOperation.done)
  95. {
  96. core.TrySetResult(asyncOperation);
  97. return false;
  98. }
  99. return true;
  100. }
  101. bool TryReturn()
  102. {
  103. TaskTracker.RemoveTracking(this);
  104. core.Reset();
  105. asyncOperation = default;
  106. cancellationToken = default;
  107. return pool.TryPush(this);
  108. }
  109. }
  110. #endregion
  111. }
  112. }