// ----------------------------------------------------------------------------------------------------------
        // INTERNAL
        // ----------------------------------------------------------------------------------------------------------

        void MoveEntitiesFrom(out NativeArray <Entity> output, EntityManager srcEntities,
                              NativeArray <ArchetypeChunk> chunks, NativeArray <EntityRemapUtility.EntityRemapInfo> entityRemapping)
        {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
            if (srcEntities == this)
            {
                throw new ArgumentException("srcEntities must not be the same as this EntityManager.");
            }
            for (int i = 0; i < chunks.Length; ++i)
            {
                if (chunks[i].m_Chunk->Archetype->HasChunkHeader)
                {
                    throw new ArgumentException(
                              "MoveEntitiesFrom can not move chunks that contain ChunkHeader components.");
                }
            }
#endif

            BeforeStructuralChange();
            srcEntities.BeforeStructuralChange();
            var archetypeChanges = EntityComponentStore->BeginArchetypeChangeTracking();

            EntityManagerMoveEntitiesUtility.MoveChunks(chunks, entityRemapping,
                                                        srcEntities.EntityComponentStore, srcEntities.ManagedComponentStore,
                                                        EntityComponentStore, ManagedComponentStore);

            var changedArchetypes = EntityComponentStore->EndArchetypeChangeTracking(archetypeChanges);
            EntityGroupManager.AddAdditionalArchetypes(changedArchetypes);

            EntityRemapUtility.GetTargets(out output, entityRemapping);
        }
        // ----------------------------------------------------------------------------------------------------------
        // PUBLIC
        // ----------------------------------------------------------------------------------------------------------

        /// <summary>
        /// Moves all entities managed by the specified EntityManager to the <see cref="World"/> of this EntityManager and fills
        /// an array with their <see cref="Entity"/> objects.
        /// </summary>
        /// <remarks>
        /// After the move, the entities are managed by this EntityManager. Use the `output` array to make post-move
        /// changes to the transferred entities.
        ///
        /// Each world has one EntityManager, which manages all the entities in that world. This function
        /// allows you to transfer entities from one World to another.
        ///
        /// **Important:** This function creates a sync point, which means that the EntityManager waits for all
        /// currently running Jobs to complete before moving the entities and no additional Jobs can start before
        /// the function is finished. A sync point can cause a drop in performance because the ECS framework may not
        /// be able to make use of the processing power of all available cores.
        /// </remarks>
        /// <param name="output">An array to receive the Entity objects of the transferred entities.</param>
        /// <param name="srcEntities">The EntityManager whose entities are appropriated.</param>
        /// <param name="entityRemapping">A set of entity transformations to make during the transfer.</param>
        /// <exception cref="ArgumentException"></exception>
        public void MoveEntitiesFrom(out NativeArray <Entity> output, EntityManager srcEntities,
                                     NativeArray <EntityRemapUtility.EntityRemapInfo> entityRemapping)
        {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
            if (srcEntities == this)
            {
                throw new ArgumentException("srcEntities must not be the same as this EntityManager.");
            }

            if (!srcEntities.m_ManagedComponentStore.AllSharedComponentReferencesAreFromChunks(srcEntities
                                                                                               .EntityComponentStore))
            {
                throw new ArgumentException(
                          "EntityManager.MoveEntitiesFrom failed - All ISharedComponentData references must be from EntityManager. (For example EntityQuery.SetFilter with a shared component type is not allowed during EntityManager.MoveEntitiesFrom)");
            }
#endif

            BeforeStructuralChange();
            srcEntities.BeforeStructuralChange();
            var archetypeChanges = EntityComponentStore->BeginArchetypeChangeTracking();

            EntityManagerMoveEntitiesUtility.MoveChunks(entityRemapping,
                                                        srcEntities.EntityComponentStore, srcEntities.ManagedComponentStore,
                                                        EntityComponentStore, ManagedComponentStore);

            EntityRemapUtility.GetTargets(out output, entityRemapping);

            var changedArchetypes = EntityComponentStore->EndArchetypeChangeTracking(archetypeChanges);
            EntityGroupManager.AddAdditionalArchetypes(changedArchetypes);

            //@TODO: Need to increment the component versions based the moved chunks...
        }
Пример #3
0
        public static void Initialize()
        {
            if (s_Types != null)
            {
                return;
            }

            ObjectOffset = UnsafeUtility.SizeOf <ObjectOffsetType>();

#if !UNITY_CSHARP_TINY
            s_CreateTypeLock     = new SpinLock();
            s_ManagedTypeToIndex = new Dictionary <Type, int>(1000);
#endif
            s_Types = new TypeInfo[MaximumTypesCount];

            #if !UNITY_CSHARP_TINY
            s_StableTypeHashToTypeIndex = new Dictionary <ulong, int>();
            #endif

            s_Count = 0;

            #if !UNITY_CSHARP_TINY
            s_Types[s_Count++] = new TypeInfo(null, 0, 0, TypeCategory.ComponentData, FastEquality.TypeInfo.Null, null, null, 0, -1, 0, 1, 0, null, 0, int.MaxValue);

            // This must always be first so that Entity is always index 0 in the archetype
            AddTypeInfoToTables(new TypeInfo(typeof(Entity), 1, sizeof(Entity), TypeCategory.EntityData,
                                             FastEquality.CreateTypeInfo <Entity>(), EntityRemapUtility.CalculateEntityOffsets <Entity>(), null, 0, -1, sizeof(Entity), UnsafeUtility.AlignOf <Entity>(), CalculateStableTypeHash(typeof(Entity)), null, 0, int.MaxValue));

            InitializeAllComponentTypes();
            #else
            StaticTypeRegistry.StaticTypeRegistry.RegisterStaticTypes();
            #endif
        }
Пример #4
0
        internal static object CloneAndPatchManagedComponent(object obj, EntityRemapUtility.EntityRemapInfo *remapping)
        {
            var clone = CloneManagedComponent(obj);

            EntityRemapUtility.PatchEntityInBoxedType(clone, remapping);
            return(clone);
        }
