Beispiel #1
0
        internal void DestroyInstance()
        {
            PreDisposeCheck();

            #if ENABLE_UNITY_COLLECTIONS_CHECKS
            m_UniversalQuery._DisallowDisposing           = null;
            m_UniversalQueryWithChunks._DisallowDisposing = null;
            #endif
            m_UniversalQuery.Dispose();
            m_UniversalQueryWithChunks.Dispose();
            m_UniversalQuery           = null;
            m_UniversalQueryWithChunks = null;

            m_DependencyManager->Dispose();
            UnsafeUtility.Free(m_DependencyManager, Allocator.Persistent);
            m_DependencyManager = null;

            Entities.EntityComponentStore.Destroy(m_EntityComponentStore);
            m_EntityComponentStore = null;

            Entities.EntityQueryManager.Destroy(m_EntityQueryManager);
            m_EntityQueryManager = null;

            m_EntityQueryManager = null;
            m_ExclusiveEntityTransaction.OnDestroy();

            m_ManagedComponentStore.Dispose();

            m_World = null;
            m_Debug = null;
        }
        internal virtual void OnBeforeCreateInternal(World world)
        {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
            m_SystemID = World.AllocateSystemID();
#endif
            m_World             = world;
            m_EntityManager     = world.EntityManager;
            m_DependencyManager = m_EntityManager.DependencyManager;

            m_JobDependencyForReadingSystems = new UnsafeIntList(0, Allocator.Persistent);
            m_JobDependencyForWritingSystems = new UnsafeIntList(0, Allocator.Persistent);

            m_EntityQueries = new EntityQuery[0];
#if !NET_DOTS
            m_AlwaysUpdateSystem = GetType().GetCustomAttributes(typeof(AlwaysUpdateSystemAttribute), true).Length != 0;
#else
            m_AlwaysUpdateSystem = false;
            var attrs = TypeManager.GetSystemAttributes(GetType());
            foreach (var attr in attrs)
            {
                if (attr.GetType() == typeof(AlwaysUpdateSystemAttribute))
                {
                    m_AlwaysUpdateSystem = true;
                }
            }
#endif
        }
Beispiel #3
0
        public void AddComponentWithValidation(UnsafeMatchingArchetypePtrList archetypeList, EntityQueryFilter filter,
                                               ComponentType componentType, ComponentDependencyManager *dependencyManager)
        {
            AssertCanAddComponent(archetypeList, componentType);

            var chunks = ChunkIterationUtility.CreateArchetypeChunkArray(archetypeList, Collections.Allocator.TempJob, ref filter, dependencyManager);

            if (chunks.Length > 0)
            {
                //@TODO the fast path for a chunk that contains a single entity is only possible if the chunk doesn't have a Locked Entity Order
                //but we should still be allowed to add zero sized components to chunks with a Locked Entity Order, even ones that only contain a single entity

                /*
                 * if ((chunks.Length == 1) && (chunks[0].Count == 1))
                 * {
                 *  var entityPtr = (Entity*) chunks[0].m_Chunk->Buffer;
                 *  StructuralChange.AddComponentEntity(EntityComponentStore, entityPtr, componentType.TypeIndex);
                 * }
                 * else
                 * {
                 */
                AddComponent((ArchetypeChunk *)NativeArrayUnsafeUtility.GetUnsafePtr(chunks), chunks.Length, componentType);

                /*
                 * }
                 */
            }

            chunks.Dispose();
        }
        static bool CheckJobDependencies(ref SafetyErrorDetails details, int type, ComponentDependencyManager *dependencyManager)
        {
            var h = dependencyManager->Safety.GetSafetyHandle(type, true);

            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 (!dependencyManager->HasReaderOrWriterDependency(type, readers[i]))
                {
                    details.m_ProblematicTypeIndex = type;
                    details.m_ProblematicHandle    = h;
                    details.m_ReaderIndex          = i;
                    return(true);
                }
            }

            if (!dependencyManager->HasReaderOrWriterDependency(type, AtomicSafetyHandle.GetWriter(h)))
            {
                details.m_ProblematicTypeIndex = type;
                details.m_ProblematicHandle    = h;
                details.m_ReaderIndex          = -1;
                return(true);
            }

            return(false);
        }
