internal void RemoveComponent(MatchingArchetypeList archetypeList, EntityQueryFilter filter, ComponentType componentType) { var jobHandle = new JobHandle(); using (var chunks = ComponentChunkIterator.CreateArchetypeChunkArray(archetypeList, Allocator.TempJob, out jobHandle, ref filter)) { jobHandle.Complete(); if (chunks.Length == 0) { return; } BeforeStructuralChange(); var archetypeChanges = EntityComponentStore->BeginArchetypeChangeTracking(); EntityComponentStore->AssertCanRemoveComponent(chunks, componentType); EntityManagerChangeArchetypeUtility.RemoveComponent(chunks, componentType, EntityComponentStore, ManagedComponentStore); var changedArchetypes = EntityComponentStore->EndArchetypeChangeTracking(archetypeChanges); EntityGroupManager.AddAdditionalArchetypes(changedArchetypes); } }
internal void DestroyEntity(MatchingArchetypeList archetypeList, EntityQueryFilter filter) { Profiler.BeginSample("DestroyEntity(EntityQuery entityQueryFilter)"); Profiler.BeginSample("GetAllMatchingChunks"); var jobHandle = new JobHandle(); using (var chunks = ComponentChunkIterator.CreateArchetypeChunkArray(archetypeList, Allocator.TempJob, out jobHandle, ref filter)) { jobHandle.Complete(); Profiler.EndSample(); if (chunks.Length != 0) { BeforeStructuralChange(); Profiler.BeginSample("EditorOnlyChecks"); EntityComponentStore->AssertCanDestroy(chunks); EntityComponentStore->AssertWillDestroyAllInLinkedEntityGroup(chunks, GetArchetypeChunkBufferType <LinkedEntityGroup>(false)); Profiler.EndSample(); Profiler.BeginSample("DeleteChunks"); EntityManagerCreateDestroyEntitiesUtility.DestroyEntities(chunks, EntityComponentStore, ManagedComponentStore); Profiler.EndSample(); } } Profiler.EndSample(); }
internal void AddComponent(MatchingArchetypeList archetypeList, EntityQueryFilter filter, ComponentType componentType) { var jobHandle = new JobHandle(); using (var chunks = ComponentChunkIterator.CreateArchetypeChunkArray(archetypeList, Allocator.TempJob, out jobHandle, ref filter)) { jobHandle.Complete(); if (chunks.Length == 0) { return; } BeforeStructuralChange(); EntityComponentStore->AssertCanAddComponent(chunks, componentType); using (var entityBatchList = m_EntityComponentStore->CreateEntityBatchList(chunks)) { EntityManagerChangeArchetypeUtility.AddComponent(entityBatchList, componentType, 0, EntityComponentStore, ManagedComponentStore, EntityGroupManager); } } }
/// <summary> /// Total number of chunks in a given MatchingArchetype list. /// </summary> /// <param name="matchingArchetypes">List of matching archetypes.</param> /// <returns>Number of chunks in a list of archetypes.</returns> internal static int CalculateNumberOfChunksWithoutFiltering(MatchingArchetypeList matchingArchetypes) { var chunkCount = 0; for (var m = matchingArchetypes.Count - 1; m >= 0; --m) { var match = matchingArchetypes.p[m]; chunkCount += match->Archetype->Chunks.Count; } return(chunkCount); }
public ComponentChunkIterator(MatchingArchetypeList match, uint globalSystemVersion, ref ComponentGroupFilter filter) { m_MatchingArchetypeList = match; m_CurrentMatchingArchetypeIndex = match.Count - 1; IndexInComponentGroup = -1; m_CurrentChunk = null; m_CurrentArchetypeIndex = m_CurrentArchetypeEntityIndex = int.MaxValue; // This will trigger UpdateCacheResolvedIndex to update the cache on first access m_CurrentChunkIndex = m_CurrentChunkEntityIndex = 0; m_GlobalSystemVersion = globalSystemVersion; m_Filter = filter; }
internal void AddSharedComponentDataBoxed(MatchingArchetypeList archetypeList, EntityQueryFilter filter, int typeIndex, int hashCode, object componentData) { //TODO: optimize this (no need to move the entity to a new chunk twice) var newSharedComponentDataIndex = 0; if (componentData != null) // null means default { newSharedComponentDataIndex = ManagedComponentStore.InsertSharedComponentAssumeNonDefault(typeIndex, hashCode, componentData); } AddSharedComponentData(archetypeList, filter, newSharedComponentDataIndex, ComponentType.FromTypeIndex(typeIndex)); }
public static void CopyFromComponentDataArray <T>(MatchingArchetypeList matchingArchetypes, NativeArray <T> componentDataArray, ArchetypeChunkComponentType <T> type, EntityQuery entityQuery, ref EntityQueryFilter filter, out JobHandle jobHandle, JobHandle dependsOn) where T : struct, IComponentData { var job = new CopyComponentArrayToChunks <T> { ComponentData = componentDataArray, ComponentType = type }; jobHandle = job.Schedule(entityQuery, dependsOn); }
/// <summary> /// Total number of entities contained in a given MatchingArchetype list. /// </summary> /// <param name="matchingArchetypes">List of matching archetypes.</param> /// <param name="filter">ComponentGroupFilter to use when calculating total number of entities.</param> /// <returns>Number of entities</returns> public static int CalculateLength(MatchingArchetypeList matchingArchetypes, ref ComponentGroupFilter filter) { // Update the archetype segments var length = 0; if (!filter.RequiresMatchesFilter) { for (var m = matchingArchetypes.Count - 1; m >= 0; --m) { var match = matchingArchetypes.p[m]; length += match->Archetype->EntityCount; } } else { for (var m = matchingArchetypes.Count - 1; m >= 0; --m) { var match = matchingArchetypes.p[m]; if (match->Archetype->EntityCount <= 0) { continue; } var archeType = match->Archetype; for (var ci = 0; ci < archeType->Chunks.Count; ++ci) { var c = archeType->Chunks.p[ci]; if (!c->MatchesFilter(match, ref filter)) { continue; } Assert.IsTrue(c->Count > 0); length += c->Count; } } } return(length); }
public static NativeArray <T> CreateComponentDataArray <T>(MatchingArchetypeList matchingArchetypes, Allocator allocator, ArchetypeChunkComponentType <T> type, EntityQuery entityQuery, ref EntityQueryFilter filter, out JobHandle jobHandle, JobHandle dependsOn) where T : struct, IComponentData { var entityCount = CalculateLength(matchingArchetypes, ref filter); var job = new GatherComponentDataJob <T> { ComponentData = new NativeArray <T>(entityCount, allocator), ComponentType = type }; jobHandle = job.Schedule(entityQuery, dependsOn); return(job.ComponentData); }
/// <summary> /// Creates a NativeArray containing the entities in a given EntityQuery. /// </summary> /// <param name="matchingArchetypes">List of matching archetypes.</param> /// <param name="allocator">Allocator to use for the array.</param> /// <param name="type">An atomic safety handle required by GatherEntitiesJob so it can call GetNativeArray() on chunks.</param> /// <param name="entityQuery">EntityQuery to gather entities from.</param> /// <param name="filter">EntityQueryFilter for calculating the length of the output array.</param> /// <param name="jobHandle">Handle to the GatherEntitiesJob job used to fill the output array.</param> /// <param name="dependsOn">Handle to a job this GatherEntitiesJob must wait on.</param> /// <returns>NativeArray of the entities in a given EntityQuery.</returns> public static NativeArray <Entity> CreateEntityArray(MatchingArchetypeList matchingArchetypes, Allocator allocator, ArchetypeChunkEntityType type, EntityQuery entityQuery, ref EntityQueryFilter filter, out JobHandle jobHandle, JobHandle dependsOn) { var entityCount = CalculateLength(matchingArchetypes, ref filter); var job = new GatherEntitiesJob { EntityType = type, Entities = new NativeArray <Entity>(entityCount, allocator) }; jobHandle = job.Schedule(entityQuery, dependsOn); return(job.Entities); }
/// <summary> /// Creates a NativeArray with all the chunks in a given archetype. /// </summary> /// <param name="matchingArchetypes">List of matching archetypes.</param> /// <param name="allocator">Allocator to use for the array.</param> /// <param name="jobHandle">Handle to the GatherChunks job used to fill the output array.</param> /// <returns>NativeArray of all the chunks in the matchingArchetypes list.</returns> public static NativeArray <ArchetypeChunk> CreateArchetypeChunkArray(MatchingArchetypeList matchingArchetypes, Allocator allocator, out JobHandle jobHandle) { var archetypeCount = matchingArchetypes.Count; var archetypes = new NativeArray <EntityArchetype>(archetypeCount, Allocator.TempJob); var offsets = new NativeArray <int>(archetypeCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var chunkCount = 0; { int i = 0; var length = 0; for (var m = matchingArchetypes.Count - 1; m >= 0; --m) { var match = matchingArchetypes.p[m]; var archetype = match->Archetype; archetypes[i] = new EntityArchetype { Archetype = archetype }; offsets[i] = length; length += archetype->Chunks.Count; i++; } chunkCount = length; } var chunks = new NativeArray <ArchetypeChunk>(chunkCount, allocator, NativeArrayOptions.UninitializedMemory); var gatherChunksJob = new GatherChunks { Archetypes = archetypes, Offsets = offsets, Chunks = chunks }; var gatherChunksJobHandle = gatherChunksJob.Schedule(archetypeCount, 1); jobHandle = gatherChunksJobHandle; return(chunks); }
internal static JobHandle PreparePrefilteredChunkLists(int unfilteredChunkCount, MatchingArchetypeList archetypes, EntityQueryFilter filter, JobHandle dependsOn, ScheduleMode mode, out NativeArray <byte> prefilterDataArray, out void *deferredCountData) { // Allocate one buffer for all prefilter data and distribute it // We keep the full buffer as a "dummy array" so we can deallocate it later with [DeallocateOnJobCompletion] var sizeofChunkArray = sizeof(ArchetypeChunk) * unfilteredChunkCount; var sizeofIndexArray = sizeof(int) * unfilteredChunkCount; var prefilterDataSize = sizeofChunkArray + sizeofIndexArray + sizeof(int); var prefilterData = (byte *)UnsafeUtility.Malloc(prefilterDataSize, 64, Allocator.TempJob); prefilterDataArray = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray <byte>(prefilterData, prefilterDataSize, Allocator.TempJob); #if ENABLE_UNITY_COLLECTIONS_CHECKS NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref prefilterDataArray, AtomicSafetyHandle.Create()); #endif JobHandle prefilterHandle = default(JobHandle); if (filter.RequiresMatchesFilter) { var prefilteringJob = new GatherChunksAndOffsetsWithFilteringJob { Archetypes = archetypes, Filter = filter, PrefilterData = prefilterData, UnfilteredChunkCount = unfilteredChunkCount }; if (mode == ScheduleMode.Batched) { prefilterHandle = prefilteringJob.Schedule(dependsOn); } else { prefilteringJob.Run(); } } else { var gatherJob = new GatherChunksAndOffsetsJob { Archetypes = archetypes, PrefilterData = prefilterData, UnfilteredChunkCount = unfilteredChunkCount }; if (mode == ScheduleMode.Batched) { prefilterHandle = gatherJob.Schedule(dependsOn); } else { gatherJob.Run(); } } // ScheduleParallelForDeferArraySize expects a ptr to a structure with a void* and a count. // It only uses the count, so this is safe to fudge deferredCountData = prefilterData + sizeofChunkArray + sizeofIndexArray; deferredCountData = (byte *)deferredCountData - sizeof(void *); return(prefilterHandle); }
/// <summary> /// Total number of entities contained in a given MatchingArchetype list. /// </summary> /// <param name="matchingArchetypes">List of matching archetypes.</param> /// <param name="filter">EntityQueryFilter to use when calculating total number of entities.</param> /// <returns>Number of entities</returns> public static int CalculateLength(MatchingArchetypeList matchingArchetypes, ref EntityQueryFilter filter) { var filterCopy = filter; // Necessary to avoid a nasty compiler error cause by fixed buffer types var length = 0; if (!filter.RequiresMatchesFilter) { for (var m = matchingArchetypes.Count - 1; m >= 0; --m) { var match = matchingArchetypes.p[m]; length += match->Archetype->EntityCount; } } else { for (var m = matchingArchetypes.Count - 1; m >= 0; --m) { var match = matchingArchetypes.p[m]; if (match->Archetype->EntityCount <= 0) { continue; } int filteredCount = 0; var archetype = match->Archetype; int chunkCount = archetype->Chunks.Count; var chunkEntityCountArray = archetype->Chunks.GetChunkEntityCountArray(); if (filter.Type == FilterType.SharedComponent) { var indexInEntityQuery0 = filterCopy.Shared.IndexInEntityQuery[0]; var sharedComponentIndex0 = filterCopy.Shared.SharedComponentIndex[0]; var componentIndexInChunk0 = match->IndexInArchetype[indexInEntityQuery0] - archetype->FirstSharedComponent; var sharedComponents0 = archetype->Chunks.GetSharedComponentValueArrayForType(componentIndexInChunk0); if (filter.Shared.Count == 1) { for (var i = 0; i < chunkCount; ++i) { if (sharedComponents0[i] == sharedComponentIndex0) { filteredCount += chunkEntityCountArray[i]; } } } else { var indexInEntityQuery1 = filterCopy.Shared.IndexInEntityQuery[1]; var sharedComponentIndex1 = filterCopy.Shared.SharedComponentIndex[1]; var componentIndexInChunk1 = match->IndexInArchetype[indexInEntityQuery1] - archetype->FirstSharedComponent; var sharedComponents1 = archetype->Chunks.GetSharedComponentValueArrayForType(componentIndexInChunk1); for (var i = 0; i < chunkCount; ++i) { if (sharedComponents0[i] == sharedComponentIndex0 && sharedComponents1[i] == sharedComponentIndex1) { filteredCount += chunkEntityCountArray[i]; } } } } else { var indexInEntityQuery0 = filterCopy.Changed.IndexInEntityQuery[0]; var componentIndexInChunk0 = match->IndexInArchetype[indexInEntityQuery0]; var changeVersions0 = archetype->Chunks.GetChangeVersionArrayForType(componentIndexInChunk0); var requiredVersion = filter.RequiredChangeVersion; if (filter.Changed.Count == 1) { for (var i = 0; i < chunkCount; ++i) { if (ChangeVersionUtility.DidChange(changeVersions0[i], requiredVersion)) { filteredCount += chunkEntityCountArray[i]; } } } else { var indexInEntityQuery1 = filterCopy.Changed.IndexInEntityQuery[1]; var componentIndexInChunk1 = match->IndexInArchetype[indexInEntityQuery1]; var changeVersions1 = archetype->Chunks.GetChangeVersionArrayForType(componentIndexInChunk1); for (var i = 0; i < chunkCount; ++i) { if (ChangeVersionUtility.DidChange(changeVersions0[i], requiredVersion) || ChangeVersionUtility.DidChange(changeVersions1[i], requiredVersion)) { filteredCount += chunkEntityCountArray[i]; } } } } length += filteredCount; } } return(length); }
/// <summary> /// Creates a NativeArray with all the chunks in a given archetype. /// </summary> /// <param name="matchingArchetypes">List of matching archetypes.</param> /// <param name="allocator">Allocator to use for the array.</param> /// <param name="jobHandle">Handle to the GatherChunks job used to fill the output array.</param> /// <returns>NativeArray of all the chunks in the matchingArchetypes list.</returns> public static NativeArray <ArchetypeChunk> CreateArchetypeChunkArray(MatchingArchetypeList matchingArchetypes, Allocator allocator, out JobHandle jobHandle, ref EntityQueryFilter filter, JobHandle dependsOn = default(JobHandle)) { var archetypeCount = matchingArchetypes.Count; var offsets = new NativeArray <int>(archetypeCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var chunkCount = 0; { for (int i = 0; i < matchingArchetypes.Count; ++i) { var archetype = matchingArchetypes.p[i]->Archetype; offsets[i] = chunkCount; chunkCount += archetype->Chunks.Count; } } if (filter.Type == FilterType.None) { var chunks = new NativeArray <ArchetypeChunk>(chunkCount, allocator, NativeArrayOptions.UninitializedMemory); var gatherChunksJob = new GatherChunks { MatchingArchetypes = matchingArchetypes.p, Offsets = offsets, Chunks = chunks }; var gatherChunksJobHandle = gatherChunksJob.Schedule(archetypeCount, 1, dependsOn); jobHandle = gatherChunksJobHandle; return(chunks); } else { var filteredCounts = new NativeArray <int>(archetypeCount + 1, Allocator.TempJob); var sparseChunks = new NativeArray <ArchetypeChunk>(chunkCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var gatherChunksJob = new GatherChunksWithFiltering { MatchingArchetypes = matchingArchetypes.p, Filter = filter, Offsets = offsets, FilteredCounts = filteredCounts, SparseChunks = sparseChunks }; gatherChunksJob.Schedule(archetypeCount, 1, dependsOn).Complete(); // accumulated filtered counts: filteredCounts[i] becomes the destination offset int totalChunks = 0; for (int i = 0; i < archetypeCount; ++i) { int currentCount = filteredCounts[i]; filteredCounts[i] = totalChunks; totalChunks += currentCount; } filteredCounts[archetypeCount] = totalChunks; var joinedChunks = new NativeArray <ArchetypeChunk>(totalChunks, allocator, NativeArrayOptions.UninitializedMemory); jobHandle = new JoinChunksJob { DestinationOffsets = filteredCounts, SparseChunks = sparseChunks, Offsets = offsets, JoinedChunks = joinedChunks }.Schedule(archetypeCount, 1); return(joinedChunks); } }
public MatchingArchetypeListDebugView(MatchingArchetypeList MatchingArchetypeList) { m_MatchingArchetypeList = MatchingArchetypeList; }