Пример #5
0
            public void Execute(int index)
            {
                Chunk *    chunk        = remapChunks[index].chunk;
                Archetype *dstArchetype = remapChunks[index].dstArchetype;

                dstEntityComponentStore->RemapChunk(dstArchetype, chunk, 0, chunk->Count, ref entityRemapping);
                EntityRemapUtility.PatchEntities(dstArchetype->ScalarEntityPatches + 1,
                                                 dstArchetype->ScalarEntityPatchCount - 1, dstArchetype->BufferEntityPatches,
                                                 dstArchetype->BufferEntityPatchCount, chunk->Buffer, chunk->Count, ref entityRemapping);

                // Fix up chunk pointers in ChunkHeaders
                if (dstArchetype->HasChunkComponents)
                {
                    var metaArchetype    = dstArchetype->MetaChunkArchetype;
                    var indexInTypeArray = ChunkDataUtility.GetIndexInTypeArray(metaArchetype, chunkHeaderType);
                    var offset           = metaArchetype->Offsets[indexInTypeArray];
                    var sizeOf           = sizeof(ChunkHeader);

                    // Set chunk header without bumping change versions since they are zeroed when processing meta chunk
                    // modifying them here would be a race condition
                    var metaChunkEntity   = chunk->metaChunkEntity;
                    var metaEntityInChunk = dstEntityComponentStore->GetEntityInChunk(metaChunkEntity);
                    var chunkHeader       = (ChunkHeader *)(metaEntityInChunk.Chunk->Buffer + (offset + sizeOf * metaEntityInChunk.IndexInChunk));
                    chunkHeader->ArchetypeChunk = new ArchetypeChunk(chunk, dstEntityComponentStore);
                }
            }
Пример #6
0
        /// <summary>
        /// Invoked for each <see cref="Entity"/> member encountered.
        /// </summary>
        /// <param name="property">The property being visited.</param>
        /// <param name="container">The source container.</param>
        /// <param name="value">The entity value.</param>
        /// <typeparam name="TContainer">The container type.</typeparam>
        /// <returns>The status of the adapter visit.</returns>
        VisitStatus IVisit <Entity> .Visit <TContainer>(Property <TContainer, Entity> property, ref TContainer container, ref Entity value)
        {
            value = null != m_Info
                ? EntityRemapUtility.RemapEntity(m_Info, value)
                : EntityRemapUtility.RemapEntityForPrefab(m_PrefabSrc, m_PrefabDst, m_PrefabCount, value);

            return(VisitStatus.Stop);
        }
Пример #7
0
 /// <summary>
 /// Moves all entities managed by the specified EntityManager to the <see cref="World"/> of this EntityManager and fills
 /// an array with their Entity objects.
 /// </summary>
 /// <remarks>
 /// After the move, the entities are managed by this EntityManager. Use the `output` array to make post-move
 /// changes to the transferred entities.
 ///
 /// Each world has one EntityManager, which manages all the entities in that world. This function
 /// allows you to transfer entities from one World to another.
 ///
 /// **Important:** This function creates a sync point, which means that the EntityManager waits for all
 /// currently running Jobs to complete before moving the entities and no additional Jobs can start before
 /// the function is finished. A sync point can cause a drop in performance because the ECS framework may not
 /// be able to make use of the processing power of all available cores.
 /// </remarks>
 /// <param name="output">An array to receive the Entity objects of the transferred entities.</param>
 /// <param name="srcEntities">The EntityManager whose entities are appropriated.</param>
 public void MoveEntitiesFrom(out NativeArray <Entity> output, EntityManager srcEntities)
 {
     using (var entityRemapping = srcEntities.CreateEntityRemapArray(Allocator.TempJob))
     {
         MoveEntitiesFromInternalAll(srcEntities, entityRemapping);
         EntityRemapUtility.GetTargets(out output, entityRemapping);
     }
 }
Пример #8
0
            public void Execute(int index)
            {
                Chunk *    chunk        = remapChunks[index].chunk;
                Archetype *dstArchetype = remapChunks[index].dstArchetype;

                dstEntityComponentStore->RemapChunk(dstArchetype, chunk, 0, chunk->Count, ref entityRemapping);
                EntityRemapUtility.PatchEntities(dstArchetype->ScalarEntityPatches + 1,
                                                 dstArchetype->ScalarEntityPatchCount - 1, dstArchetype->BufferEntityPatches,
                                                 dstArchetype->BufferEntityPatchCount, chunk->Buffer, chunk->Count, ref entityRemapping);
            }
            public void Execute(int index)
            {
                Chunk *    chunk        = remapChunks[index].chunk;
                Archetype *dstArchetype = remapChunks[index].dstArchetype;

                dstEntityComponentStore->RemapChunk(dstArchetype, chunk, 0, chunk->Count, ref entityRemapping);
                EntityRemapUtility.PatchEntities(dstArchetype->ScalarEntityPatches + 1,
                                                 dstArchetype->ScalarEntityPatchCount - 1, dstArchetype->BufferEntityPatches,
                                                 dstArchetype->BufferEntityPatchCount, chunk->Buffer, chunk->Count, ref entityRemapping);
                chunk->Archetype  = dstArchetype;
                chunk->ListIndex += dstArchetype->Chunks.Count;
                chunk->ListWithEmptySlotsIndex += dstArchetype->ChunksWithEmptySlots.Length;
            }
Пример #10
0
            public void Execute(int index)
            {
                Chunk *    chunk        = remapChunks[index].chunk;
                Archetype *dstArchetype = remapChunks[index].dstArchetype;

                dstEntityDataManager->RemapChunk(dstArchetype, chunk, 0, chunk->Count, ref entityRemapping);
                EntityRemapUtility.PatchEntities(dstArchetype->ScalarEntityPatches + 1, dstArchetype->ScalarEntityPatchCount - 1, dstArchetype->BufferEntityPatches, dstArchetype->BufferEntityPatchCount, chunk->Buffer, chunk->Count, ref entityRemapping);
                chunk->Archetype = dstArchetype;

                for (int i = 0; i < dstArchetype->NumSharedComponents; ++i)
                {
                    var componentIndex = chunk->SharedComponentValueArray[i];
                    componentIndex = remapShared[componentIndex];
                    chunk->SharedComponentValueArray[i] = componentIndex;
                }
            }
Пример #11
0
        void PatchEntitiesForPrefab(int *managedComponents, int numManagedComponents, int allocatedCount, int remappingCount, Entity *remapSrc, Entity *remapDst)
        {
#if !NET_DOTS
            for (int i = 0; i < allocatedCount; ++i)
            {
                for (int c = 0; c < numManagedComponents; c++)
                {
                    var managedComponentIndex = managedComponents[c];
                    if (managedComponentIndex != 0)
                    {
                        var obj = m_ManagedComponentData[managedComponentIndex];
                        EntityRemapUtility.PatchEntityForPrefabInBoxedType(obj, remapSrc, remapDst, remappingCount);
                    }
                }
                managedComponents += numManagedComponents;
                remapDst          += remappingCount;
            }
#endif
        }
