-
-
Save runevision/e25310fbdd88a90a4a6a67fff69cb16d to your computer and use it in GitHub Desktop.
using Unity.Burst; | |
using Unity.Collections; | |
using Unity.Collections.LowLevel.Unsafe; | |
using Unity.Jobs; | |
using UnityEngine; | |
// This example code demonstrates using Unity Burst directly on a static method without jobs. | |
// Unity NativeArrays can't be used directly in Unity Burst methods (only in Burst jobs), | |
// so we have to pass pointers to arrays instead. | |
// | |
// This PointerArray wrapper can be created from a NativeArray via simple implicit assignment: | |
// | |
// NativeArray<float> floatNativeArray = new NativeArray<float>(1000, Allocator.Persistent); | |
// PointerArray<float> floatPointerArray = floatNativeArray; | |
// | |
// The PointerArray can then be used like an array itself, including getting the Length. | |
public unsafe struct PointerArray<T> where T : unmanaged { | |
public readonly T* Array; | |
public readonly int Length; | |
public T this[uint index] { | |
get { return Array[index]; } | |
set { Array[index] = value; } | |
} | |
public T this[int index] { | |
get { return Array[index]; } | |
set { Array[index] = value; } | |
} | |
public PointerArray(T* Array, int Length) { | |
this.Array = Array; | |
this.Length = Length; | |
} | |
public static implicit operator PointerArray<T>(NativeArray<T> a) { | |
return new PointerArray<T>((T*)a.GetUnsafePtr(), a.Length); | |
} | |
} | |
[BurstCompile] | |
public class BurstMethodTester : MonoBehaviour { | |
enum Mode { NonBurstMethod, NonBurstJob, BurstMethod, BurstJob } | |
void Start() { | |
Execute(Mode.NonBurstMethod); | |
Execute(Mode.NonBurstJob); | |
Execute(Mode.BurstMethod); | |
Execute(Mode.BurstJob); | |
} | |
void Execute(Mode mode) { | |
var input = new NativeArray<float>(10000000, Allocator.Persistent); | |
var output = new NativeArray<float>(1, Allocator.Persistent); | |
for (int i = 0; i < input.Length; i++) | |
input[i] = 1.0f * i; | |
var stopwatch = new System.Diagnostics.Stopwatch(); | |
stopwatch.Start(); | |
if (mode == Mode.NonBurstMethod) { | |
PointerArray<float> outputArr = output; | |
ExecuteNonBurstMethod(input, ref outputArr); | |
} | |
else if (mode == Mode.NonBurstJob) { | |
var job = new MyNonBurstStruct { Input = input, Output = output }; | |
job.Schedule().Complete(); | |
} | |
else if (mode == Mode.BurstMethod) { | |
PointerArray<float> outputArr = output; | |
ExecuteBurstMethod(input, ref outputArr); | |
} | |
else if (mode == Mode.BurstJob) { | |
var job = new MyBurstStruct { Input = input, Output = output }; | |
job.Schedule().Complete(); | |
} | |
stopwatch.Stop(); | |
Debug.Log("Took " + stopwatch.ElapsedMilliseconds + "ms with mode " + mode | |
+ "\nThe result of the sum is: " + output[0]); | |
input.Dispose(); | |
output.Dispose(); | |
} | |
[BurstCompile] | |
public static void ExecuteBurstMethod(in PointerArray<float> Input, ref PointerArray<float> Output) { | |
float result = 0.0f; | |
for (int i = 0; i < Input.Length; i++) { | |
result += Input[i]; | |
} | |
Output[0] = result; | |
} | |
public static void ExecuteNonBurstMethod(in PointerArray<float> Input, ref PointerArray<float> Output) { | |
float result = 0.0f; | |
for (int i = 0; i < Input.Length; i++) { | |
result += Input[i]; | |
} | |
Output[0] = result; | |
} | |
[BurstCompile(CompileSynchronously = true)] | |
private struct MyBurstStruct : IJob { | |
[ReadOnly] | |
public NativeArray<float> Input; | |
[WriteOnly] | |
public NativeArray<float> Output; | |
public void Execute() { | |
float result = 0.0f; | |
for (int i = 0; i < Input.Length; i++) { | |
result += Input[i]; | |
} | |
Output[0] = result; | |
} | |
} | |
private struct MyNonBurstStruct : IJob { | |
[ReadOnly] | |
public NativeArray<float> Input; | |
[WriteOnly] | |
public NativeArray<float> Output; | |
public void Execute() { | |
float result = 0.0f; | |
for (int i = 0; i < Input.Length; i++) { | |
result += Input[i]; | |
} | |
Output[0] = result; | |
} | |
} | |
} |
What version of Unity did you have to use for this to work? I remember trying to get something like this working and founding out (to my disappointment) that it was not possible. When did this become possible ( •̯́ ^ •̯̀)
What version of Unity did you have to use for this to work?
I was using this in Unity 2019.4 and later. I don't know in which version it started working.
What version of Unity did you have to use for this to work?
Burst has always been available for static methods.
And I don't see any need for PointerArray<T>
to be required for a method to use NativeArray<T>
with burst.
Like I did
[BurstCompile]
private static void CompleteBurst(ref NativeArray<JobHandle> jobHandles, byte batchSize)
[BurstCompile]
private static void ScheduleBurst(ref NativeArray<JobForData<T>> jobArray, ref JobSchedulerBase baseScheduler, byte batchSize)
and it worked.
I may have misunderstood something.
I don't see any need for
PointerArray<T>
to be required for a method to useNativeArray<T>
with burst.
It's needed in Unity 2019.4 where it's not possible to pass NativeArrays to Burst-compiled methods. In some later version it became possible (I can't remember which version).
BurstMethod and BurstJob perform around 10x of NonBurstMethod and NonBurstJob. Times can vary a lot from one run to the next.
Job vs Method makes no difference here as there's only one job. But the Job version was the original code from Unity's documentation. I adapted the Method version from that and kept the Job version too so I could check if the Method version got the same speed boost or not.