public ComponentJobSafetyManager() { #if ENABLE_UNITY_COLLECTIONS_CHECKS m_TempSafety = AtomicSafetyHandle.Create(); #endif m_ReadJobFences = (JobHandle *)UnsafeUtility.Malloc(sizeof(JobHandle) * kMaxReadJobHandles * kMaxTypes, 16, Allocator.Persistent); UnsafeUtility.MemClear(m_ReadJobFences, sizeof(JobHandle) * kMaxReadJobHandles * kMaxTypes); m_ComponentSafetyHandles = (ComponentSafetyHandle *)UnsafeUtility.Malloc(sizeof(ComponentSafetyHandle) * kMaxTypes, 16, Allocator.Persistent); UnsafeUtility.MemClear(m_ComponentSafetyHandles, sizeof(ComponentSafetyHandle) * kMaxTypes); m_JobDependencyCombineBufferCount = 4 * 1024; m_JobDependencyCombineBuffer = (JobHandle *)UnsafeUtility.Malloc( sizeof(ComponentSafetyHandle) * m_JobDependencyCombineBufferCount, 16, Allocator.Persistent); #if ENABLE_UNITY_COLLECTIONS_CHECKS CreateComponentSafetyHandles(kMaxTypes); #endif m_HasCleanHandles = true; }
public ComponentJobSafetyManager() { #if ENABLE_UNITY_COLLECTIONS_CHECKS m_TempSafety = AtomicSafetyHandle.Create(); #endif m_ReadJobFences = (JobHandle *)UnsafeUtility.Malloc(sizeof(JobHandle) * kMaxReadJobHandles * kMaxTypes, 16, Allocator.Persistent); UnsafeUtility.MemClear(m_ReadJobFences, sizeof(JobHandle) * kMaxReadJobHandles * kMaxTypes); m_ComponentSafetyHandles = (ComponentSafetyHandle *)UnsafeUtility.Malloc(sizeof(ComponentSafetyHandle) * kMaxTypes, 16, Allocator.Persistent); UnsafeUtility.MemClear(m_ComponentSafetyHandles, sizeof(ComponentSafetyHandle) * kMaxTypes); m_JobDependencyCombineBufferCount = 4 * 1024; m_JobDependencyCombineBuffer = (JobHandle *)UnsafeUtility.Malloc( sizeof(ComponentSafetyHandle) * m_JobDependencyCombineBufferCount, 16, Allocator.Persistent); #if ENABLE_UNITY_COLLECTIONS_CHECKS for (var i = 0; i != kMaxTypes; i++) { m_ComponentSafetyHandles[i].SafetyHandle = AtomicSafetyHandle.Create(); AtomicSafetyHandle.SetAllowSecondaryVersionWriting(m_ComponentSafetyHandles[i].SafetyHandle, false); } #endif m_HasCleanHandles = true; }
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 void Dispose() { for (var i = 0; i < kMaxTypes; i++) { m_ComponentSafetyHandles[i].WriteFence.Complete(); } for (var i = 0; i < kMaxTypes * kMaxReadJobHandles; i++) { m_ReadJobFences[i].Complete(); } #if ENABLE_UNITY_COLLECTIONS_CHECKS for (var i = 0; i < kMaxTypes; i++) { var res = AtomicSafetyHandle.EnforceAllBufferJobsHaveCompletedAndRelease(m_ComponentSafetyHandles[i] .SafetyHandle); if (res == EnforceJobResult.DidSyncRunningJobs) { Debug.LogError( "Disposing EntityManager but a job is still running against the ComponentData. It appears the job has not been registered with JobComponentSystem.AddDependency."); } } AtomicSafetyHandle.Release(m_TempSafety); #endif UnsafeUtility.Free(m_JobDependencyCombineBuffer, Allocator.Persistent); UnsafeUtility.Free(m_ComponentSafetyHandles, Allocator.Persistent); m_ComponentSafetyHandles = null; UnsafeUtility.Free(m_ReadJobFences, Allocator.Persistent); m_ReadJobFences = null; }
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); }
public void OnCreate() { m_TypeArrayIndices = (ushort *)UnsafeUtility.Malloc(sizeof(ushort) * kMaxTypes, 16, Allocator.Persistent); UnsafeUtility.MemSet(m_TypeArrayIndices, 0xFF, sizeof(ushort) * kMaxTypes); #if ENABLE_UNITY_COLLECTIONS_CHECKS m_TempSafety = AtomicSafetyHandle.Create(); #endif m_ReadJobFences = (JobHandle *)UnsafeUtility.Malloc(sizeof(JobHandle) * kMaxReadJobHandles * kMaxTypes, 16, Allocator.Persistent); UnsafeUtility.MemClear(m_ReadJobFences, sizeof(JobHandle) * kMaxReadJobHandles * kMaxTypes); m_ComponentSafetyHandles = (ComponentSafetyHandle *)UnsafeUtility.Malloc(sizeof(ComponentSafetyHandle) * kMaxTypes, 16, Allocator.Persistent); UnsafeUtility.MemClear(m_ComponentSafetyHandles, sizeof(ComponentSafetyHandle) * kMaxTypes); m_JobDependencyCombineBufferCount = 4 * 1024; m_JobDependencyCombineBuffer = (JobHandle *)UnsafeUtility.Malloc( sizeof(ComponentSafetyHandle) * m_JobDependencyCombineBufferCount, 16, Allocator.Persistent); m_TypeCount = 0; IsInTransaction = false; IsInForEachDisallowStructuralChange = 0; m_ExclusiveTransactionDependency = default(JobHandle); }
public void Dispose() { for (var i = 0; i < m_DependencyHandlesCount; i++) { m_DependencyHandles[i].WriteFence.Complete(); } for (var i = 0; i < m_DependencyHandlesCount * kMaxReadJobHandles; i++) { m_ReadJobFences[i].Complete(); } Memory.Unmanaged.Free(m_JobDependencyCombineBuffer, Allocator.Persistent); Memory.Unmanaged.Free(m_TypeArrayIndices, Allocator.Persistent); Memory.Unmanaged.Free(m_DependencyHandles, Allocator.Persistent); m_DependencyHandles = null; Memory.Unmanaged.Free(m_ReadJobFences, Allocator.Persistent); m_ReadJobFences = null; #if ENABLE_UNITY_COLLECTIONS_CHECKS Safety.Dispose(); #endif }
public void OnCreate(WorldUnmanaged world) { m_World = world; m_TypeArrayIndices = (ushort *)Memory.Unmanaged.Allocate(sizeof(ushort) * kMaxTypes, 16, Allocator.Persistent); UnsafeUtility.MemSet(m_TypeArrayIndices, 0xFF, sizeof(ushort) * kMaxTypes); m_ReadJobFences = (JobHandle *)Memory.Unmanaged.Allocate(sizeof(JobHandle) * kMaxReadJobHandles * kMaxTypes, 16, Allocator.Persistent); UnsafeUtility.MemClear(m_ReadJobFences, sizeof(JobHandle) * kMaxReadJobHandles * kMaxTypes); m_DependencyHandles = (DependencyHandle *)Memory.Unmanaged.Allocate(sizeof(DependencyHandle) * kMaxTypes, 16, Allocator.Persistent); UnsafeUtility.MemClear(m_DependencyHandles, sizeof(DependencyHandle) * kMaxTypes); m_JobDependencyCombineBufferCount = 4 * 1024; m_JobDependencyCombineBuffer = (JobHandle *)Memory.Unmanaged.Allocate(sizeof(DependencyHandle) * m_JobDependencyCombineBufferCount, 16, Allocator.Persistent); m_DependencyHandlesCount = 0; _IsInTransaction = false; IsInForEachDisallowStructuralChange = 0; m_ExclusiveTransactionDependency = default; #if ENABLE_UNITY_COLLECTIONS_CHECKS Safety.OnCreate(); #endif m_Marker = new ProfilerMarker("CompleteAllJobs"); }
private unsafe string CheckJobDependencies(int type) { AtomicSafetyHandle safetyHandle = this.m_SafetyManager.GetSafetyHandle(type, true); int maxCount = AtomicSafetyHandle.GetReaderArray(safetyHandle, 0, IntPtr.Zero); JobHandle *handlePtr = (JobHandle *)stackalloc byte[(((IntPtr)maxCount) * sizeof(JobHandle))]; AtomicSafetyHandle.GetReaderArray(safetyHandle, maxCount, (IntPtr)handlePtr); int index = 0; while (true) { string str; if (index < maxCount) { if (this.m_SafetyManager.HasReaderOrWriterDependency(type, handlePtr[index])) { index++; continue; } str = $"The system {base.GetType()} reads {TypeManager.GetType(type)} via {AtomicSafetyHandle.GetReaderName(safetyHandle, index)} 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 if (!this.m_SafetyManager.HasReaderOrWriterDependency(type, AtomicSafetyHandle.GetWriter(safetyHandle))) { str = $"The system {base.GetType()} writes {TypeManager.GetType(type)} via {AtomicSafetyHandle.GetWriterName(safetyHandle)} 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 { str = null; } return(str); } }
public void OnCreate() { #if ENABLE_UNITY_COLLECTIONS_CHECKS m_TempSafety = AtomicSafetyHandle.Create(); #endif m_ReadJobFences = (JobHandle *)UnsafeUtility.Malloc(sizeof(JobHandle) * kMaxReadJobHandles * kMaxTypes, 16, Allocator.Persistent); UnsafeUtility.MemClear(m_ReadJobFences, sizeof(JobHandle) * kMaxReadJobHandles * kMaxTypes); m_ComponentSafetyHandles = (ComponentSafetyHandle *)UnsafeUtility.Malloc(sizeof(ComponentSafetyHandle) * kMaxTypes, 16, Allocator.Persistent); UnsafeUtility.MemClear(m_ComponentSafetyHandles, sizeof(ComponentSafetyHandle) * kMaxTypes); m_JobDependencyCombineBufferCount = 4 * 1024; m_JobDependencyCombineBuffer = (JobHandle *)UnsafeUtility.Malloc( sizeof(ComponentSafetyHandle) * m_JobDependencyCombineBufferCount, 16, Allocator.Persistent); #if ENABLE_UNITY_COLLECTIONS_CHECKS CreateComponentSafetyHandles(kMaxTypes); #endif m_HasCleanHandles = true; IsInTransaction = false; m_ExclusiveTransactionDependency = default(JobHandle); }
public static JobHandle ScheduleJob(JobBucket *bucket, System.Action action, JobHandle *dependedHandles, uint dependCount) { JobHandle handle; System.IntPtr ptr = Marshal.GetFunctionPointerForDelegate(action); ScheduleJob(handle.Ptr(), bucket, (void *)ptr, dependedHandles, dependCount); return(handle); }
public JobHandle AddDependency(int *readerTypes, int readerTypesCount, int *writerTypes, int writerTypesCount, JobHandle dependency) { #if ENABLE_UNITY_COLLECTIONS_CHECKS JobHandle *combinedDependencies = null; int combinedDependenciesCount = 0; #endif for (var i = 0; i != writerTypesCount; i++) { var writer = writerTypes[i]; m_ComponentSafetyHandles[writer].WriteFence = dependency; } for (var i = 0; i != readerTypesCount; i++) { var reader = readerTypes[i]; m_ReadJobFences[reader * kMaxReadJobHandles + m_ComponentSafetyHandles[reader].NumReadFences] = dependency; m_ComponentSafetyHandles[reader].NumReadFences++; if (m_ComponentSafetyHandles[reader].NumReadFences == kMaxReadJobHandles) { #if ENABLE_UNITY_COLLECTIONS_CHECKS var combined = CombineReadDependencies(reader); if (combinedDependencies == null) { JobHandle *temp = stackalloc JobHandle[readerTypesCount]; combinedDependencies = temp; } combinedDependencies[combinedDependenciesCount++] = combined; #else CombineReadDependencies(reader); #endif } } if (readerTypesCount != 0 || writerTypesCount != 0) { m_HasCleanHandles = false; } #if ENABLE_UNITY_COLLECTIONS_CHECKS if (combinedDependencies != null) { return(Unity.Jobs.LowLevel.Unsafe.JobHandleUnsafeUtility.CombineDependencies(combinedDependencies, combinedDependenciesCount)); } else { return(dependency); } #else return(dependency); #endif }
public unsafe static void CompleteAll(ref JobHandle job0, ref JobHandle job1) { JobHandle *ptr = stackalloc JobHandle[2]; *ptr = job0; ptr[1] = job1; JobHandle.ScheduleBatchedJobsAndCompleteAll((IntPtr)((void *)ptr), 2); job0 = default(JobHandle); job1 = default(JobHandle); }
public static unsafe JobHandle CombineDependencies(JobHandle *jobs, int count) { #if UNITY_SINGLETHREADED_JOBS return(default(JobHandle)); #else var fence = new JobHandle(); JobsUtility.ScheduleMultiDependencyJob(ref fence, JobsUtility.BatchScheduler, new IntPtr(jobs), count); return(fence); #endif }
private void DeleteCommentComplete() { for (int i = 0; i < Length; i++) { DeleteCommentJobHandles[i].Complete(); } UnsafeUtility.Free(DeleteCommentJobHandles, allocator); DeleteCommentJobHandles = null; _currentStage = Stage.Done; }
unsafe static void ScheduleNode(ref JobHandle *jobSched, JobHandle *jobDepends, Node *node, Point3 *points, int offset, int length, int depth, int depthSingleThreaded) { // pick median int median = length >> 1; // calc offsets var offsetL = offset; var offsetR = offset + median + 1; var lengthL = median; var lengthR = length - median - 1; var stepL = lengthL > 0 ? 1 : 0; var stepR = lengthR > 0 ? 1 + lengthL : 0; // make job var job = new BuildNodeJob() { node = node, points = points, offset = offset, length = length, depth = depth, leaf = (depth >= depthSingleThreaded), }; var jobHandle = jobSched++; if (jobDepends != null) { *jobHandle = job.Schedule(*jobDepends); } else { *jobHandle = job.Schedule(); } if (depth == 0) { JobHandle.ScheduleBatchedJobs(); } if (job.leaf) { return; } // schedule subtrees if (lengthL > 0) { ScheduleNode(ref jobSched, jobHandle, node + stepL, points, offsetL, lengthL, depth + 1, depthSingleThreaded); } if (lengthR > 0) { ScheduleNode(ref jobSched, jobHandle, node + stepR, points, offsetR, lengthR, depth + 1, depthSingleThreaded); } }
unsafe public static void CompleteAll(ref JobHandle job0, ref JobHandle job1) { JobHandle *jobs = stackalloc JobHandle[2]; jobs[0] = job0; jobs[1] = job1; ScheduleBatchedJobsAndCompleteAll(jobs, 2); job0 = new JobHandle(); job1 = new JobHandle(); }
public unsafe int GetReaderArray(int maxCount, JobHandle *handles) { int result = 0; fixed(AtomicSafetyHandle *ash = &this) { result = AtomicSafetyHandle_GetReaderArray(ash, maxCount, handles); } ExceptionReporter.Check(); return(result); }
public unsafe static void CompleteAll(ref JobHandle job0, ref JobHandle job1, ref JobHandle job2) { JobHandle *ptr = stackalloc JobHandle[3]; *ptr = job0; ptr[1] = job1; ptr[sizeof(JobHandle) * 2 / sizeof(JobHandle)] = job2; JobHandle.ScheduleBatchedJobsAndCompleteAll((IntPtr)((void *)ptr), 3); job0 = default(JobHandle); job1 = default(JobHandle); job2 = default(JobHandle); }
public unsafe JobHandle Dispose(JobHandle inputDeps) { JobHandle *deps = stackalloc JobHandle[5] { bucketStartsAndCounts.Dispose(inputDeps), xmins.Dispose(inputDeps), xmaxs.Dispose(inputDeps), yzminmaxs.Dispose(inputDeps), bodies.Dispose(inputDeps) }; return(Unity.Jobs.LowLevel.Unsafe.JobHandleUnsafeUtility.CombineDependencies(deps, 5)); }
public static unsafe JobHandle CombineDependencies(JobHandle *jobs, int count) { var fence = new JobHandle(); #if UNITY_SINGLETHREADED_JOBS fence.JobGroup = JobsUtility.GetFakeJobGroupId(); #if ENABLE_UNITY_COLLECTIONS_CHECKS JobsUtility.DebugDidScheduleJob(ref fence, jobs, count); #endif #else JobsUtility.ScheduleMultiDependencyJob(ref fence, JobsUtility.BatchScheduler, jobs, count); #endif return(fence); }
public unsafe int GetReaderArray(int maxCount, JobHandle *handles) { AtomicSafetyNode *node = GetInternalNode(); if (node == null) { return(0); } int count = node->readerCount < maxCount ? node->readerCount : maxCount; for (int i = 0; i < count; i++) { handles[i] = node->readers[i].fence; } return(node->readerCount); }
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); }
private void DeleteCommentAsyncUpdate() { bool isAnyRunning = false; for (int i = 0; i < Length; i++) { if (!DeleteCommentJobHandles[i].IsCompleted) { isAnyRunning = true; continue; } DeleteCommentJobHandles[i].Complete(); } if (isAnyRunning) { return; } if (DeleteCommentJobHandles != null) { UnsafeUtility.Free(DeleteCommentJobHandles, allocator); DeleteCommentJobHandles = null; } _currentStage = Stage.Done; }
unsafe string CheckJobDependencies(int type) { var h = m_SafetyManager.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 (!m_SafetyManager.HasReaderOrWriterDependency(type, readers[i])) { return($"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."); } } if (!m_SafetyManager.HasReaderOrWriterDependency(type, AtomicSafetyHandle.GetWriter(h))) { return($"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."); } return(null); }
unsafe public static JobHandle CombineDependencies(JobHandle *jobs, int count) { return(JobHandle.CombineDependenciesInternalPtr(jobs, count)); }
public JobHandle AddDependency(int *readerTypes, int readerTypesCount, int *writerTypes, int writerTypesCount, JobHandle dependency) { #if ENABLE_UNITY_COLLECTIONS_CHECKS JobHandle *combinedDependencies = null; var combinedDependenciesCount = 0; #endif if (readerTypesCount == 0 && writerTypesCount == 0) { ushort entityTypeArrayIndex = GetTypeArrayIndex(EntityTypeIndex); // if no dependency types are provided add read dependency to the Entity type // to ensure these jobs are still synced by CompleteAllJobsAndInvalidateArrays m_ReadJobFences[entityTypeArrayIndex * kMaxReadJobHandles + m_DependencyHandles[entityTypeArrayIndex].NumReadFences] = dependency; m_DependencyHandles[entityTypeArrayIndex].NumReadFences++; if (m_DependencyHandles[entityTypeArrayIndex].NumReadFences == kMaxReadJobHandles) { //@TODO: Check dynamically if the job debugger is enabled? #if ENABLE_UNITY_COLLECTIONS_CHECKS return(CombineReadDependencies(entityTypeArrayIndex)); #else CombineReadDependencies(entityTypeArrayIndex); #endif } return(dependency); } for (var i = 0; i != writerTypesCount; i++) { m_DependencyHandles[GetTypeArrayIndex(writerTypes[i])].WriteFence = dependency; } for (var i = 0; i != readerTypesCount; i++) { var reader = GetTypeArrayIndex(readerTypes[i]); m_ReadJobFences[reader * kMaxReadJobHandles + m_DependencyHandles[reader].NumReadFences] = dependency; m_DependencyHandles[reader].NumReadFences++; if (m_DependencyHandles[reader].NumReadFences == kMaxReadJobHandles) { #if ENABLE_UNITY_COLLECTIONS_CHECKS var combined = CombineReadDependencies(reader); if (combinedDependencies == null) { JobHandle *temp = stackalloc JobHandle[readerTypesCount]; combinedDependencies = temp; } combinedDependencies[combinedDependenciesCount++] = combined; #else CombineReadDependencies(reader); #endif } } #if ENABLE_UNITY_COLLECTIONS_CHECKS if (combinedDependencies != null) { return(JobHandleUnsafeUtility.CombineDependencies(combinedDependencies, combinedDependenciesCount)); } return(dependency); #else return(dependency); #endif }
[DllImport("JobSystemDLL")] private static extern void ScheduleJob(JobHandle *handle, JobBucket *bucket, void *funcPtr, JobHandle *dependedHandles, uint dependCount);
public JobHandle AddDependency(int *readerTypes, int readerTypesCount, int *writerTypes, int writerTypesCount, JobHandle dependency) { #if ENABLE_UNITY_COLLECTIONS_CHECKS JobHandle *combinedDependencies = null; var combinedDependenciesCount = 0; #endif m_HasCleanHandles = false; if (readerTypesCount == 0 && writerTypesCount == 0) { // if no dependency types are provided add read dependency to the Entity type // to ensure these jobs are still synced by CompleteAllJobsAndInvalidateArrays m_ReadJobFences[EntityTypeIndex * kMaxReadJobHandles + m_ComponentSafetyHandles[EntityTypeIndex].NumReadFences] = dependency; m_ComponentSafetyHandles[EntityTypeIndex].NumReadFences++; if (m_ComponentSafetyHandles[EntityTypeIndex].NumReadFences == kMaxReadJobHandles) { #if ENABLE_UNITY_COLLECTIONS_CHECKS return(CombineReadDependencies(EntityTypeIndex)); #else CombineReadDependencies(EntityTypeIndex); #endif } return(dependency); } for (var i = 0; i != writerTypesCount; i++) { var writer = writerTypes[i] & TypeManager.ClearFlagsMask; m_ComponentSafetyHandles[writer].WriteFence = dependency; } for (var i = 0; i != readerTypesCount; i++) { var reader = readerTypes[i] & TypeManager.ClearFlagsMask; m_ReadJobFences[reader * kMaxReadJobHandles + m_ComponentSafetyHandles[reader].NumReadFences] = dependency; m_ComponentSafetyHandles[reader].NumReadFences++; if (m_ComponentSafetyHandles[reader].NumReadFences == kMaxReadJobHandles) { #if ENABLE_UNITY_COLLECTIONS_CHECKS var combined = CombineReadDependencies(reader); if (combinedDependencies == null) { JobHandle *temp = stackalloc JobHandle[readerTypesCount]; combinedDependencies = temp; } combinedDependencies[combinedDependenciesCount++] = combined; #else CombineReadDependencies(reader); #endif } } #if ENABLE_UNITY_COLLECTIONS_CHECKS if (combinedDependencies != null) { return(JobHandleUnsafeUtility.CombineDependencies(combinedDependencies, combinedDependenciesCount)); } return(dependency); #else return(dependency); #endif }
// Schedule all the jobs for the simulation step. // Enqueued callbacks can choose to inject additional jobs at defined sync points. public unsafe void ScheduleStepJobs(SimulationStepInput input, JobHandle inputDeps) { if (input.TimeStep < 0) { throw new ArgumentOutOfRangeException(); } if (input.ThreadCountHint <= 0) { throw new ArgumentOutOfRangeException(); } if (input.NumSolverIterations <= 0) { throw new ArgumentOutOfRangeException(); } // Dispose event streams from previous frame JobHandle handle = DisposeEventStreams(inputDeps); // Allocate storage for input velocities m_Storage.InputVelocityCount = input.World.NumDynamicBodies; m_Context = new Context { TimeStep = input.TimeStep, InputVelocities = m_Storage.InputVelocities }; if (input.World.NumDynamicBodies == 0) { // No need to do anything, since nothing can move FinalSimulationJobHandle = handle; FinalJobHandle = handle; return; } SimulationCallbacks callbacks = input.Callbacks ?? new SimulationCallbacks(); // Find all body pairs that overlap in the broadphase handle = input.World.CollisionWorld.Broadphase.ScheduleFindOverlapsJobs( out BlockStream dynamicVsDynamicBodyPairs, out BlockStream dynamicVsStaticBodyPairs, ref m_Context, handle); var postOverlapsHandle = handle; // Sort all overlapping and jointed body pairs into phases handle = m_Scheduler.ScheduleCreatePhasedDispatchPairsJob( ref input.World, ref dynamicVsDynamicBodyPairs, ref dynamicVsStaticBodyPairs, ref m_Context, handle); // Apply gravity and copy input velocities at this point (in parallel with the scheduler, but before the callbacks) var applyGravityAndCopyInputVelocitiesHandle = Solver.ScheduleApplyGravityAndCopyInputVelocitiesJob( ref input.World.DynamicsWorld, m_Storage.InputVelocities, input.TimeStep * input.Gravity, postOverlapsHandle); handle = JobHandle.CombineDependencies(handle, applyGravityAndCopyInputVelocitiesHandle); handle = callbacks.Execute(SimulationCallbacks.Phase.PostCreateDispatchPairs, this, ref input.World, handle); // Create contact points & joint Jacobians handle = NarrowPhase.ScheduleProcessBodyPairsJobs(ref input.World, input.TimeStep, input.NumSolverIterations, ref m_Context, handle); handle = callbacks.Execute(SimulationCallbacks.Phase.PostCreateContacts, this, ref input.World, handle); // Create contact Jacobians handle = Solver.ScheduleBuildContactJacobiansJobs(ref input.World.DynamicsWorld, input.TimeStep, math.length(input.Gravity), ref m_Context, handle); handle = callbacks.Execute(SimulationCallbacks.Phase.PostCreateContactJacobians, this, ref input.World, handle); // Solve all Jacobians handle = Solver.ScheduleSolveJacobiansJobs(ref input.World.DynamicsWorld, input.TimeStep, input.NumSolverIterations, ref m_Context, handle); handle = callbacks.Execute(SimulationCallbacks.Phase.PostSolveJacobians, this, ref input.World, handle); // Integrate motions handle = Integrator.ScheduleIntegrateJobs(ref input.World.DynamicsWorld, input.TimeStep, handle); // Synchronize the collision world if (input.SynchronizeCollisionWorld) { handle = input.World.CollisionWorld.ScheduleUpdateDynamicLayer(ref input.World, input.TimeStep, input.Gravity, input.ThreadCountHint, handle); // TODO: timeStep = 0? } // Return the final simulation handle FinalSimulationJobHandle = handle; // Return the final handle, which includes disposing temporary arrays JobHandle *deps = stackalloc JobHandle[11] { FinalSimulationJobHandle, m_Context.DisposeOverlapPairs0, m_Context.DisposeOverlapPairs1, m_Context.DisposeBroadphasePairs0, m_Context.DisposeBroadphasePairs1, m_Context.DisposeContacts, m_Context.DisposeJacobians, m_Context.DisposeJointJacobians, m_Context.DisposeSolverSchedulerData, m_Context.DisposeProcessBodyPairs, m_Context.DisposePhasedDispatchPairs }; FinalJobHandle = JobHandleUnsafeUtility.CombineDependencies(deps, 11); }