Пример #12
0
        public void PatchEntities(ManagedComponentStore managedComponentStore, Archetype *archetype, Chunk *chunk, int entityCount,
                                  EntityRemapUtility.EntityRemapInfo *remapping)
        {
#if !NET_DOTS
            var managedPatches    = archetype->ManagedEntityPatches;
            var managedPatchCount = archetype->ManagedEntityPatchCount;

            // Patch managed components with entity references.
            for (int p = 0; p < managedPatchCount; p++)
            {
                var componentType = managedPatches[p].Type;

                for (int i = 0; i != entityCount; i++)
                {
                    var obj = managedComponentStore.GetManagedObject(chunk, componentType, i);
                    EntityRemapUtility.PatchEntityInBoxedType(obj, remapping);
                }
            }
#endif
        }
Пример #13
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
        }
Пример #14
0
        public void RemapChunk(Archetype *arch, Chunk *chunk, int baseIndex, int count, ref NativeArray <EntityRemapUtility.EntityRemapInfo> entityRemapping)
        {
            Assert.AreEqual(chunk->Archetype->Offsets[0], 0);
            Assert.AreEqual(chunk->Archetype->SizeOfs[0], sizeof(Entity));

            var entityInChunkStart = (Entity *)(chunk->Buffer) + baseIndex;

            for (var i = 0; i != count; i++)
            {
                var entityInChunk = entityInChunkStart + i;
                var target        = EntityRemapUtility.RemapEntity(ref entityRemapping, *entityInChunk);
                var entity        = m_Entities + target.Index;
                Assert.AreEqual(entity->Version, target.Version);

                entityInChunk->Index   = target.Index;
                entityInChunk->Version = entity->Version;
                entity->IndexInChunk   = baseIndex + i;
                entity->Archetype      = arch;
                entity->Chunk          = chunk;
            }
        }
        public void PatchEntitiesForPrefab(ManagedComponentStore managedComponentStore, Archetype *archetype, Chunk *chunk, int indexInChunk, int entityCount,
                                           EntityRemapUtility.SparseEntityRemapInfo *remapping, int remappingCount, Allocator allocator)
        {
#if !NET_DOTS
            var managedPatches    = archetype->ManagedEntityPatches;
            var managedPatchCount = archetype->ManagedEntityPatchCount;

            // Patch managed components with entity references.
            for (int p = 0; p < managedPatchCount; p++)
            {
                var componentType = managedPatches[p].Type;

                for (int e = 0; e != entityCount; e++)
                {
                    var obj = managedComponentStore.GetManagedObject(chunk, componentType, e + indexInChunk);

                    EntityRemapUtility.PatchEntityForPrefabInBoxedType(obj, remapping + e * remappingCount, remappingCount);
                }
            }
            UnsafeUtility.Free(remapping, allocator);
#endif
        }
Пример #16
0
        public void AllocateEntitiesForRemapping(EntityDataManager *srcEntityDataManager, ref NativeArray <EntityRemapUtility.EntityRemapInfo> entityRemapping)
        {
            var srcEntityData = srcEntityDataManager->m_Entities;
            var count         = srcEntityDataManager->m_EntitiesCapacity;

            for (var i = 0; i != count; i++)
            {
                if (srcEntityData[i].Chunk != null)
                {
                    var entity = m_Entities + m_EntitiesFreeIndex;
                    if (entity->IndexInChunk == -1)
                    {
                        IncreaseCapacity();
                        entity = m_Entities + m_EntitiesFreeIndex;
                    }
                    EntityRemapUtility.AddEntityRemapping(ref entityRemapping, new Entity {
                        Version = srcEntityData[i].Version, Index = i
                    }, new Entity {
                        Version = entity->Version, Index = m_EntitiesFreeIndex
                    });
                    m_EntitiesFreeIndex = entity->IndexInChunk;
                }
            }
        }
Пример #17
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();
        }
