void Move(Chunk *srcChunk, ref ArchetypeChunkFilter archetypeChunkFilter) { if (archetypeChunkFilter.Archetype->SystemStateCleanupComplete) { ChunkDataUtility.Deallocate(srcChunk); return; } var srcArchetype = srcChunk->Archetype; if (ChunkDataUtility.AreLayoutCompatible(srcArchetype, archetypeChunkFilter.Archetype)) { fixed(int *sharedComponentValues = archetypeChunkFilter.SharedComponentValues) { ChunkDataUtility.ChangeArchetypeInPlace(srcChunk, archetypeChunkFilter.Archetype, sharedComponentValues); } return; } var entityBatch = new EntityBatchInChunk { Chunk = srcChunk, Count = srcChunk->Count, StartIndex = 0 }; Move(entityBatch, ref archetypeChunkFilter); }
void Move(Entity entity, ref ArchetypeChunkFilter archetypeChunkFilter) { var srcEntityInChunk = GetEntityInChunk(entity); var entityBatch = new EntityBatchInChunk { Chunk = srcEntityInChunk.Chunk, Count = 1, StartIndex = srcEntityInChunk.IndexInChunk }; Move(entityBatch, ref archetypeChunkFilter); }
ArchetypeChunkFilter GetArchetypeChunkFilterWithChangedArchetype(Chunk *srcChunk, Archetype *dstArchetype) { var srcArchetype = srcChunk->Archetype; var archetypeChunkFilter = new ArchetypeChunkFilter(); archetypeChunkFilter.Archetype = dstArchetype; BuildSharedComponentIndicesWithChangedArchetype(srcArchetype, dstArchetype, srcChunk->SharedComponentValues, archetypeChunkFilter.SharedComponentValues); return(archetypeChunkFilter); }
void DestroyBatch(Entity *entities, Chunk *chunk, int indexInChunk, int batchCount) { var archetype = chunk->Archetype; if (!archetype->SystemStateCleanupNeeded) { DeallocateDataEntitiesInChunk(entities, chunk, indexInChunk, batchCount); ManagedChangesTracker.IncrementComponentOrderVersion(archetype, chunk->SharedComponentValues); IncrementComponentTypeOrderVersion(archetype); if (chunk->ManagedArrayIndex >= 0) { // We can just chop-off the end, no need to copy anything if (chunk->Count != indexInChunk + batchCount) { ManagedChangesTracker.CopyManagedObjects(chunk, chunk->Count - batchCount, chunk, indexInChunk, batchCount); } ManagedChangesTracker.ClearManagedObjects(chunk, chunk->Count - batchCount, batchCount); } chunk->Archetype->EntityCount -= batchCount; SetChunkCount(chunk, chunk->Count - batchCount); } else { var dstArchetypeChunkFilter = new ArchetypeChunkFilter(); dstArchetypeChunkFilter.Archetype = archetype->SystemStateResidueArchetype; if (RequiresBuildingResidueSharedComponentIndices(archetype, dstArchetypeChunkFilter.Archetype)) { BuildResidueSharedComponentIndices(archetype, dstArchetypeChunkFilter.Archetype, chunk->SharedComponentValues, dstArchetypeChunkFilter.SharedComponentValues); } if (batchCount == chunk->Count) { Move(chunk, ref dstArchetypeChunkFilter); } else { Move(new EntityBatchInChunk { Chunk = chunk, StartIndex = indexInChunk, Count = batchCount }, ref dstArchetypeChunkFilter); } } }
Chunk *GetChunkWithEmptySlots(ref ArchetypeChunkFilter archetypeChunkFilter) { var archetype = archetypeChunkFilter.Archetype; fixed(int *sharedComponentValues = archetypeChunkFilter.SharedComponentValues) { var chunk = archetype->GetExistingChunkWithEmptySlots(sharedComponentValues); if (chunk == null) { chunk = GetCleanChunk(archetype, sharedComponentValues); } return(chunk); } }
// ---------------------------------------------------------------------------------------------------------- // PUBLIC // ---------------------------------------------------------------------------------------------------------- public void CreateEntities(Archetype *archetype, Entity *entities, int count) { var archetypeChunkFilter = new ArchetypeChunkFilter(); archetypeChunkFilter.Archetype = archetype; while (count != 0) { var chunk = GetChunkWithEmptySlots(ref archetypeChunkFilter); var allocateCount = math.min(count, chunk->UnusedCount); ChunkDataUtility.Allocate(chunk, entities, allocateCount); entities += allocateCount; count -= allocateCount; } }
void DestroyBatch(Chunk *chunk, int indexInChunk, int batchCount) { var archetype = chunk->Archetype; if (!archetype->SystemStateCleanupNeeded) { DeallocateDataEntitiesInChunk(chunk, indexInChunk, batchCount); ManagedChangesTracker.IncrementComponentOrderVersion(archetype, chunk->SharedComponentValues); IncrementComponentTypeOrderVersion(archetype); chunk->Archetype->EntityCount -= batchCount; SetChunkCount(chunk, chunk->Count - batchCount); } else { var systemStateResidueArchetype = archetype->SystemStateResidueArchetype; if (archetype == systemStateResidueArchetype) { return; } var dstArchetypeChunkFilter = new ArchetypeChunkFilter(); dstArchetypeChunkFilter.Archetype = systemStateResidueArchetype; if (RequiresBuildingResidueSharedComponentIndices(archetype, dstArchetypeChunkFilter.Archetype)) { BuildResidueSharedComponentIndices(archetype, dstArchetypeChunkFilter.Archetype, chunk->SharedComponentValues, dstArchetypeChunkFilter.SharedComponentValues); } else { chunk->SharedComponentValues.CopyTo(dstArchetypeChunkFilter.SharedComponentValues, 0, archetype->NumSharedComponents); } if (batchCount == chunk->Count) { Move(chunk, ref dstArchetypeChunkFilter); } else { Move(new EntityBatchInChunk { Chunk = chunk, StartIndex = indexInChunk, Count = batchCount }, ref dstArchetypeChunkFilter); } } }
// ---------------------------------------------------------------------------------------------------------- // PUBLIC // ---------------------------------------------------------------------------------------------------------- public void CreateEntities(Archetype *archetype, Entity *entities, int count) { var archetypeChunkFilter = new ArchetypeChunkFilter(); archetypeChunkFilter.Archetype = archetype; while (count != 0) { var chunk = GetChunkWithEmptySlots(ref archetypeChunkFilter); int allocatedIndex; var allocatedCount = AllocateIntoChunk(chunk, count, out allocatedIndex); AllocateEntities(archetype, chunk, allocatedIndex, allocatedCount, entities); ChunkDataUtility.InitializeComponents(chunk, allocatedIndex, allocatedCount); chunk->SetAllChangeVersions(GlobalSystemVersion); entities += allocatedCount; count -= allocatedCount; } IncrementComponentTypeOrderVersion(archetype); }
void Move(Chunk *srcChunk, ref ArchetypeChunkFilter archetypeChunkFilter) { if (archetypeChunkFilter.Archetype->SystemStateCleanupComplete) { DeleteChunk(srcChunk); return; } var srcArchetype = srcChunk->Archetype; if (ChunkDataUtility.AreLayoutCompatible(srcArchetype, archetypeChunkFilter.Archetype)) { ChangeArchetypeInPlace(srcChunk, ref archetypeChunkFilter); return; } var entityBatch = new EntityBatchInChunk { Chunk = srcChunk, Count = srcChunk->Count, StartIndex = 0 }; Move(entityBatch, ref archetypeChunkFilter); }
void Move(EntityBatchInChunk entityBatchInChunk, ref ArchetypeChunkFilter archetypeChunkFilter) { var systemStateCleanupComplete = archetypeChunkFilter.Archetype->SystemStateCleanupComplete; var srcChunk = entityBatchInChunk.Chunk; var srcRemainingCount = entityBatchInChunk.Count; var startIndex = entityBatchInChunk.StartIndex; if ((srcRemainingCount == srcChunk->Count) && systemStateCleanupComplete) { ChunkDataUtility.Deallocate(srcChunk); return; } while (srcRemainingCount > 0) { var dstChunk = GetChunkWithEmptySlots(ref archetypeChunkFilter); var dstCount = Move(new EntityBatchInChunk { Chunk = srcChunk, Count = srcRemainingCount, StartIndex = startIndex }, dstChunk); srcRemainingCount -= dstCount; } }
public void RemoveComponents(ArchetypeChunk *chunks, int chunkCount, ComponentTypes types) { Archetype * prevArchetype = null; ArchetypeChunkFilter archetypeChunkFilter = default(ArchetypeChunkFilter); for (int i = 0; i < chunkCount; i++) { var chunk = chunks[i].m_Chunk; var archetype = chunk->Archetype; if (archetype != prevArchetype) { // returns default if no types removed archetypeChunkFilter = GetArchetypeChunkFilterWithRemovedComponents(chunk, types); prevArchetype = archetype; } if (archetypeChunkFilter.Archetype != null) { Move(chunk, ref archetypeChunkFilter); } } }
public void Move(Entity entity, Archetype *archetype, SharedComponentValues sharedComponentValues) { var archetypeChunkFilter = new ArchetypeChunkFilter(archetype, sharedComponentValues); Move(entity, ref archetypeChunkFilter); }
int InstantiateEntitiesOne(Entity srcEntity, Entity *outputEntities, int instanceCount, InstantiateRemapChunk *remapChunks, int remapChunksCount) { var src = GetEntityInChunk(srcEntity); var srcArchetype = src.Chunk->Archetype; var dstArchetype = srcArchetype->InstantiableArchetype; var archetypeChunkFilter = new ArchetypeChunkFilter(); archetypeChunkFilter.Archetype = dstArchetype; if (RequiresBuildingResidueSharedComponentIndices(srcArchetype, dstArchetype)) { BuildResidueSharedComponentIndices(srcArchetype, dstArchetype, src.Chunk->SharedComponentValues, archetypeChunkFilter.SharedComponentValues); } else { // Always copy shared component indices since GetChunkWithEmptySlots might reallocate the storage of SharedComponentValues src.Chunk->SharedComponentValues.CopyTo(archetypeChunkFilter.SharedComponentValues, 0, dstArchetype->NumSharedComponents); } Chunk *chunk = null; int instanceBeginIndex = 0; while (instanceBeginIndex != instanceCount) { chunk = GetChunkWithEmptySlots(ref archetypeChunkFilter); int indexInChunk; var allocatedCount = AllocateIntoChunk(chunk, instanceCount - instanceBeginIndex, out indexInChunk); ChunkDataUtility.ReplicateComponents(src.Chunk, src.IndexInChunk, chunk, indexInChunk, allocatedCount); AllocateEntities(dstArchetype, chunk, indexInChunk, allocatedCount, outputEntities + instanceBeginIndex); if (srcArchetype->NumManagedArrays > 0) { ManagedChangesTracker.ReplicateManagedObjects(src.Chunk, src.IndexInChunk, chunk, indexInChunk, allocatedCount, srcEntity, outputEntities + instanceBeginIndex); } chunk->SetAllChangeVersions(GlobalSystemVersion); #if UNITY_EDITOR for (var i = 0; i < allocatedCount; ++i) { CopyName(outputEntities[i + instanceBeginIndex], srcEntity); } #endif if (remapChunks != null) { remapChunks[remapChunksCount].Chunk = chunk; remapChunks[remapChunksCount].IndexInChunk = indexInChunk; remapChunks[remapChunksCount].AllocatedCount = allocatedCount; remapChunks[remapChunksCount].InstanceBeginIndex = instanceBeginIndex; remapChunksCount++; } instanceBeginIndex += allocatedCount; } if (chunk != null) { ManagedChangesTracker.IncrementComponentOrderVersion(dstArchetype, chunk->SharedComponentValues); IncrementComponentTypeOrderVersion(dstArchetype); } return(remapChunksCount); }
/// <summary> /// Fix-up the chunk to refer to a different (but layout compatible) archetype. /// - Should only be called by Move(chunk) /// </summary> void ChangeArchetypeInPlace(Chunk *srcChunk, ref ArchetypeChunkFilter dstArchetypeChunkFilter) { var dstArchetype = dstArchetypeChunkFilter.Archetype; fixed(int *sharedComponentValues = dstArchetypeChunkFilter.SharedComponentValues) { var srcArchetype = srcChunk->Archetype; ChunkDataUtility.AssertAreLayoutCompatible(srcArchetype, dstArchetype); var fixupSharedComponentReferences = (srcArchetype->NumSharedComponents > 0) || (dstArchetype->NumSharedComponents > 0); if (fixupSharedComponentReferences) { int srcFirstShared = srcArchetype->FirstSharedComponent; int dstFirstShared = dstArchetype->FirstSharedComponent; int srcCount = srcArchetype->NumSharedComponents; int dstCount = dstArchetype->NumSharedComponents; int o = 0; int n = 0; for (; n < dstCount && o < srcCount;) { int srcType = srcArchetype->Types[o + srcFirstShared].TypeIndex; int dstType = dstArchetype->Types[n + dstFirstShared].TypeIndex; if (srcType == dstType) { var srcSharedComponentDataIndex = srcChunk->SharedComponentValues[o]; var dstSharedComponentDataIndex = sharedComponentValues[n]; if (srcSharedComponentDataIndex != dstSharedComponentDataIndex) { ManagedChangesTracker.RemoveReference(srcSharedComponentDataIndex); ManagedChangesTracker.AddReference(dstSharedComponentDataIndex); } n++; o++; } else if (dstType > srcType) // removed from dstArchetype { var sharedComponentDataIndex = srcChunk->SharedComponentValues[o]; ManagedChangesTracker.RemoveReference(sharedComponentDataIndex); o++; } else // added to dstArchetype { var sharedComponentDataIndex = sharedComponentValues[n]; ManagedChangesTracker.AddReference(sharedComponentDataIndex); n++; } } for (; n < dstCount; n++) // added to dstArchetype { var sharedComponentDataIndex = sharedComponentValues[n]; ManagedChangesTracker.AddReference(sharedComponentDataIndex); } for (; o < srcCount; o++) // removed from dstArchetype { var sharedComponentDataIndex = srcChunk->SharedComponentValues[o]; ManagedChangesTracker.RemoveReference(sharedComponentDataIndex); } } var fixupManagedComponents = (srcArchetype->NumManagedArrays > 0) || (dstArchetype->NumManagedArrays > 0); if (fixupManagedComponents) { if (dstArchetype->NumManagedArrays == 0) // removed all { ManagedChangesTracker.DeallocateManagedArrayStorage(srcChunk->ManagedArrayIndex); m_ManagedArrayFreeIndex.Add(srcChunk->ManagedArrayIndex); srcChunk->ManagedArrayIndex = -1; } else { // We have changed the managed array order + size so allocate a new managed array // copy the unchanged values into it int dstManagedArrayIndex; if (!m_ManagedArrayFreeIndex.IsEmpty) { dstManagedArrayIndex = m_ManagedArrayFreeIndex.Pop <int>(); } else { dstManagedArrayIndex = m_ManagedArrayIndex; m_ManagedArrayIndex++; } ManagedChangesTracker.AllocateManagedArrayStorage(dstManagedArrayIndex, dstArchetype->NumManagedArrays * srcChunk->Capacity); int srcManagedArrayIndex = srcChunk->ManagedArrayIndex; srcChunk->ManagedArrayIndex = dstManagedArrayIndex; if (srcManagedArrayIndex != -1) { ManagedChangesTracker.MoveChunksManagedObjects(srcArchetype, srcManagedArrayIndex, dstArchetype, dstManagedArrayIndex, srcChunk->Capacity, srcChunk->Count); ManagedChangesTracker.DeallocateManagedArrayStorage(srcManagedArrayIndex); m_ManagedArrayFreeIndex.Add(srcManagedArrayIndex); } } } var count = srcChunk->Count; bool hasEmptySlots = count < srcChunk->Capacity; if (hasEmptySlots) { srcArchetype->EmptySlotTrackingRemoveChunk(srcChunk); } int chunkIndexInSrcArchetype = srcChunk->ListIndex; var dstTypes = dstArchetype->Types; var srcTypes = srcArchetype->Types; //Change version is overriden below dstArchetype->AddToChunkList(srcChunk, sharedComponentValues, 0); int chunkIndexInDstArchetype = srcChunk->ListIndex; //Copy change versions from src to dst archetype for (int isrcType = srcArchetype->TypesCount - 1, idstType = dstArchetype->TypesCount - 1; idstType >= 0; --idstType) { var dstType = dstTypes[idstType]; while (srcTypes[isrcType] > dstType) { --isrcType; } var version = srcTypes[isrcType] == dstType ? srcArchetype->Chunks.GetChangeVersion(isrcType, chunkIndexInSrcArchetype) : GlobalSystemVersion; dstArchetype->Chunks.SetChangeVersion(idstType, chunkIndexInDstArchetype, version); } srcChunk->ListIndex = chunkIndexInSrcArchetype; srcArchetype->RemoveFromChunkList(srcChunk); srcChunk->ListIndex = chunkIndexInDstArchetype; if (hasEmptySlots) { dstArchetype->EmptySlotTrackingAddChunk(srcChunk); } SetArchetype(srcChunk, dstArchetype); srcArchetype->EntityCount -= count; dstArchetype->EntityCount += count; if (srcArchetype->MetaChunkArchetype != dstArchetype->MetaChunkArchetype) { if (srcArchetype->MetaChunkArchetype == null) { CreateMetaEntityForChunk(srcChunk); } else if (dstArchetype->MetaChunkArchetype == null) { DestroyMetaChunkEntity(srcChunk->metaChunkEntity); srcChunk->metaChunkEntity = Entity.Null; } else { var metaChunk = GetChunk(srcChunk->metaChunkEntity); var archetypeChunkFilter = new ArchetypeChunkFilter(dstArchetype->MetaChunkArchetype, metaChunk->SharedComponentValues); Move(srcChunk->metaChunkEntity, ref archetypeChunkFilter); } } } }