Last active
December 17, 2020 08:18
-
-
Save RamType0/3452cf68d8096e94536f95c1ca263a18 to your computer and use it in GitHub Desktop.
ComputeBuffer.GetDataAsyncなどのメソッドを生やすAsyncGPUReadbackのUniTask向け拡張メソッド集。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using UnityEngine; | |
| using Unity.Collections; | |
| using UnityEngine.Rendering; | |
| using UnityEngine.Experimental.Rendering; | |
| namespace Cysharp.Threading.Tasks | |
| { | |
| public static class UniTaskAsyncGPUReadbackExtensions | |
| { | |
| #region AsyncGPUReadback.Request | |
| public static UniTask<NativeArray<T>> GetDataAsync<T>(this ComputeBuffer src) | |
| where T : unmanaged | |
| { | |
| var task = AsyncGPUReadbackCompletionSource<T>.Create(out var token, out var callback); | |
| AsyncGPUReadback.Request(src, callback); | |
| return new UniTask<NativeArray<T>>(task, token); | |
| } | |
| public static unsafe UniTask<NativeArray<T>> GetDataAsync<T>(this ComputeBuffer src, int offset, int length) | |
| where T : unmanaged | |
| { | |
| var task = AsyncGPUReadbackCompletionSource<T>.Create(out var token, out var callback); | |
| AsyncGPUReadback.Request(src, sizeof(T) * length, sizeof(T) * offset, callback); | |
| return new UniTask<NativeArray<T>>(task, token); | |
| } | |
| #if UNITY_2019_4_OR_NEWER | |
| public static UniTask<NativeArray<T>> GetDataAsync<T>(this GraphicsBuffer src) | |
| where T : unmanaged | |
| { | |
| var task = AsyncGPUReadbackCompletionSource<T>.Create(out var token, out var callback); | |
| AsyncGPUReadback.Request(src, callback); | |
| return new UniTask<NativeArray<T>>(task, token); | |
| } | |
| public static unsafe UniTask<NativeArray<T>> GetDataAsync<T>(this GraphicsBuffer src, int offset, int length) | |
| where T : unmanaged | |
| { | |
| var task = AsyncGPUReadbackCompletionSource<T>.Create(out var token, out var callback); | |
| AsyncGPUReadback.Request(src, sizeof(T) * length, sizeof(T) * offset, callback); | |
| return new UniTask<NativeArray<T>>(task, token); | |
| } | |
| #endif | |
| public static UniTask<NativeArray<T>> GetDataAsync<T>(this Texture src, int mipIndex = 0) | |
| where T : unmanaged | |
| { | |
| var task = AsyncGPUReadbackCompletionSource<T>.Create(out var token, out var callback); | |
| AsyncGPUReadback.Request(src, mipIndex, callback); | |
| return new UniTask<NativeArray<T>>(task, token); | |
| } | |
| public static UniTask<NativeArray<T>> GetDataAsync<T>(this Texture src, int mipIndex, TextureFormat dstFormat) | |
| where T : unmanaged | |
| { | |
| var task = AsyncGPUReadbackCompletionSource<T>.Create(out var token, out var callback); | |
| AsyncGPUReadback.Request(src, mipIndex, dstFormat, callback); | |
| return new UniTask<NativeArray<T>>(task, token); | |
| } | |
| #if UNITY_2019_4_OR_NEWER | |
| public static UniTask<NativeArray<T>> GetDataAsync<T>(this Texture src, int mipIndex, GraphicsFormat dstFormat) | |
| where T : unmanaged | |
| { | |
| var task = AsyncGPUReadbackCompletionSource<T>.Create(out var token, out var callback); | |
| AsyncGPUReadback.Request(src, mipIndex, dstFormat, callback); | |
| return new UniTask<NativeArray<T>>(task, token); | |
| } | |
| #endif | |
| public static UniTask<NativeArray<T>> GetDataAsync<T>(this Texture src, int mipIndex, int x, int width, int y, int height, int z = 0) | |
| where T : unmanaged | |
| { | |
| var task = AsyncGPUReadbackCompletionSource<T>.Create(out var token, out var callback); | |
| AsyncGPUReadback.Request(src, mipIndex, x, width, y, height, z, 1, callback); | |
| return new UniTask<NativeArray<T>>(task, token); | |
| } | |
| public static UniTask<NativeArray<T>> GetDataAsync<T>(this Texture src, int mipIndex, int x, int width, int y, int height, int z, TextureFormat dstFormat) | |
| where T : unmanaged | |
| { | |
| var task = AsyncGPUReadbackCompletionSource<T>.Create(out var token, out var callback); | |
| AsyncGPUReadback.Request(src, mipIndex, x, width, y, height, z, 1, dstFormat, callback); | |
| return new UniTask<NativeArray<T>>(task, token); | |
| } | |
| #if UNITY_2019_4_OR_NEWER | |
| public static UniTask<NativeArray<T>> GetDataAsync<T>(this Texture src, int mipIndex, int x, int width, int y, int height, int z, GraphicsFormat dstFormat) | |
| where T : unmanaged | |
| { | |
| var task = AsyncGPUReadbackCompletionSource<T>.Create(out var token, out var callback); | |
| AsyncGPUReadback.Request(src, mipIndex, x, width, y, height, z, 1, dstFormat, callback); | |
| return new UniTask<NativeArray<T>>(task, token); | |
| } | |
| #endif | |
| #endregion | |
| internal sealed class AsyncGPUReadbackCompletionSource<T> : IUniTaskSource<NativeArray<T>>, ITaskPoolNode<AsyncGPUReadbackCompletionSource<T>> | |
| where T : unmanaged | |
| { | |
| static TaskPool<AsyncGPUReadbackCompletionSource<T>> pool; | |
| AsyncGPUReadbackCompletionSource<T> nextNode; | |
| public ref AsyncGPUReadbackCompletionSource<T> NextNode => ref nextNode; | |
| readonly Action<AsyncGPUReadbackRequest> onReadbackComplete; | |
| UniTaskCompletionSourceCore<NativeArray<T>> core; | |
| public AsyncGPUReadbackCompletionSource() | |
| { | |
| onReadbackComplete = OnReadbackComplete; | |
| } | |
| public static IUniTaskSource<NativeArray<T>> Create(out short token, out Action<AsyncGPUReadbackRequest> callback) | |
| { | |
| if (!pool.TryPop(out var result)) | |
| { | |
| result = new AsyncGPUReadbackCompletionSource<T>(); | |
| } | |
| TaskTracker.TrackActiveTask(result, 3); | |
| token = result.core.Version; | |
| callback = result.onReadbackComplete; | |
| return result; | |
| } | |
| void OnReadbackComplete(AsyncGPUReadbackRequest readbackRequest) | |
| { | |
| if (readbackRequest.hasError) | |
| { | |
| core.TrySetException(new Exception("AsyncGPUReadbackRequest.hasError = true")); | |
| } | |
| else | |
| { | |
| core.TrySetResult(readbackRequest.GetData<T>()); | |
| } | |
| } | |
| public NativeArray<T> GetResult(short token) | |
| { | |
| try | |
| { | |
| return core.GetResult(token); | |
| } | |
| finally | |
| { | |
| TryReturn(); | |
| } | |
| } | |
| bool TryReturn() | |
| { | |
| TaskTracker.RemoveTracking(this); | |
| core.Reset(); | |
| return pool.TryPush(this); | |
| } | |
| public UniTaskStatus GetStatus(short token) | |
| { | |
| return core.GetStatus(token); | |
| } | |
| public void OnCompleted(Action<object> continuation, object state, short token) | |
| { | |
| core.OnCompleted(continuation, state, token); | |
| } | |
| public UniTaskStatus UnsafeGetStatus() | |
| { | |
| return core.UnsafeGetStatus(); | |
| } | |
| void IUniTaskSource.GetResult(short token) | |
| { | |
| GetResult(token); | |
| } | |
| } | |
| #region AsyncGPUReadback.RequestIntoNativeArray | |
| #if UNITY_2019_4_OR_NEWER | |
| public static UniTask GetDataAsync<T>(this ComputeBuffer src, ref NativeArray<T> output) | |
| where T : unmanaged | |
| { | |
| var task = AsyncGPUReadbackIntoNativeContainerCompletionSource.Create(out var token, out var callback); | |
| AsyncGPUReadback.RequestIntoNativeArray(ref output, src, callback); | |
| return new UniTask(task, token); | |
| } | |
| public static unsafe UniTask GetDataAsync<T>(this ComputeBuffer src, ref NativeArray<T> output, int offset, int length) | |
| where T : unmanaged | |
| { | |
| var task = AsyncGPUReadbackIntoNativeContainerCompletionSource.Create(out var token, out var callback); | |
| AsyncGPUReadback.RequestIntoNativeArray(ref output, src, sizeof(T) * length, sizeof(T) * offset, callback); | |
| return new UniTask(task, token); | |
| } | |
| public static UniTask GetDataAsync<T>(this GraphicsBuffer src, ref NativeArray<T> output) | |
| where T : unmanaged | |
| { | |
| var task = AsyncGPUReadbackIntoNativeContainerCompletionSource.Create(out var token, out var callback); | |
| AsyncGPUReadback.RequestIntoNativeArray(ref output, src, callback); | |
| return new UniTask(task, token); | |
| } | |
| public static unsafe UniTask GetDataAsync<T>(this GraphicsBuffer src, ref NativeArray<T> output, int offset, int length) | |
| where T : unmanaged | |
| { | |
| var task = AsyncGPUReadbackIntoNativeContainerCompletionSource.Create(out var token, out var callback); | |
| AsyncGPUReadback.RequestIntoNativeArray(ref output, src, sizeof(T) * length, sizeof(T) * offset, callback); | |
| return new UniTask(task, token); | |
| } | |
| public static UniTask GetDataAsync<T>(this Texture src, ref NativeArray<T> output, int mipIndex = 0) | |
| where T : unmanaged | |
| { | |
| var task = AsyncGPUReadbackIntoNativeContainerCompletionSource.Create(out var token, out var callback); | |
| AsyncGPUReadback.RequestIntoNativeArray(ref output, src, mipIndex, callback); | |
| return new UniTask(task, token); | |
| } | |
| public static UniTask GetDataAsync<T>(this Texture src, ref NativeArray<T> output, int mipIndex, TextureFormat dstFormat) | |
| where T : unmanaged | |
| { | |
| var task = AsyncGPUReadbackIntoNativeContainerCompletionSource.Create(out var token, out var callback); | |
| AsyncGPUReadback.RequestIntoNativeArray(ref output, src, mipIndex, dstFormat, callback); | |
| return new UniTask(task, token); | |
| } | |
| public static UniTask GetDataAsync<T>(this Texture src, ref NativeArray<T> output, int mipIndex, GraphicsFormat dstFormat) | |
| where T : unmanaged | |
| { | |
| var task = AsyncGPUReadbackIntoNativeContainerCompletionSource.Create(out var token, out var callback); | |
| AsyncGPUReadback.RequestIntoNativeArray(ref output, src, mipIndex, dstFormat, callback); | |
| return new UniTask(task, token); | |
| } | |
| public static UniTask GetDataAsync<T>(this Texture src, ref NativeArray<T> output, int mipIndex, int x, int width, int y, int height, int z, int depth, TextureFormat dstFormat) | |
| where T : unmanaged | |
| { | |
| var task = AsyncGPUReadbackIntoNativeContainerCompletionSource.Create(out var token, out var callback); | |
| AsyncGPUReadback.RequestIntoNativeArray(ref output, src, mipIndex, x, width, y, height, z, depth, dstFormat, callback); | |
| return new UniTask(task, token); | |
| } | |
| public static UniTask GetDataAsync<T>(this Texture src, ref NativeArray<T> output, int mipIndex, int x, int width, int y, int height, int z, int depth, GraphicsFormat dstFormat) | |
| where T : unmanaged | |
| { | |
| var task = AsyncGPUReadbackIntoNativeContainerCompletionSource.Create(out var token, out var callback); | |
| AsyncGPUReadback.RequestIntoNativeArray(ref output, src, mipIndex, x, width, y, height, z, depth, dstFormat, callback); | |
| return new UniTask(task, token); | |
| } | |
| #endif | |
| #endregion | |
| #region AsyncGPUReadback.RequestIntoNativeSlice | |
| #if UNITY_2020_2_OR_NEWER | |
| public static UniTask GetDataAsync<T>(this ComputeBuffer src, ref NativeSlice<T> output) | |
| where T : unmanaged | |
| { | |
| var task = AsyncGPUReadbackIntoNativeContainerCompletionSource.Create(out var token, out var callback); | |
| AsyncGPUReadback.RequestIntoNativeSlice(ref output, src, callback); | |
| return new UniTask(task, token); | |
| } | |
| public static unsafe UniTask GetDataAsync<T>(this ComputeBuffer src, ref NativeSlice<T> output, int offset, int length) | |
| where T : unmanaged | |
| { | |
| var task = AsyncGPUReadbackIntoNativeContainerCompletionSource.Create(out var token, out var callback); | |
| AsyncGPUReadback.RequestIntoNativeSlice(ref output, src, sizeof(T) * length, sizeof(T) * offset, callback); | |
| return new UniTask(task, token); | |
| } | |
| public static UniTask GetDataAsync<T>(this GraphicsBuffer src, ref NativeSlice<T> output) | |
| where T : unmanaged | |
| { | |
| var task = AsyncGPUReadbackIntoNativeContainerCompletionSource.Create(out var token, out var callback); | |
| AsyncGPUReadback.RequestIntoNativeSlice(ref output, src, callback); | |
| return new UniTask(task, token); | |
| } | |
| public static unsafe UniTask GetDataAsync<T>(this GraphicsBuffer src, ref NativeSlice<T> output, int offset, int length) | |
| where T : unmanaged | |
| { | |
| var task = AsyncGPUReadbackIntoNativeContainerCompletionSource.Create(out var token, out var callback); | |
| AsyncGPUReadback.RequestIntoNativeSlice(ref output, src, sizeof(T) * length, sizeof(T) * offset, callback); | |
| return new UniTask(task, token); | |
| } | |
| public static UniTask GetDataAsync<T>(this Texture src, ref NativeSlice<T> output, int mipIndex = 0) | |
| where T : unmanaged | |
| { | |
| var task = AsyncGPUReadbackIntoNativeContainerCompletionSource.Create(out var token, out var callback); | |
| AsyncGPUReadback.RequestIntoNativeSlice(ref output, src, mipIndex, callback); | |
| return new UniTask(task, token); | |
| } | |
| public static UniTask GetDataAsync<T>(this Texture src, ref NativeSlice<T> output, int mipIndex, TextureFormat dstFormat) | |
| where T : unmanaged | |
| { | |
| var task = AsyncGPUReadbackIntoNativeContainerCompletionSource.Create(out var token, out var callback); | |
| AsyncGPUReadback.RequestIntoNativeSlice(ref output, src, mipIndex, dstFormat, callback); | |
| return new UniTask(task, token); | |
| } | |
| public static UniTask GetDataAsync<T>(this Texture src, ref NativeSlice<T> output, int mipIndex, GraphicsFormat dstFormat) | |
| where T : unmanaged | |
| { | |
| var task = AsyncGPUReadbackIntoNativeContainerCompletionSource.Create(out var token, out var callback); | |
| AsyncGPUReadback.RequestIntoNativeSlice(ref output, src, mipIndex, dstFormat, callback); | |
| return new UniTask(task, token); | |
| } | |
| public static UniTask GetDataAsync<T>(this Texture src, ref NativeSlice<T> output, int mipIndex, int x, int width, int y, int height, int z, int depth, TextureFormat dstFormat) | |
| where T : unmanaged | |
| { | |
| var task = AsyncGPUReadbackIntoNativeContainerCompletionSource.Create(out var token, out var callback); | |
| AsyncGPUReadback.RequestIntoNativeSlice(ref output, src, mipIndex, x, width, y, height, z, depth, dstFormat, callback); | |
| return new UniTask(task, token); | |
| } | |
| public static UniTask GetDataAsync<T>(this Texture src, ref NativeSlice<T> output, int mipIndex, int x, int width, int y, int height, int z, int depth, GraphicsFormat dstFormat) | |
| where T : unmanaged | |
| { | |
| var task = AsyncGPUReadbackIntoNativeContainerCompletionSource.Create(out var token, out var callback); | |
| AsyncGPUReadback.RequestIntoNativeSlice(ref output, src, mipIndex, x, width, y, height, z, depth, dstFormat, callback); | |
| return new UniTask(task, token); | |
| } | |
| #endif | |
| #endregion | |
| #if UNITY_2019_4_OR_NEWER | |
| internal sealed class AsyncGPUReadbackIntoNativeContainerCompletionSource : IUniTaskSource<AsyncUnit>, ITaskPoolNode<AsyncGPUReadbackIntoNativeContainerCompletionSource> | |
| { | |
| static TaskPool<AsyncGPUReadbackIntoNativeContainerCompletionSource> pool; | |
| AsyncGPUReadbackIntoNativeContainerCompletionSource nextNode; | |
| public ref AsyncGPUReadbackIntoNativeContainerCompletionSource NextNode => ref nextNode; | |
| readonly Action<AsyncGPUReadbackRequest> onReadbackComplete; | |
| UniTaskCompletionSourceCore<AsyncUnit> core; | |
| public AsyncGPUReadbackIntoNativeContainerCompletionSource() | |
| { | |
| onReadbackComplete = OnReadbackComplete; | |
| } | |
| public static IUniTaskSource<AsyncUnit> Create(out short token, out Action<AsyncGPUReadbackRequest> callback) | |
| { | |
| if (!pool.TryPop(out var result)) | |
| { | |
| result = new AsyncGPUReadbackIntoNativeContainerCompletionSource(); | |
| } | |
| TaskTracker.TrackActiveTask(result, 3); | |
| token = result.core.Version; | |
| callback = result.onReadbackComplete; | |
| return result; | |
| } | |
| void OnReadbackComplete(AsyncGPUReadbackRequest readbackRequest) | |
| { | |
| if (readbackRequest.hasError) | |
| { | |
| core.TrySetException(new Exception("AsyncGPUReadbackRequest.hasError = true")); | |
| } | |
| else | |
| { | |
| core.TrySetResult(default); | |
| } | |
| } | |
| public AsyncUnit GetResult(short token) | |
| { | |
| try | |
| { | |
| return core.GetResult(token); | |
| } | |
| finally | |
| { | |
| TryReturn(); | |
| } | |
| } | |
| bool TryReturn() | |
| { | |
| TaskTracker.RemoveTracking(this); | |
| core.Reset(); | |
| return pool.TryPush(this); | |
| } | |
| public UniTaskStatus GetStatus(short token) | |
| { | |
| return core.GetStatus(token); | |
| } | |
| public void OnCompleted(Action<object> continuation, object state, short token) | |
| { | |
| core.OnCompleted(continuation, state, token); | |
| } | |
| public UniTaskStatus UnsafeGetStatus() | |
| { | |
| return core.UnsafeGetStatus(); | |
| } | |
| void IUniTaskSource.GetResult(short token) | |
| { | |
| GetResult(token); | |
| } | |
| } | |
| #endif | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment