static Chunk *DeallocateDataEntitiesInChunk(EntityDataManager *entityDataManager, Entity *entities, int count, out int indexInChunk, out int batchCount) { /// This is optimized for the case where the array of entities are allocated contigously in the chunk /// Thus the compacting of other elements can be batched // Calculate baseEntityIndex & chunk var baseEntityIndex = entities[0].Index; var chunk = entityDataManager->m_Entities[baseEntityIndex].Chunk; indexInChunk = entityDataManager->m_Entities[baseEntityIndex].IndexInChunk; batchCount = 0; var freeIndex = entityDataManager->m_EntitiesFreeIndex; var entityDatas = entityDataManager->m_Entities; while (batchCount < count) { var entityIndex = entities[batchCount].Index; var data = entityDatas + entityIndex; if (data->Chunk != chunk || data->IndexInChunk != indexInChunk + batchCount) { break; } data->Chunk = null; data->Version++; data->IndexInChunk = freeIndex; freeIndex = entityIndex; batchCount++; } entityDataManager->m_EntitiesFreeIndex = freeIndex; // We can just chop-off the end, no need to copy anything if (chunk->Count == indexInChunk + batchCount) { return(chunk); } // updates EntitityData->indexInChunk to point to where the components will be moved to //Assert.IsTrue(chunk->archetype->sizeOfs[0] == sizeof(Entity) && chunk->archetype->offsets[0] == 0); var movedEntities = (Entity *)(chunk->Buffer) + (chunk->Count - batchCount); for (var i = 0; i != batchCount; i++) { entityDataManager->m_Entities[movedEntities[i].Index].IndexInChunk = indexInChunk + i; } // Move component data from the end to where we deleted components ChunkDataUtility.Copy(chunk, chunk->Count - batchCount, chunk, indexInChunk, batchCount); return(chunk); }
public void SetArchetype(ArchetypeManager typeMan, Entity entity, Archetype *archetype, int *sharedComponentDataIndices) { var chunk = typeMan.GetChunkWithEmptySlots(archetype, sharedComponentDataIndices); var chunkIndex = typeMan.AllocateIntoChunk(chunk); var oldArchetype = m_Entities[entity.Index].Archetype; var oldChunk = m_Entities[entity.Index].Chunk; var oldChunkIndex = m_Entities[entity.Index].IndexInChunk; ChunkDataUtility.Convert(oldChunk, oldChunkIndex, chunk, chunkIndex); if (chunk->ManagedArrayIndex >= 0 && oldChunk->ManagedArrayIndex >= 0) { ChunkDataUtility.CopyManagedObjects(typeMan, oldChunk, oldChunkIndex, chunk, chunkIndex, 1); } m_Entities[entity.Index].Archetype = archetype; m_Entities[entity.Index].Chunk = chunk; m_Entities[entity.Index].IndexInChunk = chunkIndex; var lastIndex = oldChunk->Count - 1; // No need to replace with ourselves if (lastIndex != oldChunkIndex) { var lastEntity = (Entity *)ChunkDataUtility.GetComponentData(oldChunk, lastIndex, 0); m_Entities[lastEntity->Index].IndexInChunk = oldChunkIndex; ChunkDataUtility.Copy(oldChunk, lastIndex, oldChunk, oldChunkIndex, 1); if (oldChunk->ManagedArrayIndex >= 0) { ChunkDataUtility.CopyManagedObjects(typeMan, oldChunk, lastIndex, oldChunk, oldChunkIndex, 1); } } if (oldChunk->ManagedArrayIndex >= 0) { ChunkDataUtility.ClearManagedObjects(typeMan, oldChunk, lastIndex, 1); } --oldArchetype->EntityCount; typeMan.SetChunkCount(oldChunk, lastIndex); }
internal void DeallocateDataEntitiesInChunk(Chunk *chunk, int indexInChunk, int batchCount) { DeallocateBuffers(chunk, indexInChunk, batchCount); DeallocateManagedComponents(chunk, indexInChunk, batchCount); var freeIndex = m_NextFreeEntityIndex; var entities = (Entity *)chunk->Buffer + indexInChunk; for (var i = batchCount - 1; i >= 0; --i) { var entityIndex = entities[i].Index; m_EntityInChunkByEntity[entityIndex].Chunk = null; m_VersionByEntity[entityIndex]++; m_EntityInChunkByEntity[entityIndex].IndexInChunk = freeIndex; #if UNITY_EDITOR m_NameByEntity[entityIndex] = new NumberedWords(); #endif freeIndex = entityIndex; } m_NextFreeEntityIndex = freeIndex; m_EntityCreateDestroyVersion++; // Compute the number of things that need to moved and patched. int patchCount = Math.Min(batchCount, chunk->Count - indexInChunk - batchCount); if (0 == patchCount) { return; } // updates indexInChunk to point to where the components will be moved to //Assert.IsTrue(chunk->archetype->sizeOfs[0] == sizeof(Entity) && chunk->archetype->offsets[0] == 0); var movedEntities = (Entity *)chunk->Buffer + (chunk->Count - patchCount); for (var i = 0; i != patchCount; i++) { m_EntityInChunkByEntity[movedEntities[i].Index].IndexInChunk = indexInChunk + i; } // Move component data from the end to where we deleted components ChunkDataUtility.Copy(chunk, chunk->Count - patchCount, chunk, indexInChunk, patchCount); }
public void MoveEntityToChunk(ArchetypeManager typeMan, Entity entity, Chunk *newChunk, int newChunkIndex) { var oldChunk = m_Entities[entity.Index].Chunk; Assert.IsTrue(oldChunk->Archetype == newChunk->Archetype); var oldChunkIndex = m_Entities[entity.Index].IndexInChunk; ChunkDataUtility.Copy(oldChunk, oldChunkIndex, newChunk, newChunkIndex, 1); if (oldChunk->ManagedArrayIndex >= 0) { ChunkDataUtility.CopyManagedObjects(typeMan, oldChunk, oldChunkIndex, newChunk, newChunkIndex, 1); } m_Entities[entity.Index].Chunk = newChunk; m_Entities[entity.Index].IndexInChunk = newChunkIndex; var lastIndex = oldChunk->Count - 1; // No need to replace with ourselves if (lastIndex != oldChunkIndex) { var lastEntity = (Entity *)ChunkDataUtility.GetComponentData(oldChunk, lastIndex, 0); m_Entities[lastEntity->Index].IndexInChunk = oldChunkIndex; ChunkDataUtility.Copy(oldChunk, lastIndex, oldChunk, oldChunkIndex, 1); if (oldChunk->ManagedArrayIndex >= 0) { ChunkDataUtility.CopyManagedObjects(typeMan, oldChunk, lastIndex, oldChunk, oldChunkIndex, 1); } } if (oldChunk->ManagedArrayIndex >= 0) { ChunkDataUtility.ClearManagedObjects(typeMan, oldChunk, lastIndex, 1); } newChunk->Archetype->EntityCount--; typeMan.SetChunkCount(oldChunk, oldChunk->Count - 1); }
private static void DeallocateDataEntitiesInChunk(EntityDataManager *entityDataManager, Entity *entities, Chunk *chunk, int indexInChunk, int batchCount) { DeallocateBuffers(entityDataManager, entities, chunk, batchCount); var freeIndex = entityDataManager->m_EntitiesFreeIndex; var entityDatas = entityDataManager->m_Entities; for (var i = batchCount - 1; i >= 0; --i) { var entityIndex = entities[i].Index; var data = entityDatas + entityIndex; data->Chunk = null; data->Version++; data->IndexInChunk = freeIndex; freeIndex = entityIndex; } entityDataManager->m_EntitiesFreeIndex = freeIndex; // Compute the number of things that need to moved and patched. int patchCount = Math.Min(batchCount, chunk->Count - indexInChunk - batchCount); if (0 == patchCount) { return; } // updates EntitityData->indexInChunk to point to where the components will be moved to //Assert.IsTrue(chunk->archetype->sizeOfs[0] == sizeof(Entity) && chunk->archetype->offsets[0] == 0); var movedEntities = (Entity *)chunk->Buffer + (chunk->Count - patchCount); for (var i = 0; i != patchCount; i++) { entityDataManager->m_Entities[movedEntities[i].Index].IndexInChunk = indexInChunk + i; } // Move component data from the end to where we deleted components ChunkDataUtility.Copy(chunk, chunk->Count - patchCount, chunk, indexInChunk, patchCount); }
// ---------------------------------------------------------------------------------------------------------- // Core, self-contained functions to change chunks. No other functions should actually move data from // one Chunk to another, or otherwise change the structure of a Chunk after creation. // ---------------------------------------------------------------------------------------------------------- /// <summary> /// Move subset of chunk data into another chunk. /// - Chunks can be of same archetype (but differ by shared component values) /// - Returns number moved. Caller handles if less than indicated in srcBatch. /// </summary> /// <returns></returns> int Move(EntityBatchInChunk srcBatch, Chunk *dstChunk) { var srcChunk = srcBatch.Chunk; var srcChunkIndex = srcBatch.StartIndex; var srcCount = srcBatch.Count; var srcArchetype = srcChunk->Archetype; var dstArchetype = dstChunk->Archetype; // Note (srcArchetype == dstArchetype) is valid // Archetypes can the the same, but chunks still differ because filter is different (e.g. shared component) int dstChunkIndex; var dstCount = AllocateIntoChunk(dstChunk, srcCount, out dstChunkIndex); // If can only move partial batch, move from the end so that remainder of batch isn't affected. srcChunkIndex = srcChunkIndex + srcCount - dstCount; ChunkDataUtility.Convert(srcChunk, srcChunkIndex, dstChunk, dstChunkIndex, dstCount); if (dstChunk->ManagedArrayIndex >= 0 && srcChunk->ManagedArrayIndex >= 0) { ManagedChangesTracker.CopyManagedObjects(srcChunk, srcChunkIndex, dstChunk, dstChunkIndex, dstCount); } var dstEntities = (Entity *)ChunkDataUtility.GetComponentDataRO(dstChunk, dstChunkIndex, 0); for (int i = 0; i < dstCount; i++) { var entity = dstEntities[i]; SetArchetype(entity, dstArchetype); SetEntityInChunk(entity, new EntityInChunk { Chunk = dstChunk, IndexInChunk = dstChunkIndex + i }); } // Fill in moved component data from the end. var srcTailIndex = srcChunkIndex + dstCount; var srcTailCount = srcChunk->Count - srcTailIndex; var fillCount = math.min(dstCount, srcTailCount); if (fillCount > 0) { var fillStartIndex = srcChunk->Count - fillCount; ChunkDataUtility.Copy(srcChunk, fillStartIndex, srcChunk, srcChunkIndex, fillCount); var fillEntities = (Entity *)ChunkDataUtility.GetComponentDataRO(srcChunk, srcChunkIndex, 0); for (int i = 0; i < fillCount; i++) { var entity = fillEntities[i]; SetEntityInChunk(entity, new EntityInChunk { Chunk = srcChunk, IndexInChunk = srcChunkIndex + i }); } if (srcChunk->ManagedArrayIndex >= 0) { ManagedChangesTracker.CopyManagedObjects(srcChunk, fillStartIndex, srcChunk, srcChunkIndex, fillCount); } } if (srcChunk->ManagedArrayIndex >= 0) { ManagedChangesTracker.ClearManagedObjects(srcChunk, srcChunk->Count - dstCount, dstCount); } srcArchetype->EntityCount -= dstCount; dstChunk->SetAllChangeVersions(GlobalSystemVersion); srcChunk->SetAllChangeVersions(GlobalSystemVersion); ManagedChangesTracker.IncrementComponentOrderVersion(srcArchetype, srcChunk->SharedComponentValues); IncrementComponentTypeOrderVersion(srcArchetype); ManagedChangesTracker.IncrementComponentOrderVersion(dstArchetype, dstChunk->SharedComponentValues); IncrementComponentTypeOrderVersion(dstArchetype); SetChunkCount(srcChunk, srcChunk->Count - dstCount); // Cannot DestroyEntities unless SystemStateCleanupComplete on the entity chunk. if (dstChunk->Archetype->SystemStateCleanupComplete) { DestroyEntities(dstEntities, dstCount); } return(dstCount); }