Skip to content

Instantly share code, notes, and snippets.

@runevision
Last active April 5, 2025 08:05
Show Gist options
  • Save runevision/e25310fbdd88a90a4a6a67fff69cb16d to your computer and use it in GitHub Desktop.
Save runevision/e25310fbdd88a90a4a6a67fff69cb16d to your computer and use it in GitHub Desktop.

Revisions

  1. runevision revised this gist Feb 27, 2024. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion BurstMethodTester.cs
    Original file line number Diff line number Diff line change
    @@ -34,7 +34,7 @@ public PointerArray(T* Array, int Length) {
    this.Length = Length;
    }

    public static implicit operator PointerArray<T>(NativeArray<float> a) {
    public static implicit operator PointerArray<T>(NativeArray<T> a) {
    return new PointerArray<T>((T*)a.GetUnsafePtr(), a.Length);
    }
    }
  2. runevision revised this gist Feb 27, 2024. 1 changed file with 9 additions and 6 deletions.
    15 changes: 9 additions & 6 deletions BurstMethodTester.cs
    Original file line number Diff line number Diff line change
    @@ -19,6 +19,11 @@ 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; }
    @@ -56,18 +61,16 @@ void Execute(Mode mode) {
    stopwatch.Start();

    if (mode == Mode.NonBurstMethod) {
    PointerArray<float> inputArr = input;
    PointerArray<float> outputArr = output;
    ExecuteNonBurstMethod(ref inputArr, ref outputArr);
    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> inputArr = input;
    PointerArray<float> outputArr = output;
    ExecuteBurstMethod(ref inputArr, ref outputArr);
    ExecuteBurstMethod(input, ref outputArr);
    }
    else if (mode == Mode.BurstJob) {
    var job = new MyBurstStruct { Input = input, Output = output };
    @@ -83,15 +86,15 @@ void Execute(Mode mode) {
    }

    [BurstCompile]
    public static void ExecuteBurstMethod(ref PointerArray<float> Input, ref PointerArray<float> Output) {
    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(ref PointerArray<float> Input, ref PointerArray<float> Output) {
    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];
  3. runevision created this gist Feb 26, 2024.
    134 changes: 134 additions & 0 deletions BurstMethodTester.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,134 @@
    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[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<float> 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> inputArr = input;
    PointerArray<float> outputArr = output;
    ExecuteNonBurstMethod(ref inputArr, 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> inputArr = input;
    PointerArray<float> outputArr = output;
    ExecuteBurstMethod(ref inputArr, 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(ref 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(ref 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;
    }
    }
    }