JobHandel Dept Question

IM a but confused why this is not working, if I have a dependency chained why must I still call Complete() before I can deallocate vtxArray. If someone would help me understand I would be thankful.

nvalidOperationException: The previously scheduled job HexagonSphereBuildSystem:BuildTriangles reads from the Unity.Entities.EntityTypeHandle BuildTriangles.safety. You must call JobHandle.Complete() on the job HexagonSphereBuildSystem:BuildTriangles, before you can deallocate the Unity.Entities.EntityTypeHandle safely.

var dep0 = Entities
    .WithName($"BuildVertices")
    .WithSharedComponentFilter( new BuildComponent(){Value = true})
    .ForEach((int entityInQueryIndex, Entity e, ref HexagonSphereVertexComponent v, in HexagonSphereComponent h) =>
    {
        Debug.Log($"Working on vertex {v.Index}");
        v.MeshIndex = entityInQueryIndex;
    }).ScheduleParallel(Dependency);

_queryVertices.SetSharedComponentFilter(new BuildComponent(){Value = true});
var vtxArray = _queryVertices.ToEntityArray(Allocator.Temp);
var dep1 =Entities
    .WithReadOnly(vtxArray)
    .WithName($"BuildTriangles")
    .WithSharedComponentFilter( new BuildComponent(){Value = true})
    .ForEach((int entityInQueryIndex, Entity e, ref HexagonSphereTriangleComponent t, in HexagonSphereComponent h) =>
    {
        Debug.Log($"Working on triangle {t.Index}");
        var vA = h.HexagonSphere.Value.TriangleVertABC[t.Index][0];
        var vB = h.HexagonSphere.Value.TriangleVertABC[t.Index][1];
        var vC = h.HexagonSphere.Value.TriangleVertABC[t.Index][2];
        t.MeshIndices[0] = GetComponent<HexagonSphereVertexComponent>(vtxArray[vA]).MeshIndex;
        t.MeshIndices[1] = GetComponent<HexagonSphereVertexComponent>(vtxArray[vB]).MeshIndex;
        t.MeshIndices[1] = GetComponent<HexagonSphereVertexComponent>(vtxArray[vC]).MeshIndex;
    }).ScheduleParallel(dep0);

JobHandle dep3 = JobHandle.CombineDependencies(dep1, dep0);
vtxArray.Dispose(dep3);

You shouldn’t have to.

Firstly a random thing
JobHandle dep3 = JobHandle.CombineDependencies(dep1, dep0);
You don’t need this since dep1 depends on dep0 already so dep3 == dep1

