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