Пример #18
0
        internal void MoveChunksFromFiltered(
            NativeArray <ArchetypeChunk> chunks,
            NativeArray <EntityRemapUtility.EntityRemapInfo> entityRemapping,
            EntityComponentStore *srcEntityComponentStore,
            ManagedComponentStore srcManagedComponentStore)
        {
            var access = GetCheckedEntityDataAccess();
            var ecs    = access->EntityComponentStore;
            var mcs    = access->ManagedComponentStore;

            new MoveChunksJob
            {
                srcEntityComponentStore = srcEntityComponentStore,
                dstEntityComponentStore = ecs,
                entityRemapping         = entityRemapping,
                chunks = chunks
            }.Run();

            int chunkCount  = chunks.Length;
            var remapChunks = new NativeArray <RemapChunk>(chunkCount, Allocator.TempJob);

            Archetype *previousSrcArchetypee = null;
            Archetype *dstArchetype          = null;
            int        managedComponentCount = 0;

            NativeList <IntPtr> managedChunks = new NativeList <IntPtr>(0, Allocator.TempJob);

            for (int i = 0; i < chunkCount; ++i)
            {
                var chunk     = chunks[i].m_Chunk;
                var archetype = chunk->Archetype;

                // Move Chunk World. ChangeVersion:Yes OrderVersion:Yes
                if (previousSrcArchetypee != archetype)
                {
                    dstArchetype = ecs->GetOrCreateArchetype(archetype->Types, archetype->TypesCount);
                }

                remapChunks[i] = new RemapChunk {
                    chunk = chunk, dstArchetype = dstArchetype
                };

                if (dstArchetype->NumManagedComponents > 0)
                {
                    managedComponentCount += chunk->Count * dstArchetype->NumManagedComponents;
                    managedChunks.Add((IntPtr)chunk);
                }

                if (archetype->MetaChunkArchetype != null)
                {
                    Entity srcEntity = chunk->metaChunkEntity;
                    Entity dstEntity;

                    ecs->CreateEntities(dstArchetype->MetaChunkArchetype, &dstEntity, 1);

                    var srcEntityInChunk = srcEntityComponentStore->GetEntityInChunk(srcEntity);
                    var dstEntityInChunk = ecs->GetEntityInChunk(dstEntity);

                    ChunkDataUtility.SwapComponents(srcEntityInChunk.Chunk, srcEntityInChunk.IndexInChunk, dstEntityInChunk.Chunk, dstEntityInChunk.IndexInChunk, 1,
                                                    srcEntityComponentStore->GlobalSystemVersion, ecs->GlobalSystemVersion);
                    EntityRemapUtility.AddEntityRemapping(ref entityRemapping, srcEntity, dstEntity);

                    srcEntityComponentStore->DestroyEntities(&srcEntity, 1);
                }
            }

            NativeArray <int> srcManagedIndices = default;
            NativeArray <int> dstManagedIndices = default;
            int nonNullManagedComponentCount    = 0;

            if (managedComponentCount > 0)
            {
                srcManagedIndices = new NativeArray <int>(managedComponentCount, Allocator.TempJob);
                dstManagedIndices = new NativeArray <int>(managedComponentCount, Allocator.TempJob);
                new
                GatherManagedComponentIndicesInChunkJob()
                {
                    SrcEntityComponentStore = srcEntityComponentStore,
                    DstEntityComponentStore = ecs,
                    SrcManagedIndices       = srcManagedIndices,
                    DstManagedIndices       = dstManagedIndices,
                    Chunks       = managedChunks,
                    NonNullCount = &nonNullManagedComponentCount
                }.Run();
            }

            mcs.Playback(ref ecs->ManagedChangesTracker);
            srcManagedComponentStore.Playback(ref srcEntityComponentStore->ManagedChangesTracker);

            k_ProfileMoveSharedComponents.Begin();
            var remapShared = mcs.MoveSharedComponents(srcManagedComponentStore, chunks, Allocator.TempJob);

            k_ProfileMoveSharedComponents.End();

            if (managedComponentCount > 0)
            {
                k_ProfileMoveManagedComponents.Begin();
                mcs.MoveManagedComponentsFromDifferentWorld(srcManagedIndices, dstManagedIndices, nonNullManagedComponentCount, srcManagedComponentStore);
                srcEntityComponentStore->m_ManagedComponentFreeIndex.Add(srcManagedIndices.GetUnsafeReadOnlyPtr(), sizeof(int) * srcManagedIndices.Length);
                k_ProfileMoveManagedComponents.End();
            }

            new ChunkPatchEntities
            {
                RemapChunks          = remapChunks,
                EntityRemapping      = entityRemapping,
                EntityComponentStore = ecs
            }.Run();

            var remapChunksJob = new RemapChunksFilteredJob
            {
                dstEntityComponentStore = ecs,
                remapChunks             = remapChunks,
                entityRemapping         = entityRemapping,
                chunkHeaderType         = TypeManager.GetTypeIndex <ChunkHeader>()
            }.Schedule(remapChunks.Length, 1);

            var moveChunksBetweenArchetypeJob = new MoveFilteredChunksBetweenArchetypexJob
            {
                RemapChunks         = remapChunks,
                RemapShared         = remapShared,
                GlobalSystemVersion = ecs->GlobalSystemVersion
            }.Schedule(remapChunksJob);

            moveChunksBetweenArchetypeJob.Complete();

            mcs.Playback(ref ecs->ManagedChangesTracker);

            if (managedComponentCount > 0)
            {
                srcManagedIndices.Dispose();
                dstManagedIndices.Dispose();
            }
            managedChunks.Dispose();
            remapShared.Dispose();
            remapChunks.Dispose();
        }
        void InstantiateEntitiesGroup(Entity *srcEntities, int srcEntityCount,
                                      Entity *outputRootEntities, int instanceCount)
        {
            int totalCount = srcEntityCount * instanceCount;

            var tempAllocSize = sizeof(EntityRemapUtility.SparseEntityRemapInfo) * totalCount +
                                sizeof(InstantiateRemapChunk) * totalCount + sizeof(Entity) * instanceCount;
            byte *    allocation;
            const int kMaxStackAllocSize = 16 * 1024;

            if (tempAllocSize > kMaxStackAllocSize)
            {
                allocation = (byte *)UnsafeUtility.Malloc(tempAllocSize, 16, Allocator.Temp);
            }
            else
            {
                var temp = stackalloc byte[tempAllocSize];

                allocation = temp;
            }

            var entityRemap    = (EntityRemapUtility.SparseEntityRemapInfo *)allocation;
            var remapChunks    = (InstantiateRemapChunk *)(entityRemap + totalCount);
            var outputEntities = (Entity *)(remapChunks + totalCount);

            var remapChunksCount = 0;

            for (int i = 0; i != srcEntityCount; i++)
            {
                var srcEntity = srcEntities[i];

                remapChunksCount = InstantiateEntitiesOne(srcEntity,
                                                          outputEntities, instanceCount, remapChunks, remapChunksCount);

                for (int r = 0; r != instanceCount; r++)
                {
                    var ptr = entityRemap + (r * srcEntityCount + i);
                    ptr->Src    = srcEntity;
                    ptr->Target = outputEntities[r];
                }

                if (i == 0)
                {
                    for (int r = 0; r != instanceCount; r++)
                    {
                        outputRootEntities[r] = outputEntities[r];
                    }
                }
            }


            for (int i = 0; i != remapChunksCount; i++)
            {
                var chunk              = remapChunks[i].Chunk;
                var dstArchetype       = chunk->Archetype;
                var allocatedCount     = remapChunks[i].AllocatedCount;
                var indexInChunk       = remapChunks[i].IndexInChunk;
                var instanceBeginIndex = remapChunks[i].InstanceBeginIndex;

                var localRemap = entityRemap + instanceBeginIndex * srcEntityCount;

                EntityRemapUtility.PatchEntitiesForPrefab(dstArchetype->ScalarEntityPatches + 1, dstArchetype->ScalarEntityPatchCount - 1,
                                                          dstArchetype->BufferEntityPatches, dstArchetype->BufferEntityPatchCount,
                                                          chunk->Buffer, indexInChunk, allocatedCount, localRemap, srcEntityCount);

                ManagedChangesTracker.PatchEntitiesForPrefab(dstArchetype, chunk, indexInChunk, allocatedCount, localRemap, srcEntityCount, Allocator.Temp);
            }

            if (tempAllocSize > kMaxStackAllocSize)
            {
                UnsafeUtility.Free(allocation, Allocator.Temp);
            }
        }
