Beispiel #1
0
            public void Execute()
            {
                DstEntityComponentStore->AllocateManagedComponentIndices((int *)DstManagedIndices.GetUnsafePtr(), DstManagedIndices.Length);
                int srcCounter = 0;

                for (var iChunk = 0; iChunk < SrcEntityComponentStore->m_Archetypes.Length; ++iChunk)
                {
                    var srcArchetype = SrcEntityComponentStore->m_Archetypes.Ptr[iChunk];
                    for (var j = 0; j < srcArchetype->Chunks.Count; ++j)
                    {
                        var chunk = srcArchetype->Chunks.p[j];
                        var firstManagedComponent = srcArchetype->FirstManagedComponent;
                        var numManagedComponents  = srcArchetype->NumManagedComponents;
                        for (int i = 0; i < numManagedComponents; ++i)
                        {
                            int type = i + firstManagedComponent;
                            var a    = (int *)ChunkDataUtility.GetComponentDataRO(chunk, 0, type);
                            for (int ei = 0; ei < chunk->Count; ++ei)
                            {
                                var managedComponentIndex = a[ei];
                                if (managedComponentIndex == 0)
                                {
                                    continue;
                                }

                                SrcManagedIndices[srcCounter] = managedComponentIndex;
                                a[ei] = DstManagedIndices[srcCounter++];
                            }
                        }
                    }
                }

                Assert.AreEqual(SrcManagedIndices.Length, srcCounter);
            }
Beispiel #2
0
        public int CheckInternalConsistency()
        {
            var aliveEntities = 0;
            var entityType    = TypeManager.GetTypeIndex <Entity>();

            for (var i = 0; i != m_EntitiesCapacity; i++)
            {
                if (m_Entities[i].Chunk == null)
                {
                    continue;
                }

                aliveEntities++;
                var archetype = m_Entities[i].Archetype;
                Assert.AreEqual(entityType, archetype->Types[0].TypeIndex);
                var entity =
                    *(Entity *)ChunkDataUtility.GetComponentDataRO(m_Entities[i].Chunk, m_Entities[i].IndexInChunk, 0);
                Assert.AreEqual(i, entity.Index);
                Assert.AreEqual(m_Entities[i].Version, entity.Version);

                Assert.IsTrue(Exists(entity));
            }

            return(aliveEntities);
        }
Beispiel #3
0
 internal void AddExistingChunk(Chunk *chunk)
 {
     for (int iEntity = 0; iEntity < chunk->Count; ++iEntity)
     {
         var entity = (Entity *)ChunkDataUtility.GetComponentDataRO(chunk, iEntity, 0);
         m_Entities[entity->Index].Chunk        = chunk;
         m_Entities[entity->Index].IndexInChunk = iEntity;
         m_Entities[entity->Index].Archetype    = chunk->Archetype;
     }
 }
Beispiel #4
0
        public void SetArchetype(ArchetypeManager typeMan, Entity entity, Archetype *archetype,
                                 int *sharedComponentDataIndices)
        {
            var chunk      = typeMan.GetChunkWithEmptySlots(archetype, sharedComponentDataIndices);
            var chunkIndex = typeMan.AllocateIntoChunk(chunk);

            var oldArchetype  = m_Entities[entity.Index].Archetype;
            var oldChunk      = m_Entities[entity.Index].Chunk;
            var oldChunkIndex = m_Entities[entity.Index].IndexInChunk;

            ChunkDataUtility.Convert(oldChunk, oldChunkIndex, chunk, chunkIndex);
            if (chunk->ManagedArrayIndex >= 0 && oldChunk->ManagedArrayIndex >= 0)
            {
                ChunkDataUtility.CopyManagedObjects(typeMan, oldChunk, oldChunkIndex, chunk, chunkIndex, 1);
            }

            m_Entities[entity.Index].Archetype    = archetype;
            m_Entities[entity.Index].Chunk        = chunk;
            m_Entities[entity.Index].IndexInChunk = chunkIndex;

            var lastIndex = oldChunk->Count - 1;

            // No need to replace with ourselves
            if (lastIndex != oldChunkIndex)
            {
                var lastEntity = (Entity *)ChunkDataUtility.GetComponentDataRO(oldChunk, lastIndex, 0);
                m_Entities[lastEntity->Index].IndexInChunk = oldChunkIndex;

                ChunkDataUtility.Copy(oldChunk, lastIndex, oldChunk, oldChunkIndex, 1);
                if (oldChunk->ManagedArrayIndex >= 0)
                {
                    ChunkDataUtility.CopyManagedObjects(typeMan, oldChunk, lastIndex, oldChunk, oldChunkIndex, 1);
                }
            }

            if (oldChunk->ManagedArrayIndex >= 0)
            {
                ChunkDataUtility.ClearManagedObjects(typeMan, oldChunk, lastIndex, 1);
            }

            --oldArchetype->EntityCount;
            typeMan.SetChunkCount(oldChunk, lastIndex);
        }
