How to check for Job completion many times per frame?

I have a sequence of jobs that depend on each other but finish really quickly (like thousands of sequences every frame) and I want to schedule the next job in the sequence asap, ideally exactly when the first job completes. What are valid strategies in this case?

I have considered:

  • Schedule() with JobHandle dependsOn

  • I cannot use that since all Jobs depend on each other’s native collections (at least compiler keeps telling me that)

  • Schedule in Update, Complete in LateUpdate

  • I would need more “Update” points during a frame. I could check again in OnPreCull, OnPreRender, etc events, but that just seems wrong and introduces too much delay.

  • Use a Coroutine with WaitUntil()

  • Can’t do that. Coroutines only run once per frame, that introduces too much delay.

  • Use async/await with a timed await that lets me repeatedly check for job completion

  • I worry that this would add unnecessary overhead and it may check far too often or rarely depending on CPU speed.

Am I missing something obvious here, like a delegate or event that runs when a Job completes?

Here’s the job sequence I need to schedule, from top to bottom. The meshData and the vertexBuilder’s Quads array are used by multiple jobs.

        JobHandle ISingleMeshBuilderInternal.ScheduleVertexBuilder() => _vertexBuilder.Schedule();

        JobHandle ISingleMeshBuilderInternal.ScheduleMeshSetup(Mesh.MeshData meshData)
        {
            var meshInfo = _vertexBuilder.GetMeshInfo();
            var setupJob = new SetupMeshJob(meshData, meshInfo, MeshBuilder.DefaultVertexAttributes, MeshBuilder.DefaultMeshUpdateFlags);
            return setupJob.Schedule();
        }

        JobHandle ISingleMeshBuilderInternal.ScheduleAssignVertices(Mesh.MeshData meshData)
        {
            var quads = (_vertexBuilder as IOrientedQuadBuilder).Quads;
            return ScheduleJob.AssignQuadVertices(meshData, quads);
        }

        JobHandle ISingleMeshBuilderInternal.ScheduleAssignIndices(Mesh.MeshData meshData, JobHandle vertexHandle)
        {
            var quadCount = (_vertexBuilder as IOrientedQuadBuilder).Quads.Length;
            return ScheduleJob.AssignQuadIndices(meshData, quadCount, vertexHandle);
        }

The first option (Schedule with JobHandle dependsOn). If compiler is complaining but you are sure that you are doing it right, you can simply disable the safety checks for that container in your jobs (but something is telling me that if you are doing it right it shouldn’t be complaining).

Thanks, I thought so. I’ll try again, I may not have tried all combinations of native attributes. The big issue being meshData which is provided by the Mesh.AllocateWritableMeshData API and internally maps to the same native container which complicates things.

I resolved some dependency issues and ended up with one dependsOn JobHandle for three of the four jobs, and using CombineDependencies to return the combined JobHandle to wait on. And a special case where the first job needs to Complete before the second but doesn‘t have to if it runs deterministically (ie vertex/index count known ahead of time).