Example #1
0
        public void SIZ_TagComponentDoesNotChangeCapacity()
        {
            var entity0 = m_Manager.CreateEntity(typeof(EcsTestData));
            var entity1 = m_Manager.CreateEntity(typeof(EcsTestData), typeof(EcsTestTag));

            unsafe {
                // a system ran, the version should match the global
                var chunk0     = m_Manager.Entities->GetComponentChunk(entity0);
                var chunk1     = m_Manager.Entities->GetComponentChunk(entity1);
                var archetype0 = chunk0->Archetype;
                var archetype1 = chunk1->Archetype;

                ChunkDataUtility.GetIndexInTypeArray(chunk0->Archetype, TypeManager.GetTypeIndex <EcsTestData2>());

                Assert.AreEqual(archetype0->BytesPerInstance, archetype1->BytesPerInstance);
            }
        }
Example #2
0
        public void SIZ_TagComponentDoesNotChangeCapacity()
        {
            var entity0 = m_Manager.CreateEntity(typeof(EcsTestData));
            var entity1 = m_Manager.CreateEntity(typeof(EcsTestData), typeof(EcsTestTag));

            unsafe {
                // a system ran, the version should match the global
                var chunk0     = m_Manager.EntityComponentStore->GetChunk(entity0);
                var chunk1     = m_Manager.EntityComponentStore->GetChunk(entity1);
                var archetype0 = chunk0->Archetype;
                var archetype1 = chunk1->Archetype;

                ChunkDataUtility.GetIndexInTypeArray(chunk0->Archetype, TypeManager.GetTypeIndex <EcsTestData2>());

                Assert.True(ChunkDataUtility.AreLayoutCompatible(archetype0, archetype1));
            }
        }
        public unsafe void ArchetypeIsManaged()
        {
            var types = new ComponentType[]
            {
                typeof(EcsTestData),
                typeof(ConversionTestHybridComponent),
#if !UNITY_DISABLE_MANAGED_COMPONENTS
                typeof(EcsTestManagedComponent)
#endif
            };

            var archetype = m_Manager.CreateArchetype(types).Archetype;

            Assert.IsFalse(archetype->IsManaged(ChunkDataUtility.GetIndexInTypeArray(archetype, types[0].TypeIndex)));
            Assert.IsTrue(archetype->IsManaged(ChunkDataUtility.GetIndexInTypeArray(archetype, types[1].TypeIndex)));
#if !UNITY_DISABLE_MANAGED_COMPONENTS
            Assert.IsTrue(archetype->IsManaged(ChunkDataUtility.GetIndexInTypeArray(archetype, types[2].TypeIndex)));
#endif
        }
Example #4
0
        private static unsafe void ClearChunkHeaderComponents(Chunk *chunk)
        {
            int chunkHeaderTypeIndex = TypeManager.GetTypeIndex <ChunkHeader>();
            var archetype            = chunk->Archetype;
            var typeIndexInArchetype = ChunkDataUtility.GetIndexInTypeArray(chunk->Archetype, chunkHeaderTypeIndex);

            if (typeIndexInArchetype == -1)
            {
                return;
            }

            var buffer       = chunk->Buffer;
            var length       = chunk->Count;
            var startOffset  = archetype->Offsets[typeIndexInArchetype];
            var chunkHeaders = (ChunkHeader *)(buffer + startOffset);

            for (int i = 0; i < length; ++i)
            {
                chunkHeaders[i].chunk = null;
            }
        }
