internal void MoveChunksFromAll( NativeArray <EntityRemapUtility.EntityRemapInfo> entityRemapping, EntityComponentStore *srcEntityComponentStore, ManagedComponentStore srcManagedComponentStore) { var access = GetCheckedEntityDataAccess(); var ecs = access->EntityComponentStore; var mcs = access->ManagedComponentStore; var moveChunksJob = new MoveAllChunksJob { srcEntityComponentStore = srcEntityComponentStore, dstEntityComponentStore = ecs, entityRemapping = entityRemapping }.Schedule(); int managedComponentCount = srcEntityComponentStore->ManagedComponentIndexUsedCount; NativeArray <int> srcManagedIndices = default; NativeArray <int> dstManagedIndices = default; JobHandle gatherManagedComponentIndices = default; if (managedComponentCount > 0) { srcManagedIndices = new NativeArray <int>(managedComponentCount, Allocator.TempJob); dstManagedIndices = new NativeArray <int>(managedComponentCount, Allocator.TempJob); ecs->ReserveManagedComponentIndices(managedComponentCount); gatherManagedComponentIndices = new GatherAllManagedComponentIndicesJob { SrcEntityComponentStore = srcEntityComponentStore, DstEntityComponentStore = ecs, SrcManagedIndices = srcManagedIndices, DstManagedIndices = dstManagedIndices }.Schedule(); } JobHandle.ScheduleBatchedJobs(); int chunkCount = 0; for (var i = 0; i < srcEntityComponentStore->m_Archetypes.Length; ++i) { var srcArchetype = srcEntityComponentStore->m_Archetypes.Ptr[i]; chunkCount += srcArchetype->Chunks.Count; } var remapChunks = new NativeArray <RemapChunk>(chunkCount, Allocator.TempJob); var remapArchetypes = new NativeArray <RemapArchetype>(srcEntityComponentStore->m_Archetypes.Length, Allocator.TempJob); int chunkIndex = 0; int archetypeIndex = 0; for (var i = 0; i < srcEntityComponentStore->m_Archetypes.Length; ++i) { var srcArchetype = srcEntityComponentStore->m_Archetypes.Ptr[i]; if (srcArchetype->Chunks.Count != 0) { var dstArchetype = ecs->GetOrCreateArchetype(srcArchetype->Types, srcArchetype->TypesCount); remapArchetypes[archetypeIndex] = new RemapArchetype { srcArchetype = srcArchetype, dstArchetype = dstArchetype }; srcEntityComponentStore->m_ChunkListChangesTracker.TrackArchetype(srcArchetype); ecs->m_ChunkListChangesTracker.TrackArchetype(srcArchetype); for (var j = 0; j < srcArchetype->Chunks.Count; ++j) { var srcChunk = srcArchetype->Chunks[j]; remapChunks[chunkIndex] = new RemapChunk { chunk = srcChunk, dstArchetype = dstArchetype }; chunkIndex++; } archetypeIndex++; ecs->IncrementComponentTypeOrderVersion(dstArchetype); } } moveChunksJob.Complete(); mcs.Playback(ref ecs->ManagedChangesTracker); srcManagedComponentStore.Playback(ref srcEntityComponentStore->ManagedChangesTracker); k_ProfileMoveSharedComponents.Begin(); var remapShared = mcs.MoveAllSharedComponents(srcManagedComponentStore, Allocator.TempJob); k_ProfileMoveSharedComponents.End(); gatherManagedComponentIndices.Complete(); k_ProfileMoveManagedComponents.Begin(); mcs.MoveManagedComponentsFromDifferentWorld(srcManagedIndices, dstManagedIndices, srcManagedIndices.Length, srcManagedComponentStore); srcEntityComponentStore->m_ManagedComponentFreeIndex.Length = 0; srcEntityComponentStore->m_ManagedComponentIndex = 1; k_ProfileMoveManagedComponents.End(); new ChunkPatchEntities { RemapChunks = remapChunks, EntityRemapping = entityRemapping, EntityComponentStore = ecs }.Run(); var remapAllChunksJob = new RemapAllChunksJob { dstEntityComponentStore = ecs, remapChunks = remapChunks, entityRemapping = entityRemapping }.Schedule(remapChunks.Length, 1); var remapArchetypesJob = new RemapAllArchetypesJob { remapArchetypes = remapArchetypes, remapShared = remapShared, dstEntityComponentStore = ecs, chunkHeaderType = TypeManager.GetTypeIndex <ChunkHeader>() }.Schedule(archetypeIndex, 1, remapAllChunksJob); mcs.Playback(ref ecs->ManagedChangesTracker); if (managedComponentCount > 0) { srcManagedIndices.Dispose(); dstManagedIndices.Dispose(); } remapArchetypesJob.Complete(); remapShared.Dispose(); remapChunks.Dispose(); }
public BufferFromEntity <T> GetBufferFromEntity <T>(bool isReadOnly = false) where T : struct, IBufferElementData { return(GetBufferFromEntity <T>(TypeManager.GetTypeIndex <T>(), isReadOnly)); }
public DynamicBuffer <T> GetBuffer <T>(Entity entity) where T : struct, IBufferElementData { var typeIndex = TypeManager.GetTypeIndex <T>(); #if ENABLE_UNITY_COLLECTIONS_CHECKS Entities->AssertEntityHasComponent(entity, typeIndex); if (TypeManager.GetTypeInfo <T>().Category != TypeManager.TypeCategory.BufferData) { throw new ArgumentException( $"GetBuffer<{typeof(T)}> may not be IComponentData or ISharedComponentData; currently {TypeManager.GetTypeInfo<T>().Category}"); } #endif ComponentJobSafetyManager.CompleteReadAndWriteDependency(typeIndex); BufferHeader *header = (BufferHeader *)Entities->GetComponentDataWithTypeRW(entity, typeIndex, Entities->GlobalSystemVersion); #if ENABLE_UNITY_COLLECTIONS_CHECKS return(new DynamicBuffer <T>(header, ComponentJobSafetyManager.GetSafetyHandle(typeIndex, false), ComponentJobSafetyManager.GetBufferSafetyHandle(typeIndex), false)); #else return(new DynamicBuffer <T>(header)); #endif }
public static ComponentType ChunkComponentReadOnly <T>() { var typeIndex = TypeManager.MakeChunkComponentTypeIndex(TypeManager.GetTypeIndex <T>()); return(ReadOnly(typeIndex)); }
public TypeHeapElement(int index, Type t) { unsortedIndex = index; typeName = TypeManager.SystemName(t); }
public Type GetManagedType() { return(TypeManager.GetType(TypeIndex)); }
public static ComponentType ReadWrite(Type type) { return(FromTypeIndex(TypeManager.GetTypeIndex(type))); }
public int GetSharedComponentVersion <T>(T sharedData) where T : struct { var index = FindSharedComponentIndex(TypeManager.GetTypeIndex <T>(), sharedData); return(index == -1 ? 0 : m_SharedComponentVersion[index]); }
internal void GetIndexFromEntity(out IndexFromEntity output) { #if ENABLE_UNITY_COLLECTIONS_CHECKS output = new IndexFromEntity(m_ComponentGroupData, m_SafetyManager.GetSafetyHandle(TypeManager.GetTypeIndex <Entity>(), true)); #else output = new IndexFromEntity(m_ComponentGroupData); #endif }
public FixedArrayFromEntity <T> GetFixedArrayFromEntity <T>(bool isReadOnly = false) where T : struct { AddReaderWriter(isReadOnly ? ComponentType.ReadOnly <T>() : ComponentType.Create <T>()); return(EntityManager.GetFixedArrayFromEntity <T>(TypeManager.GetTypeIndex <T>(), isReadOnly)); }
void CheckJobDependencies(int type, bool isReading, JobHandle dependency) { var h = m_SafetyManager.GetSafetyHandle(type, true); unsafe { if (!isReading) { var readerCount = AtomicSafetyHandle.GetReaderArray(h, 0, IntPtr.Zero); JobHandle *readers = stackalloc JobHandle[readerCount]; AtomicSafetyHandle.GetReaderArray(h, readerCount, (IntPtr)readers); for (var i = 0; i < readerCount; ++i) { if (!JobHandle.CheckFenceIsDependencyOrDidSyncFence(readers[i], dependency)) { throw new InvalidOperationException($"The system {GetType()} reads {TypeManager.GetType(type)} via {AtomicSafetyHandle.GetReaderName(h, i)} but that type was not returned as a job dependency. To ensure correct behavior of other systems, the job or a dependency of it must be returned from the OnUpdate method."); } } } var writer = AtomicSafetyHandle.GetWriter(h); if (!JobHandle.CheckFenceIsDependencyOrDidSyncFence(writer, dependency)) { throw new InvalidOperationException($"The system {GetType()} writes {TypeManager.GetType(type)} via {AtomicSafetyHandle.GetWriterName(h)} but that was not returned as a job dependency. To ensure correct behavior of other systems, the job or a dependency of it must be returned from the OnUpdate method."); } } }
public static void ReplicateComponents(Chunk *srcChunk, int srcIndex, Chunk *dstChunk, int dstBaseIndex, int count, ref EntityComponentStore entityComponentStore) { var srcArchetype = srcChunk->Archetype; var srcBuffer = srcChunk->Buffer; var dstBuffer = dstChunk->Buffer; var dstArchetype = dstChunk->Archetype; var srcOffsets = srcArchetype->Offsets; var srcSizeOfs = srcArchetype->SizeOfs; var srcBufferCapacities = srcArchetype->BufferCapacities; var srcTypes = srcArchetype->Types; var dstTypes = dstArchetype->Types; var dstOffsets = dstArchetype->Offsets; var dstTypeIndex = 1; var nativeComponentsEnd = srcArchetype->NativeComponentsEnd; for (var srcTypeIndex = 1; srcTypeIndex != nativeComponentsEnd; srcTypeIndex++) { var srcType = srcTypes[srcTypeIndex]; var dstType = dstTypes[dstTypeIndex]; // Type does not exist in destination. Skip it. if (srcType.TypeIndex != dstType.TypeIndex) { continue; } var srcSizeOf = srcSizeOfs[srcTypeIndex]; var src = srcBuffer + (srcOffsets[srcTypeIndex] + srcSizeOf * srcIndex); var dst = dstBuffer + (dstOffsets[dstTypeIndex] + srcSizeOf * dstBaseIndex); UnsafeUtility.MemCpyReplicate(dst, src, srcSizeOf, count); dstTypeIndex++; } dstTypeIndex = dstArchetype->FirstBufferComponent; var bufferComponentsEnd = srcArchetype->BufferComponentsEnd; for (var srcTypeIndex = srcArchetype->FirstBufferComponent; srcTypeIndex != bufferComponentsEnd; srcTypeIndex++) { var srcType = srcTypes[srcTypeIndex]; var dstType = dstTypes[dstTypeIndex]; // Type does not exist in destination. Skip it. if (srcType.TypeIndex != dstType.TypeIndex) { continue; } var srcSizeOf = srcSizeOfs[srcTypeIndex]; var src = srcBuffer + (srcOffsets[srcTypeIndex] + srcSizeOf * srcIndex); var dst = dstBuffer + (dstOffsets[dstTypeIndex] + srcSizeOf * dstBaseIndex); var srcBufferCapacity = srcBufferCapacities[srcTypeIndex]; var alignment = 8; // TODO: Need a way to compute proper alignment for arbitrary non-generic types in TypeManager var elementSize = TypeManager.GetTypeInfo(srcType.TypeIndex).ElementSize; for (int i = 0; i < count; ++i) { BufferHeader *srcHdr = (BufferHeader *)src; BufferHeader *dstHdr = (BufferHeader *)dst; BufferHeader.Initialize(dstHdr, srcBufferCapacity); BufferHeader.Assign(dstHdr, BufferHeader.GetElementPointer(srcHdr), srcHdr->Length, elementSize, alignment, false, 0); dst += srcSizeOf; } dstTypeIndex++; } if (dstArchetype->NumManagedComponents > 0) { ReplicateManagedComponents(srcChunk, srcIndex, dstChunk, dstBaseIndex, count, ref entityComponentStore); } }
public static void ReplicateManagedComponents(Chunk *srcChunk, int srcIndex, Chunk *dstChunk, int dstBaseIndex, int count, ref EntityComponentStore entityComponentStore) { var dstArchetype = dstChunk->Archetype; var srcArchetype = srcChunk->Archetype; var srcTypes = srcArchetype->Types; var dstTypes = dstArchetype->Types; var srcOffsets = srcArchetype->Offsets; var dstOffsets = dstArchetype->Offsets; int componentCount = dstArchetype->NumManagedComponents; int nonNullManagedComponents = 0; int nonNullHybridComponents = 0; var componentIndices = stackalloc int[componentCount]; var componentDstArrayStart = stackalloc IntPtr[componentCount]; var firstDstManagedComponent = dstArchetype->FirstManagedComponent; var dstTypeIndex = firstDstManagedComponent; var managedComponentsEnd = srcArchetype->ManagedComponentsEnd; var srcBaseAddr = srcChunk->Buffer + sizeof(int) * srcIndex; var dstBaseAddr = dstChunk->Buffer + sizeof(int) * dstBaseIndex; bool hasHybridComponents = dstArchetype->HasHybridComponents; for (var srcTypeIndex = srcArchetype->FirstManagedComponent; srcTypeIndex != managedComponentsEnd; srcTypeIndex++) { var srcType = srcTypes[srcTypeIndex]; var dstType = dstTypes[dstTypeIndex]; // Type does not exist in destination. Skip it. if (srcType.TypeIndex != dstType.TypeIndex) { continue; } int srcManagedComponentIndex = *(int *)(srcBaseAddr + srcOffsets[srcTypeIndex]); var dstArrayStart = dstBaseAddr + dstOffsets[dstTypeIndex]; if (srcManagedComponentIndex == 0) { UnsafeUtility.MemClear(dstArrayStart, sizeof(int) * count); } else { if (hasHybridComponents && TypeManager.GetTypeInfo(srcType.TypeIndex).Category == TypeManager.TypeCategory.Class) { //Hybrid component, put at end of array var index = componentCount - nonNullHybridComponents - 1; componentIndices[index] = srcManagedComponentIndex; componentDstArrayStart[index] = (IntPtr)dstArrayStart; ++nonNullHybridComponents; } else { componentIndices[nonNullManagedComponents] = srcManagedComponentIndex; componentDstArrayStart[nonNullManagedComponents] = (IntPtr)dstArrayStart; ++nonNullManagedComponents; } } dstTypeIndex++; } entityComponentStore.ReserveManagedComponentIndices(count * (nonNullManagedComponents + nonNullHybridComponents)); entityComponentStore.ManagedChangesTracker.CloneManagedComponentBegin(componentIndices, nonNullManagedComponents, count); for (int c = 0; c < nonNullManagedComponents; ++c) { var dst = (int *)(componentDstArrayStart[c]); entityComponentStore.AllocateManagedComponentIndices(dst, count); entityComponentStore.ManagedChangesTracker.CloneManagedComponentAddDstIndices(dst, count); } if (hasHybridComponents) { var dstEntities = (Entity *)dstChunk->Buffer + dstBaseIndex; entityComponentStore.ManagedChangesTracker.CloneHybridComponentBegin( componentIndices + componentCount - nonNullHybridComponents, nonNullHybridComponents, dstEntities, count); for (int c = componentCount - nonNullHybridComponents; c < componentCount; ++c) { var dst = (int *)(componentDstArrayStart[c]); entityComponentStore.AllocateManagedComponentIndices(dst, count); entityComponentStore.ManagedChangesTracker.CloneHybridComponentAddDstIndices(dst, count); } } }
public static void InitializeSystems(World world) { var allSystemTypes = TypeManager.GetSystems(); var allSystemNames = TypeManager.SystemNames; if (allSystemTypes.Length == 0) { throw new InvalidOperationException("DefaultTinyWorldInitialization: No Systems found."); } // Create top level presentation system and simulation systems. InitializationSystemGroup initializationSystemGroup = new InitializationSystemGroup(); world.AddManager(initializationSystemGroup); SimulationSystemGroup simulationSystemGroup = new SimulationSystemGroup(); world.AddManager(simulationSystemGroup); PresentationSystemGroup presentationSystemGroup = new PresentationSystemGroup(); world.AddManager(presentationSystemGroup); // Create the working set of systems. int nSystems = 0; Type[] systemTypes = new Type[allSystemTypes.Length]; ComponentSystem[] systems = new ComponentSystem[allSystemTypes.Length]; #if WRITE_LOG Console.WriteLine("--- Adding systems:"); #endif for (int i = 0; i < allSystemTypes.Length; i++) { if (TypeManager.GetSystemAttributes(allSystemTypes[i], typeof(DisableAutoCreationAttribute)).Length > 0) { continue; } if (allSystemTypes[i] == initializationSystemGroup.GetType() || allSystemTypes[i] == simulationSystemGroup.GetType() || allSystemTypes[i] == presentationSystemGroup.GetType()) { continue; } if (world.GetExistingManager(allSystemTypes[i]) != null) { continue; } #if WRITE_LOG Console.WriteLine(allSystemNames[i]); #endif systemTypes[nSystems] = allSystemTypes[i]; systems[nSystems] = TypeManager.ConstructSystem(allSystemTypes[i]); world.AddManager(systems[nSystems]); nSystems++; } #if WRITE_LOG Console.WriteLine("--- Adding systems Done."); #endif for (int i = 0; i < nSystems; ++i) { var sysType = systemTypes[i]; var system = systems[i]; var groups = TypeManager.GetSystemAttributes(sysType, typeof(UpdateInGroupAttribute)); if (groups.Length == 0) { simulationSystemGroup.AddSystemToUpdateList(system); } for (int g = 0; g < groups.Length; ++g) { var groupType = groups[g] as UpdateInGroupAttribute; var groupSystem = world.GetExistingManager(groupType.GroupType) as ComponentSystemGroup; if (groupSystem == null) { throw new Exception("DefaultTinyWorldInitialization failed to find existing SystemGroup."); } groupSystem.AddSystemToUpdateList(system); } } }
public static ComponentType Exclude <T>() { return(Exclude(TypeManager.GetTypeIndex <T>())); }
internal void GetEntityArray(ref ComponentChunkIterator iterator, int length, out EntityArray output) { iterator.IndexInComponentGroup = 0; #if ENABLE_UNITY_COLLECTIONS_CHECKS //@TODO: Comment on why this has to be false... output = new EntityArray(iterator, length, m_SafetyManager.GetSafetyHandle(TypeManager.GetTypeIndex <Entity>(), false)); #else output = new EntityArray(iterator, length); #endif }
public ComponentType(Type type, AccessMode accessModeType = AccessMode.ReadWrite) { TypeIndex = TypeManager.GetTypeIndex(type); AccessModeType = accessModeType; }
public static unsafe TransformAccessArray GetTransformAccessArray(this EntityQuery group) { var state = (TransformAccessArrayState?)group._CachedState ?? new TransformAccessArrayState(); var orderVersion = group._EntityComponentStore->GetComponentTypeOrderVersion(TypeManager.GetTypeIndex <Transform>()); if (state.Data.isCreated && orderVersion == state.OrderVersion) { return(state.Data); } state.OrderVersion = orderVersion; UnityEngine.Profiling.Profiler.BeginSample("DirtyTransformAccessArrayUpdate"); var trans = group.ToComponentArray <Transform>(); if (!state.Data.isCreated) { state.Data = new TransformAccessArray(trans); } else { state.Data.SetTransforms(trans); } UnityEngine.Profiling.Profiler.EndSample(); group._CachedState = state; return(state.Data); }
public static ComponentType ReadWrite <T>() { return(FromTypeIndex(TypeManager.GetTypeIndex <T>())); }
public ComponentType(Type type, AccessMode accessModeType = AccessMode.ReadWrite) { TypeIndex = TypeManager.GetTypeIndex(type); this.AccessModeType = accessModeType; FixedArrayLength = -1; }
public static ComponentType ChunkComponent <T>() { var typeIndex = TypeManager.MakeChunkComponentTypeIndex(TypeManager.GetTypeIndex <T>()); return(FromTypeIndex(typeIndex)); }
/// <summary> /// Adds the collection of systems to the world by injecting them into the root level system groups /// (InitializationSystemGroup, SimulationSystemGroup and PresentationSystemGroup) /// </summary> public static void AddSystemsToRootLevelSystemGroups(World world, params Type[] systemTypes) { var initializationSystemGroup = world.GetOrCreateSystem <InitializationSystemGroup>(); var simulationSystemGroup = world.GetOrCreateSystem <SimulationSystemGroup>(); var presentationSystemGroup = world.GetOrCreateSystem <PresentationSystemGroup>(); var systems = world.GetOrCreateSystemsAndLogException(systemTypes.ToArray()); // Add systems to their groups, based on the [UpdateInGroup] attribute. foreach (var system in systems) { if (system == null) { continue; } // Skip the built-in root-level system groups var type = system.GetType(); if (type == typeof(InitializationSystemGroup) || type == typeof(SimulationSystemGroup) || type == typeof(PresentationSystemGroup)) { continue; } var groups = TypeManager.GetSystemAttributes(system.GetType(), typeof(UpdateInGroupAttribute)); if (groups.Length == 0) { simulationSystemGroup.AddSystemToUpdateList(system); } foreach (var g in groups) { var group = g as UpdateInGroupAttribute; if (group == null) { continue; } if (!TypeManager.IsSystemAGroup(group.GroupType)) { Debug.LogError($"Invalid [UpdateInGroup] attribute for {type}: {group.GroupType} must be derived from ComponentSystemGroup."); continue; } var groupMgr = world.GetExistingSystem(group.GroupType); if (groupMgr == null) { // Warn against unexpected behaviour combining DisableAutoCreation and UpdateInGroup var parentDisableAutoCreation = TypeManager.GetSystemAttributes(group.GroupType, typeof(DisableAutoCreationAttribute)).Length > 0; if (parentDisableAutoCreation) { Debug.LogWarning($"A system {type} wants to execute in {group.GroupType} but this group has [DisableAutoCreation] and {type} does not. The system will not be added to any group and thus not update."); } else { Debug.LogWarning( $"A system {type} could not be added to group {group.GroupType}, because the group was not created. Fix these errors before continuing. The system will not be added to any group and thus not update."); } continue; } var groupSys = groupMgr as ComponentSystemGroup; if (groupSys != null) { groupSys.AddSystemToUpdateList(system); } } } // Update player loop initializationSystemGroup.SortSystems(); simulationSystemGroup.SortSystems(); presentationSystemGroup.SortSystems(); }
public void CheckInternalConsistency() { // Iterate by archetype var entityCountByArchetype = 0; for (var i = 0; i < m_Archetypes.Length; ++i) { var archetype = m_Archetypes.Ptr[i]; var countInArchetype = 0; for (var j = 0; j < archetype->Chunks.Count; ++j) { var chunk = archetype->Chunks.p[j]; Assert.IsTrue(chunk->Archetype == archetype); Assert.IsTrue(chunk->Capacity >= chunk->Count); Assert.AreEqual(chunk->Count, archetype->Chunks.GetChunkEntityCount(j)); var chunkEntities = (Entity *)chunk->Buffer; AssertEntitiesExist(chunkEntities, chunk->Count); if (!chunk->Locked) { if (chunk->Count < chunk->Capacity) { if (archetype->NumSharedComponents == 0) { Assert.IsTrue(chunk->ListWithEmptySlotsIndex >= 0 && chunk->ListWithEmptySlotsIndex < archetype->ChunksWithEmptySlots.Length); Assert.IsTrue( chunk == archetype->ChunksWithEmptySlots.Ptr[chunk->ListWithEmptySlotsIndex]); } else { Assert.IsTrue(archetype->FreeChunksBySharedComponents.Contains(chunk)); } } } countInArchetype += chunk->Count; if (chunk->Archetype->HasChunkHeader) // Chunk entities with chunk components are not supported { Assert.IsFalse(chunk->Archetype->HasChunkComponents); } Assert.AreEqual(chunk->Archetype->HasChunkComponents, chunk->metaChunkEntity != Entity.Null); if (chunk->metaChunkEntity != Entity.Null) { var chunkHeaderTypeIndex = TypeManager.GetTypeIndex <ChunkHeader>(); AssertEntitiesExist(&chunk->metaChunkEntity, 1); AssertEntityHasComponent(chunk->metaChunkEntity, chunkHeaderTypeIndex); var chunkHeader = *(ChunkHeader *)GetComponentDataWithTypeRO(chunk->metaChunkEntity, chunkHeaderTypeIndex); Assert.IsTrue(chunk == chunkHeader.ArchetypeChunk.m_Chunk); var metaChunk = GetChunk(chunk->metaChunkEntity); Assert.IsTrue(metaChunk->Archetype == chunk->Archetype->MetaChunkArchetype); } } Assert.AreEqual(countInArchetype, archetype->EntityCount); entityCountByArchetype += countInArchetype; } // Iterate by free list Assert.IsTrue(m_EntityInChunkByEntity[m_NextFreeEntityIndex].Chunk == null); var entityCountByFreeList = EntitiesCapacity; int freeIndex = m_NextFreeEntityIndex; while (freeIndex != -1) { Assert.IsTrue(m_EntityInChunkByEntity[freeIndex].Chunk == null); Assert.IsTrue(freeIndex < EntitiesCapacity); freeIndex = m_EntityInChunkByEntity[freeIndex].IndexInChunk; entityCountByFreeList--; } // iterate by entities var entityCountByEntities = 0; var entityType = TypeManager.GetTypeIndex <Entity>(); for (var i = 0; i != EntitiesCapacity; i++) { var chunk = m_EntityInChunkByEntity[i].Chunk; if (chunk == null) { continue; } entityCountByEntities++; var archetype = m_ArchetypeByEntity[i]; Assert.AreEqual((IntPtr)archetype, (IntPtr)chunk->Archetype); Assert.AreEqual(entityType, archetype->Types[0].TypeIndex); Assert.IsTrue(m_EntityInChunkByEntity[i].IndexInChunk < m_EntityInChunkByEntity[i].Chunk->Count); var entity = *(Entity *)ChunkDataUtility.GetComponentDataRO(m_EntityInChunkByEntity[i].Chunk, m_EntityInChunkByEntity[i].IndexInChunk, 0); Assert.AreEqual(i, entity.Index); Assert.AreEqual(m_VersionByEntity[i], entity.Version); Assert.IsTrue(Exists(entity)); } Assert.AreEqual(entityCountByEntities, entityCountByArchetype); // Enabling this fails SerializeEntitiesWorksWithBlobAssetReferences. // There is some special entity 0 usage in the serialization code. // @TODO: Review with simon looks like a potential leak? //Assert.AreEqual(entityCountByEntities, entityCountByFreeList); }
internal void FlushPendingBuffers(bool playBack) { m_ProducerHandle.Complete(); m_ProducerHandle = new JobHandle(); int length; #if ENABLE_UNITY_COLLECTIONS_CHECKS length = m_PendingBuffers.Count; #else length = m_PendingBuffers.Length; #endif #if ENABLE_UNITY_COLLECTIONS_CHECKS List <string> playbackErrorLog = null; bool completeAllJobsBeforeDispose = false; #endif for (int i = 0; i < length; ++i) { var buffer = m_PendingBuffers[i]; if (!buffer.IsCreated) { continue; } if (playBack) { #if ENABLE_UNITY_COLLECTIONS_CHECKS try { var system = GetSystemFromSystemID(World, buffer.SystemID); var systemName = system != null?TypeManager.GetSystemName(system.GetType()) : "Unknown"; Profiler.BeginSample(systemName); buffer.Playback(EntityManager); Profiler.EndSample(); } catch (Exception e) { var system = GetSystemFromSystemID(World, buffer.SystemID); var systemType = system != null?system.GetType().ToString() : "Unknown"; var error = $"{e.Message}\nEntityCommandBuffer was recorded in {systemType} and played back in {GetType()}.\n" + e.StackTrace; if (playbackErrorLog == null) { playbackErrorLog = new List <string>(); } playbackErrorLog.Add(error); completeAllJobsBeforeDispose = true; } #else buffer.Playback(EntityManager); #endif } #if ENABLE_UNITY_COLLECTIONS_CHECKS try { if (completeAllJobsBeforeDispose) { // If we get here, there was an error during playback (potentially a race condition on the // buffer itself), and we should wait for all jobs writing to this command buffer to complete before attempting // to dispose of the command buffer to prevent a potential race condition. buffer.WaitForWriterJobs(); completeAllJobsBeforeDispose = false; } buffer.Dispose(); } catch (Exception e) { var system = GetSystemFromSystemID(World, buffer.SystemID); var systemType = system != null?system.GetType().ToString() : "Unknown"; var error = $"{e.Message}\nEntityCommandBuffer was recorded in {systemType} and disposed in {GetType()}.\n" + e.StackTrace; if (playbackErrorLog == null) { playbackErrorLog = new List <string>(); } playbackErrorLog.Add(error); } #else buffer.Dispose(); #endif m_PendingBuffers[i] = buffer; } #if ENABLE_UNITY_COLLECTIONS_CHECKS if (playbackErrorLog != null) { #if !NET_DOTS var exceptionMessage = new StringBuilder(); foreach (var err in playbackErrorLog) { exceptionMessage.AppendLine(err); } #else var exceptionMessage = ""; foreach (var err in playbackErrorLog) { exceptionMessage += err; exceptionMessage += '\n'; } #endif throw new System.ArgumentException(exceptionMessage.ToString()); } #endif }
public virtual void SortSystemUpdateList() { #if !UNITY_CSHARP_TINY lookupDictionary = null; #endif // Populate dictionary mapping systemType to system-and-before/after-types. // This is clunky - it is easier to understand, and cleaner code, to // just use a Dictionary<Type, SysAndDep>. However, Tiny doesn't currently have // the ability to use Type as a key to a NativeHash, so we're stuck until that gets addressed. // // Likewise, this is important shared code. It can be done cleaner with 2 versions, but then... // 2 sets of bugs and slightly different behavior will creep in. // var sysAndDep = new SysAndDep[m_systemsToUpdate.Count]; for (int i = 0; i < m_systemsToUpdate.Count; ++i) { var sys = m_systemsToUpdate[i]; if (TypeManager.IsSystemAGroup(sys.GetType())) { (sys as ComponentSystemGroup).SortSystemUpdateList(); } sysAndDep[i] = new SysAndDep { system = sys, updateBefore = new List <Type>(), nAfter = 0, }; } for (int i = 0; i < m_systemsToUpdate.Count; ++i) { var sys = m_systemsToUpdate[i]; var before = TypeManager.GetSystemAttributes(sys.GetType(), typeof(UpdateBeforeAttribute)); var after = TypeManager.GetSystemAttributes(sys.GetType(), typeof(UpdateAfterAttribute)); foreach (var attr in before) { var dep = attr as UpdateBeforeAttribute; int depIndex = LookupSysAndDep(dep.SystemType, sysAndDep); if (depIndex < 0) { #if !UNITY_CSHARP_TINY Debug.LogWarning("Ignoring invalid [UpdateBefore] dependency for " + sys.GetType() + ": " + dep.SystemType + " must be a member of the same ComponentSystemGroup."); #else Debug.LogWarning("WARNING: invalid [UpdateBefore] dependency:"); Debug.LogWarning(TypeManager.SystemName(sys.GetType())); Debug.LogWarning(" depends on a non-sibling or non-ComponentSystem."); #endif continue; } sysAndDep[i].updateBefore.Add(dep.SystemType); sysAndDep[depIndex].nAfter++; } foreach (var attr in after) { var dep = attr as UpdateAfterAttribute; int depIndex = LookupSysAndDep(dep.SystemType, sysAndDep); if (depIndex < 0) { #if !UNITY_CSHARP_TINY Debug.LogWarning("Ignoring invalid [UpdateAfter] dependency for " + sys.GetType() + ": " + dep.SystemType + " must be a member of the same ComponentSystemGroup."); #else Debug.LogWarning("WARNING: invalid [UpdateAfter] dependency:"); Debug.LogWarning(TypeManager.SystemName(sys.GetType())); Debug.LogWarning(" depends on a non-sibling or non-ComponentSystem."); #endif continue; } sysAndDep[depIndex].updateBefore.Add(sys.GetType()); sysAndDep[i].nAfter++; } } // Clear the systems list and rebuild it in sorted order from the lookup table var readySystems = new Heap <TypeHeapElement>(m_systemsToUpdate.Count); m_systemsToUpdate.Clear(); for (int i = 0; i < sysAndDep.Length; ++i) { if (sysAndDep[i].nAfter == 0) { readySystems.Insert(new TypeHeapElement(i, sysAndDep[i].system.GetType())); } } while (!readySystems.Empty) { int sysIndex = readySystems.Extract().unsortedIndex; SysAndDep sd = sysAndDep[sysIndex]; Type sysType = sd.system.GetType(); sysAndDep[sysIndex] = new SysAndDep(); // "Remove()" m_systemsToUpdate.Add(sd.system); foreach (var beforeType in sd.updateBefore) { int beforeIndex = LookupSysAndDep(beforeType, sysAndDep); if (beforeIndex < 0) { throw new Exception("Bug in SortSystemUpdateList(), beforeIndex < 0"); } if (sysAndDep[beforeIndex].nAfter <= 0) { throw new Exception("Bug in SortSystemUpdateList(), nAfter <= 0"); } sysAndDep[beforeIndex].nAfter--; if (sysAndDep[beforeIndex].nAfter == 0) { readySystems.Insert(new TypeHeapElement(beforeIndex, sysAndDep[beforeIndex].system.GetType())); } } } for (int i = 0; i < sysAndDep.Length; ++i) { if (sysAndDep[i].system != null) { // Since no System in the circular dependency would have ever been added // to the heap, we should have values for everything in sysAndDep. Check, // just in case. #if ENABLE_UNITY_COLLECTIONS_CHECKS var visitedSystems = new List <ComponentSystemBase>(); var startIndex = i; var currentIndex = i; while (true) { if (sysAndDep[currentIndex].system != null) { visitedSystems.Add(sysAndDep[currentIndex].system); } currentIndex = LookupSysAndDep(sysAndDep[currentIndex].updateBefore[0], sysAndDep); if (currentIndex < 0 || currentIndex == startIndex || sysAndDep[currentIndex].system == null) { throw new CircularSystemDependencyException(visitedSystems); } } #else sysAndDep[i] = new SysAndDep(); #endif } } }
public static ComponentType ChunkComponentExclude(Type type) { var typeIndex = TypeManager.MakeChunkComponentTypeIndex(TypeManager.GetTypeIndex(type)); return(Exclude(typeIndex)); }
internal void SetSharedComponentDataBoxed(Entity entity, int typeIndex, int hashCode, object componentData) { BeforeStructuralChange(); Entities->AssertEntityHasComponent(entity, typeIndex); var newSharedComponentDataIndex = 0; if (componentData != null) // null means default { newSharedComponentDataIndex = m_SharedComponentManager.InsertSharedComponentAssumeNonDefault(typeIndex, hashCode, componentData, TypeManager.GetTypeInfo(typeIndex).FastEqualityTypeInfo); } Entities->SetSharedComponentDataIndex(ArchetypeManager, m_SharedComponentManager, entity, typeIndex, newSharedComponentDataIndex); m_SharedComponentManager.RemoveReference(newSharedComponentDataIndex); }
public static ComponentType Exclude(Type type) { return(Exclude(TypeManager.GetTypeIndex(type))); }
public int GetComponentOrderVersion <T>() { return(Entities->GetComponentTypeOrderVersion(TypeManager.GetTypeIndex <T>())); }
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(); }