Beispiel #5
0
        public static EntityQueryManager *Create(ComponentDependencyManager *dependencyManager)
        {
            var queryManager = (EntityQueryManager *)UnsafeUtility.Malloc(sizeof(EntityQueryManager), 64, Allocator.Persistent);

            queryManager->m_DependencyManager       = dependencyManager;
            queryManager->m_GroupDataChunkAllocator = new BlockAllocator();
            ref var groupCache = ref UnsafeUtilityEx.As <UntypedUnsafeHashMap, UnsafeMultiHashMap <int, int> >(ref queryManager->m_EntityGroupDataCacheUntyped);
Beispiel #6
0
        internal void DestroyInstance()
        {
            EndExclusiveEntityTransaction();

            m_DependencyManager->PreDisposeCheck();

            m_UniversalQuery.Dispose();
            m_UniversalQuery = null;

            m_UniversalQueryWithChunks.Dispose();
            m_UniversalQueryWithChunks = null;

            m_DependencyManager->Dispose();
            UnsafeUtility.Free(m_DependencyManager, Allocator.Persistent);
            m_DependencyManager = null;

            Entities.EntityComponentStore.Destroy(m_EntityComponentStore);

            m_EntityComponentStore = null;
            m_EntityQueryManager.Dispose();
            m_EntityQueryManager = null;
            m_ExclusiveEntityTransaction.OnDestroy();

            m_ManagedComponentStore.Dispose();

            m_World = null;
            m_Debug = null;
        }
Beispiel #7
0
 public EntityQueryManager(ComponentDependencyManager *safetyManager)
 {
     m_JobSafetyManager        = safetyManager;
     m_GroupDataChunkAllocator = new ChunkAllocator();
     m_EntityGroupDataCache    = new NativeMultiHashMap <int, int>(1024, Allocator.Persistent);
     m_EntityGroupDatas        = new UnsafeEntityQueryDataPtrList(0, Allocator.Persistent);
 }
Beispiel #8
0
        public void RemoveComponentWithValidation(UnsafeMatchingArchetypePtrList archetypeList, EntityQueryFilter filter,
                                                  ComponentType componentType, ComponentDependencyManager *dependencyManager)
        {
            var chunks = ChunkIterationUtility.CreateArchetypeChunkArray(archetypeList, Collections.Allocator.TempJob, ref filter, dependencyManager);

            RemoveComponentWithValidation(chunks, componentType);
            chunks.Dispose();
        }
Beispiel #9
0
        /// <summary>
        /// Creates a NativeArray with all the chunks in a given archetype filtered by the provided EntityQueryFilter.
        /// This function will sync the needed types in the EntityQueryFilter.
        /// </summary>
        /// <param name="matchingArchetypes">List of matching archetypes.</param>
        /// <param name="allocator">Allocator to use for the array.</param>
        /// <param name="jobHandle">Handle to the GatherChunks job used to fill the output array.</param>
        /// <param name="filter">Filter used to filter the resulting chunks</param>
        /// <param name="dependencyManager">The ComponentDependencyManager belonging to this world</param>
        /// <param name="dependsOn">All jobs spawned will depend on this JobHandle</param>

        /// <returns>NativeArray of all the chunks in the matchingArchetypes list.</returns>
        public static NativeArray <ArchetypeChunk> CreateArchetypeChunkArray(
            UnsafeMatchingArchetypePtrList matchingArchetypes, Allocator allocator,
            ref EntityQueryFilter filter, ComponentDependencyManager *dependencyManager)
        {
            EntityQuery.SyncFilterTypes(ref matchingArchetypes, ref filter, dependencyManager);
            var chunks = CreateArchetypeChunkArrayWithoutSync(matchingArchetypes, allocator, out var jobHandle, ref filter);

            jobHandle.Complete();
            return(chunks);
        }
Beispiel #10
0
    public EntityDataAccess(EntityManager entityManager, bool isMainThread)
    {
        m_EntityManager      = GCHandle.Alloc(entityManager, GCHandleType.Weak);
        EntityComponentStore = entityManager.EntityComponentStore;
        EntityQueryManager   = entityManager.EntityQueryManager;
        DependencyManager    = entityManager.DependencyManager;

        m_IsMainThread        = isMainThread;
        m_EntityOnlyArchetype = default;
    }
 internal ArchetypeChunkIterator(UnsafeMatchingArchetypePtrList match, ComponentDependencyManager *safetyManager, uint globalSystemVersion,
                                 ref EntityQueryFilter filter)
 {
     m_MatchingArchetypeList               = match;
     m_CurrentArchetypeIndex               = 0;
     m_CurrentChunkInArchetypeIndex        = -1;
     m_CurrentChunkFirstEntityIndexInQuery = 0;
     m_PreviousMatchingChunk               = null;
     m_Filter = filter;
     m_GlobalSystemVersion = globalSystemVersion;
     m_SafetyManager       = safetyManager;
 }
        internal EntityManager(World world)
        {
            TypeManager.Initialize();
            StructuralChange.Initialize();
            EntityCommandBuffer.Initialize();

            m_World = world;

            m_DependencyManager =
                (ComponentDependencyManager *)UnsafeUtility.Malloc(sizeof(ComponentDependencyManager), 64,
                                                                   Allocator.Persistent);
            m_DependencyManager->OnCreate();

            m_EntityComponentStore  = Entities.EntityComponentStore.Create(world.SequenceNumber << 32);
            m_EntityQueryManager    = Unity.Entities.EntityQueryManager.Create(m_DependencyManager);
            m_ManagedComponentStore = new ManagedComponentStore();

            m_EntityDataAccess = new EntityDataAccess(this, true);

            m_ExclusiveEntityTransaction = new ExclusiveEntityTransaction(this);

            m_UniversalQuery = CreateEntityQuery(
                new EntityQueryDesc
            {
                Options = EntityQueryOptions.IncludePrefab | EntityQueryOptions.IncludeDisabled
            }
                );

            m_UniversalQueryWithChunks = CreateEntityQuery(
                new EntityQueryDesc
            {
                All     = new[] { ComponentType.ReadWrite <ChunkHeader>() },
                Options = EntityQueryOptions.IncludeDisabled | EntityQueryOptions.IncludePrefab
            },
                new EntityQueryDesc
            {
                Options = EntityQueryOptions.IncludeDisabled | EntityQueryOptions.IncludePrefab
            }
                );

            #if ENABLE_UNITY_COLLECTIONS_CHECKS
            m_UniversalQuery._DisallowDisposing           = "EntityManager.UniversalQuery may not be disposed";
            m_UniversalQueryWithChunks._DisallowDisposing = "EntityManager.UniversalQuery may not be disposed";
            #endif
        }
        internal void OnAfterDestroyInternal()
        {
            foreach (var query in m_EntityQueries)
            {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                query._DisallowDisposing = null;
#endif
                query.Dispose();
            }

            m_EntityQueries     = null;
            m_EntityManager     = null;
            m_World             = null;
            m_DependencyManager = null;

            m_JobDependencyForReadingSystems.Dispose();
            m_JobDependencyForWritingSystems.Dispose();
        }
        static string CheckJobDependencies(object system, int type, ComponentDependencyManager *dependencyManager)
        {
            var h = dependencyManager->Safety.GetSafetyHandle(type, true);

            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 (!dependencyManager->HasReaderOrWriterDependency(type, readers[i]))
                {
                    if (IsSystemV1(system))
                    {
                        return($"The system {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.");
                    }
                    else
                    {
                        return($"The system {system.GetType()} reads {TypeManager.GetType(type)} via {AtomicSafetyHandle.GetReaderName(h, i)} but that type was not assigned to the Dependency property. To ensure correct behavior of other systems, the job or a dependency must be assigned to the Dependency property before returning from the OnUpdate method.");
                    }
                }
            }

            if (!dependencyManager->HasReaderOrWriterDependency(type, AtomicSafetyHandle.GetWriter(h)))
            {
                if (IsSystemV1(system))
                {
                    return($"The system {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.");
                }
                else
                {
                    return($"The system {system.GetType()} writes {TypeManager.GetType(type)} via {AtomicSafetyHandle.GetWriterName(h)} but that type was not assigned to the Dependency property. To ensure correct behavior of other systems, the job or a dependency must be assigned to the Dependency property before returning from the OnUpdate method.");
                }
            }

            return(null);
        }
