Search Unity

[Bug?] Sequential NativeQueue<T>.Concurrent calls seem to break safety checks

Discussion in 'Entity Component System' started by tertle, Aug 7, 2018.

  1. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,759
    -edit- just realized the title is terribly written. should be sequential nativequeue concurrent jobs

    Scheduling jobs one after the other that use the same NativeQueue.Concurrent throws an exception, even though they have a dependency on each other.

    Code (CSharp):
    1. using Unity.Burst;
    2. using Unity.Collections;
    3. using Unity.Entities;
    4. using Unity.Jobs;
    5.  
    6. public class TestQueueSystem : JobComponentSystem
    7. {
    8.     private NativeQueue<Entity> _entities;
    9.  
    10.     [BurstCompile]
    11.     private struct TestJob : IJobParallelFor
    12.     {
    13.         public NativeQueue<Entity>.Concurrent Entities;
    14.  
    15.         public void Execute(int index)
    16.         {
    17.      
    18.         }
    19.     }
    20.  
    21.     protected override void OnCreateManager(int capacity)
    22.     {
    23.         _entities = new NativeQueue<Entity>(Allocator.Persistent);
    24.     }
    25.  
    26.     protected override void OnDestroyManager()
    27.     {
    28.         _entities.Dispose();
    29.     }
    30.  
    31.     protected override JobHandle OnUpdate(JobHandle jobHandle)
    32.     {
    33.         for (var index = 0; index < 5; index++)
    34.         {
    35.             var testJob = new TestJob
    36.             {
    37.                 Entities = _entities,
    38.             };
    39.             jobHandle = testJob.Schedule(123, 64, jobHandle);
    40.         }
    41.  
    42.         return jobHandle;
    43.     }
    44. }
    As far as I'm aware this is safe and should work fine as each job has a dependency on the previous job.
    Disable checks with a [NativeDisableContainerSafetyRestriction] let's it work fine and as far as I can tell, it works as intended.
    Doing a similar thing with other NativeContainers works fine, for example NativeArray

    Code (CSharp):
    1. using Unity.Burst;
    2. using Unity.Collections;
    3. using Unity.Entities;
    4. using Unity.Jobs;
    5.  
    6. public class TestQueueSystem : JobComponentSystem
    7. {
    8.     private NativeArray<Entity> _entities;
    9.  
    10.     [BurstCompile]
    11.     private struct TestJob : IJobParallelFor
    12.     {
    13.         public NativeArray<Entity> Entities;
    14.  
    15.         public void Execute(int index)
    16.         {
    17.      
    18.         }
    19.     }
    20.  
    21.     protected override void OnCreateManager(int capacity)
    22.     {
    23.         _entities = new NativeArray<Entity>(125, Allocator.Persistent);
    24.     }
    25.  
    26.     protected override void OnDestroyManager()
    27.     {
    28.         _entities.Dispose();
    29.     }
    30.  
    31.     protected override JobHandle OnUpdate(JobHandle jobHandle)
    32.     {
    33.         for (var index = 0; index < 5; index++)
    34.         {
    35.             var testJob = new TestJob
    36.             {
    37.                 Entities = _entities,
    38.             };
    39.             jobHandle = testJob.Schedule(123, 64, jobHandle);
    40.         }
    41.  
    42.         return jobHandle;
    43.     }
    44. }
     
    Last edited: Aug 7, 2018
  2. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,759
    Actually this reminds me of an issue I previously had. EntityCommandBuffer suffers from the same issue, you can't chain it between jobs that have dependencies on each other, even the non concurrent version.

    Code (CSharp):
    1. for (var faction = 0; faction < _fogSystem.Factions.Count; faction++)
    2. {
    3.     var setupNewComponents = new SetupNewComponentsJob
    4.     {
    5.         EntityCommandBuffer = PostUpdateCommands
    6.     };
    7.  
    8.     jobHandle = setupNewComponents.Schedule(jobHandle);
    9. }
    10.  
    11. private struct SetupNewComponentsJob : IJob
    12. {
    13.     public EntityCommandBuffer EntityCommandBuffer;
    14.    
    15.     public void Execute()
    16.     {
    17.     }
    18. }
    does not work.
     
    Last edited: Aug 7, 2018