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;
        }
Beispiel #3
0
        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));
        }
Beispiel #4
0
 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));
        }
Beispiel #7
0
        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));
            }
        }
Beispiel #8
0
        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);
        }
Beispiel #11
0
        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));
        }
Beispiel #12
0
        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));
        }
Beispiel #14
0
        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);
        }
Beispiel #17
0
        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);
        }
Beispiel #18
0
        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();
        }
Beispiel #19
0
        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);
        }
Beispiel #20
0
        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);
        }
Beispiel #22
0
        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);
        }