Пример #20
0
        private static ComponentType BuildComponentType(Type type)
        {
            var          componentSize = 0;
            TypeCategory category;

            FastEquality.Layout[] fastEqualityLayout = null;
            EntityOffsetInfo[]    entityOffsets      = null;
            var memoryOrdering = CalculateMemoryOrdering(type);

            if (typeof(IComponentData).IsAssignableFrom(type))
            {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                if (type.IsClass)
                {
                    throw new ArgumentException($"{type} is an IComponentData, and thus must be a struct.");
                }
                if (!UnsafeUtility.IsBlittable(type))
                {
                    throw new ArgumentException(
                              $"{type} is an IComponentData, and thus must be blittable (No managed object is allowed on the struct).");
                }
#endif

                category           = TypeCategory.ComponentData;
                componentSize      = UnsafeUtility.SizeOf(type);
                fastEqualityLayout = FastEquality.CreateLayout(type);
                entityOffsets      = EntityRemapUtility.CalculateEntityOffsets(type);
            }
            else if (typeof(ISharedComponentData).IsAssignableFrom(type))
            {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                if (type.IsClass)
                {
                    throw new ArgumentException($"{type} is an ISharedComponentData, and thus must be a struct.");
                }
#endif

                category           = TypeCategory.ISharedComponentData;
                fastEqualityLayout = FastEquality.CreateLayout(type);
            }
            else if (type.IsValueType)
            {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                if (!UnsafeUtility.IsBlittable(type))
                {
                    throw new ArgumentException($"{type} is used for FixedArrays, and thus must be blittable.");
                }
#endif
                category      = TypeCategory.OtherValueType;
                componentSize = UnsafeUtility.SizeOf(type);
            }
            else if (type.IsClass)
            {
                category = TypeCategory.Class;
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                if (type.FullName == "Unity.Entities.GameObjectEntity")
                {
                    throw new ArgumentException(
                              "GameObjectEntity can not be used from EntityManager. The component is ignored when creating entities for a GameObject.");
                }
#endif
            }
#if ENABLE_UNITY_COLLECTIONS_CHECKS
            else
            {
                throw new ArgumentException($"'{type}' is not a valid component");
            }
Пример #21
0
        public static TypeInfo BuildComponentType(Type type)
        {
            TypeCategory componentData;
            int          size = 0;

            FastEquality.TypeInfo @null         = FastEquality.TypeInfo.Null;
            EntityOffsetInfo[]    entityOffsets = null;
            int   bufferCapacity = -1;
            ulong memoryOrdering = CalculateMemoryOrdering(type);
            int   num4           = 0;

            if (type.IsInterface)
            {
                throw new ArgumentException($"{type} is an interface. It must be a concrete type.");
            }
            if (typeof(IComponentData).IsAssignableFrom(type))
            {
                if (!type.IsValueType)
                {
                    throw new ArgumentException($"{type} is an IComponentData, and thus must be a struct.");
                }
                if (!UnsafeUtility.IsBlittable(type))
                {
                    throw new ArgumentException($"{type} is an IComponentData, and thus must be blittable (No managed object is allowed on the struct).");
                }
                componentData = TypeCategory.ComponentData;
                if (IsZeroSizeStruct(type))
                {
                    size = 0;
                }
                else
                {
                    size = UnsafeUtility.SizeOf(type);
                }
                @null         = FastEquality.CreateTypeInfo(type);
                entityOffsets = EntityRemapUtility.CalculateEntityOffsets(type);
            }
            else if (typeof(IBufferElementData).IsAssignableFrom(type))
            {
                if (!type.IsValueType)
                {
                    throw new ArgumentException($"{type} is an IBufferElementData, and thus must be a struct.");
                }
                if (!UnsafeUtility.IsBlittable(type))
                {
                    throw new ArgumentException($"{type} is an IBufferElementData, and thus must be blittable (No managed object is allowed on the struct).");
                }
                componentData = TypeCategory.BufferData;
                num4          = UnsafeUtility.SizeOf(type);
                InternalBufferCapacityAttribute customAttribute = (InternalBufferCapacityAttribute)type.GetCustomAttribute(typeof(InternalBufferCapacityAttribute));
                if (customAttribute != null)
                {
                    bufferCapacity = customAttribute.Capacity;
                }
                else
                {
                    bufferCapacity = 0x80 / num4;
                }
                size          = sizeof(BufferHeader) + (bufferCapacity * num4);
                @null         = FastEquality.CreateTypeInfo(type);
                entityOffsets = EntityRemapUtility.CalculateEntityOffsets(type);
            }
            else if (typeof(ISharedComponentData).IsAssignableFrom(type))
            {
                if (!type.IsValueType)
                {
                    throw new ArgumentException($"{type} is an ISharedComponentData, and thus must be a struct.");
                }
                componentData = TypeCategory.ISharedComponentData;
                @null         = FastEquality.CreateTypeInfo(type);
            }
            else
            {
                if (!type.IsClass)
                {
                    throw new ArgumentException($"{type} is not a valid component.");
                }
                componentData = TypeCategory.Class;
                if (type.FullName == "Unity.Entities.GameObjectEntity")
                {
                    throw new ArgumentException("GameObjectEntity cannot be used from EntityManager. The component is ignored when creating entities for a GameObject.");
                }
                if (UnityEngineComponentType == null)
                {
                    throw new ArgumentException($"{type} cannot be used from EntityManager. If it inherits UnityEngine.Component, you must first register {typeof(TypeManager)}.{"UnityEngineComponentType"} or include the Unity.Entities.Hybrid assembly in your build.");
                }
                if (!UnityEngineComponentType.IsAssignableFrom(type))
                {
                    throw new ArgumentException($"{type} must inherit {UnityEngineComponentType}.");
                }
            }
            int num5 = 0;

            foreach (Type type2 in s_SingularInterfaces)
            {
                if (type2.IsAssignableFrom(type))
                {
                    num5++;
                }
            }
            if (num5 > 1)
            {
                throw new ArgumentException($"Component {type} can only implement one of IComponentData, ISharedComponentData and IBufferElementData");
            }
            return(new TypeInfo(type, size, componentData, @null, entityOffsets, memoryOrdering, bufferCapacity, (num4 > 0) ? num4 : size));
        }
Пример #22
0
 /// <summary>
 /// Moves all entities managed by the specified EntityManager to the <see cref="World"/> of this EntityManager and fills
 /// an array with their <see cref="Entity"/> objects.
 /// </summary>
 /// <remarks>
 /// After the move, the entities are managed by this EntityManager. Use the `output` array to make post-move
 /// changes to the transferred entities.
 ///
 /// Each world has one EntityManager, which manages all the entities in that world. This function
 /// allows you to transfer entities from one World to another.
 ///
 /// **Important:** This function creates a sync point, which means that the EntityManager waits for all
 /// currently running Jobs to complete before moving the entities and no additional Jobs can start before
 /// the function is finished. A sync point can cause a drop in performance because the ECS framework may not
 /// be able to make use of the processing power of all available cores.
 /// </remarks>
 /// <param name="output">An array to receive the Entity objects of the transferred entities.</param>
 /// <param name="srcEntities">The EntityManager whose entities are appropriated.</param>
 /// <param name="entityRemapping">A set of entity transformations to make during the transfer.</param>
 /// <exception cref="ArgumentException"></exception>
 public void MoveEntitiesFrom(out NativeArray <Entity> output, EntityManager srcEntities, NativeArray <EntityRemapUtility.EntityRemapInfo> entityRemapping)
 {
     MoveEntitiesFromInternalAll(srcEntities, entityRemapping);
     EntityRemapUtility.GetTargets(out output, entityRemapping);
 }
Пример #23
0
        internal void MoveChunksFrom(
            NativeArray <ArchetypeChunk> chunks,
            NativeArray <EntityRemapUtility.EntityRemapInfo> entityRemapping,
            EntityComponentStore *srcEntityComponentStore,
            ManagedComponentStore srcManagedComponentStore)
        {
            new MoveChunksJob
            {
                srcEntityComponentStore = srcEntityComponentStore,
                dstEntityComponentStore = EntityComponentStore,
                entityRemapping         = entityRemapping,
                chunks = chunks
            }.Run();

            var managedArrayChunks = new NativeList <IntPtr>(Allocator.Temp);

            int chunkCount  = chunks.Length;
            var remapChunks = new NativeArray <RemapChunk>(chunkCount, Allocator.TempJob);

            for (int i = 0; i < chunkCount; ++i)
            {
                var chunk     = chunks[i].m_Chunk;
                var archetype = chunk->Archetype;

                //TODO: this should not be done more than once for each archetype
                var dstArchetype = EntityComponentStore->GetOrCreateArchetype(archetype->Types, archetype->TypesCount);

                remapChunks[i] = new RemapChunk {
                    chunk = chunk, dstArchetype = dstArchetype
                };

                if (archetype->NumManagedArrays > 0)
                {
                    managedArrayChunks.Add((IntPtr)chunk);
                }

                if (archetype->MetaChunkArchetype != null)
                {
                    Entity srcEntity = chunk->metaChunkEntity;
                    Entity dstEntity;

                    EntityComponentStore->CreateEntities(dstArchetype->MetaChunkArchetype, &dstEntity, 1);

                    var srcEntityInChunk = srcEntityComponentStore->GetEntityInChunk(srcEntity);
                    var dstEntityInChunk = EntityComponentStore->GetEntityInChunk(dstEntity);

                    ChunkDataUtility.SwapComponents(srcEntityInChunk.Chunk, srcEntityInChunk.IndexInChunk, dstEntityInChunk.Chunk, dstEntityInChunk.IndexInChunk, 1,
                                                    srcEntityComponentStore->GlobalSystemVersion, EntityComponentStore->GlobalSystemVersion);
                    EntityRemapUtility.AddEntityRemapping(ref entityRemapping, srcEntity, dstEntity);

                    srcEntityComponentStore->DestroyEntities(&srcEntity, 1);
                }
            }

            var managedArrayDstIndices = new NativeArray <int>(managedArrayChunks.Length, Allocator.TempJob);
            var managedArraySrcIndices = new NativeArray <int>(managedArrayChunks.Length, Allocator.TempJob);

            EntityComponentStore->ReserveManagedObjectArrays(managedArrayDstIndices);

            var remapManaged = new RemapManagedArraysJob
            {
                chunks     = managedArrayChunks,
                dstIndices = managedArrayDstIndices,
                srcIndices = managedArraySrcIndices,
            }.Schedule(managedArrayChunks.Length, 64);

            ManagedComponentStore.Playback(ref EntityComponentStore->ManagedChangesTracker);
            srcManagedComponentStore.Playback(ref srcEntityComponentStore->ManagedChangesTracker);

            k_ProfileMoveObjectComponents.Begin();
            remapManaged.Complete();
            m_ManagedComponentStore.MoveManagedObjectArrays(managedArraySrcIndices, managedArrayDstIndices, srcManagedComponentStore);
            k_ProfileMoveObjectComponents.End();

            managedArrayDstIndices.Dispose();
            managedArraySrcIndices.Dispose();
            managedArrayChunks.Dispose();

            k_ProfileMoveSharedComponents.Begin();
            var remapShared =
                ManagedComponentStore.MoveSharedComponents(srcManagedComponentStore, chunks, Allocator.TempJob);

            k_ProfileMoveSharedComponents.End();

            new ChunkPatchEntities
            {
                RemapChunks          = remapChunks,
                EntityRemapping      = entityRemapping,
                EntityComponentStore = EntityComponentStore
            }.Run();

            var remapChunksJob = new RemapChunksJob
            {
                dstEntityComponentStore = EntityComponentStore,
                remapChunks             = remapChunks,
                entityRemapping         = entityRemapping
            }.Schedule(remapChunks.Length, 1);

            var moveChunksBetweenArchetypeJob = new MoveChunksBetweenArchetypeJob
            {
                remapChunks         = remapChunks,
                remapShared         = remapShared,
                globalSystemVersion = EntityComponentStore->GlobalSystemVersion
            }.Schedule(remapChunksJob);

            moveChunksBetweenArchetypeJob.Complete();

            ManagedComponentStore.Playback(ref EntityComponentStore->ManagedChangesTracker);

            remapShared.Dispose();
            remapChunks.Dispose();
        }
Пример #24
0
        internal static TypeInfo BuildComponentType(Type type, int *writeGroups, int writeGroupCount)
        {
            var          componentSize = 0;
            TypeCategory category;
            var          typeInfo = FastEquality.TypeInfo.Null;

            EntityOffsetInfo[] entityOffsets       = null;
            EntityOffsetInfo[] blobAssetRefOffsets = null;
            int bufferCapacity   = -1;
            var memoryOrdering   = CalculateMemoryOrdering(type);
            var stableTypeHash   = CalculateStableTypeHash(type);
            var maxChunkCapacity = int.MaxValue;

            var maxCapacityAttribute = type.GetCustomAttribute <MaximumChunkCapacityAttribute>();

            if (maxCapacityAttribute != null)
            {
                maxChunkCapacity = maxCapacityAttribute.Capacity;
            }

            int elementSize      = 0;
            int alignmentInBytes = 0;

#if ENABLE_UNITY_COLLECTIONS_CHECKS
            if (type.IsInterface)
            {
                throw new ArgumentException($"{type} is an interface. It must be a concrete type.");
            }
#endif
            if (typeof(IComponentData).IsAssignableFrom(type))
            {
                CheckIsAllowedAsComponentData(type, nameof(IComponentData));

                category = TypeCategory.ComponentData;
                if (TypeManager.IsZeroSizeStruct(type))
                {
                    componentSize = 0;
                }
                else
                {
                    componentSize = UnsafeUtility.SizeOf(type);
                }

                typeInfo            = FastEquality.CreateTypeInfo(type);
                entityOffsets       = EntityRemapUtility.CalculateEntityOffsets(type);
                blobAssetRefOffsets = CalculatBlobAssetRefOffsets(type);

                int sizeInBytes = UnsafeUtility.SizeOf(type);
                // TODO: Implement UnsafeUtility.AlignOf(type)
                alignmentInBytes = 16;
                if (sizeInBytes < 16 && (sizeInBytes & (sizeInBytes - 1)) == 0)
                {
                    alignmentInBytes = sizeInBytes;
                }
            }
            else if (typeof(IBufferElementData).IsAssignableFrom(type))
            {
                CheckIsAllowedAsComponentData(type, nameof(IBufferElementData));

                category    = TypeCategory.BufferData;
                elementSize = UnsafeUtility.SizeOf(type);

                var capacityAttribute = (InternalBufferCapacityAttribute)type.GetCustomAttribute(typeof(InternalBufferCapacityAttribute));
                if (capacityAttribute != null)
                {
                    bufferCapacity = capacityAttribute.Capacity;
                }
                else
                {
                    bufferCapacity = 128 / elementSize; // Rather than 2*cachelinesize, to make it cross platform deterministic
                }
                componentSize       = sizeof(BufferHeader) + bufferCapacity * elementSize;
                typeInfo            = FastEquality.CreateTypeInfo(type);
                entityOffsets       = EntityRemapUtility.CalculateEntityOffsets(type);
                blobAssetRefOffsets = CalculatBlobAssetRefOffsets(type);

                int sizeInBytes = UnsafeUtility.SizeOf(type);
                // TODO: Implement UnsafeUtility.AlignOf(type)
                alignmentInBytes = 16;
                if (sizeInBytes < 16 && (sizeInBytes & (sizeInBytes - 1)) == 0)
                {
                    alignmentInBytes = sizeInBytes;
                }
            }
            else if (typeof(ISharedComponentData).IsAssignableFrom(type))
            {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                if (!type.IsValueType)
                {
                    throw new ArgumentException($"{type} is an ISharedComponentData, and thus must be a struct.");
                }
#endif
                entityOffsets = EntityRemapUtility.CalculateEntityOffsets(type);
                category      = TypeCategory.ISharedComponentData;
                typeInfo      = FastEquality.CreateTypeInfo(type);
            }
            else if (type.IsClass)
            {
                category = TypeCategory.Class;
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                if (type.FullName == "Unity.Entities.GameObjectEntity")
                {
                    throw new ArgumentException(
                              "GameObjectEntity cannot be used from EntityManager. The component is ignored when creating entities for a GameObject.");
                }
                if (UnityEngineComponentType == null)
                {
                    throw new ArgumentException(
                              $"{type} cannot be used from EntityManager. If it inherits UnityEngine.Component, you must first register TypeManager.UnityEngineComponentType or include the Unity.Entities.Hybrid assembly in your build.");
                }
                if (!UnityEngineComponentType.IsAssignableFrom(type))
                {
                    throw new ArgumentException($"{type} must inherit {UnityEngineComponentType}.");
                }
#endif
            }
            else
            {
                throw new ArgumentException($"{type} is not a valid component.");
            }

#if ENABLE_UNITY_COLLECTIONS_CHECKS
            CheckComponentType(type);
#endif
            int typeIndex = s_Count;
            return(new TypeInfo(type, typeIndex, componentSize, category, typeInfo, entityOffsets, blobAssetRefOffsets, memoryOrdering,
                                bufferCapacity, elementSize > 0 ? elementSize : componentSize, alignmentInBytes, stableTypeHash, writeGroups, writeGroupCount, maxChunkCapacity));
        }
Пример #25
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;

            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);
        }