Beispiel #5
0
        public void MoveEntityToChunk(ArchetypeManager typeMan, Entity entity, Chunk *newChunk, int newChunkIndex)
        {
            var oldChunk = m_Entities[entity.Index].Chunk;

            Assert.IsTrue(oldChunk->Archetype == newChunk->Archetype);

            var oldChunkIndex = m_Entities[entity.Index].IndexInChunk;

            ChunkDataUtility.Copy(oldChunk, oldChunkIndex, newChunk, newChunkIndex, 1);

            if (oldChunk->ManagedArrayIndex >= 0)
            {
                ChunkDataUtility.CopyManagedObjects(typeMan, oldChunk, oldChunkIndex, newChunk, newChunkIndex, 1);
            }

            m_Entities[entity.Index].Chunk        = newChunk;
            m_Entities[entity.Index].IndexInChunk = newChunkIndex;

            var lastIndex = oldChunk->Count - 1;

            // No need to replace with ourselves
            if (lastIndex != oldChunkIndex)
            {
                var lastEntity = (Entity *)ChunkDataUtility.GetComponentDataRO(oldChunk, lastIndex, 0);
                m_Entities[lastEntity->Index].IndexInChunk = oldChunkIndex;

                ChunkDataUtility.Copy(oldChunk, lastIndex, oldChunk, oldChunkIndex, 1);
                if (oldChunk->ManagedArrayIndex >= 0)
                {
                    ChunkDataUtility.CopyManagedObjects(typeMan, oldChunk, lastIndex, oldChunk, oldChunkIndex, 1);
                }
            }

            if (oldChunk->ManagedArrayIndex >= 0)
            {
                ChunkDataUtility.ClearManagedObjects(typeMan, oldChunk, lastIndex, 1);
            }

            newChunk->Archetype->EntityCount--;
            typeMan.SetChunkCount(oldChunk, oldChunk->Count - 1);
        }
Beispiel #6
0
        public void PatchEntities(Archetype *archetype, Chunk *chunk, int entityCount,
                                  EntityRemapUtility.EntityRemapInfo *remapping)
        {
#if !NET_DOTS
            var firstManagedComponent = archetype->FirstManagedComponent;
            var numManagedComponents  = archetype->NumManagedComponents;
            for (int i = 0; i < numManagedComponents; ++i)
            {
                int type = i + firstManagedComponent;
                var a    = (int *)ChunkDataUtility.GetComponentDataRO(chunk, 0, type);
                for (int ei = 0; ei < entityCount; ++ei)
                {
                    if (a[ei] != 0)
                    {
                        var obj = m_ManagedComponentData[a[ei]];
                        EntityRemapUtility.PatchEntityInBoxedType(obj, remapping);
                    }
                }
            }
#endif
        }
Beispiel #7
0
            public void Execute()
            {
                var count = DstManagedIndices.Length;

                DstEntityComponentStore->AllocateManagedComponentIndices((int *)DstManagedIndices.GetUnsafePtr(), count);

                int srcCounter = 0;

                for (var iChunk = 0; iChunk < Chunks.Length; ++iChunk)
                {
                    var chunk                 = (Chunk *)Chunks[iChunk];
                    var srcArchetype          = chunk->Archetype;
                    var firstManagedComponent = srcArchetype->FirstManagedComponent;
                    var numManagedComponents  = srcArchetype->NumManagedComponents;
                    for (int i = 0; i < numManagedComponents; ++i)
                    {
                        int type = i + firstManagedComponent;
                        var a    = (int *)ChunkDataUtility.GetComponentDataRO(chunk, 0, type);
                        for (int ei = 0; ei < chunk->Count; ++ei)
                        {
                            var managedComponentIndex = a[ei];
                            if (managedComponentIndex == 0)
                            {
                                continue;
                            }

                            SrcManagedIndices[srcCounter] = managedComponentIndex;
                            a[ei] = DstManagedIndices[srcCounter++];
                        }
                    }
                }

                if (srcCounter < count)
                {
                    DstEntityComponentStore->m_ManagedComponentFreeIndex.Add((int *)DstManagedIndices.GetUnsafePtr() + srcCounter, (count - srcCounter) * sizeof(int));
                }
                *NonNullCount = srcCounter;
            }
