Esempio n. 1
0
            // This must be run after chunks have been remapped since FreeChunksBySharedComponents needs the shared component
            // indices in the chunks to be remapped
            public void Execute(int index)
            {
                var srcArchetype = remapArchetypes[index].srcArchetype;
                var dstArchetype = remapArchetypes[index].dstArchetype;

                UnsafeLinkedListNode.InsertListBefore(dstArchetype->ChunkList.End, &srcArchetype->ChunkList);

                if (srcArchetype->NumSharedComponents == 0)
                {
                    if (!srcArchetype->ChunkListWithEmptySlots.IsEmpty)
                    {
                        UnsafeLinkedListNode.InsertListBefore(dstArchetype->ChunkListWithEmptySlots.End,
                                                              &srcArchetype->ChunkListWithEmptySlots);
                    }
                }
                else
                {
                    remapArchetypes[index].dstArchetype->FreeChunksBySharedComponents.AppendFrom(&remapArchetypes[index].srcArchetype->FreeChunksBySharedComponents);
                }

                dstArchetype->EntityCount += srcArchetype->EntityCount;
                dstArchetype->ChunkCount  += srcArchetype->ChunkCount;
                srcArchetype->EntityCount  = 0;
                srcArchetype->ChunkCount   = 0;
            }
        public void ConstructChunk(Archetype *archetype, Chunk *chunk, int *sharedComponentDataIndices)
        {
            chunk->Archetype = archetype;

            chunk->Count         = 0;
            chunk->Capacity      = archetype->ChunkCapacity;
            chunk->ChunkListNode = new UnsafeLinkedListNode();
            chunk->ChunkListWithEmptySlotsNode = new UnsafeLinkedListNode();

            var numSharedComponents   = archetype->NumSharedComponents;
            var numTypes              = archetype->TypesCount;
            var sharedComponentOffset = Chunk.GetSharedComponentOffset(numSharedComponents);
            var changeVersionOffset   = Chunk.GetChangedComponentOffset(numTypes, numSharedComponents);

            chunk->SharedComponentValueArray = (int *)((byte *)chunk + sharedComponentOffset);
            chunk->ChangeVersion             = (uint *)((byte *)chunk + changeVersionOffset);

            archetype->ChunkList.Add(&chunk->ChunkListNode);
            archetype->ChunkCount += 1;

            Assert.IsTrue(!archetype->ChunkList.IsEmpty);
            Assert.IsTrue(chunk == (Chunk *)archetype->ChunkList.Back);

            if (numSharedComponents == 0)
            {
                archetype->ChunkListWithEmptySlots.Add(&chunk->ChunkListWithEmptySlotsNode);
                Assert.IsTrue(chunk == GetChunkFromEmptySlotNode(archetype->ChunkListWithEmptySlots.Back));
                Assert.IsTrue(!archetype->ChunkListWithEmptySlots.IsEmpty);
            }
            else
            {
                var sharedComponentValueArray = chunk->SharedComponentValueArray;
                UnsafeUtility.MemCpy(sharedComponentValueArray, sharedComponentDataIndices, archetype->NumSharedComponents * sizeof(int));

                for (var i = 0; i < archetype->NumSharedComponents; ++i)
                {
                    var sharedComponentIndex = sharedComponentValueArray[i];
                    m_SharedComponentManager.AddReference(sharedComponentIndex);
                }

                archetype->FreeChunksBySharedComponents.Add(chunk);
                Assert.IsTrue(archetype->FreeChunksBySharedComponents.GetChunkWithEmptySlots(sharedComponentDataIndices, archetype->NumSharedComponents) != null);
            }

            if (archetype->NumManagedArrays > 0)
            {
                chunk->ManagedArrayIndex = AllocateManagedArrayStorage(archetype->NumManagedArrays * chunk->Capacity);
            }
            else
            {
                chunk->ManagedArrayIndex = -1;
            }

            for (var i = 0; i < archetype->TypesCount; i++)
            {
                chunk->ChangeVersion[i] = 0;
            }
        }