Пример #26
0
        public static TypeInfo BuildComponentType(Type type)
        {
            var          componentSize = 0;
            TypeCategory category;
            var          typeInfo = FastEquality.TypeInfo.Null;

            EntityOffsetInfo[] entityOffsets = null;
            int bufferCapacity = -1;
            var memoryOrdering = CalculateMemoryOrdering(type);
            int elementSize    = 0;

            if (typeof(IComponentData).IsAssignableFrom(type))
            {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                if (!type.IsValueType)
                {
                    throw new ArgumentException($"{type} is an IComponentData, and thus must be a struct.");
                }
                if (!UnsafeUtility.IsBlittable(type))
                {
                    throw new ArgumentException(
                              $"{type} is an IComponentData, and thus must be blittable (No managed object is allowed on the struct).");
                }
#endif

                category = TypeCategory.ComponentData;
                if (TypeManager.IsZeroSizeStruct(type))
                {
                    componentSize = 0;
                }
                else
                {
                    componentSize = UnsafeUtility.SizeOf(type);
                }

                typeInfo      = FastEquality.CreateTypeInfo(type);
                entityOffsets = EntityRemapUtility.CalculateEntityOffsets(type);
            }
            else if (typeof(IBufferElementData).IsAssignableFrom(type))
            {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                if (!type.IsValueType)
                {
                    throw new ArgumentException($"{type} is an IBufferElementData, and thus must be a struct.");
                }
                if (!UnsafeUtility.IsBlittable(type))
                {
                    throw new ArgumentException(
                              $"{type} is an IBufferElementData, and thus must be blittable (No managed object is allowed on the struct).");
                }
#endif

                category    = TypeCategory.BufferData;
                elementSize = UnsafeUtility.SizeOf(type);

                var capacityAttribute = (InternalBufferCapacityAttribute)type.GetCustomAttribute(typeof(InternalBufferCapacityAttribute));
                if (capacityAttribute != null)
                {
                    bufferCapacity = capacityAttribute.Capacity;
                }
                else
                {
                    bufferCapacity = 128 / elementSize; // Rather than 2*cachelinesize, to make it cross platform deterministic
                }
                componentSize = sizeof(BufferHeader) + bufferCapacity * elementSize;
                typeInfo      = FastEquality.CreateTypeInfo(type);
                entityOffsets = EntityRemapUtility.CalculateEntityOffsets(type);
            }
            else if (typeof(ISharedComponentData).IsAssignableFrom(type))
            {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                if (!type.IsValueType)
                {
                    throw new ArgumentException($"{type} is an ISharedComponentData, and thus must be a struct.");
                }
#endif

                category = TypeCategory.ISharedComponentData;
                typeInfo = FastEquality.CreateTypeInfo(type);
            }
            else if (type.IsClass)
            {
                category = TypeCategory.Class;
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                if (type.FullName == "Unity.Entities.GameObjectEntity")
                {
                    throw new ArgumentException(
                              "GameObjectEntity can not be used from EntityManager. The component is ignored when creating entities for a GameObject.");
                }
#endif
            }
            else
            {
                throw new ArgumentException($"'{type}' is not a valid component");
            }

#if ENABLE_UNITY_COLLECTIONS_CHECKS
            {
                int typeCount = 0;
                foreach (Type t in s_SingularInterfaces)
                {
                    if (t.IsAssignableFrom(type))
                    {
                        ++typeCount;
                    }
                }

                if (typeCount > 1)
                {
                    throw new ArgumentException($"Component {type} can only implement one of IComponentData, ISharedComponentData and IBufferElementData");
                }
            }
#endif
            return(new TypeInfo(type, componentSize, category, typeInfo, entityOffsets, memoryOrdering, bufferCapacity, elementSize > 0 ? elementSize : componentSize));
        }