Beispiel #8
0
        public void CheckInternalConsistency(object[] managedComponentData)
        {
            Assert.IsTrue(ManagedChangesTracker.Empty);
            var managedComponentIndices = new UnsafeBitArray(m_ManagedComponentIndex, Allocator.Temp);

            Assert.IsTrue(managedComponentData.Length >= m_ManagedComponentIndex);
            for (int i = m_ManagedComponentIndex; i < managedComponentData.Length; ++i)
            {
                Assert.IsNull(managedComponentData[i]);
            }

            // Iterate by archetype
            var entityCountByArchetype = 0;

            for (var i = 0; i < m_Archetypes.Length; ++i)
            {
                var archetype        = m_Archetypes.Ptr[i];
                int managedTypeBegin = archetype->FirstManagedComponent;
                int managedTypeEnd   = archetype->ManagedComponentsEnd;

                var countInArchetype = 0;
                for (var j = 0; j < archetype->Chunks.Count; ++j)
                {
                    var chunk = archetype->Chunks.p[j];
                    Assert.IsTrue(chunk->Archetype == archetype);
                    Assert.IsTrue(chunk->Capacity >= chunk->Count);
                    Assert.AreEqual(chunk->Count, archetype->Chunks.GetChunkEntityCount(j));

                    var chunkEntities = (Entity *)chunk->Buffer;
                    AssertEntitiesExist(chunkEntities, chunk->Count);

                    if (!chunk->Locked)
                    {
                        if (chunk->Count < chunk->Capacity)
                        {
                            if (archetype->NumSharedComponents == 0)
                            {
                                Assert.IsTrue(chunk->ListWithEmptySlotsIndex >= 0 && chunk->ListWithEmptySlotsIndex <
                                              archetype->ChunksWithEmptySlots.Length);
                                Assert.IsTrue(
                                    chunk == archetype->ChunksWithEmptySlots.Ptr[chunk->ListWithEmptySlotsIndex]);
                            }
                            else
                            {
                                Assert.IsTrue(archetype->FreeChunksBySharedComponents.Contains(chunk));
                            }
                        }
                    }

                    countInArchetype += chunk->Count;

                    if (chunk->Archetype->HasChunkHeader) // Chunk entities with chunk components are not supported
                    {
                        Assert.IsFalse(chunk->Archetype->HasChunkComponents);
                    }

                    Assert.AreEqual(chunk->Archetype->HasChunkComponents, chunk->metaChunkEntity != Entity.Null);
                    if (chunk->metaChunkEntity != Entity.Null)
                    {
                        var chunkHeaderTypeIndex = TypeManager.GetTypeIndex <ChunkHeader>();
                        AssertEntitiesExist(&chunk->metaChunkEntity, 1);
                        AssertEntityHasComponent(chunk->metaChunkEntity, chunkHeaderTypeIndex);
                        var chunkHeader =
                            *(ChunkHeader *)GetComponentDataWithTypeRO(chunk->metaChunkEntity,
                                                                       chunkHeaderTypeIndex);
                        Assert.IsTrue(chunk == chunkHeader.ArchetypeChunk.m_Chunk);
                        var metaChunk = GetChunk(chunk->metaChunkEntity);
                        Assert.IsTrue(metaChunk->Archetype == chunk->Archetype->MetaChunkArchetype);
                    }

                    for (int iType = managedTypeBegin; iType < managedTypeEnd; ++iType)
                    {
                        var managedIndicesInChunk = (int *)(chunk->Buffer + archetype->Offsets[iType]);
                        for (int ie = 0; ie < chunk->Count; ++ie)
                        {
                            var index = managedIndicesInChunk[ie];
                            if (index == 0)
                            {
                                continue;
                            }

                            Assert.IsTrue(index < m_ManagedComponentIndex, "Managed component index in chunk is out of range.");
                            Assert.IsFalse(managedComponentIndices.IsSet(index), "Managed component index is used multiple times.");
                            managedComponentIndices.Set(index, true);
                        }
                    }
                }

                Assert.AreEqual(countInArchetype, archetype->EntityCount);

                entityCountByArchetype += countInArchetype;
            }

            for (int i = 0; i < m_ManagedComponentIndex; ++i)
            {
                Assert.AreEqual(managedComponentData[i] != null, managedComponentIndices.IsSet(i));
            }

            var freeManagedIndices = (int *)m_ManagedComponentFreeIndex.Ptr;
            var freeManagedCount   = m_ManagedComponentFreeIndex.Length / sizeof(int);

            for (int i = 0; i < freeManagedCount; ++i)
            {
                var index = freeManagedIndices[i];
                Assert.IsTrue(0 < index && index < m_ManagedComponentIndex, "Managed component index in free list is out of range.");
                Assert.IsFalse(managedComponentIndices.IsSet(index), "Managed component was marked as free but is used in chunk.");
                managedComponentIndices.Set(index, true);
            }

            Assert.IsTrue(m_ManagedComponentIndex - 1 == 0 || managedComponentIndices.TestAll(1, m_ManagedComponentIndex - 1), "Managed component index has leaked.");
            managedComponentIndices.Dispose();

            // Iterate by free list
            Assert.IsTrue(m_EntityInChunkByEntity[m_NextFreeEntityIndex].Chunk == null);

            var entityCountByFreeList = EntitiesCapacity;
            int freeIndex             = m_NextFreeEntityIndex;

            while (freeIndex != -1)
            {
                Assert.IsTrue(m_EntityInChunkByEntity[freeIndex].Chunk == null);
                Assert.IsTrue(freeIndex < EntitiesCapacity);

                freeIndex = m_EntityInChunkByEntity[freeIndex].IndexInChunk;

                entityCountByFreeList--;
            }

            // iterate by entities
            var entityCountByEntities = 0;
            var entityType            = TypeManager.GetTypeIndex <Entity>();

            for (var i = 0; i != EntitiesCapacity; i++)
            {
                var chunk = m_EntityInChunkByEntity[i].Chunk;
                if (chunk == null)
                {
                    continue;
                }

                entityCountByEntities++;
                var archetype = m_ArchetypeByEntity[i];
                Assert.AreEqual((IntPtr)archetype, (IntPtr)chunk->Archetype);
                Assert.AreEqual(entityType, archetype->Types[0].TypeIndex);
                Assert.IsTrue(m_EntityInChunkByEntity[i].IndexInChunk < m_EntityInChunkByEntity[i].Chunk->Count);
                var entity = *(Entity *)ChunkDataUtility.GetComponentDataRO(m_EntityInChunkByEntity[i].Chunk,
                                                                            m_EntityInChunkByEntity[i].IndexInChunk, 0);
                Assert.AreEqual(i, entity.Index);
                Assert.AreEqual(m_VersionByEntity[i], entity.Version);

                Assert.IsTrue(Exists(entity));
            }


            Assert.AreEqual(entityCountByEntities, entityCountByArchetype);

            // Enabling this fails SerializeEntitiesWorksWithBlobAssetReferences.
            // There is some special entity 0 usage in the serialization code.

            // @TODO: Review with simon looks like a potential leak?
            //Assert.AreEqual(entityCountByEntities, entityCountByFreeList);
        }
