internal static unsafe JobHandle ScheduleInternal <T>( ref T jobData, EntityQuery query, JobHandle dependsOn, ScheduleMode mode, int batchesPerChunk, bool isParallel = true) where T : struct, IJobEntityBatch { var queryImpl = query._GetImpl(); var queryData = queryImpl->_QueryData; var cachedChunks = queryData->GetMatchingChunkCache(); // Don't schedule the job if there are no chunks to work on var chunkCount = cachedChunks.Length; JobEntityBatchWrapper <T> jobEntityBatchWrapper = new JobEntityBatchWrapper <T> { #if ENABLE_UNITY_COLLECTIONS_CHECKS // All IJobEntityBatch jobs have a EntityManager safety handle to ensure that BeforeStructuralChange throws an error if // jobs without any other safety handles are still running (haven't been synced). safety = new EntitySafetyHandle { m_Safety = queryImpl->SafetyHandles->GetEntityManagerSafetyHandle() }, #endif MatchingArchetypes = queryData->MatchingArchetypes, CachedChunks = cachedChunks, Filter = queryImpl->_Filter, JobData = jobData, JobsPerChunk = batchesPerChunk, IsParallel = isParallel ? 1 : 0 }; var scheduleParams = new JobsUtility.JobScheduleParameters( UnsafeUtility.AddressOf(ref jobEntityBatchWrapper), isParallel ? JobEntityBatchProducer <T> .InitializeParallel() : JobEntityBatchProducer <T> .InitializeSingle(), dependsOn, mode); if (!isParallel) { return(JobsUtility.Schedule(ref scheduleParams)); } else { return(JobsUtility.ScheduleParallelFor(ref scheduleParams, chunkCount * batchesPerChunk, 1)); } }
internal static unsafe JobHandle ScheduleInternal <T>( ref T jobData, EntityQuery query, JobHandle dependsOn, ScheduleMode mode, int batchesPerChunk, bool isParallel = true) where T : struct, IJobEntityBatch { var queryImpl = query._GetImpl(); var filteredChunkCount = queryImpl->CalculateChunkCount(); var batches = new NativeArray <ArchetypeChunk>(filteredChunkCount * batchesPerChunk, Allocator.TempJob); var prefilterHandle = new PrefilterForJobEntityBatch { MatchingArchetypes = queryImpl->_QueryData->MatchingArchetypes, Filter = queryImpl->_Filter, BatchesPerChunk = batchesPerChunk, EntityComponentStore = queryImpl->_Access->EntityComponentStore, Batches = batches }.Schedule(dependsOn); JobEntityBatchWrapper <T> jobEntityBatchWrapper = new JobEntityBatchWrapper <T> { #if ENABLE_UNITY_COLLECTIONS_CHECKS // All IJobEntityBatch jobs have a EntityManager safety handle to ensure that BeforeStructuralChange throws an error if // jobs without any other safety handles are still running (haven't been synced). safety = new EntitySafetyHandle { m_Safety = queryImpl->SafetyHandles->GetEntityManagerSafetyHandle() }, #endif JobData = jobData, Batches = batches, JobsPerChunk = batchesPerChunk, IsParallel = isParallel ? 1 : 0 }; var scheduleParams = new JobsUtility.JobScheduleParameters( UnsafeUtility.AddressOf(ref jobEntityBatchWrapper), isParallel ? JobEntityBatchProducer <T> .InitializeParallel() : JobEntityBatchProducer <T> .InitializeSingle(), prefilterHandle, mode); #if ENABLE_UNITY_COLLECTIONS_CHECKS try { #endif if (!isParallel) { return(JobsUtility.Schedule(ref scheduleParams)); } else { return(JobsUtility.ScheduleParallelFor(ref scheduleParams, filteredChunkCount * batchesPerChunk, 1)); } #if ENABLE_UNITY_COLLECTIONS_CHECKS } catch (InvalidOperationException e) { prefilterHandle.Complete(); batches.Dispose(); throw e; } #endif }
internal static unsafe JobHandle ScheduleInternal <T>( ref T jobData, EntityQuery query, JobHandle dependsOn, ScheduleMode mode, int batchesPerChunk, bool isParallel = true, NativeArray <Entity> limitToEntityArray = default(NativeArray <Entity>)) where T : struct, IJobEntityBatch { var queryImpl = query._GetImpl(); var queryData = queryImpl->_QueryData; var cachedChunks = queryData->GetMatchingChunkCache(); // Don't schedule the job if there are no chunks to work on var chunkCount = cachedChunks.Length; var useEntityArray = limitToEntityArray.IsCreated; var prebuiltBatchList = default(UnsafeList); var perBatchMatchingArchetypeIndex = default(UnsafeIntList); var batchCount = chunkCount * batchesPerChunk; if (useEntityArray) { prebuiltBatchList = new UnsafeList(Allocator.TempJob); perBatchMatchingArchetypeIndex = new UnsafeIntList(0, Allocator.TempJob); // Forces the creation of an EntityQueryMask, which is necessary to filter batches. var access = queryImpl->_Access; access->EntityQueryManager->GetEntityQueryMask(queryData, access->EntityComponentStore); ChunkIterationUtility.FindBatchesForEntityArrayWithQuery( queryImpl->_Access->EntityComponentStore, queryData, ref queryImpl->_Filter, (Entity *)limitToEntityArray.GetUnsafePtr(), limitToEntityArray.Length, ref prebuiltBatchList, ref perBatchMatchingArchetypeIndex); batchCount = prebuiltBatchList.Length; } JobEntityBatchWrapper <T> jobEntityBatchWrapper = new JobEntityBatchWrapper <T> { #if ENABLE_UNITY_COLLECTIONS_CHECKS // All IJobEntityBatch jobs have a EntityManager safety handle to ensure that BeforeStructuralChange throws an error if // jobs without any other safety handles are still running (haven't been synced). safety = new EntitySafetyHandle { m_Safety = queryImpl->SafetyHandles->GetEntityManagerSafetyHandle() }, #endif MatchingArchetypes = queryData->MatchingArchetypes, CachedChunks = cachedChunks, Filter = queryImpl->_Filter, JobData = jobData, JobsPerChunk = batchesPerChunk, IsParallel = isParallel ? 1 : 0, UsePrebuiltBatchList = useEntityArray ? 1: 0, PrebuiltBatchList = prebuiltBatchList, PrebuiltBatchListMatchingArchetypeIndices = perBatchMatchingArchetypeIndex }; var scheduleParams = new JobsUtility.JobScheduleParameters( UnsafeUtility.AddressOf(ref jobEntityBatchWrapper), isParallel ? JobEntityBatchProducer <T> .InitializeParallel() : JobEntityBatchProducer <T> .InitializeSingle(), dependsOn, mode); var result = default(JobHandle); if (!isParallel) { result = JobsUtility.Schedule(ref scheduleParams); } else { result = JobsUtility.ScheduleParallelFor(ref scheduleParams, batchCount, 1); } if (useEntityArray) { result = prebuiltBatchList.Dispose(result); result = perBatchMatchingArchetypeIndex.Dispose(result); } return(result); }