I suspect this is something else. A few things,

  • is this the full job?
  • if not, are you writing back to Dependency with your final job handle
  • what is _queryVertices?
  • Here is the full system stripped out
  • _queryVertices is the same query as the .ForEach((int entityInQueryIndex, Entity e, ref HexagonSphereVertexComponent v, in HexagonSphereComponent h) as in they the same entities.
  • JobHandle dep3 = JobHandle.CombineDependencies(dep1, dep0); was my desperate attempt to get his working.

IM not sure what im going wrong here

InvalidOperationException: The previously scheduled job TestASystem:BuildTriangles reads from the Unity.Entities.EntityTypeHandle BuildTriangles.safety. You must call JobHandle.Complete() on the job TestASystem:BuildTriangles, before you can deallocate the Unity.Entities.EntityTypeHandle safely.

public class TestASystem : SystemBase
{
    private EntityQuery _queryTriangles;
    private EntityQuery _queryVertices;
 
    protected override void OnCreate()
    {
        base.OnCreate();

     
        _queryTriangles = EntityManager.CreateEntityQuery(
            ComponentType.ReadOnly<HexagonSphereTriangleComponent>(),
            ComponentType.ReadOnly<TagBuild>(),
            ComponentType.ReadOnly<HexagonSphereComponent>(),
            typeof(BuildComponent));
         
        _queryVertices = EntityManager.CreateEntityQuery(
            ComponentType.ReadOnly<HexagonSphereVertexComponent>(),
            ComponentType.ReadOnly<HexagonSphereComponent>(),
            typeof(BuildComponent));

    }
 
    protected override void OnUpdate()
    {
     
        var dep0 = Entities
            .WithName($"BuildVertices")
            .WithSharedComponentFilter( new BuildComponent(){Value = true})
            .ForEach((int entityInQueryIndex, Entity e, ref HexagonSphereVertexComponent v, in HexagonSphereComponent h) =>
            {
                Debug.Log($"Working on vertex {v.Index}");
                v.MeshIndex = entityInQueryIndex;
            }).ScheduleParallel(Dependency);
        
        _queryVertices.SetSharedComponentFilter(new BuildComponent(){Value = true});
        var vtxArray = _queryVertices.ToEntityArray(Allocator.TempJob);
        var dep1 =Entities
            .WithReadOnly(vtxArray)
            .WithName($"BuildTriangles")
            .WithSharedComponentFilter( new BuildComponent(){Value = true})
            .ForEach((int entityInQueryIndex, Entity e, ref HexagonSphereTriangleComponent t, in HexagonSphereComponent h) =>
            {
                Debug.Log($"Working on triangle {t.Index}");
                var vA = h.HexagonSphere.Value.TriangleVertABC[t.Index][0];
                var vB = h.HexagonSphere.Value.TriangleVertABC[t.Index][1];
                var vC = h.HexagonSphere.Value.TriangleVertABC[t.Index][2];
                t.MeshIndices[0] = GetComponent<HexagonSphereVertexComponent>(vtxArray[vA]).MeshIndex;
                t.MeshIndices[1] = GetComponent<HexagonSphereVertexComponent>(vtxArray[vB]).MeshIndex;
                t.MeshIndices[1] = GetComponent<HexagonSphereVertexComponent>(vtxArray[vC]).MeshIndex;
            }).ScheduleParallel(dep0);
        
        JobHandle dep3 = JobHandle.CombineDependencies(dep1, dep0);
        vtxArray.Dispose(dep3);
    }
}

6705628--770287--Screen Shot 2021-01-08 at 10.34.57 PM.png

It’s a very interesting error because i’ve never come across it on EntityTypeHandle

But this is what I was expecting from reading it. This is your problem I think.

You’re executing ToEntityArray on the main thread while the previous BuildVertices job is still running which has access to the entity handle.

Also just a thing of note. You do realize your SetSharedComponentFilter will affect the previous BuildVertices job

I see, is there a way to create a dependency on the _queryVertices.ToEntityArray(Allocator.TempJob); to the previous Entities.ForEach?

EDIT:

Ok turns out the solution is pretty simple in my case, I just move the query to the start of the system before the lambdas jobs

Thanks @tertle for the help

What @tertle meant, is you’re not writing to Dependency property back and thus have all these jobs completion out of dependency chain.

Yea something is still not working, I didn’t see I had a comple() and that why I thought it worked Could you show me an example, I’m not following here. Should I be grabbing the Property at the start and write to it on each schedule?

In your code you shouldn’t do it by yourself, codegen will handle it automatically just write it without In\Out dependencies and just pass Dependency to Dispose and write back to Dependency.
I see there is a lack of knowledge about Dependencies. I recommend you read docs (Job dependencies | Entities | 0.16.0-preview.21) and source code first to understand it better as dependencies are one of the core pillars for Unity ECS implementation. Or it will bite you every time :slight_smile:

Is the componentType.ReadOnly…ReadWrite and WithReadOnly() used by code gen to create dependency or it is purely from passing in as in and ref

They all used for constructing dependency chains depends on access type. Open DOTS->DOTS Compiler->Open Inspector and look to which ILPP will convert your system

OK thank you, seems to be working now