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

How do use a CommandBuffer (from a BarrierSystem) in an IJobParallelFor or IJobChunk?

Discussion in 'Entity Component System' started by davenirline, Nov 28, 2018.

  1. davenirline

    davenirline

    Joined:
    Jul 7, 2010
    Posts:
    969
    I'm making a job with this pattern:
    Code (CSharp):
    1. private struct Job : IJobChunk {
    2.     public EntityCommandBuffer commandBuffer;
    3.     // ... Other variables
    4.  
    5.     public void Execute(ArchetypeChunk chunk, int chunkIndex) {
    6.         // Processing here
    7.     }
    8. }
    The commandBuffer will be supplied using BarrierSystem.CreateCommandBuffer(). I couldn't get it to work. I get this error:

    InvalidOperationException: The previously scheduled job PlaySpriteAnimationSystem:Job writes to the NativeArray Job.data.commandBuffer. You must call JobHandle.Complete() on the job PlaySpriteAnimationSystem:Job, before you can deallocate the NativeArray safely.
    Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle.CheckDeallocateAndThrow (Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle handle) <0x3c724870 + 0x00052> in <2f14d49edc704940aee557642343f344>:0
    Unity.Collections.LowLevel.Unsafe.DisposeSentinel.Dispose (Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle safety, Unity.Collections.LowLevel.Unsafe.DisposeSentinel& sentinel) (at C:/buildslave/unity/build/Runtime/Export/NativeArray/DisposeSentinel.cs:41)
    Unity.Entities.EntityCommandBuffer.Dispose () (at C:/Users/Marnel/AppData/Local/Unity/cache/packages/staging-packages.unity.com/com.unity.entities@0.0.12-preview.21/Unity.Entities/EntityCommandBuffer.cs:606)
    Unity.Entities.BarrierSystem.FlushBuffers (System.Boolean playBack) (at C:/Users/Marnel/AppData/Local/Unity/cache/packages/staging-packages.unity.com/com.unity.entities@0.0.12-preview.21/Unity.Entities/ComponentSystem.cs:682)
    Unity.Entities.BarrierSystem.OnUpdate () (at C:/Users/Marnel/AppData/Local/Unity/cache/packages/staging-packages.unity.com/com.unity.entities@0.0.12-preview.21/Unity.Entities/ComponentSystem.cs:641)
    Unity.Entities.ComponentSystem.InternalUpdate () (at C:/Users/Marnel/AppData/Local/Unity/cache/packages/staging-packages.unity.com/com.unity.entities@0.0.12-preview.21/Unity.Entities/ComponentSystem.cs:375)
    Unity.Entities.ScriptBehaviourManager.Update () (at C:/Users/Marnel/AppData/Local/Unity/cache/packages/staging-packages.unity.com/com.unity.entities@0.0.12-preview.21/Unity.Entities/ScriptBehaviourManager.cs:77)
    Unity.Entities.ScriptBehaviourUpdateOrder+DummyDelagateWrapper.TriggerUpdate () (at C:/Users/Marnel/AppData/Local/Unity/cache/packages/staging-packages.unity.com/com.unity.entities@0.0.12-preview.21/Unity.Entities/ScriptBehaviourUpdateOrder.cs:703)

    I want to call JobHandle.Complete() in the BarrierSystem but it has a sealed OnUpdate(). I tried using EntityCommandBuffer.Concurrent. It's the same error. The only solution to this is to turn the job into an IJob.
     
  2. e199

    e199

    Joined:
    Mar 24, 2015
    Posts:
    101
  3. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    Use the EndFrameBarrier!
    Code (CSharp):
    1. [inject] EndFrameBarrier endFrameBarrier;
    2.  
    3. void Update(...) {
    4.      var commandBuffer = endFrameBarrier.CreateCommandBuffer();
    5.  
    6.      //use ToConcurrent() if you are in a IJobParallelFor
    7.     // commandBuffer.ToConcurrent();
    8. }

    You can also use your own Barrier! Barriers are working as synch points!
     
  4. davenirline

    davenirline

    Joined:
    Jul 7, 2010
    Posts:
    969
    I'm wrong. Using an IJob doesn't work either.
     
  5. davenirline

    davenirline

    Joined:
    Jul 7, 2010
    Posts:
    969
    This is what I'm doing. I'm using an internal class then using an [UpdateBefore] on the main system class:
    Code (CSharp):
    1. [UpdateBefore(typeof(Barrier))]
    2. public class MySystem {
    3.     private class Barrier : BarrierSystem {
    4.     }
    5. }
     
  6. davenirline

    davenirline

    Joined:
    Jul 7, 2010
    Posts:
    969
    EndFrameBarrier doesn't work either.
     
  7. davenirline

    davenirline

    Joined:
    Jul 7, 2010
    Posts:
    969
    I see the problem now. If I use Inject, it works. I'm trying to avoid it so I was always using World.Active.GetOrCreateManager(). I guess they're not the same.
     
  8. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,683
    It’s known issue. Inject-less barriers work incorrect in some cases.