static unsafe JobHandle Schedule <T>(ref T jobData, IntPtr arrayLengthPtr, int innerloopBatchCount, JobHandle dependsOn) where T : struct, IJobParallelForDefer { #if UNITY_SINGLETHREADED_JOBS var arrayLength = UnsafeUtility.AsRef <int>(arrayLengthPtr.ToPointer()); for (var i = 0; i < arrayLength; ++i) { jobData.Execute(i); } DoDeallocateOnJobCompletion(jobData); return(new JobHandle()); #else var jobStruct = new JobStructDefer <T>() { JobData = jobData, ArrayLengthPtr = arrayLengthPtr, }; var jobDataPtr = UnsafeUtility.Malloc(UnsafeUtility.SizeOf <JobStructDefer <T> >(), UnsafeUtility.AlignOf <JobStructDefer <T> >(), Allocator.TempJob); UnsafeUtility.CopyStructureToPtr(ref jobStruct, jobDataPtr); var scheduleParams = new JobsUtility.JobScheduleParameters(jobDataPtr, JobStructDefer <T> .Initialize(), dependsOn, ScheduleMode.Batched); return(JobsUtility.ScheduleParallelFor(ref scheduleParams, JobsUtility.JobQueueThreadCount, innerloopBatchCount)); #endif }
/// <summary> /// Schedule the job for execution on worker threads. /// forEachCount is a pointer to the number of iterations, when dependsOn has completed. /// This API is unsafe, it is recommended to use the NativeList based Schedule method instead. /// </summary> /// <param name="jobData"></param> /// <param name="forEachCount"></param> /// <param name="innerloopBatchCount"></param> /// <param name="dependsOn"></param> /// <typeparam name="T"></typeparam> /// <returns></returns> public static unsafe JobHandle Schedule <T>(this T jobData, int *forEachCount, int innerloopBatchCount, JobHandle dependsOn = new JobHandle()) where T : struct, IJobParallelForDefer { var scheduleParams = new JobsUtility.JobScheduleParameters( UnsafeUtility.AddressOf(ref jobData), JobStructDefer <T> .Initialize(), dependsOn, ScheduleMode.Batched); var forEachListPtr = (byte *)forEachCount - sizeof(void *); return(JobsUtility.ScheduleParallelForDeferArraySize(ref scheduleParams, innerloopBatchCount, forEachListPtr, null)); }
static unsafe JobHandle Schedule <T>(ref T jobData, IntPtr arrayLengthPtr, int innerloopBatchCount, JobHandle dependsOn) where T : struct, IJobParallelForDefer { #if UNITY_SINGLETHREADED_JOBS var arrayLength = UnsafeUtility.AsRef <int>(arrayLengthPtr.ToPointer()); for (var i = 0; i < arrayLength; ++i) { jobData.Execute(i); } DoDeallocateOnJobCompletion(jobData); return(new JobHandle()); #else // Protect against garbage collection if (!JobStructDefer <T> .ExecuteHandle.IsAllocated) { JobStructDefer <T> .ExecuteDelegate = JobStructDefer <T> .Execute; JobStructDefer <T> .ExecuteHandle = GCHandle.Alloc(JobStructDefer <T> .ExecuteDelegate); JobStructDefer <T> .ExecuteFunctionPtr = Marshal.GetFunctionPointerForDelegate(JobStructDefer <T> .ExecuteDelegate); } // Protect against garbage collection if (!JobStructDefer <T> .CleanupHandle.IsAllocated) { JobStructDefer <T> .CleanupDelegate = JobStructDefer <T> .Cleanup; JobStructDefer <T> .CleanupHandle = GCHandle.Alloc(JobStructDefer <T> .CleanupDelegate); JobStructDefer <T> .CleanupFunctionPtr = Marshal.GetFunctionPointerForDelegate(JobStructDefer <T> .CleanupDelegate); } var jobFunctionPtr = JobStructDefer <T> .ExecuteFunctionPtr; var completionFuncPtr = JobStructDefer <T> .CleanupFunctionPtr; var jobStruct = new JobStructDefer <T>() { JobData = jobData, ArrayLengthPtr = arrayLengthPtr, }; var jobDataPtr = UnsafeUtility.Malloc(UnsafeUtility.SizeOf <JobStructDefer <T> >(), UnsafeUtility.AlignOf <JobStructDefer <T> >(), Allocator.TempJob); UnsafeUtility.CopyStructureToPtr(ref jobStruct, jobDataPtr); return(JobsUtility.ScheduleJobForEach(jobFunctionPtr, completionFuncPtr, new IntPtr(jobDataPtr), JobsUtility.JobQueueThreadCount, innerloopBatchCount, dependsOn)); #endif }
/// <summary> /// Schedule the job for execution on worker threads. /// list.Length is used as the iteration count. /// Note that it is required to embed the list on the job struct as well. /// </summary> /// <param name="jobData">The job and data to schedule.</param> /// <param name="list">list.Length is used as the iteration count.</param> /// <param name="innerloopBatchCount">Granularity in which workstealing is performed. A value of 32, means the job queue will steal 32 iterations and then perform them in an efficient inner loop.</param> /// <param name="dependsOn">Dependencies are used to ensure that a job executes on workerthreads after the dependency has completed execution. Making sure that two jobs reading or writing to same data do not run in parallel.</param> /// <returns>JobHandle The handle identifying the scheduled job. Can be used as a dependency for a later job or ensure completion on the main thread.</returns> public static unsafe JobHandle Schedule <T, U>(this T jobData, NativeList <U> list, int innerloopBatchCount, JobHandle dependsOn = new JobHandle()) where T : struct, IJobParallelForDefer where U : struct { void *atomicSafetyHandlePtr = null; var scheduleParams = new JobsUtility.JobScheduleParameters( UnsafeUtility.AddressOf(ref jobData), JobStructDefer <T> .Initialize(), dependsOn, ScheduleMode.Batched); #if ENABLE_UNITY_COLLECTIONS_CHECKS var safety = NativeListUnsafeUtility.GetAtomicSafetyHandle(ref list); atomicSafetyHandlePtr = UnsafeUtility.AddressOf(ref safety); #endif return(JobsUtility.ScheduleParallelForDeferArraySize(ref scheduleParams, innerloopBatchCount, NativeListUnsafeUtility.GetInternalListDataPtrUnchecked(ref list), atomicSafetyHandlePtr)); }