Esempio n. 3
0
        public void ConstructChunk(Archetype *archetype, Chunk *chunk, int *sharedComponentDataIndices)
        {
            chunk->Archetype = archetype;

            chunk->Count         = 0;
            chunk->Capacity      = archetype->ChunkCapacity;
            chunk->ChunkListNode = new UnsafeLinkedListNode();
            chunk->ChunkListWithEmptySlotsNode = new UnsafeLinkedListNode();
            chunk->SharedComponentValueArray   =
                (int *)((byte *)chunk + Chunk.GetSharedComponentOffset(archetype->NumSharedComponents));
            chunk->ChangeVersion = (uint *)((byte *)chunk +
                                            Chunk.GetChangedComponentOffset(archetype->TypesCount,
                                                                            archetype->NumSharedComponents));

            archetype->ChunkList.Add(&chunk->ChunkListNode);
            archetype->ChunkCount += 1;
            archetype->ChunkListWithEmptySlots.Add(&chunk->ChunkListWithEmptySlotsNode);

            Assert.IsTrue(!archetype->ChunkList.IsEmpty);
            Assert.IsTrue(!archetype->ChunkListWithEmptySlots.IsEmpty);

            Assert.IsTrue(chunk == (Chunk *)archetype->ChunkList.Back);
            Assert.IsTrue(chunk == GetChunkFromEmptySlotNode(archetype->ChunkListWithEmptySlots.Back));

            if (archetype->NumManagedArrays > 0)
            {
                chunk->ManagedArrayIndex = AllocateManagedArrayStorage(archetype->NumManagedArrays * chunk->Capacity);
            }
            else
            {
                chunk->ManagedArrayIndex = -1;
            }

            for (var i = 0; i < archetype->TypesCount; i++)
            {
                chunk->ChangeVersion[i] = 0;
            }

            if (archetype->NumSharedComponents <= 0)
            {
                return;
            }

            var sharedComponentValueArray = chunk->SharedComponentValueArray;

            CopySharedComponentDataIndexArray(sharedComponentValueArray, sharedComponentDataIndices,
                                              chunk->Archetype->NumSharedComponents);

            if (sharedComponentDataIndices == null)
            {
                return;
            }

            for (var i = 0; i < archetype->NumSharedComponents; ++i)
            {
                m_SharedComponentManager.AddReference(sharedComponentValueArray[i]);
            }
        }
Esempio n. 4
0
        public void ConstructChunk(Archetype *archetype, Chunk *chunk, int *sharedComponentDataIndices)
        {
            chunk->Archetype = archetype;

            chunk->Count         = 0;
            chunk->Capacity      = archetype->ChunkCapacity;
            chunk->ChunkListNode = new UnsafeLinkedListNode();
            chunk->ChunkListWithEmptySlotsNode = new UnsafeLinkedListNode();
            chunk->SharedComponentValueArray   = (int *)((byte *)(chunk) + Chunk.GetSharedComponentOffset(archetype->NumSharedComponents));

            archetype->ChunkList.Add(&chunk->ChunkListNode);
            archetype->ChunkListWithEmptySlots.Add(&chunk->ChunkListWithEmptySlotsNode);

            Assert.IsTrue(!archetype->ChunkList.IsEmpty);
            Assert.IsTrue(!archetype->ChunkListWithEmptySlots.IsEmpty);

            Assert.IsTrue(chunk == (Chunk *)(archetype->ChunkList.Back));
            Assert.IsTrue(chunk == GetChunkFromEmptySlotNode(archetype->ChunkListWithEmptySlots.Back));

            if (archetype->NumManagedArrays > 0)
            {
                chunk->ManagedArrayIndex = m_ManagedArrays.Count;
                var man = new ManagedArrayStorage();
                man.Chunk        = chunk;
                man.ManagedArray = new object[archetype->NumManagedArrays * chunk->Capacity];
                m_ManagedArrays.Add(man);
            }
            else
            {
                chunk->ManagedArrayIndex = -1;
            }


            if (archetype->NumSharedComponents <= 0)
            {
                return;
            }

            var sharedComponentValueArray = chunk->SharedComponentValueArray;

            CopySharedComponentDataIndexArray(sharedComponentValueArray, sharedComponentDataIndices, chunk->Archetype->NumSharedComponents);

            if (sharedComponentDataIndices == null)
            {
                return;
            }

            for (var i = 0; i < archetype->NumSharedComponents; ++i)
            {
                m_SharedComponentManager.AddReference(sharedComponentValueArray[i]);
            }
        }
