Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question How to Use Static Readonly Arrays in Burst

Discussion in 'Burst' started by linexx, Feb 12, 2023.

  1. linexx

    linexx

    Joined:
    Jun 12, 2017
    Posts:
    3
    Hey,
    I'm trying to use the job system and burst to calculate some noise and derivatives for terrain generation. In the job routine, I therefore call the function 3dNoise() in my noise class, which consists of some constants and the function itself:

    Code (CSharp):
    1.  static class noise{
    2.           private static readonly int[] someconstant={1,2,3,4}
    3.           private static readonly float3[] grad3d={
    4.              new float3(1,0,0),
    5.              new float3(0,1,0),
    6.              ...}
    7.  
    8.           public static float3 3dNoise(){
    9.                  //Some magic happens here using the constants
    10.            }
    11.     }

    While the code can run, I get a burst error message saying:
    *The static readonly array field `Unity.Mathematics.float3[] Noise::grad3d` of type `Noise` is not supported by Burst*

    I tried to convert the float3[] to an NativeArray<float3>, but also cant seem to make it work.
    External and internal calls are not allowed inside static constructors: Unity.Collections.LowLevel.Unsafe.UnsafeUtility.MallocTracked(long size, int alignment, Unity.Collections.Allocator allocator, int callstacksToSkip)
    Code (CSharp):
    1. private static readonly NativeArray<float3> grad3d = new NativeArray<float3>(16,Allocator.Persistent){
    2.            [0]=new float3( 1f, 0f 0f),
    3.            [1]=new float3(-0f, 1f, 0f),...}
    How can I make this work with burst or delcare a static readonly nativearray<float3> with the values already assigned?
    Thanks!
     
  2. tim_jones

    tim_jones

    Unity Technologies

    Joined:
    May 2, 2019
    Posts:
    287
    @linexx which version of Burst are you using? And how many items are in the `grad3d` array? We fixed a bug (and the bugfix is in Burst 1.8.3) that affected arrays with many items. If you're not on 1.8.3, you could try upgrading to that to see if it fixes the problem.
     
  3. linexx

    linexx

    Joined:
    Jun 12, 2017
    Posts:
    3
    Just updated to the newest version of burst (1.8.3) Unity version 2023.1.0b2, but the error still remains. The array contains only 32 elements
     
  4. MarcoPersson

    MarcoPersson

    Unity Technologies

    Joined:
    Jul 21, 2021
    Posts:
    49
    Can you post a snippet with the whole array?
     
  5. linexx

    linexx

    Joined:
    Jun 12, 2017
    Posts:
    3
    This is the array(s). I'm using this noise library from catlikecoding (https://catlikecoding.com/unity/tutorials/simplex-noise/)
    Code (CSharp):
    1. private static readonly float3[] grad3d = {
    2.         new float3( 1f, 1f, 0f),
    3.         new float3(-1f, 1f, 0f),
    4.         new float3( 1f,-1f, 0f),
    5.         new float3(-1f,-1f, 0f),
    6.         new float3( 1f, 0f, 1f),
    7.         new float3(-1f, 0f, 1f),
    8.         new float3( 1f, 0f,-1f),
    9.         new float3(-1f, 0f,-1f),
    10.         new float3( 0f, 1f, 1f),
    11.         new float3( 0f,-1f, 1f),
    12.         new float3( 0f, 1f,-1f),
    13.         new float3( 0f,-1f,-1f),
    14.      
    15.         new float3( 1f, 1f, 0f),
    16.         new float3(-1f, 1f, 0f),
    17.         new float3( 0f,-1f, 1f),
    18.         new float3( 0f,-1f,-1f)
    19.     };
    20.  
    21.     private static readonly float3[] simplexGradients3D = {
    22.         math.normalize(new float3( 1f, 1f, 0f)),
    23.         math.normalize(new float3(-1f, 1f, 0f)),
    24.         math.normalize(new float3( 1f,-1f, 0f)),
    25.         math.normalize(new float3(-1f,-1f, 0f)),
    26.         math.normalize(new float3( 1f, 0f, 1f)),
    27.         math.normalize(new float3(-1f, 0f, 1f)),
    28.         math.normalize(new float3( 1f, 0f,-1f)),
    29.         math.normalize(new float3(-1f, 0f,-1f)),
    30.         math.normalize(new float3( 0f, 1f, 1f)),
    31.         math.normalize(new float3( 0f,-1f, 1f)),
    32.         math.normalize(new float3( 0f, 1f,-1f)),
    33.         math.normalize(new float3( 0f,-1f,-1f)),
    34.      
    35.         math.normalize(new float3( 1f, 1f, 0f)),
    36.         math.normalize(new float3(-1f, 1f, 0f)),
    37.         math.normalize(new float3( 1f,-1f, 0f)),
    38.         math.normalize(new float3(-1f,-1f, 0f)),
    39.         math.normalize(new float3( 1f, 0f, 1f)),
    40.         math.normalize(new float3(-1f, 0f, 1f)),
    41.         math.normalize(new float3( 1f, 0f,-1f)),
    42.         math.normalize(new float3(-1f, 0f,-1f)),
    43.         math.normalize(new float3( 0f, 1f, 1f)),
    44.         math.normalize(new float3( 0f,-1f, 1f)),
    45.         math.normalize(new float3( 0f, 1f,-1f)),
    46.         math.normalize(new float3( 0f,-1f,-1f)),
    47.      
    48.         math.normalize(new float3( 1f, 1f, 1f)),
    49.         math.normalize(new float3(-1f, 1f, 1f)),
    50.         math.normalize(new float3( 1f,-1f, 1f)),
    51.         math.normalize(new float3(-1f,-1f, 1f)),
    52.         math.normalize(new float3( 1f, 1f,-1f)),
    53.         math.normalize(new float3(-1f, 1f,-1f)),
    54.         math.normalize(new float3( 1f,-1f,-1f)),
    55.         math.normalize(new float3(-1f,-1f,-1f))
    56.     };
    Im calling the function from inside my IJobFor struct (simplified for better readability):

    Code (CSharp):
    1.    
    2.   [BurstCompile]
    3.     public struct CalcTerrainDataJob : IJobFor{
    4.     public NativeArray<float3> vertcies;
    5.  
    6.     public void Execute (int i){
    7.            GenerateTerrainData(i);
    8.         }
    9.  
    10.      void GenerateTerrainData(int i){
    11.             vertices[i]=Noise.Sum(position);  
    12.         }
    13.     }
     
  6. MarcoPersson

    MarcoPersson

    Unity Technologies

    Joined:
    Jul 21, 2021
    Posts:
    49
    Hi @linexx, the reason why this isn't working for you is because of the math.normalize uses System.Math.Sqrt which we right now can't guarantee will yield the exact same results at compile-time as it does at runtime.
     
  7. tim_jones

    tim_jones

    Unity Technologies

    Joined:
    May 2, 2019
    Posts:
    287
    @linexx as a workaround, you could:
    1. Create a NativeArray in managed code, containing the desired values
    2. Pass this NativeArray to your Burst job
    You need to create the NativeArray somewhere not visible to Burst, in purely managed code. It can still be in a static constructor, as long as the static field is in a class that doesn't contain any other static fields used by Burst. As you found, you can't do it in a static constructor that's visible to Burst, e.g.

    Code (CSharp):
    1. private static readonly NativeArray<float3> grad3d = new NativeArray<float3>(16,Allocator.Persistent){
    2.            [0]=new float3( 1f, 0f 0f),
    3.            [1]=new float3(-0f, 1f, 0f),...}