Example #5
0
        [StandaloneFixme] // IJob
        public void CHG_IncrementedOnInjection()
        {
            var entity0    = m_Manager.CreateEntity(typeof(EcsTestData), typeof(EcsTestData2));
            var bumpSystem = World.CreateManager <BumpVersionSystem>();

            var oldGlobalVersion = m_Manager.GlobalSystemVersion;

            bumpSystem.Update();

            var value0 = m_Manager.GetComponentData <EcsTestData2>(entity0).value0;

            Assert.AreEqual(10, value0);

            Assert.That(m_Manager.GlobalSystemVersion > oldGlobalVersion);

            unsafe {
                // a system ran, the version should match the global
                var chunk0    = m_Manager.Entities->GetComponentChunk(entity0);
                var td2index0 = ChunkDataUtility.GetIndexInTypeArray(chunk0->Archetype, TypeManager.GetTypeIndex <EcsTestData2>());
                Assert.AreEqual(m_Manager.GlobalSystemVersion, chunk0->GetChangeVersion(td2index0));
            }
        }
        static unsafe void WriteChunkData(YamlWriter writer, EntityManager entityManager, Chunk *initialChunk, Archetype *archetype, bool dumpChunkRawData)
        {
            using (writer.WriteCollection(k_ChunkDataCollectionTag))
            {
                using (writer.WriteCollection("Header"))
                {
                    WriteEntity(writer, nameof(Chunk.metaChunkEntity), initialChunk->metaChunkEntity);
                    writer.WriteKeyValue(nameof(Chunk.Capacity), initialChunk->Capacity)
                    .WriteKeyValue(nameof(Chunk.Count), initialChunk->Count);

                    if (dumpChunkRawData)
                    {
                        writer.WriteFormattedBinaryData("RawData", initialChunk, Chunk.kBufferOffset);
                    }
                }

                // First pass to sort by component type
                var entitiesByChunkIndex   = new Dictionary <int, Entity>();
                var componentDataList      = new List <int>();
                var chunkComponentDataList = new List <int>();
                var chunkTypes             = archetype->Types;
                for (int typeI = 0; typeI < archetype->TypesCount; typeI++)
                {
                    var componentType = &chunkTypes[typeI];
                    var type          = TypeManager.GetType(componentType->TypeIndex);
                    var typeInfo      = TypeManager.GetTypeInfo(componentType->TypeIndex);

                    if (componentType->IsChunkComponent)
                    {
                        chunkComponentDataList.Add(typeI);
                    }

                    // Is it a Component Data ?
                    else if (typeof(IComponentData).IsAssignableFrom(type) || typeof(Entity).IsAssignableFrom(type) || typeof(IBufferElementData).IsAssignableFrom(type))
                    {
                        // Ignore Tag Component, no data to dump
                        if (typeInfo.IsZeroSized)
                        {
                            continue;
                        }

                        if (typeof(Entity).IsAssignableFrom(type))
                        {
                            componentDataList.Insert(0, typeI);

                            for (int i = 0; i < initialChunk->Count;)
                            {
                                var entity = (Entity)Marshal.PtrToStructure((IntPtr)initialChunk->Buffer + archetype->SizeOfs[0] * i, type);
                                if (entityManager.Exists(entity))
                                {
                                    entitiesByChunkIndex.Add(i, entity);
                                    i++;
                                }
                            }
                        }
                        else
                        {
                            componentDataList.Add(typeI);
                        }
                    }
                }

                // Parse the Component Data for this chunk and store them
                using (writer.WriteCollection(k_ComponentDataCollectionTag))
                {
                    foreach (var typeI in componentDataList)
                    {
                        var componentTypeInArchetype = &chunkTypes[typeI];
                        var componentType            = TypeManager.GetType(componentTypeInArchetype->TypeIndex);
                        var componentTypeInfo        = TypeManager.GetTypeInfo(componentTypeInArchetype->TypeIndex);
                        var componentExtractedInfo   = TypeDataExtractor.GetTypeExtractedInfo(componentType);

                        using (writer.WriteCollection(k_ComponentDataTag))
                        {
                            writer.WriteInlineMap("info", new[]
                            {
                                new KeyValuePair <object, object>(nameof(Type), componentType.Name),
                                new KeyValuePair <object, object>(nameof(TypeManager.TypeInfo.SizeInChunk), componentTypeInfo.SizeInChunk)
                            });

                            using (writer.WriteCollection("Entities"))
                            {
                                var indexInTypeArray       = ChunkDataUtility.GetIndexInTypeArray(archetype, componentTypeInArchetype->TypeIndex);
                                var componentOffsetInChunk = archetype->Offsets[indexInTypeArray];
                                var componentSize          = archetype->SizeOfs[indexInTypeArray];
                                var componentsBuffer       = initialChunk->Buffer + componentOffsetInChunk;
                                var entityData             = new Dictionary <string, string>();

                                // Dump all entities in this chunk
                                foreach (var kvp in entitiesByChunkIndex)
                                {
                                    var entity = kvp.Value;
                                    entityData.Clear();

                                    // Get the location of the component data
                                    var compData = componentsBuffer + kvp.Key * componentSize;

                                    // If the component we are dumping is a Dynamic Buffer
                                    if (typeof(IBufferElementData).IsAssignableFrom(componentType))
                                    {
                                        var header = (BufferHeader *)compData;
                                        var begin  = BufferHeader.GetElementPointer(header);
                                        var size   = Marshal.SizeOf(componentType);

                                        using (writer.WriteCollection(entity.ToString()))
                                        {
                                            for (var it = 0; it < header->Length; it++)
                                            {
                                                var item = begin + (size * it);
                                                entityData.Clear();

                                                // Dump each field of the current entity's component data
                                                foreach (var componentFieldInfo in componentExtractedInfo.Fields)
                                                {
                                                    var compDataObject = Marshal.PtrToStructure((IntPtr)item + componentFieldInfo.Offset, componentFieldInfo.Type);
                                                    entityData.Add(componentFieldInfo.Name, compDataObject.ToString());
                                                }
                                                writer.WriteInlineMap($"{it:0000}", entityData);
                                            }
                                        }
                                    }

                                    // If it's a Component Data
                                    else
                                    {
                                        // Dump each field of the current entity's component data
                                        foreach (var componentFieldInfo in componentExtractedInfo.Fields)
                                        {
                                            var compDataObject = Marshal.PtrToStructure((IntPtr)compData + componentFieldInfo.Offset, componentFieldInfo.Type);
                                            entityData.Add(componentFieldInfo.Name, compDataObject.ToString());
                                        }
                                        writer.WriteInlineMap(entity.ToString(), entityData);
                                    }
                                }
                                if (dumpChunkRawData)
                                {
                                    var csize = EntityComponentStore.GetComponentArraySize(componentSize, archetype->ChunkCapacity);
                                    writer.WriteFormattedBinaryData("RawData", componentsBuffer, csize, componentOffsetInChunk + Chunk.kBufferOffset);
                                }
                            }
                        }
                    }
                }
            }
        }
 public static unsafe int GetIndexInTypeArray(this ArchetypeChunk chunk, int typeIndex)
 {
     return(ChunkDataUtility.GetIndexInTypeArray(chunk.m_Chunk->Archetype, typeIndex));
 }
            public void Execute()
            {
                var addedSharedComponentsCount   = 0;
                var removedSharedComponentsCount = 0;
                var removedEntityCurrentCount    = 0;
                var addedEntityCurrentCount      = 0;

                for (var i = 0; i < RemovedShadowChunks.Length; i++)
                {
                    var chunkSequenceNumber = RemovedShadowChunks[i];
                    var shadowChunk         = ShadowChunksBySequenceNumber[chunkSequenceNumber];

                    UnsafeUtility.MemCpy((Entity *)RemovedEntities.GetUnsafePtr() + removedEntityCurrentCount, shadowChunk.EntityDataBuffer, shadowChunk.EntityCount * sizeof(Entity));
                    UnsafeUtility.MemCpyReplicate((int *)RemovedEntitiesMappingToComponent.GetUnsafePtr() + removedEntityCurrentCount, &removedSharedComponentsCount, sizeof(int), shadowChunk.EntityCount);
                    removedEntityCurrentCount += shadowChunk.EntityCount;

                    IndicesInManagedComponentStore[removedSharedComponentsCount++] = SharedComponentValueIndexByChunk[chunkSequenceNumber];

                    ShadowChunksBySequenceNumber.Remove(chunkSequenceNumber);
                    SharedComponentValueIndexByChunk.Remove(chunkSequenceNumber);
                    UnsafeUtility.Free(shadowChunk.EntityDataBuffer, Allocator.Persistent);
                }

                for (var i = 0; i < GatheredChanges.Length; i++)
                {
                    var changes = GatheredChanges[i];
                    if (changes.RemovedEntities.Length == 0)
                    {
                        continue;
                    }

                    UnsafeUtility.MemCpy((Entity *)RemovedEntities.GetUnsafePtr() + removedEntityCurrentCount, changes.RemovedEntities.Ptr, changes.RemovedEntities.Length * sizeof(Entity));
                    UnsafeUtility.MemCpyReplicate((int *)RemovedEntitiesMappingToComponent.GetUnsafePtr() + removedEntityCurrentCount, &removedSharedComponentsCount, sizeof(int), changes.RemovedEntities.Length);
                    removedEntityCurrentCount += changes.RemovedEntities.Length;

                    IndicesInManagedComponentStore[removedSharedComponentsCount++] = SharedComponentValueIndexByChunk[changes.Chunk->SequenceNumber];
                }

                for (var i = 0; i < GatheredChanges.Length; i++)
                {
                    var changes = GatheredChanges[i];
                    if (changes.AddedEntities.Length == 0)
                    {
                        continue;
                    }

                    var chunkSequenceNumber = changes.Chunk->SequenceNumber;

                    if (changes.AddedEntities.Length > 0)
                    {
                        var archetype                 = changes.Chunk->Archetype;
                        var indexInTypeArray          = ChunkDataUtility.GetIndexInTypeArray(archetype, TypeIndex);
                        var sharedComponentValueArray = changes.Chunk->SharedComponentValues;
                        var sharedComponentOffset     = indexInTypeArray - archetype->FirstSharedComponent;
                        var sharedComponentDataIndex  = sharedComponentValueArray[sharedComponentOffset];

                        SharedComponentValueIndexByChunk[chunkSequenceNumber] = sharedComponentDataIndex;

                        UnsafeUtility.MemCpy((Entity *)AddedEntities.GetUnsafePtr() + addedEntityCurrentCount, changes.AddedEntities.Ptr, changes.AddedEntities.Length * sizeof(Entity));
                        var index = removedSharedComponentsCount + addedSharedComponentsCount;
                        UnsafeUtility.MemCpyReplicate((int *)AddedEntitiesMappingToComponent.GetUnsafePtr() + addedEntityCurrentCount, &index, sizeof(int), changes.AddedEntities.Length);
                        addedEntityCurrentCount += changes.AddedEntities.Length;

                        IndicesInManagedComponentStore[index] = sharedComponentDataIndex;
                        addedSharedComponentsCount++;
                    }
                }
            }
            public void Execute(int index)
            {
                var chunk            = Chunks[index].m_Chunk;
                var archetype        = chunk->Archetype;
                var indexInTypeArray = ChunkDataUtility.GetIndexInTypeArray(archetype, TypeIndex);

                if (indexInTypeArray == -1) // Archetype doesn't match required component
                {
                    return;
                }

                var changesForChunk = GatheredChanges + index;

                if (ShadowChunksBySequenceNumber.TryGetValue(chunk->SequenceNumber, out var shadow))
                {
                    if (!ChangeVersionUtility.DidChange(chunk->GetChangeVersion(0), shadow.Version))
                    {
                        return;
                    }

                    if (!changesForChunk->AddedEntities.IsCreated)
                    {
                        changesForChunk->Chunk           = chunk;
                        changesForChunk->AddedEntities   = new UnsafeList(Allocator.TempJob);
                        changesForChunk->RemovedEntities = new UnsafeList(Allocator.TempJob);
                    }

                    var entityDataPtr = (Entity *)(chunk->Buffer + archetype->Offsets[0]);
                    var currentCount  = chunk->Count;
                    var previousCount = shadow.EntityCount;
                    var i             = 0;
                    for (; i < currentCount && i < previousCount; i++)
                    {
                        var currentEntity  = entityDataPtr[i];
                        var previousEntity = shadow.EntityDataBuffer[i];

                        if (currentEntity != previousEntity)
                        {
                            // CHANGED ENTITY!
                            changesForChunk->RemovedEntities.Add(previousEntity);
                            changesForChunk->AddedEntities.Add(currentEntity);
                        }
                    }

                    for (; i < currentCount; i++)
                    {
                        // NEW ENTITY!
                        changesForChunk->AddedEntities.Add(entityDataPtr[i]);
                    }

                    for (; i < previousCount; i++)
                    {
                        // REMOVED ENTITY!
                        changesForChunk->RemovedEntities.Add(shadow.EntityDataBuffer[i]);
                    }
                }
                else
                {
                    // This is a new chunk
                    var addedEntities = new UnsafeList(sizeof(Entity), 4, chunk->Count, Allocator.TempJob);
                    var entityDataPtr = chunk->Buffer + archetype->Offsets[0];
                    addedEntities.AddRange <Entity>(entityDataPtr, chunk->Count);
                    changesForChunk->Chunk         = chunk;
                    changesForChunk->AddedEntities = addedEntities;
                }
            }
            public void Execute()
            {
                var knownChunks     = ShadowChunksBySequenceNumber.GetKeyArray(Allocator.Temp);
                var processedChunks = new NativeHashMap <ulong, byte>(Chunks.Length, Allocator.Temp);

                for (var index = 0; index < Chunks.Length; index++)
                {
                    var chunk            = Chunks[index].m_Chunk;
                    var archetype        = chunk->Archetype;
                    var indexInTypeArray = ChunkDataUtility.GetIndexInTypeArray(archetype, TypeIndex);
                    if (indexInTypeArray == -1) // Archetype doesn't match required component
                    {
                        continue;
                    }

                    var componentVersion = chunk->GetChangeVersion(indexInTypeArray);
                    var entityVersion    = chunk->GetChangeVersion(0);
                    var sequenceNumber   = chunk->SequenceNumber;
                    processedChunks[sequenceNumber] = 0;
                    var entityDataPtr    = chunk->Buffer + archetype->Offsets[0];
                    var componentDataPtr = chunk->Buffer + archetype->Offsets[indexInTypeArray];

                    if (ShadowChunksBySequenceNumber.TryGetValue(sequenceNumber, out var shadow))
                    {
                        if (!ChangeVersionUtility.DidChange(componentVersion, shadow.ComponentVersion) &&
                            !ChangeVersionUtility.DidChange(entityVersion, shadow.EntityVersion))
                        {
                            continue;
                        }

                        UnsafeUtility.MemCpy(shadow.EntityDataBuffer, entityDataPtr, chunk->Count * sizeof(Entity));
                        UnsafeUtility.MemCpy(shadow.ComponentDataBuffer, componentDataPtr, chunk->Count * ComponentSize);

                        shadow.Count            = chunk->Count;
                        shadow.ComponentVersion = componentVersion;
                        shadow.EntityVersion    = entityVersion;

                        ShadowChunksBySequenceNumber[sequenceNumber] = shadow;
                    }
                    else
                    {
                        ShadowChunksBySequenceNumber.Add(sequenceNumber, *(AllocatedShadowChunks + index));
                    }
                }

                for (var i = 0; i < knownChunks.Length; i++)
                {
                    var chunkSequenceNumber = knownChunks[i];
                    if (!processedChunks.ContainsKey(chunkSequenceNumber))
                    {
                        // This is a missing chunk
                        var shadowChunk = ShadowChunksBySequenceNumber[chunkSequenceNumber];

                        // REMOVED COMPONENT DATA!
                        RemovedChunkComponentDataBuffer.AddRange(shadowChunk.ComponentDataBuffer, shadowChunk.Count * ComponentSize);
                        RemovedChunkEntities.AddRange(shadowChunk.EntityDataBuffer, shadowChunk.Count);

                        UnsafeUtility.Free(shadowChunk.ComponentDataBuffer, Allocator.Persistent);
                        UnsafeUtility.Free(shadowChunk.EntityDataBuffer, Allocator.Persistent);

                        ShadowChunksBySequenceNumber.Remove(chunkSequenceNumber);
                    }
                }

                knownChunks.Dispose();
                processedChunks.Dispose();
            }
            public void Execute(int index)
            {
                var chunk            = Chunks[index].m_Chunk;
                var archetype        = chunk->Archetype;
                var indexInTypeArray = ChunkDataUtility.GetIndexInTypeArray(archetype, TypeIndex);

                if (indexInTypeArray == -1) // Archetype doesn't match required component
                {
                    return;
                }

                var changesForChunk = GatheredChanges + index;

                if (ShadowChunksBySequenceNumber.TryGetValue(chunk->SequenceNumber, out var shadow))
                {
                    if (!ChangeVersionUtility.DidChange(chunk->GetChangeVersion(indexInTypeArray), shadow.ComponentVersion) &&
                        !ChangeVersionUtility.DidChange(chunk->GetChangeVersion(0), shadow.EntityVersion))
                    {
                        return;
                    }

                    if (!changesForChunk->AddedComponentEntities.IsCreated)
                    {
                        changesForChunk->AddedComponentEntities     = new UnsafeList(Allocator.TempJob);
                        changesForChunk->AddedComponentDataBuffer   = new UnsafeList(Allocator.TempJob);
                        changesForChunk->RemovedComponentEntities   = new UnsafeList(Allocator.TempJob);
                        changesForChunk->RemovedComponentDataBuffer = new UnsafeList(Allocator.TempJob);
                    }

                    var entityDataPtr    = chunk->Buffer + archetype->Offsets[0];
                    var componentDataPtr = chunk->Buffer + archetype->Offsets[indexInTypeArray];

                    var currentCount  = chunk->Count;
                    var previousCount = shadow.Count;

                    var i = 0;

                    for (; i < currentCount && i < previousCount; i++)
                    {
                        var currentComponentData  = componentDataPtr + ComponentSize * i;
                        var previousComponentData = shadow.ComponentDataBuffer + ComponentSize * i;

                        var entity         = *(Entity *)(entityDataPtr + sizeof(Entity) * i);
                        var previousEntity = *(Entity *)(shadow.EntityDataBuffer + sizeof(Entity) * i);

                        if (entity != previousEntity ||
                            UnsafeUtility.MemCmp(currentComponentData, previousComponentData, ComponentSize) != 0)
                        {
                            // CHANGED COMPONENT DATA!
                            OnRemovedComponent(changesForChunk, previousEntity, previousComponentData, ComponentSize);
                            OnNewComponent(changesForChunk, entity, currentComponentData, ComponentSize);
                        }
                    }

                    for (; i < currentCount; i++)
                    {
                        // NEW COMPONENT DATA!
                        var entity = *(Entity *)(entityDataPtr + sizeof(Entity) * i);
                        var currentComponentData = componentDataPtr + ComponentSize * i;
                        OnNewComponent(changesForChunk, entity, currentComponentData, ComponentSize);
                    }

                    for (; i < previousCount; i++)
                    {
                        // REMOVED COMPONENT DATA!
                        var entity = *(Entity *)(entityDataPtr + sizeof(Entity) * i);
                        var previousComponentData = shadow.ComponentDataBuffer + ComponentSize * i;
                        OnRemovedComponent(changesForChunk, entity, previousComponentData, ComponentSize);
                    }
                }
                else
                {
                    // This is a new chunk
                    var addedComponentDataBuffer = new UnsafeList(ComponentSize, 4, chunk->Count, Allocator.TempJob);
                    var addedComponentEntities   = new UnsafeList(sizeof(Entity), 4, chunk->Count, Allocator.TempJob);

                    var entityDataPtr    = chunk->Buffer + archetype->Offsets[0];
                    var componentDataPtr = chunk->Buffer + archetype->Offsets[indexInTypeArray];

                    addedComponentDataBuffer.AddRange <byte>(componentDataPtr, chunk->Count * ComponentSize);
                    addedComponentEntities.AddRange <Entity>(entityDataPtr, chunk->Count);

                    changesForChunk->AddedComponentDataBuffer = addedComponentDataBuffer;
                    changesForChunk->AddedComponentEntities   = addedComponentEntities;
                }
            }