Пример #27
0
        public static void MoveChunks(
            NativeArray <ArchetypeChunk> chunks,
            NativeArray <EntityRemapUtility.EntityRemapInfo> entityRemapping,
            EntityComponentStore *srcEntityComponentStore,
            ManagedComponentStore srcManagedComponentStore,
            EntityComponentStore *dstEntityComponentStore,
            ManagedComponentStore dstManagedComponentStore)
        {
            new MoveChunksJob
            {
                srcEntityComponentStore = srcEntityComponentStore,
                dstEntityComponentStore = dstEntityComponentStore,
                entityRemapping         = entityRemapping,
                chunks = chunks
            }.Run();

            int chunkCount  = chunks.Length;
            var remapChunks = new NativeArray <RemapChunk>(chunkCount, Allocator.TempJob);

            for (int i = 0; i < chunkCount; ++i)
            {
                var chunk     = chunks[i].m_Chunk;
                var archetype = chunk->Archetype;

                //TODO: this should not be done more than once for each archetype
                var dstArchetype =
                    EntityManagerCreateArchetypeUtility.GetOrCreateArchetype(archetype->Types, archetype->TypesCount,
                                                                             dstEntityComponentStore);

                remapChunks[i] = new RemapChunk {
                    chunk = chunk, dstArchetype = dstArchetype
                };
                chunk->SequenceNumber = dstEntityComponentStore->AssignSequenceNumber(chunk);

                if (archetype->MetaChunkArchetype != null)
                {
                    Entity srcEntity = chunk->metaChunkEntity;
                    Entity dstEntity;

                    EntityManagerCreateDestroyEntitiesUtility.CreateEntities(dstArchetype->MetaChunkArchetype,
                                                                             &dstEntity, 1,
                                                                             dstEntityComponentStore, dstManagedComponentStore);

                    srcEntityComponentStore->GetChunk(srcEntity, out var srcChunk, out var srcIndex);
                    dstEntityComponentStore->GetChunk(dstEntity, out var dstChunk, out var dstIndex);

                    ChunkDataUtility.SwapComponents(srcChunk, srcIndex, dstChunk, dstIndex, 1,
                                                    srcEntityComponentStore->GlobalSystemVersion, dstEntityComponentStore->GlobalSystemVersion);
                    EntityRemapUtility.AddEntityRemapping(ref entityRemapping, srcEntity, dstEntity);

                    EntityManagerCreateDestroyEntitiesUtility.DestroyEntities(&srcEntity, 1,
                                                                              srcEntityComponentStore, srcManagedComponentStore);
                }
            }

            k_ProfileMoveSharedComponents.Begin();
            var remapShared =
                dstManagedComponentStore.MoveSharedComponents(srcManagedComponentStore, chunks,
                                                              entityRemapping,
                                                              Allocator.TempJob);

            k_ProfileMoveSharedComponents.End();

            var remapChunksJob = new RemapChunksJob
            {
                dstEntityComponentStore = dstEntityComponentStore,
                remapChunks             = remapChunks,
                entityRemapping         = entityRemapping
            }.Schedule(remapChunks.Length, 1);

            var moveChunksBetweenArchetypeJob = new MoveChunksBetweenArchetypeJob
            {
                remapChunks         = remapChunks,
                remapShared         = remapShared,
                globalSystemVersion = dstEntityComponentStore->GlobalSystemVersion
            }.Schedule(remapChunksJob);

            moveChunksBetweenArchetypeJob.Complete();

            remapShared.Dispose();
            remapChunks.Dispose();
        }
 unsafe public VisitStatus Visit <TProperty, TContainer>(IPropertyVisitor visitor, TProperty property, ref TContainer container, ref Entity value, ref ChangeTracker changeTracker)
     where TProperty : IProperty <TContainer, Entity>
 {
     value = EntityRemapUtility.RemapEntityForPrefab(RemapInfo, RemapInfoCount, value);
     return(VisitStatus.Handled);
 }