Beispiel #15
0
        internal EntityManager(World world)
        {
            TypeManager.Initialize();
            StructuralChange.Initialize();

            m_World = world;

            m_DependencyManager =
                (ComponentDependencyManager *)UnsafeUtility.Malloc(sizeof(ComponentDependencyManager), 64,
                                                                   Allocator.Persistent);
            m_DependencyManager->OnCreate();

            m_EntityComponentStore  = Entities.EntityComponentStore.Create(world.SequenceNumber << 32);
            m_ManagedComponentStore = new ManagedComponentStore();
            m_EntityQueryManager    = new EntityQueryManager(m_DependencyManager);
            m_EntityDataAccess      = new EntityDataAccess(this, true);

            m_ExclusiveEntityTransaction = new ExclusiveEntityTransaction(this);

            m_UniversalQuery = CreateEntityQuery(
                new EntityQueryDesc
            {
                Options = EntityQueryOptions.IncludePrefab | EntityQueryOptions.IncludeDisabled
            }
                );

            m_UniversalQueryWithChunks = CreateEntityQuery(
                new EntityQueryDesc
            {
                All     = new[] { ComponentType.ReadWrite <ChunkHeader>() },
                Options = EntityQueryOptions.IncludeDisabled | EntityQueryOptions.IncludePrefab
            },
                new EntityQueryDesc
            {
                Options = EntityQueryOptions.IncludeDisabled | EntityQueryOptions.IncludePrefab
            }
                );
        }
        internal static bool CheckSafetyAfterUpdate(ref UnsafeIntList readingSystems, ref UnsafeIntList writingSystems,
                                                    ComponentDependencyManager *dependencyManager, out SafetyErrorDetails details)
        {
            details = default;

            // Check that all reading and writing jobs are a dependency of the output job, to
            // catch systems that forget to add one of their jobs to the dependency graph.
            //
            // Note that this check is not strictly needed as we would catch the mistake anyway later,
            // but checking it here means we can flag the system that has the mistake, rather than some
            // other (innocent) system that is doing things correctly.

            //@TODO: It is not ideal that we call m_SafetyManager.GetDependency,
            //       it can result in JobHandle.CombineDependencies calls.
            //       Which seems like debug code might have side-effects

            for (var index = 0; index < readingSystems.Length; index++)
            {
                var type = readingSystems.Ptr[index];
                if (CheckJobDependencies(ref details, type, dependencyManager))
                {
                    return(true);
                }
            }

            for (var index = 0; index < writingSystems.Length; index++)
            {
                var type = writingSystems.Ptr[index];
                if (CheckJobDependencies(ref details, type, dependencyManager))
                {
                    return(true);
                }
            }

// EmergencySyncAllJobs(ref readingSystems, ref writingSystems, dependencyManager);

            return(false);
        }
        internal static void EmergencySyncAllJobs(ref UnsafeIntList readingSystems, ref UnsafeIntList writingSystems, ComponentDependencyManager *dependencyManager)
        {
            for (int i = 0; i != readingSystems.Length; i++)
            {
                int type = readingSystems.Ptr[i];
                AtomicSafetyHandle.EnforceAllBufferJobsHaveCompleted(dependencyManager->Safety.GetSafetyHandle(type, true));
            }

            for (int i = 0; i != writingSystems.Length; i++)
            {
                int type = writingSystems.Ptr[i];
                AtomicSafetyHandle.EnforceAllBufferJobsHaveCompleted(dependencyManager->Safety.GetSafetyHandle(type, true));
            }
        }
        internal static string CheckSafetyAfterUpdate(object system, ref UnsafeIntList readingSystems, ref UnsafeIntList writingSystems, ComponentDependencyManager *dependencyManager)
        {
            // Check that all reading and writing jobs are a dependency of the output job, to
            // catch systems that forget to add one of their jobs to the dependency graph.
            //
            // Note that this check is not strictly needed as we would catch the mistake anyway later,
            // but checking it here means we can flag the system that has the mistake, rather than some
            // other (innocent) system that is doing things correctly.

            //@TODO: It is not ideal that we call m_SafetyManager.GetDependency,
            //       it can result in JobHandle.CombineDependencies calls.
            //       Which seems like debug code might have side-effects

            string dependencyError = null;

            for (var index = 0; index < readingSystems.Length && dependencyError == null; index++)
            {
                var type = readingSystems.Ptr[index];
                dependencyError = CheckJobDependencies(system, type, dependencyManager);
            }

            for (var index = 0; index < writingSystems.Length && dependencyError == null; index++)
            {
                var type = writingSystems.Ptr[index];
                dependencyError = CheckJobDependencies(system, type, dependencyManager);
            }

            if (dependencyError != null)
            {
                EmergencySyncAllJobs(ref readingSystems, ref writingSystems, dependencyManager);
            }

            return(dependencyError);
        }
 public static void Create(EntityQueryManager *queryManager, ComponentDependencyManager *dependencyManager)
 {
     queryManager->m_DependencyManager       = dependencyManager;
     queryManager->m_GroupDataChunkAllocator = new BlockAllocator(AllocatorManager.Persistent, 16 * 1024 * 1024); // 16MB should be enough
     ref var groupCache = ref UnsafeUtility.As <UntypedUnsafeHashMap, UnsafeMultiHashMap <int, int> >(ref queryManager->m_EntityGroupDataCacheUntyped);