public NativeArray <T> GetFixedArray <T>(Entity entity) where T : struct { var typeIndex = TypeManager.GetTypeIndex <T>(); #if ENABLE_UNITY_COLLECTIONS_CHECKS m_Entities->AssertEntityHasComponent(entity, typeIndex); if (TypeManager.GetComponentType <T>().Category != TypeManager.TypeCategory.OtherValueType) { throw new ArgumentException($"GetComponentFixedArray<{typeof(T)}> may not be IComponentData or ISharedComponentData"); } #endif ComponentJobSafetyManager.CompleteWriteDependency(typeIndex); byte *ptr; int length; m_Entities->GetComponentDataWithTypeAndFixedArrayLength(entity, typeIndex, out ptr, out length); var array = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray <T>(ptr, length, Allocator.Invalid); #if ENABLE_UNITY_COLLECTIONS_CHECKS NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref array, ComponentJobSafetyManager.GetSafetyHandle(typeIndex, false)); #endif return(array); }
public ComponentType(Type type, AccessMode accessModeType = AccessMode.ReadWrite) { TypeIndex = TypeManager.GetTypeIndex(type); var ct = TypeManager.GetComponentType(TypeIndex); BufferCapacity = ct.BufferCapacity; AccessModeType = accessModeType; }
private static bool IsDefaultObject <T>(ref T component, out int hashCode) where T : struct, ISharedComponentData { int typeIndex = TypeManager.GetTypeIndex <T>(); var layout = TypeManager.GetComponentType(typeIndex).FastEqualityLayout; var defaultValue = default(T); hashCode = FastEquality.GetHashCode(ref component, layout); return(FastEquality.Equals(ref defaultValue, ref component, layout)); }
internal FixedArrayFromEntity(int typeIndex, EntityDataManager *entityData, AtomicSafetyHandle safety) { m_Safety = safety; m_TypeIndex = typeIndex; m_Entities = entityData; if (TypeManager.GetComponentType(m_TypeIndex).Category != TypeManager.TypeCategory.OtherValueType) { throw new ArgumentException($"GetComponentFixedArray<{typeof(T)}> may not be IComponentData or ISharedComponentData"); } }
public static ComponentType FromTypeIndex(int typeIndex) { TypeManager.ComponentType ct = TypeManager.GetComponentType(typeIndex); ComponentType type; type.TypeIndex = typeIndex; type.AccessModeType = AccessMode.ReadWrite; type.BufferCapacity = ct.BufferCapacity; return(type); }
private unsafe int FindSharedComponentIndex <T>(int typeIndex, T newData) where T : struct { var defaultVal = default(T); var typeInfo = TypeManager.GetComponentType(typeIndex).FastEqualityTypeInfo; if (FastEquality.Equals(ref defaultVal, ref newData, typeInfo)) { return(0); } return(FindNonDefaultSharedComponentIndex(typeIndex, FastEquality.GetHashCode(ref newData, typeInfo), UnsafeUtility.AddressOf(ref newData), typeInfo)); }
unsafe int FindSharedComponentIndex <T>(int typeIndex, T newData) where T : struct { var defaultVal = default(T); var fastLayout = TypeManager.GetComponentType(typeIndex).FastEqualityLayout; if (FastEquality.Equals(ref defaultVal, ref newData, fastLayout)) { return(0); } else { return(FindNonDefaultSharedComponentIndex(typeIndex, FastEquality.GetHashCode(ref newData, fastLayout), UnsafeUtility.AddressOf(ref newData), fastLayout)); } }
internal BufferDataFromEntity(int typeIndex, EntityDataManager *entityData, bool isReadOnly, AtomicSafetyHandle safety) { m_Safety = safety; m_TypeIndex = typeIndex; m_Entities = entityData; m_IsReadOnly = isReadOnly; m_TypeLookupCache = 0; m_GlobalSystemVersion = entityData->GlobalSystemVersion; if (TypeManager.GetComponentType(m_TypeIndex).Category != TypeManager.TypeCategory.BufferData) { throw new ArgumentException( $"GetComponentBufferArray<{typeof(T)}> must be IBufferElementData"); } }
public void RemoveReference(int index) { if (index == 0) { return; } var newCount = --m_SharedComponentRefCount[index]; Assert.IsTrue(newCount >= 0); if (newCount != 0) { return; } var typeIndex = m_SharedComponentType[index]; var typeInfo = TypeManager.GetComponentType(typeIndex).FastEqualityTypeInfo; var hashCode = GetHashCodeFast(m_SharedComponentData[index], typeInfo); m_SharedComponentData[index] = null; m_SharedComponentType[index] = -1; m_SharedComponentVersion[index] = m_FreeListIndex; m_FreeListIndex = index; int itemIndex; NativeMultiHashMapIterator <int> iter; if (!m_HashLookup.TryGetFirstValue(hashCode, out itemIndex, out iter)) { #if ENABLE_UNITY_COLLECTIONS_CHECKS throw new System.ArgumentException("RemoveReference didn't find element in in hashtable"); #endif } do { if (itemIndex == index) { m_HashLookup.Remove(iter); break; } }while (m_HashLookup.TryGetNextValue(out itemIndex, ref iter)) ; }
internal BufferHeader *AddEntityBufferCommand <T>(EntityCommandBufferChain *chain, ECBCommand op, Entity e) where T : struct, IBufferElementData { var typeIndex = TypeManager.GetTypeIndex <T>(); var type = TypeManager.GetComponentType <T>(); var sizeNeeded = Align(sizeof(EntityBufferCommand) + type.SizeInChunk, 8); var data = (EntityBufferCommand *)Reserve(chain, sizeNeeded); data->Header.Header.CommandType = (int)op; data->Header.Header.TotalSize = sizeNeeded; data->Header.Entity = e; data->ComponentTypeIndex = typeIndex; data->ComponentSize = type.SizeInChunk; BufferHeader.Initialize(&data->TempBuffer, type.BufferCapacity); return(&data->TempBuffer); }
public void RemoveReference(int index) { if (index == 0) { return; } var newCount = --m_SharedComponentRefCount[index]; if (newCount != 0) { return; } var typeIndex = m_SharedComponentType[index]; var fastLayout = TypeManager.GetComponentType(typeIndex).FastEqualityLayout; var hashCode = GetHashCodeFast(m_SharedComponentData[index], fastLayout); m_SharedComponentData[index] = null; m_SharedComponentType[index] = -1; int itemIndex; NativeMultiHashMapIterator <int> iter; if (!m_HashLookup.TryGetFirstValue(hashCode, out itemIndex, out iter)) { return; } do { if (itemIndex != index) { continue; } m_HashLookup.Remove(iter); break; }while (m_HashLookup.TryGetNextValue(out itemIndex, ref iter)); }
public int InsertSharedComponent <T>(T newData) where T : struct { int typeIndex = TypeManager.GetTypeIndex <T>(); int index = FindSharedComponentIndex(TypeManager.GetTypeIndex <T>(), newData); if (index == 0) { return(0); } else if (index != -1) { m_SharedComponentRefCount[index]++; return(index); } else { var fastLayout = TypeManager.GetComponentType(typeIndex).FastEqualityLayout; var hashcode = FastEquality.GetHashCode(ref newData, fastLayout); return(Add(typeIndex, hashcode, newData)); } }
public int InsertSharedComponent <T>(T newData) where T : struct { var typeIndex = TypeManager.GetTypeIndex <T>(); var index = FindSharedComponentIndex(TypeManager.GetTypeIndex <T>(), newData); if (index == 0) { return(0); } if (index != -1) { m_SharedComponentRefCount[index]++; return(index); } var typeInfo = TypeManager.GetComponentType(typeIndex).FastEqualityTypeInfo; var hashcode = FastEquality.GetHashCode(ref newData, typeInfo); return(Add(typeIndex, hashcode, newData)); }
unsafe public void MoveSharedComponents(SharedComponentDataManager srcSharedComponents, int *sharedComponentIndices, int sharedComponentIndicesCount) { for (int i = 0; i != sharedComponentIndicesCount; i++) { int srcIndex = sharedComponentIndices[i]; if (srcIndex == 0) { continue; } var srcData = srcSharedComponents.m_SharedComponentData[srcIndex]; int typeIndex = srcSharedComponents.m_SharedComponentType[srcIndex]; var fastLayout = TypeManager.GetComponentType(typeIndex).FastEqualityLayout; var hashCode = GetHashCodeFast(srcData, fastLayout); int dstIndex = InsertSharedComponentAssumeNonDefault(typeIndex, hashCode, srcData, fastLayout); srcSharedComponents.RemoveReference(srcIndex); sharedComponentIndices[i] = dstIndex; } }
public unsafe NativeArray <int> MoveAllSharedComponents(SharedComponentDataManager srcSharedComponents, Allocator allocator) { var remap = new NativeArray <int>(srcSharedComponents.GetSharedComponentCount(), allocator); remap[0] = 0; for (int srcIndex = 1; srcIndex < remap.Length; ++srcIndex) { var srcData = srcSharedComponents.m_SharedComponentData[srcIndex]; if (srcData == null) { continue; } var typeIndex = srcSharedComponents.m_SharedComponentType[srcIndex]; var typeInfo = TypeManager.GetComponentType(typeIndex).FastEqualityTypeInfo; var hashCode = GetHashCodeFast(srcData, typeInfo); var dstIndex = InsertSharedComponentAssumeNonDefault(typeIndex, hashCode, srcData, typeInfo); m_SharedComponentRefCount[dstIndex] += srcSharedComponents.m_SharedComponentRefCount[srcIndex] - 1; remap[srcIndex] = dstIndex; } srcSharedComponents.m_HashLookup.Clear(); srcSharedComponents.m_SharedComponentVersion.ResizeUninitialized(1); srcSharedComponents.m_SharedComponentRefCount.ResizeUninitialized(1); srcSharedComponents.m_SharedComponentType.ResizeUninitialized(1); srcSharedComponents.m_SharedComponentData.Clear(); srcSharedComponents.m_SharedComponentData.Add(null); srcSharedComponents.m_FreeListIndex = -1; return(remap); }
internal void SetSharedComponentDataBoxed(Entity entity, int typeIndex, int hashCode, object componentData) { BeforeStructuralChange(); m_Entities->AssertEntityHasComponent(entity, typeIndex); int newSharedComponentDataIndex = 0; if (componentData != null) // null means default { newSharedComponentDataIndex = m_SharedComponentManager.InsertSharedComponentAssumeNonDefault(typeIndex, hashCode, componentData, TypeManager.GetComponentType(typeIndex).FastEqualityLayout); } m_Entities->SetSharedComponentDataIndex(m_ArchetypeManager, m_SharedComponentManager, entity, typeIndex, newSharedComponentDataIndex); m_SharedComponentManager.RemoveReference(newSharedComponentDataIndex); }
public Archetype *GetOrCreateArchetype(ComponentTypeInArchetype *types, int count, EntityGroupManager groupManager) { var type = GetExistingArchetype(types, count); if (type != null) { return(type); } AssertArchetypeComponents(types, count); // This is a new archetype, allocate it and add it to the hash map type = (Archetype *)m_ArchetypeChunkAllocator.Allocate(sizeof(Archetype), 8); type->TypesCount = count; type->Types = (ComponentTypeInArchetype *)m_ArchetypeChunkAllocator.Construct( sizeof(ComponentTypeInArchetype) * count, 4, types); type->EntityCount = 0; type->ChunkCount = 0; type->NumSharedComponents = 0; type->SharedComponentOffset = null; for (var i = 0; i < count; ++i) { if (TypeManager.GetComponentType(types[i].TypeIndex).Category == TypeManager.TypeCategory.ISharedComponentData) { ++type->NumSharedComponents; } } var chunkDataSize = Chunk.GetChunkBufferSize(type->TypesCount, type->NumSharedComponents); // FIXME: proper alignment type->Offsets = (int *)m_ArchetypeChunkAllocator.Allocate(sizeof(int) * count, 4); type->SizeOfs = (int *)m_ArchetypeChunkAllocator.Allocate(sizeof(int) * count, 4); type->TypeMemoryOrder = (int *)m_ArchetypeChunkAllocator.Allocate(sizeof(int) * count, 4); var bytesPerInstance = 0; for (var i = 0; i < count; ++i) { var cType = TypeManager.GetComponentType(types[i].TypeIndex); var sizeOf = cType.SizeInChunk * types[i].FixedArrayLengthMultiplier; type->SizeOfs[i] = sizeOf; bytesPerInstance += sizeOf; } type->ChunkCapacity = chunkDataSize / bytesPerInstance; #if ENABLE_UNITY_COLLECTIONS_CHECKS if (bytesPerInstance > chunkDataSize) { throw new ArgumentException( $"Entity archetype component data is too large. The maximum component data is {chunkDataSize} but the component data is {bytesPerInstance}"); } Assert.IsTrue(Chunk.kMaximumEntitiesPerChunk >= type->ChunkCapacity); #endif // For serialization a stable ordering of the components in the // chunk is desired. The type index is not stable, since it depends // on the order in which types are added to the TypeManager. // A permutation of the types ordered by a TypeManager-generated // memory ordering is used instead. var memoryOrderings = new NativeArray <UInt64>(count, Allocator.Temp); for (int i = 0; i < count; ++i) { memoryOrderings[i] = TypeManager.GetComponentType(types[i].TypeIndex).MemoryOrdering; } for (int i = 0; i < count; ++i) { int index = i; while (index > 1 && memoryOrderings[i] < memoryOrderings[type->TypeMemoryOrder[index - 1]]) { type->TypeMemoryOrder[index] = type->TypeMemoryOrder[index - 1]; --index; } type->TypeMemoryOrder[index] = i; } memoryOrderings.Dispose(); var usedBytes = 0; for (var i = 0; i < count; ++i) { var index = type->TypeMemoryOrder[i]; var sizeOf = type->SizeOfs[index]; type->Offsets[index] = usedBytes; usedBytes += sizeOf * type->ChunkCapacity; } type->NumManagedArrays = 0; type->ManagedArrayOffset = null; for (var i = 0; i < count; ++i) { if (TypeManager.GetComponentType(types[i].TypeIndex).Category == TypeManager.TypeCategory.Class) { ++type->NumManagedArrays; } } if (type->NumManagedArrays > 0) { type->ManagedArrayOffset = (int *)m_ArchetypeChunkAllocator.Allocate(sizeof(int) * count, 4); var mi = 0; for (var i = 0; i < count; ++i) { var cType = TypeManager.GetComponentType(types[i].TypeIndex); if (cType.Category == TypeManager.TypeCategory.Class) { type->ManagedArrayOffset[i] = mi++; } else { type->ManagedArrayOffset[i] = -1; } } } if (type->NumSharedComponents > 0) { type->SharedComponentOffset = (int *)m_ArchetypeChunkAllocator.Allocate(sizeof(int) * count, 4); var mi = 0; for (var i = 0; i < count; ++i) { var cType = TypeManager.GetComponentType(types[i].TypeIndex); if (cType.Category == TypeManager.TypeCategory.ISharedComponentData) { type->SharedComponentOffset[i] = mi++; } else { type->SharedComponentOffset[i] = -1; } } } // Update the list of all created archetypes type->PrevArchetype = m_LastArchetype; m_LastArchetype = type; UnsafeLinkedListNode.InitializeList(&type->ChunkList); UnsafeLinkedListNode.InitializeList(&type->ChunkListWithEmptySlots); m_TypeLookup.Add(GetHash(types, count), (IntPtr)type); type->SystemStateCleanupComplete = ArchetypeSystemStateCleanupComplete(type); type->SystemStateCleanupNeeded = ArchetypeSystemStateCleanupNeeded(type); groupManager.OnArchetypeAdded(type); return(type); }
public static void MoveChunks(ArchetypeManager srcArchetypeManager, EntityDataManager *srcEntityDataManager, SharedComponentDataManager srcSharedComponents, ArchetypeManager dstArchetypeManager, EntityGroupManager dstGroupManager, SharedComponentDataManager dstSharedComponentDataManager, EntityDataManager *dstEntityDataManager, SharedComponentDataManager dstSharedComponents) { var entityRemapping = new NativeArray <EntityRemapUtility.EntityRemapInfo>(srcEntityDataManager->Capacity, Allocator.Temp); var entityPatches = new NativeList <EntityRemapUtility.EntityPatchInfo>(128, Allocator.Temp); dstEntityDataManager->AllocateEntitiesForRemapping(srcEntityDataManager, ref entityRemapping); var srcArchetype = srcArchetypeManager.m_LastArchetype; while (srcArchetype != null) { if (srcArchetype->EntityCount != 0) { if (srcArchetype->NumManagedArrays != 0) { throw new ArgumentException("MoveEntitiesFrom is not supported with managed arrays"); } var dstArchetype = dstArchetypeManager.GetOrCreateArchetype(srcArchetype->Types, srcArchetype->TypesCount, dstGroupManager); entityPatches.Clear(); for (var i = 1; i != dstArchetype->TypesCount; i++) { EntityRemapUtility.AppendEntityPatches(ref entityPatches, TypeManager.GetComponentType(dstArchetype->Types[i].TypeIndex).EntityOffsets, dstArchetype->Offsets[i], dstArchetype->SizeOfs[i]); } for (var c = srcArchetype->ChunkList.Begin; c != srcArchetype->ChunkList.End; c = c->Next) { var chunk = (Chunk *)c; dstEntityDataManager->RemapChunk(dstArchetype, chunk, 0, chunk->Count, ref entityRemapping); EntityRemapUtility.PatchEntities(ref entityPatches, chunk->Buffer, chunk->Count, ref entityRemapping); chunk->Archetype = dstArchetype; if (dstArchetype->NumSharedComponents > 0) { dstSharedComponents.MoveSharedComponents(srcSharedComponents, chunk->SharedComponentValueArray, dstArchetype->NumSharedComponents); } } UnsafeLinkedListNode.InsertListBefore(dstArchetype->ChunkList.End, &srcArchetype->ChunkList); if (!srcArchetype->ChunkListWithEmptySlots.IsEmpty) { UnsafeLinkedListNode.InsertListBefore(dstArchetype->ChunkListWithEmptySlots.End, &srcArchetype->ChunkListWithEmptySlots); } dstArchetype->EntityCount += srcArchetype->EntityCount; dstArchetype->ChunkCount += srcArchetype->ChunkCount; srcArchetype->EntityCount = 0; srcArchetype->ChunkCount = 0; } srcArchetype = srcArchetype->PrevArchetype; } srcEntityDataManager->FreeAllEntities(); entityRemapping.Dispose(); entityPatches.Dispose(); }
public void RemoveComponent(Entity entity, ComponentType type, ArchetypeManager archetypeManager, SharedComponentDataManager sharedComponentDataManager, EntityGroupManager groupManager, ComponentTypeInArchetype *componentTypeInArchetypeArray) { var componentType = new ComponentTypeInArchetype(type); var archetype = GetArchetype(entity); var removedTypes = 0; for (var t = 0; t < archetype->TypesCount; ++t) { if (archetype->Types[t].TypeIndex == componentType.TypeIndex) { ++removedTypes; } else { componentTypeInArchetypeArray[t - removedTypes] = archetype->Types[t]; } } Assert.AreNotEqual(-1, removedTypes); var newType = archetypeManager.GetOrCreateArchetype(componentTypeInArchetypeArray, archetype->TypesCount - removedTypes, groupManager); int *sharedComponentDataIndices = null; if (newType->NumSharedComponents > 0) { var oldSharedComponentDataIndices = GetComponentChunk(entity)->SharedComponentValueArray; var removedComponentIsShared = TypeManager.TypeCategory.ISharedComponentData == TypeManager.GetComponentType(type.TypeIndex).Category; removedTypes = 0; if (removedComponentIsShared) { int *tempAlloc = stackalloc int[newType->NumSharedComponents]; sharedComponentDataIndices = tempAlloc; int srcIndex = 0; int dstIndex = 0; for (var t = 0; t < archetype->TypesCount; ++t) { if (archetype->SharedComponentOffset[t] != -1) { if (archetype->Types[t].TypeIndex == componentType.TypeIndex) { srcIndex++; } else { sharedComponentDataIndices[dstIndex] = oldSharedComponentDataIndices[srcIndex]; srcIndex++; dstIndex++; } } } } else { // reuse old sharedComponentDataIndices sharedComponentDataIndices = oldSharedComponentDataIndices; } } IncrementComponentOrderVersion(archetype, GetComponentChunk(entity), sharedComponentDataManager); SetArchetype(archetypeManager, entity, newType, sharedComponentDataIndices); }
public void AddComponent(Entity entity, ComponentType type, ArchetypeManager archetypeManager, SharedComponentDataManager sharedComponentDataManager, EntityGroupManager groupManager, ComponentTypeInArchetype *componentTypeInArchetypeArray) { var componentType = new ComponentTypeInArchetype(type); var archetype = GetArchetype(entity); var t = 0; while (t < archetype->TypesCount && archetype->Types[t] < componentType) { componentTypeInArchetypeArray[t] = archetype->Types[t]; ++t; } componentTypeInArchetypeArray[t] = componentType; while (t < archetype->TypesCount) { componentTypeInArchetypeArray[t + 1] = archetype->Types[t]; ++t; } var newType = archetypeManager.GetOrCreateArchetype(componentTypeInArchetypeArray, archetype->TypesCount + 1, groupManager); int *sharedComponentDataIndices = null; if (newType->NumSharedComponents > 0) { var oldSharedComponentDataIndices = GetComponentChunk(entity)->SharedComponentValueArray; var newComponentIsShared = (TypeManager.TypeCategory.ISharedComponentData == TypeManager.GetComponentType(type.TypeIndex).Category); if (newComponentIsShared) { int *stackAlloced = stackalloc int[newType->NumSharedComponents]; sharedComponentDataIndices = stackAlloced; if (archetype->SharedComponentOffset == null) { sharedComponentDataIndices[0] = 0; } else { t = 0; var sharedIndex = 0; while (t < archetype->TypesCount && archetype->Types[t] < componentType) { if (archetype->SharedComponentOffset[t] != -1) { sharedComponentDataIndices[sharedIndex] = oldSharedComponentDataIndices[sharedIndex]; ++sharedIndex; } ++t; } sharedComponentDataIndices[sharedIndex] = 0; while (t < archetype->TypesCount) { if (archetype->SharedComponentOffset[t] != -1) { sharedComponentDataIndices[sharedIndex + 1] = oldSharedComponentDataIndices[sharedIndex]; ++sharedIndex; } ++t; } } } else { // reuse old sharedComponentDataIndices sharedComponentDataIndices = oldSharedComponentDataIndices; } } SetArchetype(archetypeManager, entity, newType, sharedComponentDataIndices); IncrementComponentOrderVersion(newType, GetComponentChunk(entity), sharedComponentDataManager); }
public Archetype *GetOrCreateArchetype(ComponentTypeInArchetype *types, int count, EntityGroupManager groupManager) { var type = GetExistingArchetype(types, count); if (type != null) { return(type); } AssertArchetypeComponents(types, count); // This is a new archetype, allocate it and add it to the hash map type = (Archetype *)m_ArchetypeChunkAllocator.Allocate(sizeof(Archetype), 8); type->TypesCount = count; type->Types = (ComponentTypeInArchetype *)m_ArchetypeChunkAllocator.Construct( sizeof(ComponentTypeInArchetype) * count, 4, types); type->EntityCount = 0; type->ChunkCount = 0; type->NumSharedComponents = 0; type->SharedComponentOffset = null; var disabledTypeIndex = TypeManager.GetTypeIndex <Disabled>(); type->Disabled = false; for (var i = 0; i < count; ++i) { if (TypeManager.GetComponentType(types[i].TypeIndex).Category == TypeManager.TypeCategory.ISharedComponentData) { ++type->NumSharedComponents; } if (types[i].TypeIndex == disabledTypeIndex) { type->Disabled = true; } } // Compute how many IComponentData types store Entities and need to be patched. // Types can have more than one entity, which means that this count is not necessarily // the same as the type count. int scalarEntityPatchCount = 0; int bufferEntityPatchCount = 0; for (var i = 0; i < count; ++i) { var ct = TypeManager.GetComponentType(types[i].TypeIndex); var entityOffsets = ct.EntityOffsets; if (entityOffsets == null) { continue; } if (ct.BufferCapacity >= 0) { bufferEntityPatchCount += entityOffsets.Length; } else { scalarEntityPatchCount += entityOffsets.Length; } } var chunkDataSize = Chunk.GetChunkBufferSize(type->TypesCount, type->NumSharedComponents); // FIXME: proper alignment type->Offsets = (int *)m_ArchetypeChunkAllocator.Allocate(sizeof(int) * count, 4); type->SizeOfs = (int *)m_ArchetypeChunkAllocator.Allocate(sizeof(int) * count, 4); type->TypeMemoryOrder = (int *)m_ArchetypeChunkAllocator.Allocate(sizeof(int) * count, 4); type->ScalarEntityPatches = (EntityRemapUtility.EntityPatchInfo *)m_ArchetypeChunkAllocator.Allocate(sizeof(EntityRemapUtility.EntityPatchInfo) * scalarEntityPatchCount, 4); type->ScalarEntityPatchCount = scalarEntityPatchCount; type->BufferEntityPatches = (EntityRemapUtility.BufferEntityPatchInfo *)m_ArchetypeChunkAllocator.Allocate(sizeof(EntityRemapUtility.BufferEntityPatchInfo) * bufferEntityPatchCount, 4); type->BufferEntityPatchCount = bufferEntityPatchCount; var bytesPerInstance = 0; for (var i = 0; i < count; ++i) { var cType = TypeManager.GetComponentType(types[i].TypeIndex); var sizeOf = cType.SizeInChunk; // Note that this includes internal capacity and header overhead for buffers. type->SizeOfs[i] = sizeOf; bytesPerInstance += sizeOf; } type->ChunkCapacity = chunkDataSize / bytesPerInstance; #if ENABLE_UNITY_COLLECTIONS_CHECKS if (bytesPerInstance > chunkDataSize) { throw new ArgumentException( $"Entity archetype component data is too large. The maximum component data is {chunkDataSize} but the component data is {bytesPerInstance}"); } Assert.IsTrue(Chunk.kMaximumEntitiesPerChunk >= type->ChunkCapacity); #endif // For serialization a stable ordering of the components in the // chunk is desired. The type index is not stable, since it depends // on the order in which types are added to the TypeManager. // A permutation of the types ordered by a TypeManager-generated // memory ordering is used instead. var memoryOrderings = new NativeArray <UInt64>(count, Allocator.Temp); for (int i = 0; i < count; ++i) { memoryOrderings[i] = TypeManager.GetComponentType(types[i].TypeIndex).MemoryOrdering; } for (int i = 0; i < count; ++i) { int index = i; while (index > 1 && memoryOrderings[i] < memoryOrderings[type->TypeMemoryOrder[index - 1]]) { type->TypeMemoryOrder[index] = type->TypeMemoryOrder[index - 1]; --index; } type->TypeMemoryOrder[index] = i; } memoryOrderings.Dispose(); var usedBytes = 0; for (var i = 0; i < count; ++i) { var index = type->TypeMemoryOrder[i]; var sizeOf = type->SizeOfs[index]; type->Offsets[index] = usedBytes; usedBytes += sizeOf * type->ChunkCapacity; } type->NumManagedArrays = 0; type->ManagedArrayOffset = null; for (var i = 0; i < count; ++i) { if (TypeManager.GetComponentType(types[i].TypeIndex).Category == TypeManager.TypeCategory.Class) { ++type->NumManagedArrays; } } if (type->NumManagedArrays > 0) { type->ManagedArrayOffset = (int *)m_ArchetypeChunkAllocator.Allocate(sizeof(int) * count, 4); var mi = 0; for (var i = 0; i < count; ++i) { var cType = TypeManager.GetComponentType(types[i].TypeIndex); if (cType.Category == TypeManager.TypeCategory.Class) { type->ManagedArrayOffset[i] = mi++; } else { type->ManagedArrayOffset[i] = -1; } } } if (type->NumSharedComponents > 0) { type->SharedComponentOffset = (int *)m_ArchetypeChunkAllocator.Allocate(sizeof(int) * count, 4); var mi = 0; for (var i = 0; i < count; ++i) { var cType = TypeManager.GetComponentType(types[i].TypeIndex); if (cType.Category == TypeManager.TypeCategory.ISharedComponentData) { type->SharedComponentOffset[i] = mi++; } else { type->SharedComponentOffset[i] = -1; } } } // Fill in arrays of scalar and buffer entity patches var scalarPatchInfo = type->ScalarEntityPatches; var bufferPatchInfo = type->BufferEntityPatches; for (var i = 0; i != count; i++) { var ct = TypeManager.GetComponentType(types[i].TypeIndex); var offsets = ct.EntityOffsets; if (ct.BufferCapacity >= 0) { bufferPatchInfo = EntityRemapUtility.AppendBufferEntityPatches(bufferPatchInfo, offsets, type->Offsets[i], type->SizeOfs[i], ct.ElementSize); } else { scalarPatchInfo = EntityRemapUtility.AppendEntityPatches(scalarPatchInfo, offsets, type->Offsets[i], type->SizeOfs[i]); } } type->ScalarEntityPatchCount = scalarEntityPatchCount; type->BufferEntityPatchCount = bufferEntityPatchCount; // Update the list of all created archetypes type->PrevArchetype = m_LastArchetype; m_LastArchetype = type; UnsafeLinkedListNode.InitializeList(&type->ChunkList); UnsafeLinkedListNode.InitializeList(&type->ChunkListWithEmptySlots); type->FreeChunksBySharedComponents.Init(8); m_TypeLookup.Add(GetHash(types, count), (IntPtr)type); type->SystemStateCleanupComplete = ArchetypeSystemStateCleanupComplete(type); type->SystemStateCleanupNeeded = ArchetypeSystemStateCleanupNeeded(type); groupManager.OnArchetypeAdded(type); return(type); }
public Archetype *GetOrCreateArchetype(ComponentTypeInArchetype *types, int count, EntityGroupManager groupManager) { var type = GetExistingArchetype(types, count); if (type != null) { return(type); } AssertArchetypeComponents(types, count); // This is a new archetype, allocate it and add it to the hash map type = (Archetype *)m_ArchetypeChunkAllocator.Allocate(sizeof(Archetype), 8); type->TypesCount = count; type->Types = (ComponentTypeInArchetype *)m_ArchetypeChunkAllocator.Construct(sizeof(ComponentTypeInArchetype) * count, 4, types); type->EntityCount = 0; type->NumSharedComponents = 0; type->SharedComponentOffset = null; for (var i = 0; i < count; ++i) { if (TypeManager.GetComponentType(types[i].TypeIndex).Category == TypeManager.TypeCategory.ISharedComponentData) { ++type->NumSharedComponents; } } var chunkDataSize = Chunk.GetChunkBufferSize(type->NumSharedComponents); // FIXME: proper alignment type->Offsets = (int *)m_ArchetypeChunkAllocator.Allocate(sizeof(int) * count, 4); type->SizeOfs = (int *)m_ArchetypeChunkAllocator.Allocate(sizeof(int) * count, 4); var bytesPerInstance = 0; for (var i = 0; i < count; ++i) { var cType = TypeManager.GetComponentType(types[i].TypeIndex); var sizeOf = cType.SizeInChunk * types[i].FixedArrayLengthMultiplier; type->SizeOfs[i] = sizeOf; bytesPerInstance += sizeOf; } type->ChunkCapacity = chunkDataSize / bytesPerInstance; Assert.IsTrue(Chunk.kMaximumEntitiesPerChunk >= type->ChunkCapacity); var usedBytes = 0; for (var i = 0; i < count; ++i) { var sizeOf = type->SizeOfs[i]; type->Offsets[i] = usedBytes; usedBytes += sizeOf * type->ChunkCapacity; } type->NumManagedArrays = 0; type->ManagedArrayOffset = null; for (var i = 0; i < count; ++i) { if (TypeManager.GetComponentType(types[i].TypeIndex).Category == TypeManager.TypeCategory.Class) { ++type->NumManagedArrays; } } if (type->NumManagedArrays > 0) { type->ManagedArrayOffset = (int *)m_ArchetypeChunkAllocator.Allocate(sizeof(int) * count, 4); var mi = 0; for (var i = 0; i < count; ++i) { var cType = TypeManager.GetComponentType(types[i].TypeIndex); if (cType.Category == TypeManager.TypeCategory.Class) { type->ManagedArrayOffset[i] = mi++; } else { type->ManagedArrayOffset[i] = -1; } } } if (type->NumSharedComponents > 0) { type->SharedComponentOffset = (int *)m_ArchetypeChunkAllocator.Allocate(sizeof(int) * count, 4); var mi = 0; for (var i = 0; i < count; ++i) { var cType = TypeManager.GetComponentType(types[i].TypeIndex); if (cType.Category == TypeManager.TypeCategory.ISharedComponentData) { type->SharedComponentOffset[i] = mi++; } else { type->SharedComponentOffset[i] = -1; } } } // Update the list of all created archetypes type->PrevArchetype = m_LastArchetype; m_LastArchetype = type; UnsafeLinkedListNode.InitializeList(&type->ChunkList); UnsafeLinkedListNode.InitializeList(&type->ChunkListWithEmptySlots); m_TypeLookup.Add(GetHash(types, count), (IntPtr)type); groupManager.OnArchetypeAdded(type); return(type); }