Beispiel #9
0
        // ----------------------------------------------------------------------------------------------------------
        // Core, self-contained functions to change chunks. No other functions should actually move data from
        // one Chunk to another, or otherwise change the structure of a Chunk after creation.
        // ----------------------------------------------------------------------------------------------------------

        /// <summary>
        /// Move subset of chunk data into another chunk.
        /// - Chunks can be of same archetype (but differ by shared component values)
        /// - Returns number moved. Caller handles if less than indicated in srcBatch.
        /// </summary>
        /// <returns></returns>
        int Move(EntityBatchInChunk srcBatch, Chunk *dstChunk)
        {
            var srcChunk      = srcBatch.Chunk;
            var srcChunkIndex = srcBatch.StartIndex;
            var srcCount      = srcBatch.Count;
            var srcArchetype  = srcChunk->Archetype;
            var dstArchetype  = dstChunk->Archetype;

            // Note (srcArchetype == dstArchetype) is valid
            // Archetypes can the the same, but chunks still differ because filter is different (e.g. shared component)

            int dstChunkIndex;
            var dstCount = AllocateIntoChunk(dstChunk, srcCount, out dstChunkIndex);

            // If can only move partial batch, move from the end so that remainder of batch isn't affected.
            srcChunkIndex = srcChunkIndex + srcCount - dstCount;

            ChunkDataUtility.Convert(srcChunk, srcChunkIndex, dstChunk, dstChunkIndex, dstCount);

            if (dstChunk->ManagedArrayIndex >= 0 && srcChunk->ManagedArrayIndex >= 0)
            {
                ManagedChangesTracker.CopyManagedObjects(srcChunk, srcChunkIndex, dstChunk, dstChunkIndex, dstCount);
            }

            var dstEntities = (Entity *)ChunkDataUtility.GetComponentDataRO(dstChunk, dstChunkIndex, 0);

            for (int i = 0; i < dstCount; i++)
            {
                var entity = dstEntities[i];

                SetArchetype(entity, dstArchetype);
                SetEntityInChunk(entity, new EntityInChunk {
                    Chunk = dstChunk, IndexInChunk = dstChunkIndex + i
                });
            }

            // Fill in moved component data from the end.
            var srcTailIndex = srcChunkIndex + dstCount;
            var srcTailCount = srcChunk->Count - srcTailIndex;
            var fillCount    = math.min(dstCount, srcTailCount);

            if (fillCount > 0)
            {
                var fillStartIndex = srcChunk->Count - fillCount;

                ChunkDataUtility.Copy(srcChunk, fillStartIndex, srcChunk, srcChunkIndex, fillCount);

                var fillEntities = (Entity *)ChunkDataUtility.GetComponentDataRO(srcChunk, srcChunkIndex, 0);
                for (int i = 0; i < fillCount; i++)
                {
                    var entity = fillEntities[i];
                    SetEntityInChunk(entity, new EntityInChunk {
                        Chunk = srcChunk, IndexInChunk = srcChunkIndex + i
                    });
                }

                if (srcChunk->ManagedArrayIndex >= 0)
                {
                    ManagedChangesTracker.CopyManagedObjects(srcChunk, fillStartIndex, srcChunk, srcChunkIndex, fillCount);
                }
            }

            if (srcChunk->ManagedArrayIndex >= 0)
            {
                ManagedChangesTracker.ClearManagedObjects(srcChunk, srcChunk->Count - dstCount, dstCount);
            }

            srcArchetype->EntityCount -= dstCount;

            dstChunk->SetAllChangeVersions(GlobalSystemVersion);
            srcChunk->SetAllChangeVersions(GlobalSystemVersion);

            ManagedChangesTracker.IncrementComponentOrderVersion(srcArchetype, srcChunk->SharedComponentValues);
            IncrementComponentTypeOrderVersion(srcArchetype);

            ManagedChangesTracker.IncrementComponentOrderVersion(dstArchetype, dstChunk->SharedComponentValues);
            IncrementComponentTypeOrderVersion(dstArchetype);

            SetChunkCount(srcChunk, srcChunk->Count - dstCount);

            // Cannot DestroyEntities unless SystemStateCleanupComplete on the entity chunk.
            if (dstChunk->Archetype->SystemStateCleanupComplete)
            {
                DestroyEntities(dstEntities, dstCount);
            }

            return(dstCount);
        }
