Beispiel #1
0
        public static JobHandle GetChangedChunks <T>(
            this EntityQuery query,
            ComponentSystemBase system,
            Allocator allocator,
            ref NativeQueue <VTuple <int, int> > .ParallelWriter changedEntitySlices,
            JobHandle inputDeps,
            bool changeAll = false)
            where T : struct, IComponentData
        {
            var chunks = query.CreateArchetypeChunkArrayAsync(allocator, out var createChunksHandle);

            inputDeps = JobHandle.CombineDependencies(inputDeps, createChunksHandle);
            var indicesState = new NativeArray <int>(chunks.Length, Allocator.TempJob);

            inputDeps = new MemsetNativeArray <int> {
                Source = indicesState,
                Value  = -1
            }.Schedule(indicesState.Length, 64, inputDeps);
            inputDeps = new GatherChunkChanged <T> {
                ChunkType         = system.GetArchetypeChunkComponentType <T>(true),
                ChangedIndices    = indicesState,
                LastSystemVersion = system.LastSystemVersion,
                ForceChange       = changeAll
            }.Schedule(query, inputDeps);

            inputDeps = new ExtractChangedSlicesFromChunks {
                Source = indicesState,
                Chunks = chunks,
                Slices = changedEntitySlices
            }.Schedule(indicesState.Length, 64, inputDeps);
            inputDeps = indicesState.Dispose(inputDeps);
            return(inputDeps);
        }
        public unsafe JobHandle GetEntityQueryMatchDiffAsync(EntityQuery query, NativeList <Entity> newEntities, NativeList <Entity> missingEntities)
        {
            using (k_GetEntityQueryMatchDiffAsync.Auto())
            {
                newEntities.Clear();
                missingEntities.Clear();

                var queryMask = m_World.EntityManager.GetEntityQueryMask(query);

                var chunks = query.CreateArchetypeChunkArrayAsync(Allocator.TempJob, out var chunksJobHandle);
                k_GetEntityQueryMatchDiffAsyncAllocateBuffers.Begin();
                m_GatheredChanges.Clear();
                m_GatheredChanges.Resize(chunks.Length, NativeArrayOptions.ClearMemory);
                m_AllocatedShadowChunksForTheFrame.Clear();
                m_AllocatedShadowChunksForTheFrame.ResizeUninitialized(chunks.Length);
                m_RemovedChunkEntities.Clear();
                k_GetEntityQueryMatchDiffAsyncAllocateBuffers.End();

                k_GetEntityQueryMatchDiffAsyncScheduling.Begin();
                var gatherEntityChangesJob = new GatherEntityChangesJob
                {
                    QueryMask = queryMask,
                    Chunks    = chunks,
                    ShadowChunksBySequenceNumber = m_ShadowChunks,
                    GatheredChanges = (ChangesCollector *)m_GatheredChanges.GetUnsafeList()->Ptr
                }.Schedule(chunks.Length, 1, chunksJobHandle);

                var allocateNewShadowChunksJobHandle = new AllocateNewShadowChunksJob
                {
                    QueryMask = queryMask,
                    Chunks    = chunks,
                    ShadowChunksBySequenceNumber = m_ShadowChunks,
                    AllocatedShadowChunks        = (ShadowChunk *)m_AllocatedShadowChunksForTheFrame.GetUnsafeList()->Ptr
                }.Schedule(chunks.Length, 1, chunksJobHandle);

                var copyJobHandle = new CopyEntityDataJob
                {
                    QueryMask = queryMask,
                    Chunks    = chunks, // deallocate on job completion
                    ShadowChunksBySequenceNumber = m_ShadowChunks,
                    AllocatedShadowChunks        = m_AllocatedShadowChunksForTheFrame,
                    RemovedChunkEntities         = m_RemovedChunkEntities
                }.Schedule(JobHandle.CombineDependencies(gatherEntityChangesJob, allocateNewShadowChunksJobHandle));

                var concatResults = new ConcatResultsJob
                {
                    GatheredChanges      = m_GatheredChanges, // deallocate on job completion
                    RemovedChunkEntities = m_RemovedChunkEntities,
                    AddedEntities        = newEntities,
                    RemovedEntities      = missingEntities
                }.Schedule(copyJobHandle);
                k_GetEntityQueryMatchDiffAsyncScheduling.End();

                return(concatResults);
            }
        }