Esempio n. 5
0
        void AddMultiple(UnsafeLinkedListNode *list)
        {
            var    firstChunk = ArchetypeManager.GetChunkFromEmptySlotNode(list->Begin);
            UInt32 hash       = GetHashCode(firstChunk->SharedComponentValueArray, firstChunk->Archetype->NumSharedComponents);

            int * sharedComponentDataIndices = firstChunk->SharedComponentValueArray;
            int   numSharedComponents        = firstChunk->Archetype->NumSharedComponents;
            Node *node     = &buckets[hash & hashMask];
            Node *lastNode = &buckets[hashMask];
            Node *freeNode = null;

            while (!node->IsFree())
            {
                if (!node->IsDeleted())
                {
                    if (node->CheckEqual(hash, sharedComponentDataIndices, numSharedComponents))
                    {
                        UnsafeLinkedListNode.InsertListBefore(node->list.End, list);
                        return;
                    }
                }
                else
                {
                    if (freeNode == null)
                    {
                        freeNode = node;
                    }
                }

                node = node + 1;
                if (node > lastNode)
                {
                    node = buckets;
                }
            }

            if (freeNode == null)
            {
                freeNode = node;
                --emptyNodes;
            }

            freeNode->hash = hash;
            UnsafeLinkedListNode.InitializeList(&freeNode->list);
            UnsafeLinkedListNode.InsertListBefore(freeNode->list.End, list);

            if (ShouldGrow(emptyNodes))
            {
                Grow();
            }
        }
Esempio n. 6
0
        public ArchetypeManager(SharedComponentDataManager sharedComponentManager)
        {
            m_SharedComponentManager = sharedComponentManager;
            m_TypeLookup             = new NativeMultiHashMap <uint, IntPtr>(256, Allocator.Persistent);

            m_EmptyChunkPool = (UnsafeLinkedListNode *)m_ArchetypeChunkAllocator.Allocate(sizeof(UnsafeLinkedListNode), UnsafeUtility.AlignOf <UnsafeLinkedListNode>());
            UnsafeLinkedListNode.InitializeList(m_EmptyChunkPool);

#if UNITY_ASSERTIONS
            // Buffer should be 16 byte aligned to ensure component data layout itself can gurantee being aligned
            var offset = UnsafeUtility.GetFieldOffset(typeof(Chunk).GetField("Buffer"));
            Assert.IsTrue(offset % 16 == 0, "Chunk buffer must be 16 byte aligned");
#endif
        }
