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

Error with NativeList, maybe a Bug?

Discussion in 'Entity Component System' started by Gaaammmler, Jul 7, 2019.

  1. Gaaammmler

    Gaaammmler

    Joined:
    Apr 10, 2018
    Posts:
    16
    Hello,

    i got the following Error from this Job:
    InvalidOperationException: The native container may not be deallocated on a job.
    Use [DeallocateOnJobCompletionAttribute] to deallocate a native container safely on job completion.
    I Dispose the list afterwards and the native array Buildings with [DeallocateOnJobCompletion] but for NativeList [DeallocateOnJobCompletion] doesnt work, because its not implemented yet.
    Anyone know why i get the error message?

    Code (CSharp):
    1.  
    2. protected override JobHandle OnUpdate(JobHandle inputDependencies)
    3.         {
    4.  
    5.            
    6.    if (deferredList.IsCreated)
    7.                 deferredList.Dispose();
    8.  
    9.             CreatePhysicsWorldSystem.FinalJobHandle.Complete();
    10.             deferredList = new NativeList<float3>(50, Allocator.TempJob);
    11.  
    12.             var query = GetEntityQuery(typeof(NewBuildingPreview));
    13.             var buildingsBefore = query.ToEntityArray(Allocator.TempJob);
    14.  
    15.      
    16.             var buildingSystemJob = new BuildingSystemJob
    17.             {
    18.                 positions = deferredList,
    19.                 CollisionWorldSystem = CreatePhysicsWorldSystem.PhysicsWorld.CollisionWorld,
    20.             };
    21.  
    22.  
    23.             var jobHandle = buildingSystemJob.Schedule(this, inputDependencies);
    24.             jobHandle.Complete();
    25.  
    26.            
    27.             AddComponentJob addComponentJob = new AddComponentJob
    28.             {
    29.                 BuildingsBefore = buildingsBefore,
    30.                 CommandBuffer = m_EntityCommandBufferSystem.CreateCommandBuffer().ToConcurrent(),
    31.                 positions = buildingSystemJob.positions,
    32.             };
    33.        
    34.             jobHandle = addComponentJob.Schedule(this, jobHandle);
    35.             m_EntityCommandBufferSystem.AddJobHandleForProducer(jobHandle);
    36.  
    37.             return jobHandle;
    38.         }

    My start code from my BuildingSystemJob:
    Code (CSharp):
    1.  
    2. [BurstCompile]
    3.         struct BuildingSystemJob : IJobForEachWithEntity<BuildObject, PlayerInput>
    4.         {
    5.             [ReadOnly] public CollisionWorld CollisionWorldSystem;
    6.             [NativeDisableParallelForRestriction] public NativeList<float3> positions;
    7. ...
    8.  
    My start code from my AddComponentJob:
    Code (CSharp):
    1.   struct AddComponentJob : IJobForEachWithEntity<BuildObject, PlayerInput>
    2.         {
    3.             [DeallocateOnJobCompletion] [ReadOnly] public NativeArray<Entity> BuildingsBefore;
    4.             [ReadOnly] public NativeList<float3> positions;
    5.    
    6.             public EntityCommandBuffer.Concurrent CommandBuffer;
    7. ...
    8.  
     
    Last edited: Jul 10, 2019
  2. ThreeIce

    ThreeIce

    Joined:
    Aug 15, 2019
    Posts:
    8
    I met the problem too. Did you solve it?
    Thanks
     
  3. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,753
    You can't use DeallocateOnJobCompletion on a list.

    Even though it's been passed in as a NativeArray (deferred) it was still declared as a native list.
     
  4. daschatten

    daschatten

    Joined:
    Jul 16, 2015
    Posts:
    208
    I solved this by just keeping the list:
    • Declare it as a member of the System
    • Initialize it in OnCreate() with Allocator.Persistent
    • Dispose it in OnDestroy
    • Clear it every frame
     
  5. Soaryn

    Soaryn

    Joined:
    Apr 17, 2015
    Posts:
    328
    Alternatively, you can dispose a list in a schedule via the list.Dispose(JobHandle) method allowing your job to run, then dispose. I'm kind of hoping they add that on the NativeArray just to add consistency. I'd be interested to see if there were any noticeable performance differences between constantly clearing a persistent list vs creating a new tempJob list each frame.
     
    daniel-holz and daschatten like this.
  6. Gaaammmler

    Gaaammmler

    Joined:
    Apr 10, 2018
    Posts:
    16
    Yeah sorry i fixed it like following:
    Code (CSharp):
    1.  
    2.  
    3.     public class SelectObjectSystem : JobComponentSystem
    4.     {
    5.         NativeList<int> deferredList;
    6.  
    7. protected override JobHandle OnUpdate(JobHandle inputDeps)
    8.         {
    9.             CreatePhysicsWorldSystem.FinalJobHandle.Complete();
    10.             if (deferredList.IsCreated)
    11.                 deferredList.Dispose();
    12.             deferredList = new NativeList<int>(Allocator.TempJob);
    13.  
    14.             var job = new SelectObjectSystemJob
    15.             {
    16.                 CollisionWorldSystem = CreatePhysicsWorldSystem.PhysicsWorld.CollisionWorld,
    17.                 iDs = deferredList,
    18.             };
    19.             inputDeps = job.Schedule(this, inputDeps);
    20.             inputDeps.Complete();
    21.             return inputDeps;
    22.  
    23.         }
    24.  
    25.  protected override void OnDestroyManager()
    26.         {
    27.             if (deferredList.IsCreated)
    28.                 deferredList.Dispose();
    29.         }
    30. }
    31.  
    32.  
    33.  
     
  7. Soaryn

    Soaryn

    Joined:
    Apr 17, 2015
    Posts:
    328
    Don't call complete on other system jobs, that creates an entire sync point and bogs down the scheduler.
    Also, don't call complete on your job that you are returning. That literally does nothing useful :p

    Also deferredList.Dispose(inputDeps) would schedule a dispose after your job is done so you needn't manually wait nor store a global var.
     
  8. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,683
    Hm... He is not using deferred list as I can see, and Deallocate on right place on array from query... He edited his first post?