Beispiel #3
0
        protected override JobHandle OnUpdate(JobHandle inputDeps)
        {
            JobHandle bulletHandle;
            JobHandle asteroidHandle;
            JobHandle levelHandle;
            JobHandle settingsHandle;

            var asteroidJob = new DestroyAsteroidJob
            {
                commandBuffer = barrier.CreateCommandBuffer().ToConcurrent(),
                bulletChunks  = bulletGroup.CreateArchetypeChunkArrayAsync(Allocator.TempJob, out bulletHandle),
                bulletAgeType = GetArchetypeChunkComponentType <BulletAgeComponent>(true),
                positionType  = GetArchetypeChunkComponentType <Translation>(true),
                sphereType    = GetArchetypeChunkComponentType <CollisionSphereComponent>(true),
                entityType    = GetArchetypeChunkEntityType(),
                level         = m_LevelGroup.ToComponentDataArrayAsync <LevelComponent>(Allocator.TempJob, out levelHandle)
            };
            var shipJob = new DestroyShipJob
            {
                commandBuffer    = barrier.CreateCommandBuffer().ToConcurrent(),
                asteroidChunks   = asteroidGroup.CreateArchetypeChunkArrayAsync(Allocator.TempJob, out asteroidHandle),
                bulletChunks     = asteroidJob.bulletChunks,
                bulletAgeType    = asteroidJob.bulletAgeType,
                positionType     = asteroidJob.positionType,
                sphereType       = asteroidJob.sphereType,
                playerIdType     = GetArchetypeChunkComponentType <PlayerIdComponentData>(),
                entityType       = asteroidJob.entityType,
                serverSettings   = settingsGroup.ToComponentDataArrayAsync <ServerSettings>(Allocator.TempJob, out settingsHandle),
                playerClearQueue = playerClearQueue.AsParallelWriter(),
                level            = asteroidJob.level
            };
            var asteroidDep = JobHandle.CombineDependencies(inputDeps, bulletHandle, levelHandle);
            var shipDep     = JobHandle.CombineDependencies(asteroidDep, asteroidHandle, settingsHandle);

            var h1 = asteroidJob.Schedule(asteroidGroup, asteroidDep);
            var h2 = shipJob.Schedule(shipGroup, shipDep);

            var handle = JobHandle.CombineDependencies(h1, h2);

            barrier.AddJobHandleForProducer(handle);

            var cleanupShipJob = new ClearShipPointerJob
            {
                playerClearQueue = playerClearQueue,
                commandTarget    = GetComponentDataFromEntity <CommandTargetComponent>()
            };
            var cleanupChunkJob = new ChunkCleanupJob
            {
                bulletChunks   = shipJob.bulletChunks,
                asteroidChunks = shipJob.asteroidChunks,
                level          = shipJob.level
            };

            return(JobHandle.CombineDependencies(cleanupShipJob.Schedule(h2), cleanupChunkJob.Schedule(handle)));
        }