Beispiel #10
0
        public void CheckInternalConsistency()
        {
            // Iterate by archetype
            var entityCountByArchetype = 0;

            for (var i = m_Archetypes.Length - 1; i >= 0; --i)
            {
                var archetype = m_Archetypes.Ptr[i];

                var countInArchetype = 0;
                for (var j = 0; j < archetype->Chunks.Count; ++j)
                {
                    var chunk = archetype->Chunks.p[j];
                    Assert.IsTrue(chunk->Archetype == archetype);
                    Assert.IsTrue(chunk->Capacity >= chunk->Count);
                    Assert.AreEqual(chunk->Count, archetype->Chunks.GetChunkEntityCount(j));

                    var chunkEntities = (Entity *)chunk->Buffer;
                    AssertEntitiesExist(chunkEntities, chunk->Count);

                    if (!chunk->Locked)
                    {
                        if (chunk->Count < chunk->Capacity)
                        {
                            if (archetype->NumSharedComponents == 0)
                            {
                                Assert.IsTrue(chunk->ListWithEmptySlotsIndex >= 0 && chunk->ListWithEmptySlotsIndex <
                                              archetype->ChunksWithEmptySlots.Length);
                                Assert.IsTrue(
                                    chunk == archetype->ChunksWithEmptySlots.Ptr[chunk->ListWithEmptySlotsIndex]);
                            }
                            else
                            {
                                Assert.IsTrue(archetype->FreeChunksBySharedComponents.Contains(chunk));
                            }
                        }
                    }

                    countInArchetype += chunk->Count;

                    if (chunk->Archetype->HasChunkHeader) // Chunk entities with chunk components are not supported
                    {
                        Assert.IsFalse(chunk->Archetype->HasChunkComponents);
                    }

                    Assert.AreEqual(chunk->Archetype->HasChunkComponents, chunk->metaChunkEntity != Entity.Null);
                    if (chunk->metaChunkEntity != Entity.Null)
                    {
                        var chunkHeaderTypeIndex = TypeManager.GetTypeIndex <ChunkHeader>();
                        AssertEntitiesExist(&chunk->metaChunkEntity, 1);
                        AssertEntityHasComponent(chunk->metaChunkEntity, chunkHeaderTypeIndex);
                        var chunkHeader =
                            *(ChunkHeader *)GetComponentDataWithTypeRO(chunk->metaChunkEntity,
                                                                       chunkHeaderTypeIndex);
                        Assert.IsTrue(chunk == chunkHeader.ArchetypeChunk.m_Chunk);
                        var metaChunk = GetChunk(chunk->metaChunkEntity);
                        Assert.IsTrue(metaChunk->Archetype == chunk->Archetype->MetaChunkArchetype);
                    }
                }

                Assert.AreEqual(countInArchetype, archetype->EntityCount);

                entityCountByArchetype += countInArchetype;
            }

            // Iterate by free list
            Assert.IsTrue(m_EntityInChunkByEntity[m_NextFreeEntityIndex].Chunk == null);

            var entityCountByFreeList = EntitiesCapacity;
            int freeIndex             = m_NextFreeEntityIndex;

            while (freeIndex != -1)
            {
                Assert.IsTrue(m_EntityInChunkByEntity[freeIndex].Chunk == null);
                Assert.IsTrue(freeIndex < EntitiesCapacity);

                freeIndex = m_EntityInChunkByEntity[freeIndex].IndexInChunk;

                entityCountByFreeList--;
            }


            // iterate by entities
            var entityCountByEntities = 0;
            var entityType            = TypeManager.GetTypeIndex <Entity>();

            for (var i = 0; i != EntitiesCapacity; i++)
            {
                var chunk = m_EntityInChunkByEntity[i].Chunk;
                if (chunk == null)
                {
                    continue;
                }

                entityCountByEntities++;
                var archetype = m_ArchetypeByEntity[i];
                Assert.AreEqual((IntPtr)archetype, (IntPtr)chunk->Archetype);
                Assert.AreEqual(entityType, archetype->Types[0].TypeIndex);
                Assert.IsTrue(m_EntityInChunkByEntity[i].IndexInChunk < m_EntityInChunkByEntity[i].Chunk->Count);
                var entity = *(Entity *)ChunkDataUtility.GetComponentDataRO(m_EntityInChunkByEntity[i].Chunk,
                                                                            m_EntityInChunkByEntity[i].IndexInChunk, 0);
                Assert.AreEqual(i, entity.Index);
                Assert.AreEqual(m_VersionByEntity[i], entity.Version);

                Assert.IsTrue(Exists(entity));
            }


            Assert.AreEqual(entityCountByEntities, entityCountByArchetype);

            // Enabling this fails SerializeEntitiesWorksWithBlobAssetReferences.
            // There is some special entity 0 usage in the serialization code.

            // @TODO: Review with simon looks like a potential leak?
            //Assert.AreEqual(entityCountByEntities, entityCountByFreeList);
        }