Search Unity

  1. If you have experience with import & exporting custom (.unitypackage) packages, please help complete a survey (open until May 15, 2024).
    Dismiss Notice
  2. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice

Burst generates buggy code whenever struct size goes beyond 20 bytes.

Discussion in 'Burst' started by georgeq, Mar 18, 2019.

  1. georgeq

    georgeq

    Joined:
    Mar 5, 2014
    Posts:
    662
    I have 2 jobs scheduled to run one after the other, the first Job is Burst compiled while the second is not. The first job generates a value (LaneL in the code below) which is used on the second job to access an array. The value is passed from one job to the other inside a NativeArray of the following struct:

    Code (CSharp):
    1.    [Serializable]
    2.    public struct UpdateResult {
    3.       public float  SteerToPath;
    4.       public int    LaneL;
    5.       public int    LaneR;
    6.       public int    Lane;
    7.       public float  LateralDistance;
    8.       public float  Heading;
    9.    }
    Running the game with the structure as is shown above causes the second job to throw the following exception:

    IndexOutOfRangeException: Index -1071644672 is out of range of '6' Length.
    Unity.Collections.NativeArray`1[T].FailOutOfRangeError (System.Int32 index) (at C:/buildslave/unity/build/Runtime/Export/NativeArray/NativeArray.cs:207)
    Unity.Collections.NativeArray`1[T].CheckElementReadAccess (System.Int32 index) (at C:/buildslave/unity/build/Runtime/Export/NativeArray/NativeArray.cs:113)
    Unity.Collections.NativeArray`1[T].get_Item (System.Int32 index) (at C:/buildslave/unity/build/Runtime/Export/NativeArray/NativeArray.cs:138)
    Casablanca.AIJob.Execute () (at Assets/Casablanca/Scripts/Runtime/Jobs/AIJob.cs:557)
    Unity.Jobs.IJobExtensions+JobStruct`1[T].Execute (T& data, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, Unity.Jobs.LowLevel.Unsafe.JobRanges& ranges, System.Int32 jobIndex) (at C:/buildslave/unity/build/Runtime/Jobs/Managed/IJob.cs:30)

    Which indicates the job crashed because the value contained in LaneL was -1071644672, since the value is generated in the fist job, it is obvious that the bug is in the first job. But if I disable Burst on the first job, the exception is never thrown because the values of LaneL always range between 1 and 4 clearly inside the array range (0 to 6).

    I'm currently using 1.0.0 preview 1, however few days ago I had similar issue with preview 2 which made me think there's some kind of data alignment bug on the Burst compiler, so I ran a simple test:

    I commented all the code that updates and uses LaneR, since it's not being used anywhere anymore I can remove it from the struct (theoretically) without any consequences for the code that affects LaneL, however if I re-enable Burst on the first job and remove LaneR form the struct the exception is not thrown:

    Code (CSharp):
    1.    [Serializable]
    2.    public struct UpdateResult {
    3.       public float  SteerToPath;
    4.       public int    LaneL;
    5.      // public int    LaneR;
    6.       public int    Lane;
    7.       public float  LateralDistance;
    8.       public float  Heading;
    9.    }
    So, with the Burst compiler enabled, just by un-commenting LaneR the values of LaneL become corrupted, while commenting the line corrects the bug. Disabling Burst no corruption is generated.

    I did several tests, renaming the member, moving it to another position, changing the data type, and whenever I added a new member to the struct, the values of LaneL became corrupted, so I suspect whatever makes the struct size greater that 20 bytes generates buggy code. To confirm this, I ran 2 tests, first I changed the data type of Lane to long which triggered the bug, the second test was to change the data type of Lane, LaneL and LaneR to short which did not generate buggy code.
     
  2. georgeq

    georgeq

    Joined:
    Mar 5, 2014
    Posts:
    662
    I've been working with the burst compiler for months and I've never had any mayor issues until I modified this data structure, here's how my game runs with Burst:



    and without:



    I thought the problem was because I declared the array as [WriteOnly] but the problem persisted after I removed the attribute. There's something wrong I think with the data alignment, because when I moved these data to another structure the problem disappeared.
     
    Last edited: Mar 19, 2019