| | 1 | | using System; |
| | 2 | | using System.Threading; |
| | 3 | | using Cysharp.Threading.Tasks; |
| | 4 | |
|
| | 5 | | namespace GPUSkinning |
| | 6 | | { |
| | 7 | | public interface IGPUSkinningThrottler : IDisposable |
| | 8 | | { |
| | 9 | | void Bind(IGPUSkinning gpuSkinning); |
| | 10 | | void SetThrottling(int framesBetweenUpdates); |
| | 11 | | void Start(); |
| | 12 | | void Stop(); |
| | 13 | | } |
| | 14 | |
|
| | 15 | | public class GPUSkinningThrottler : IGPUSkinningThrottler |
| | 16 | | { |
| | 17 | | internal static int startingFrame = 0; |
| | 18 | |
|
| | 19 | | internal IGPUSkinning gpuSkinning; |
| | 20 | | internal int framesBetweenUpdates; |
| | 21 | | internal int currentFrame; |
| 1309 | 22 | | internal CancellationTokenSource updateCts = new CancellationTokenSource(); |
| | 23 | |
|
| 1309 | 24 | | public GPUSkinningThrottler() |
| | 25 | | { |
| 1309 | 26 | | framesBetweenUpdates = 1; |
| 1309 | 27 | | currentFrame = startingFrame++; |
| 1309 | 28 | | } |
| | 29 | |
|
| 0 | 30 | | public void Bind(IGPUSkinning gpuSkinning) { this.gpuSkinning = gpuSkinning; } |
| 0 | 31 | | public void SetThrottling(int newFramesBetweenUpdates) { framesBetweenUpdates = newFramesBetweenUpdates; } |
| | 32 | |
|
| | 33 | | public void Start() |
| | 34 | | { |
| 5 | 35 | | updateCts?.Cancel(); |
| 5 | 36 | | updateCts?.Dispose(); |
| 5 | 37 | | updateCts = new CancellationTokenSource(); |
| 5 | 38 | | UpdateTask(updateCts.Token); |
| 5 | 39 | | } |
| | 40 | |
|
| | 41 | | private async UniTaskVoid UpdateTask(CancellationToken ct) |
| | 42 | | { |
| 31 | 43 | | while (true) |
| | 44 | | { |
| 36 | 45 | | ct.ThrowIfCancellationRequested(); |
| 36 | 46 | | currentFrame++; |
| 36 | 47 | | if (currentFrame % framesBetweenUpdates == 0) |
| 23 | 48 | | gpuSkinning.Update(); |
| | 49 | | // AttachExternalCancellation is needed because WaitForEndOfFrame cancellation would take a frame |
| 108 | 50 | | await UniTask.DelayFrame(1, PlayerLoopTiming.PostLateUpdate, ct).AttachExternalCancellation(ct); |
| | 51 | | } |
| | 52 | | } |
| | 53 | | public void Stop() |
| | 54 | | { |
| 1 | 55 | | updateCts?.Cancel(); |
| 1 | 56 | | updateCts?.Dispose(); |
| 1 | 57 | | updateCts = null; |
| 1 | 58 | | } |
| | 59 | |
|
| | 60 | | public void Dispose() |
| | 61 | | { |
| 1411 | 62 | | updateCts?.Cancel(); |
| 1411 | 63 | | updateCts?.Dispose(); |
| 1411 | 64 | | updateCts = null; |
| 1411 | 65 | | } |
| | 66 | | } |
| | 67 | | } |