Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 

164 linhas
6.2 KiB

  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> WithCancellation(this AsyncGPUReadbackRequest asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
  19. {
  20. return ToUniTask(asyncOperation, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
  21. }
  22. public static UniTask<AsyncGPUReadbackRequest> ToUniTask(this AsyncGPUReadbackRequest asyncOperation, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
  23. {
  24. if (asyncOperation.done) return UniTask.FromResult(asyncOperation);
  25. return new UniTask<AsyncGPUReadbackRequest>(AsyncGPUReadbackRequestAwaiterConfiguredSource.Create(asyncOperation, timing, cancellationToken, cancelImmediately, out var token), token);
  26. }
  27. sealed class AsyncGPUReadbackRequestAwaiterConfiguredSource : IUniTaskSource<AsyncGPUReadbackRequest>, IPlayerLoopItem, ITaskPoolNode<AsyncGPUReadbackRequestAwaiterConfiguredSource>
  28. {
  29. static TaskPool<AsyncGPUReadbackRequestAwaiterConfiguredSource> pool;
  30. AsyncGPUReadbackRequestAwaiterConfiguredSource nextNode;
  31. public ref AsyncGPUReadbackRequestAwaiterConfiguredSource NextNode => ref nextNode;
  32. static AsyncGPUReadbackRequestAwaiterConfiguredSource()
  33. {
  34. TaskPool.RegisterSizeGetter(typeof(AsyncGPUReadbackRequestAwaiterConfiguredSource), () => pool.Size);
  35. }
  36. AsyncGPUReadbackRequest asyncOperation;
  37. CancellationToken cancellationToken;
  38. CancellationTokenRegistration cancellationTokenRegistration;
  39. bool cancelImmediately;
  40. UniTaskCompletionSourceCore<AsyncGPUReadbackRequest> core;
  41. AsyncGPUReadbackRequestAwaiterConfiguredSource()
  42. {
  43. }
  44. public static IUniTaskSource<AsyncGPUReadbackRequest> Create(AsyncGPUReadbackRequest asyncOperation, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
  45. {
  46. if (cancellationToken.IsCancellationRequested)
  47. {
  48. return AutoResetUniTaskCompletionSource<AsyncGPUReadbackRequest>.CreateFromCanceled(cancellationToken, out token);
  49. }
  50. if (!pool.TryPop(out var result))
  51. {
  52. result = new AsyncGPUReadbackRequestAwaiterConfiguredSource();
  53. }
  54. result.asyncOperation = asyncOperation;
  55. result.cancellationToken = cancellationToken;
  56. result.cancelImmediately = cancelImmediately;
  57. if (cancelImmediately && cancellationToken.CanBeCanceled)
  58. {
  59. result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
  60. {
  61. var promise = (AsyncGPUReadbackRequestAwaiterConfiguredSource)state;
  62. promise.core.TrySetCanceled(promise.cancellationToken);
  63. }, result);
  64. }
  65. TaskTracker.TrackActiveTask(result, 3);
  66. PlayerLoopHelper.AddAction(timing, result);
  67. token = result.core.Version;
  68. return result;
  69. }
  70. public AsyncGPUReadbackRequest GetResult(short token)
  71. {
  72. try
  73. {
  74. return core.GetResult(token);
  75. }
  76. finally
  77. {
  78. if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
  79. {
  80. TryReturn();
  81. }
  82. else
  83. {
  84. TaskTracker.RemoveTracking(this);
  85. }
  86. }
  87. }
  88. void IUniTaskSource.GetResult(short token)
  89. {
  90. GetResult(token);
  91. }
  92. public UniTaskStatus GetStatus(short token)
  93. {
  94. return core.GetStatus(token);
  95. }
  96. public UniTaskStatus UnsafeGetStatus()
  97. {
  98. return core.UnsafeGetStatus();
  99. }
  100. public void OnCompleted(Action<object> continuation, object state, short token)
  101. {
  102. core.OnCompleted(continuation, state, token);
  103. }
  104. public bool MoveNext()
  105. {
  106. if (cancellationToken.IsCancellationRequested)
  107. {
  108. core.TrySetCanceled(cancellationToken);
  109. return false;
  110. }
  111. if (asyncOperation.hasError)
  112. {
  113. core.TrySetException(new Exception("AsyncGPUReadbackRequest.hasError = true"));
  114. return false;
  115. }
  116. if (asyncOperation.done)
  117. {
  118. core.TrySetResult(asyncOperation);
  119. return false;
  120. }
  121. return true;
  122. }
  123. bool TryReturn()
  124. {
  125. TaskTracker.RemoveTracking(this);
  126. core.Reset();
  127. asyncOperation = default;
  128. cancellationToken = default;
  129. cancellationTokenRegistration.Dispose();
  130. cancelImmediately = default;
  131. return pool.TryPush(this);
  132. }
  133. }
  134. #endregion
  135. }
  136. }