An open source Danmaku development kit for Unity3D.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Batch jobs and use pointer arithmetic

james713 1e875dc7 51fad1ed

+101 -33
+3 -3
Assets/DanmakU/Runtime/Core/DanmakuPool.cs
··· 83 83 /// The recommended batch size for processing Danmaku in parallelizable jobs. 84 84 /// </summary> 85 85 /// <seealso cref="Unity.Jobs.IJobParallelFor"/> 86 - public const int kBatchSize = 1024; 86 + public const int kBatchSize = 128; 87 87 const int kGrowthFactor = 2; 88 88 89 89 /// <summary> ··· 159 159 var count = ActiveCount; 160 160 if (count <= 0) return dependency; 161 161 new NativeSlice<Vector2>(OldPositions, 0, count).CopyFrom(new NativeSlice<Vector2>(Positions, 0, count)); 162 - var move = new MoveDanmaku(this).Schedule(count, kBatchSize, dependency); 163 - dependency = new BoundsCheckDanmaku(this).Schedule(count, kBatchSize, move); 162 + var move = new MoveDanmaku(this).ScheduleBatch(count, kBatchSize, dependency); 163 + dependency = new BoundsCheckDanmaku(this).ScheduleBatch(count, kBatchSize, move); 164 164 dependency = new DestroyDanmaku(this).Schedule(dependency); 165 165 if (DanmakuCollider.ColliderCount > 0) { 166 166 dependency = new CollideDanamku(this).Schedule(count, kBatchSize, dependency);
+15 -8
Assets/DanmakU/Runtime/Core/Jobs/BoundsCheckDanmaku.cs
··· 1 1 using UnityEngine; 2 2 using Unity.Jobs; 3 3 using Unity.Collections; 4 + using Unity.Collections.LowLevel.Unsafe; 4 5 5 6 namespace DanmakU { 6 7 7 - internal struct BoundsCheckDanmaku : IJobParallelFor { 8 + internal struct BoundsCheckDanmaku : IJobBatchedFor { 8 9 9 10 public float DeltaTime; 10 11 [ReadOnly] public NativeArray<Vector2> Positions; ··· 23 24 max = bounds.Max; 24 25 } 25 26 26 - public void Execute(int index) { 27 - var position = Positions[index]; 28 - if (position.x >= min.x && position.x <= max.x && 29 - position.y >= min.y && position.y <= max.y) { 30 - Times[index] += DeltaTime; 31 - } else { 32 - Times[index] = float.MinValue; 27 + public unsafe void Execute(int start, int end) { 28 + var positionPtr = (Vector2*)Positions.GetUnsafeReadOnlyPtr() + start; 29 + var timePtr = (float*)Times.GetUnsafePtr() + start; 30 + var positionEnd = positionPtr + (end - start); 31 + while (positionPtr < positionEnd) { 32 + var x = positionPtr->x; 33 + var y = positionPtr->y; 34 + if (x >= min.x && x <= max.x && y >= min.y && y <= max.y) { 35 + *timePtr++ += DeltaTime; 36 + } else { 37 + *timePtr++ = float.MinValue; 38 + } 39 + positionPtr++; 33 40 } 34 41 } 35 42
+16 -9
Assets/DanmakU/Runtime/Core/Jobs/MoveDanmaku.cs
··· 5 5 6 6 namespace DanmakU { 7 7 8 - internal struct MoveDanmaku : IJobParallelFor { 8 + internal struct MoveDanmaku : IJobBatchedFor { 9 9 10 10 public float DeltaTime; 11 11 ··· 22 22 AngularSpeeds = pool.AngularSpeeds; 23 23 } 24 24 25 - public unsafe void Execute(int index) { 26 - var positionPtr = (float*)Positions.GetUnsafePtr() + (index * 2); 27 - var rotationPtr = (float*)Rotations.GetUnsafePtr() + index; 28 - var speed = Speeds[index]; 29 - var rotation = *rotationPtr + AngularSpeeds[index] * DeltaTime; 30 - *rotationPtr = rotation; 31 - *positionPtr++ += speed * Mathf.Cos(rotation)* DeltaTime; 32 - *positionPtr += speed * Mathf.Sin(rotation) * DeltaTime; 25 + public unsafe void Execute(int start, int end) { 26 + var positionPtr = (Vector2*)Positions.GetUnsafePtr() + start; 27 + var rotationPtr = (float*)Rotations.GetUnsafePtr() + start; 28 + var speedPtr = (float*)Speeds.GetUnsafeReadOnlyPtr() + start; 29 + var angularSpeedPtr = (float*)AngularSpeeds.GetUnsafeReadOnlyPtr() + start; 30 + var rotationEnd = rotationPtr + (end - start); 31 + while (rotationPtr < rotationEnd) { 32 + var speed = *speedPtr++; 33 + var rotation = *rotationPtr + *angularSpeedPtr++ * DeltaTime; 34 + *rotationPtr = rotation; 35 + positionPtr->x += speed * Mathf.Cos(rotation) * DeltaTime; 36 + positionPtr->y += speed * Mathf.Sin(rotation) * DeltaTime; 37 + rotationPtr++; 38 + positionPtr++; 39 + } 33 40 } 34 41 35 42 }
+49
Assets/DanmakU/Runtime/IJobBatchedFor.cs
··· 1 + using System; 2 + using System.Threading; 3 + using Unity.Collections.LowLevel.Unsafe; 4 + using Unity.Jobs; 5 + using Unity.Jobs.LowLevel.Unsafe; 6 + using UnityEngine; 7 + 8 + namespace DanmakU { 9 + 10 + internal interface IJobBatchedFor { 11 + void Execute(int start, int end); 12 + } 13 + 14 + internal static class BatchedForJobStruct<T> where T : struct, IJobBatchedFor { 15 + 16 + delegate void ExecuteJobFunction(ref T data, IntPtr additionalPtr, IntPtr bufferRangePatchData, ref JobRanges ranges, int jobIndex); 17 + 18 + public static IntPtr Initialize() { 19 + return JobsUtility.CreateJobReflectionData(typeof(T), JobType.ParallelFor, (ExecuteJobFunction)Execute); 20 + } 21 + 22 + public static unsafe void Execute(ref T data, IntPtr additionalData, IntPtr bufferRangePatchData, 23 + ref JobRanges ranges, int jobIndex) { 24 + int start, end; 25 + while (JobsUtility.GetWorkStealingRange(ref ranges, jobIndex, out start, out end)) { 26 + #if ENABLE_UNITY_COLLECTIONS_CHECKS 27 + JobsUtility.PatchBufferMinMaxRanges(bufferRangePatchData, UnsafeUtility.AddressOf(ref data), start, end - start); 28 + #endif 29 + data.Execute(start, end); 30 + } 31 + } 32 + 33 + } 34 + 35 + internal unsafe static class IJobBatchedForExtensions { 36 + 37 + public static JobHandle ScheduleBatch<T>(this T jobData, 38 + int arrayLength, 39 + int minIndicesPerJobCount, 40 + JobHandle dependsOn = new JobHandle()) where T : struct, IJobBatchedFor 41 + { 42 + var scheduleParams = 43 + new JobsUtility.JobScheduleParameters(UnsafeUtility.AddressOf(ref jobData), 44 + BatchedForJobStruct<T>.Initialize(), dependsOn, ScheduleMode.Batched); 45 + return JobsUtility.ScheduleParallelFor(ref scheduleParams, arrayLength, minIndicesPerJobCount); 46 + } 47 + } 48 + 49 + }
+11
Assets/DanmakU/Runtime/IJobBatchedFor.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 0a9fa82d71e0de349bba3c4bef28ef11 3 + MonoImporter: 4 + externalObjects: {} 5 + serializedVersion: 2 6 + defaultReferences: [] 7 + executionOrder: 0 8 + icon: {instanceID: 0} 9 + userData: 10 + assetBundleName: 11 + assetBundleVariant:
+5 -11
Assets/DanmakU/Runtime/Modifiers/DanmakuAcceleration.cs
··· 22 22 if (acceleration.Approximately(0f)) return dependency; 23 23 if (Mathf.Approximately(acceleration.Size, 0f)) { 24 24 return new ApplyFixedAcceleration { 25 - Count = pool.ActiveCount, 26 25 Acceleration = acceleration.Center, 27 26 Speeds = pool.Speeds 28 - }.Schedule(); 27 + }.ScheduleBatch(pool.ActiveCount, DanmakuPool.kBatchSize, dependency); 29 28 } else { 30 29 return new ApplyRandomAcceleration { 31 30 Acceleration = acceleration.Center, ··· 34 33 } 35 34 } 36 35 37 - struct ApplyFixedAcceleration : IJob, IJobParallelFor { 36 + struct ApplyFixedAcceleration : IJobBatchedFor { 38 37 39 - public int Count; 40 38 public float Acceleration; 41 39 public NativeArray<float> Speeds; 42 40 43 - public unsafe void Execute() { 41 + public unsafe void Execute(int start, int end) { 44 42 var ptr = (float*)(Speeds.GetUnsafePtr()); 45 - var end = ptr + Count; 46 - while (ptr < end) { 43 + var pEnd = ptr + (end - start); 44 + while (ptr < pEnd) { 47 45 *ptr++ += Acceleration; 48 46 } 49 - } 50 - 51 - public void Execute(int index) { 52 - Speeds[index] += Acceleration; 53 47 } 54 48 55 49 }
+2 -2
Assets/Test Scene.unity
··· 294 294 FrameRate: 0 295 295 Arc: 296 296 Count: 297 - _min: 500 298 - _max: 500 297 + _min: 5 298 + _max: 5 299 299 ArcLength: 300 300 _min: 6.2831855 301 301 _max: 6.2831855