Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question Why can't I [BurstCompile] this job with a bool?

Discussion in 'C# Job System' started by Snubber, Apr 10, 2023.

  1. Snubber

    Snubber

    Joined:
    Jan 20, 2020
    Posts:
    65
    I have a job that I had `[BurstCompile]` on. However once I added a bool property to it, it would cause this exception to occur at runtime, unless I either removed `[BurstCompile]` or disabled Burst Compilation.
    Exception:


    Code (CSharp):
    1. System.IndexOutOfRangeException: Index {0} is out of restricted IJobParallelFor range [{1}...{2}] in ReadWriteBuffer.
    2.  
    3.     This Exception was thrown from a job compiled with Burst, which has limited exception support.
    4.     0x00007ffcbf37972c (ad4992c77b22662ddf38e24e48d0cb5) [unknown:0] Unity.Jobs.IJobExtensions.JobStruct`1<TerrainGenerator.GenerateWalkable>.Execute(ref TerrainGenerator.GenerateWalkable data, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, ref Unity.Jobs.LowLevel.Unsafe.JobRanges ranges, int jobIndex) -> void_aef4d46f9ec6d18a03913cfa3cd76414 from UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
    5.     0x00007ffcbf378e46 (ad4992c77b22662ddf38e24e48d0cb5) 9199adbb5895f5d6e28062be980c1a49
    6.     0x00007ff7e8117e10 (Unity) ExecuteJob
    7.     0x00007ff7e811900f (Unity) ForwardJobToManaged
    8.     0x00007ff7e8114140 (Unity) JobQueue::Exec
    9.     0x00007ff7e811446e (Unity) JobQueue::ExecuteJobFromHighPriorityStack
    10.     0x00007ff7e8114b44 (Unity) JobQueue::ProcessJobs
    11.     0x00007ff7e8116d5f (Unity) JobQueue::WorkLoop
    12.     0x00007ff7e8317d57 (Unity) Thread::RunThreadWrapper
    13.     0x00007ffd021e7614 (KERNEL32) BaseThreadInitThunk
    14.     0x00007ffd03e626a1 (ntdll) RtlUserThreadStart
    And here is the job: (the error is happening when I added the `village` bool)

    Code (CSharp):
    1. public struct GenerateWalkable : IJob
    2.         {
    3.             [ReadOnly] public NativeArray<TerrainVertexData> terrainVertexData;
    4.             [ReadOnly] public float startingAreaWall;
    5.             [ReadOnly] public SBCommon.Terrain.Version terrainVersion;
    6.             [ReadOnly] public bool village;
    7.             public NativeArray<bool> walkable;
    8.             public void Execute()
    9.             {
    10.                 for (int x = 0; x < chunkSize; x++)
    11.                 {
    12.                     for (int z = 0; z < chunkSize; z++)
    13.                     {
    14.                         var walkableIndex = x + z * chunkSize;
    15.                         if (village)
    16.                         {
    17.                             walkable[walkableIndex] = false;
    18.                         }
    19.                         else
    20.                         {
    21.                             if ((int)terrainVersion >= (int)SBCommon.Terrain.Version._startingArea
    22.                                 && terrainVertexData[tvdIndex(x, z)].diff < startingAreaWall)
    23.                             {
    24.                                 walkable[walkableIndex] = false;
    25.                             }
    26.                             else
    27.                             {
    28.                                 walkable[walkableIndex] = true;
    29.                             }
    30.                         }
    31.                     }
    32.                 }
    33.             }
    34.         }
     
  2. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    5,078
    Your job is an IJob but the error indicates that the issue is with a IJobParallelFor. For the latter, you have to use the index provided by the Execute method as parameter, unless you add some NativeDisable... attribute to it (can't remember which). So somehow the error seems unrelated to the job code you posted.

    Note that you're probably losing a big chunk of performance by adding this if/else block with the bool. It is usually more efficient to have two separate jobs, one for villages and one for not-villages even if that means going over the same vertex data / walkable arrays twice! This can be important when optimizing for performance.
     
  3. Mortuus17

    Mortuus17

    Joined:
    Jan 6, 2020
    Posts:
    105
    Nope. The compiler sees the bool is loop-invaraint. It will compile 2 loops, one for villages and one for non-villages and jumps to the appropriate loop once in the beginning. ~40 clock cycles at max.
     
    Deleted User likes this.