Esempio n. 7
0
        public void Add(Chunk *chunk)
        {
            int * sharedComponentDataIndices = chunk->SharedComponentValueArray;
            int   numSharedComponents        = chunk->Archetype->NumSharedComponents;
            uint  hash     = GetHashCode(sharedComponentDataIndices, numSharedComponents);
            Node *node     = &buckets[hash & hashMask];
            Node *lastNode = &buckets[hashMask];
            Node *freeNode = null;

            while (!node->IsFree())
            {
                if (!node->IsDeleted())
                {
                    if (node->CheckEqual(hash, sharedComponentDataIndices, numSharedComponents))
                    {
                        node->list.Add(&chunk->ChunkListWithEmptySlotsNode);
                        return;
                    }
                }
                else
                {
                    if (freeNode == null)
                    {
                        freeNode = node;
                    }
                }

                node = node + 1;
                if (node > lastNode)
                {
                    node = buckets;
                }
            }

            if (freeNode == null)
            {
                freeNode = node;
                --emptyNodes;
            }

            freeNode->hash = hash;
            UnsafeLinkedListNode.InitializeList(&freeNode->list);
            freeNode->list.Add(&chunk->ChunkListWithEmptySlotsNode);

            if (ShouldGrow(emptyNodes))
            {
                Grow();
            }
        }
        private unsafe void AddMultiple(UnsafeLinkedListNode *list)
        {
            Chunk *chunkPtr = ref ArchetypeManager.GetChunkFromEmptySlotNode(list.Begin);
            uint   hashCode = this.GetHashCode(chunkPtr->SharedComponentValueArray, chunkPtr->Archetype.NumSharedComponents);
            int *  sharedComponentValueArray = chunkPtr->SharedComponentValueArray;
            int    numSharedComponents       = chunkPtr->Archetype.NumSharedComponents;
            Node * buckets  = this.buckets + ((hashCode & this.hashMask) * sizeof(Node));
            Node * nodePtr2 = this.buckets + (this.hashMask * sizeof(Node));
            Node * nodePtr3 = null;

            while (true)
            {
                if (buckets.IsFree())
                {
                    if (nodePtr3 == null)
                    {
                        nodePtr3 = buckets;
                        this.emptyNodes--;
                    }
                    nodePtr3->hash = hashCode;
                    UnsafeLinkedListNode.InitializeList(&nodePtr3->list);
                    UnsafeLinkedListNode.InsertListBefore(nodePtr3->list.End, list);
                    if (this.ShouldGrow(this.emptyNodes))
                    {
                        this.Grow();
                    }
                    break;
                }
                if (!buckets.IsDeleted())
                {
                    if (buckets.CheckEqual(hashCode, sharedComponentValueArray, numSharedComponents))
                    {
                        UnsafeLinkedListNode.InsertListBefore(buckets->list.End, list);
                        break;
                    }
                }
                else if (nodePtr3 == null)
                {
                    nodePtr3 = buckets;
                }
                buckets++;
                if (buckets > nodePtr2)
                {
                    buckets = this.buckets;
                }
            }
        }
        public unsafe void Add(Chunk *chunk)
        {
            int * sharedComponentValueArray = chunk.SharedComponentValueArray;
            int   numSharedComponents       = chunk.Archetype.NumSharedComponents;
            uint  hashCode = this.GetHashCode(sharedComponentValueArray, numSharedComponents);
            Node *buckets  = this.buckets + ((hashCode & this.hashMask) * sizeof(Node));
            Node *nodePtr2 = this.buckets + (this.hashMask * sizeof(Node));
            Node *nodePtr3 = null;

            while (true)
            {
                if (buckets.IsFree())
                {
                    if (nodePtr3 == null)
                    {
                        nodePtr3 = buckets;
                        this.emptyNodes--;
                    }
                    nodePtr3->hash = hashCode;
                    UnsafeLinkedListNode.InitializeList(&nodePtr3->list);
                    nodePtr3->list.Add(&chunk.ChunkListWithEmptySlotsNode);
                    if (this.ShouldGrow(this.emptyNodes))
                    {
                        this.Grow();
                    }
                    break;
                }
                if (!buckets.IsDeleted())
                {
                    if (buckets.CheckEqual(hashCode, sharedComponentValueArray, numSharedComponents))
                    {
                        buckets->list.Add(&chunk.ChunkListWithEmptySlotsNode);
                        break;
                    }
                }
                else if (nodePtr3 == null)
                {
                    nodePtr3 = buckets;
                }
                buckets++;
                if (buckets > nodePtr2)
                {
                    buckets = this.buckets;
                }
            }
        }
Esempio n. 10
0
        public static void MoveChunks(ArchetypeManager srcArchetypeManager, EntityDataManager *srcEntityDataManager, SharedComponentDataManager srcSharedComponents, ArchetypeManager dstArchetypeManager, EntityGroupManager dstGroupManager, SharedComponentDataManager dstSharedComponentDataManager, EntityDataManager *dstEntityDataManager, SharedComponentDataManager dstSharedComponents)
        {
            var entitiesArray = new NativeArray <Entity>(Chunk.kMaximumEntitiesPerChunk, Allocator.Temp);
            var entitiesPtr   = (Entity *)entitiesArray.GetUnsafePtr();

            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);

                    for (var c = srcArchetype->ChunkList.Begin; c != srcArchetype->ChunkList.End; c = c->Next)
                    {
                        Chunk *chunk = (Chunk *)c;

                        EntityDataManager.FreeDataEntitiesInChunk(srcEntityDataManager, chunk, chunk->Count);
                        dstEntityDataManager->AllocateEntities(dstArchetype, chunk, 0, chunk->Count, entitiesPtr);

                        chunk->Archetype = dstArchetype;

                        if (dstArchetype->NumSharedComponents > 0)
                        {
                            dstSharedComponents.MoveSharedComponents(srcSharedComponents, chunk->SharedComponentValueArray, dstArchetype->NumSharedComponents);
                        }
                    }

                    //@TODO: Patch Entity references in IComponentData...

                    UnsafeLinkedListNode.InsertListBefore(dstArchetype->ChunkList.End, &srcArchetype->ChunkList);
                    UnsafeLinkedListNode.InsertListBefore(dstArchetype->ChunkListWithEmptySlots.End, &srcArchetype->ChunkListWithEmptySlots);

                    dstArchetype->EntityCount += srcArchetype->EntityCount;
                    srcArchetype->EntityCount  = 0;
                }

                srcArchetype = srcArchetype->PrevArchetype;
            }
            entitiesArray.Dispose();
        }
        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);
        }
Esempio n. 12
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);
        }
Esempio n. 13
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();
        }
Esempio n. 14
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);
        }