Beispiel #4
0
        public unsafe JobHandle GetEntityQueryMatchDiffAsync(EntityQuery query, NativeList <Entity> newEntities, NativeList <Entity> missingEntities)
        {
            newEntities.Clear();
            missingEntities.Clear();

            var queryMask = m_World.EntityManager.GetEntityQueryMask(query);

            var chunks          = query.CreateArchetypeChunkArrayAsync(Allocator.TempJob, out var chunksJobHandle);
            var gatheredChanges = new NativeArray <ChangesCollector>(chunks.Length, Allocator.TempJob);
            var allocatedShadowChunksForTheFrame = new NativeArray <ShadowChunk>(chunks.Length, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
            var removedChunkEntities             = new NativeList <Entity>(Allocator.TempJob);

            var gatherEntityChangesJob = new GatherEntityChangesJob
            {
                QueryMask = queryMask,
                Chunks    = chunks,
                ShadowChunksBySequenceNumber = m_ShadowChunks,
                GatheredChanges = (ChangesCollector *)NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(gatheredChanges)
            }.Schedule(chunks.Length, 1, chunksJobHandle);

            var allocateNewShadowChunksJobHandle = new AllocateNewShadowChunksJob
            {
                QueryMask = queryMask,
                Chunks    = chunks,
                ShadowChunksBySequenceNumber = m_ShadowChunks,
                AllocatedShadowChunks        = (ShadowChunk *)NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(allocatedShadowChunksForTheFrame)
            }.Schedule(chunks.Length, 1, chunksJobHandle);

            var copyJobHandle = new CopyEntityDataJob
            {
                QueryMask = queryMask,
                Chunks    = chunks,                                              // deallocate on job completion
                ShadowChunksBySequenceNumber = m_ShadowChunks,
                AllocatedShadowChunks        = allocatedShadowChunksForTheFrame, // deallocate on job completion
                RemovedChunkEntities         = removedChunkEntities
            }.Schedule(JobHandle.CombineDependencies(gatherEntityChangesJob, allocateNewShadowChunksJobHandle));

            var concatResults = new ConcatResultsJob
            {
                GatheredChanges      = gatheredChanges, // deallocate on job completion
                RemovedChunkEntities = removedChunkEntities.AsDeferredJobArray(),
                AddedEntities        = newEntities,
                RemovedEntities      = missingEntities
            }.Schedule(copyJobHandle);

            return(removedChunkEntities.Dispose(concatResults));
        }
Beispiel #5
0
    protected override JobHandle OnUpdate(JobHandle inputDependencies)
    {
        _lastAllocation++;
        LastJob.Complete();

        if (_batchQueue.Count > 0)
        {
            return(inputDependencies);
        }

        Profiler.BeginSample("Dependencies");
        var voxelColorType   = GetArchetypeChunkComponentType <VoxelColor>(true);
        var matrixType       = GetArchetypeChunkComponentType <LocalToWorld>(true);
        var chunks           = _query.CreateArchetypeChunkArrayAsync(Allocator.TempJob, out var chunksHandle);
        var chunkCount       = _query.CalculateChunkCount();
        var spaceRequirement = _query.CalculateEntityCount();
        var indexMappings    = new NativeArray <int>(chunkCount, Allocator.TempJob);
        var indexing         = new IndexingJob
        {
            IndexMappings  = indexMappings,
            Chunks         = chunks,
            ChunksPerBatch = chunksPerBatch
        }.Schedule(JobHandle.CombineDependencies(inputDependencies, chunksHandle));

        Profiler.EndSample();

        JobHandle deps = indexing;

        Profiler.BeginSample("Prepare Space");
        if (_lastColors.Length == spaceRequirement && _lastAllocation < 4)
        {
            var colorClear = new MemsetNativeArray <VoxelColor>
            {
                Source = _lastColors,
                Value  = default
            }.Schedule(_lastColors.Length, 256, inputDependencies);
        public unsafe ComponentChanges GatherComponentChanges(EntityManager entityManager, EntityQuery query, Allocator allocator)
        {
            using (k_GatherComponentChanges.Auto())
            {
                var chunks = query.CreateArchetypeChunkArrayAsync(Allocator.TempJob, out var chunksJobHandle);
                k_GatherComponentChangesBufferAlloc.Begin();
                m_AllocatedShadowChunksForTheFrame.Clear();
                m_AllocatedShadowChunksForTheFrame.ResizeUninitialized(chunks.Length);
                m_GatheredChanges.Clear();
                m_GatheredChanges.Resize(chunks.Length, NativeArrayOptions.ClearMemory);
                m_RemovedShadowChunks.Clear();
                k_GatherComponentChangesBufferAlloc.End();
                k_GatherComponentChangesResultBufferAlloc.Begin();
                var sharedComponentDataBuffer = new NativeList <GCHandle>(allocator);
                var addedEntities             = new NativeList <Entity>(allocator);
                var addedEntitiesMapping      = new NativeList <int>(allocator);
                var removedEntities           = new NativeList <Entity>(allocator);
                var removedEntitiesMapping    = new NativeList <int>(allocator);

                var indexOfFirstAdded = 0;
                var indicesInManagedComponentStore = new NativeList <int>(Allocator.TempJob);
                k_GatherComponentChangesResultBufferAlloc.End();

                k_GatherComponentChangesJobWorkScheduling.Begin();
                var changesJobHandle = new GatherChangesJob
                {
                    TypeIndex = m_TypeIndex,
                    Chunks    = chunks,
                    ShadowChunksBySequenceNumber = m_ShadowChunks,
                    GatheredChanges = (ChangesCollector *)m_GatheredChanges.GetUnsafeList()->Ptr
                }.Schedule(chunks.Length, 1, chunksJobHandle);

                var allocateNewShadowChunksJobHandle = new AllocateNewShadowChunksJob
                {
                    TypeIndex = m_TypeIndex,
                    Chunks    = chunks,
                    ShadowChunksBySequenceNumber = m_ShadowChunks,
                    AllocatedShadowChunks        = (ShadowChunk *)m_AllocatedShadowChunksForTheFrame.GetUnsafeList()->Ptr
                }.Schedule(chunks.Length, 1, chunksJobHandle);

                var copyJobHandle = new CopyStateToShadowChunksJob
                {
                    TypeIndex = m_TypeIndex,
                    Chunks    = chunks,
                    ShadowChunksBySequenceNumber = m_ShadowChunks,
                    AllocatedShadowChunks        = (ShadowChunk *)m_AllocatedShadowChunksForTheFrame.GetUnsafeList()->Ptr,
                    RemovedChunks = m_RemovedShadowChunks
                }.Schedule(JobHandle.CombineDependencies(changesJobHandle, allocateNewShadowChunksJobHandle));

                var prepareResultJob = new PrepareResultsJob
                {
                    GatheredChanges                = m_GatheredChanges,
                    RemovedShadowChunks            = m_RemovedShadowChunks.AsDeferredJobArray(),
                    IndexOfFirstAdded              = &indexOfFirstAdded,
                    ShadowChunksBySequenceNumber   = m_ShadowChunks,
                    IndicesInManagedComponentStore = indicesInManagedComponentStore,
                    AddedEntities = addedEntities,
                    AddedEntitiesMappingToComponent = addedEntitiesMapping,
                    RemovedEntities = removedEntities,
                    RemovedEntitiesMappingToComponent = removedEntitiesMapping,
                }.Schedule(copyJobHandle);

                var concatResultsJob = new ConcatResultsJob
                {
                    TypeIndex                         = m_TypeIndex,
                    GatheredChanges                   = m_GatheredChanges,
                    RemovedShadowChunks               = m_RemovedShadowChunks.AsDeferredJobArray(),
                    ShadowChunksBySequenceNumber      = m_ShadowChunks,
                    SharedComponentValueIndexByChunk  = m_ManagedComponentIndexInCopyByChunk,
                    IndicesInManagedComponentStore    = indicesInManagedComponentStore.AsDeferredJobArray(),
                    AddedEntities                     = addedEntities.AsDeferredJobArray(),
                    AddedEntitiesMappingToComponent   = addedEntitiesMapping.AsDeferredJobArray(),
                    RemovedEntities                   = removedEntities.AsDeferredJobArray(),
                    RemovedEntitiesMappingToComponent = removedEntitiesMapping.AsDeferredJobArray()
                }.Schedule(prepareResultJob);
                k_GatherComponentChangesJobWorkScheduling.End();

                k_GatherComponentChangesJobWorkCompleting.Begin();
                concatResultsJob.Complete();
                k_GatherComponentChangesJobWorkCompleting.End();

                k_GatherComponentChangesResultProcessing.Begin();
                sharedComponentDataBuffer.Capacity = indicesInManagedComponentStore.Length;
                for (var i = 0; i < indexOfFirstAdded; i++)
                {
                    sharedComponentDataBuffer.AddNoResize(GCHandle.Alloc(m_ManagedComponentStoreStateCopy[indicesInManagedComponentStore[i]]));
                }

                var count = entityManager.GetCheckedEntityDataAccess()->ManagedComponentStore.GetSharedComponentCount();
                m_ManagedComponentStoreStateCopy.Capacity = count;
                m_ManagedComponentStoreStateCopy.Clear();

                // Add the default component value in position 0
                // and query GetSharedComponentData *NonDefault* Boxed to avoid calling Activator.CreateInstance for the default value.
                // A downside is the default shared component value is reused between runs and can be mutated by user code.
                // Can be prevented by adding a check like TypeManager.Equals(m_DefaultComponentDataValue, default(T)) but that would be more expensive.
                m_ManagedComponentStoreStateCopy.Add(m_DefaultComponentDataValue);
                for (var i = 1; i < count; i++)
                {
                    var sharedComponentDataNonDefaultBoxed = entityManager.GetCheckedEntityDataAccess()->ManagedComponentStore.GetSharedComponentDataNonDefaultBoxed(i);
                    m_ManagedComponentStoreStateCopy.Add(sharedComponentDataNonDefaultBoxed);
                }

                for (var i = indexOfFirstAdded; i < indicesInManagedComponentStore.Length; i++)
                {
                    sharedComponentDataBuffer.AddNoResize(GCHandle.Alloc(m_ManagedComponentStoreStateCopy[indicesInManagedComponentStore[i]]));
                }
                k_GatherComponentChangesResultProcessing.End();

                k_GatherComponentChangesResultBufferDispose.Begin();
                for (var i = 0; i < m_GatheredChanges.Length; i++)
                {
                    var c = m_GatheredChanges[i];
                    c.Dispose();
                }

                chunks.Dispose();
                indicesInManagedComponentStore.Dispose();
                k_GatherComponentChangesResultBufferDispose.End();

                return(new ComponentChanges(m_TypeIndex, sharedComponentDataBuffer, addedEntities, addedEntitiesMapping, removedEntities, removedEntitiesMapping));
            }
        }
        public unsafe ComponentChanges GatherComponentChangesAsync(EntityQuery query, Allocator allocator, out JobHandle jobHandle)
        {
            using (k_GatherComponentChangesAsync.Auto())
            {
                var chunks = query.CreateArchetypeChunkArrayAsync(Allocator.TempJob, out var chunksJobHandle);

                k_GatherComponentChangesAsyncBufferAlloc.Begin();
                m_AllocatedShadowChunksForTheFrame.Clear();
                m_AllocatedShadowChunksForTheFrame.ResizeUninitialized(chunks.Length);
                m_GatheredChanges.Clear();
                m_GatheredChanges.Resize(chunks.Length, NativeArrayOptions.ClearMemory);
                m_RemovedChunkBuffer.Clear();
                m_RemovedChunkEntities.Clear();
                var result = new NativeReference <Result>(allocator);
                k_GatherComponentChangesAsyncBufferAlloc.End();

                k_GatherComponentChangesAsyncScheduling.Begin();
                var changesJobHandle = new GatherComponentChangesJob
                {
                    TypeIndex     = m_TypeIndex,
                    ComponentSize = m_ComponentSize,
                    Chunks        = chunks,
                    ShadowChunksBySequenceNumber = m_PreviousChunksBySequenceNumber,
                    GatheredChanges = (ChangesCollector *)m_GatheredChanges.GetUnsafeList()->Ptr
                }.Schedule(chunks.Length, 1, chunksJobHandle);

                var allocateNewShadowChunksJobHandle = new AllocateNewShadowChunksJob
                {
                    TypeIndex     = m_TypeIndex,
                    ComponentSize = m_ComponentSize,
                    Chunks        = chunks,
                    ShadowChunksBySequenceNumber = m_PreviousChunksBySequenceNumber,
                    AllocatedShadowChunks        = (ShadowChunk *)m_AllocatedShadowChunksForTheFrame.GetUnsafeList()->Ptr
                }.Schedule(chunks.Length, 1, chunksJobHandle);

                var copyJobHandle = new CopyComponentDataJob
                {
                    TypeIndex     = m_TypeIndex,
                    ComponentSize = m_ComponentSize,
                    Chunks        = chunks,
                    ShadowChunksBySequenceNumber    = m_PreviousChunksBySequenceNumber,
                    AllocatedShadowChunks           = (ShadowChunk *)m_AllocatedShadowChunksForTheFrame.GetUnsafeList()->Ptr,
                    RemovedChunkComponentDataBuffer = m_RemovedChunkBuffer,
                    RemovedChunkEntities            = m_RemovedChunkEntities
                }.Schedule(JobHandle.CombineDependencies(changesJobHandle, allocateNewShadowChunksJobHandle));

                var concatResultJobHandle = new ConcatResultJob
                {
                    ComponentSize   = m_ComponentSize,
                    Allocator       = allocator,
                    GatheredChanges = m_GatheredChanges.AsDeferredJobArray(),
                    RemovedChunkComponentDataBuffer = m_RemovedChunkBuffer.AsDeferredJobArray(),
                    RemovedChunkEntities            = m_RemovedChunkEntities.AsDeferredJobArray(),

                    Result = result
                }.Schedule(copyJobHandle);

                jobHandle = JobHandle.CombineDependencies(chunks.Dispose(copyJobHandle), concatResultJobHandle);
                k_GatherComponentChangesAsyncScheduling.End();

                return(new ComponentChanges(m_TypeIndex, result));
            }
        }
        public unsafe ComponentChanges GatherComponentChangesAsync(EntityQuery query, Allocator allocator, out JobHandle jobHandle)
        {
            var chunks = query.CreateArchetypeChunkArrayAsync(Allocator.TempJob, out var chunksJobHandle);
            var allocatedShadowChunksForTheFrame = new NativeArray <ShadowChunk>(chunks.Length, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
            var gatheredChanges      = new NativeArray <ChangesCollector>(chunks.Length, Allocator.TempJob);
            var removedChunkBuffer   = new NativeList <byte>(Allocator.TempJob);
            var removedChunkEntities = new NativeList <Entity>(Allocator.TempJob);

            var buffer            = new NativeList <byte>(allocator);
            var addedComponents   = new NativeList <Entity>(allocator);
            var removedComponents = new NativeList <Entity>(allocator);

            var changesJobHandle = new GatherComponentChangesJob
            {
                TypeIndex     = m_TypeIndex,
                ComponentSize = m_ComponentSize,
                Chunks        = chunks,
                ShadowChunksBySequenceNumber = m_PreviousChunksBySequenceNumber,
                GatheredChanges = (ChangesCollector *)NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(gatheredChanges)
            }.Schedule(chunks.Length, 1, chunksJobHandle);

            var allocateNewShadowChunksJobHandle = new AllocateNewShadowChunksJob
            {
                TypeIndex     = m_TypeIndex,
                ComponentSize = m_ComponentSize,
                Chunks        = chunks,
                ShadowChunksBySequenceNumber = m_PreviousChunksBySequenceNumber,
                AllocatedShadowChunks        = (ShadowChunk *)NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(allocatedShadowChunksForTheFrame)
            }.Schedule(chunks.Length, 1, chunksJobHandle);

            var copyJobHandle = new CopyComponentDataJob
            {
                TypeIndex     = m_TypeIndex,
                ComponentSize = m_ComponentSize,
                Chunks        = chunks,
                ShadowChunksBySequenceNumber    = m_PreviousChunksBySequenceNumber,
                AllocatedShadowChunks           = (ShadowChunk *)NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(allocatedShadowChunksForTheFrame),
                RemovedChunkComponentDataBuffer = removedChunkBuffer,
                RemovedChunkEntities            = removedChunkEntities
            }.Schedule(JobHandle.CombineDependencies(changesJobHandle, allocateNewShadowChunksJobHandle));

            var concatResultJobHandle = new ConcatResultJob
            {
                ComponentSize   = m_ComponentSize,
                GatheredChanges = gatheredChanges,
                RemovedChunkComponentDataBuffer = removedChunkBuffer.AsDeferredJobArray(),
                RemovedChunkEntities            = removedChunkEntities.AsDeferredJobArray(),

                ComponentDataBuffer = buffer,
                AddedComponents     = addedComponents,
                RemovedComponents   = removedComponents
            }.Schedule(copyJobHandle);

            var handles = new NativeArray <JobHandle>(5, Allocator.Temp)
            {
                [0] = chunks.Dispose(copyJobHandle),
                [1] = gatheredChanges.Dispose(concatResultJobHandle),
                [2] = removedChunkBuffer.Dispose(concatResultJobHandle),
                [3] = removedChunkEntities.Dispose(concatResultJobHandle),
                [4] = allocatedShadowChunksForTheFrame.Dispose(copyJobHandle)
            };

            jobHandle = JobHandle.CombineDependencies(handles);
            handles.Dispose();

            return(new ComponentChanges(m_TypeIndex, buffer, addedComponents, removedComponents));
        }