Пример #29
0
        public static void Initialize()
        {
            if (s_Types != null)
            {
                return;
            }

            ObjectOffset     = UnsafeUtility.SizeOf <ObjectOffsetType>();
            s_CreateTypeLock = new SpinLock();
            s_Types          = new TypeInfo[MaximumTypesCount];
            s_Count          = 0;

            s_Types[s_Count++] = new TypeInfo(null, 0, TypeCategory.ComponentData, FastEquality.TypeInfo.Null, null, 0, -1, 0);
            // This must always be first so that Entity is always index 0 in the archetype
            s_Types[s_Count++] = new TypeInfo(typeof(Entity), sizeof(Entity), TypeCategory.EntityData,
                                              FastEquality.CreateTypeInfo(typeof(Entity)), EntityRemapUtility.CalculateEntityOffsets(typeof(Entity)), 0, -1, sizeof(Entity));
        }
Пример #30
0
 public static void Initialize()
 {
     if (s_Types == null)
     {
         ObjectOffset     = UnsafeUtility.SizeOf <ObjectOffsetType>();
         s_CreateTypeLock = new System.Threading.SpinLock();
         s_Types          = new TypeInfo[0x2800];
         s_Count          = 0;
         s_Count++;
         s_Types[s_Count] = new TypeInfo(null, 0, TypeCategory.ComponentData, FastEquality.TypeInfo.Null, null, 0L, -1, 0);
         s_Count++;
         s_Types[s_Count] = new TypeInfo(typeof(Entity), sizeof(Entity), TypeCategory.EntityData, FastEquality.CreateTypeInfo(typeof(Entity)), EntityRemapUtility.CalculateEntityOffsets(typeof(Entity)), 0L, -1, sizeof(Entity));
     }
 }