public static unsafe IntPtr CreateJobReflectionData(Type type, Type _, Delegate executeDelegate, Delegate cleanupDelegate = null, ManagedJobForEachDelegate codegenExecuteDelegate = null, ManagedJobDelegate codegenCleanupDelegate = null, int codegenUnmanagedJobSize = -1, ManagedJobMarshalDelegate codegenMarshalToBurstDelegate = null) { // Tiny doesn't use this on any codepath currently; may need future support for custom jobs. Assert.IsTrue(cleanupDelegate == null, "Runtime needs support for cleanup delegates in jobs."); Assert.IsTrue(codegenExecuteDelegate != null, "Code gen should have supplied an execute wrapper."); #if ENABLE_UNITY_COLLECTIONS_CHECKS && !UNITY_DOTSRUNTIME_IL2CPP Assert.IsTrue((codegenUnmanagedJobSize != -1 && codegenMarshalToBurstDelegate != null) || (codegenUnmanagedJobSize == -1 && codegenMarshalToBurstDelegate == null), "Code gen should have supplied a marshal wrapper."); #endif ReflectionDataProxy *reflectionDataPtr = (ReflectionDataProxy *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <ReflectionDataProxy>(), UnsafeUtility.AlignOf <ReflectionDataProxy>(), Allocator.Persistent); var reflectionData = new ReflectionDataProxy(); // Protect against garbage collector relocating delegate ReflectionDataStore store = new ReflectionDataStore(executeDelegate, codegenCleanupDelegate, codegenExecuteDelegate, codegenMarshalToBurstDelegate); store.next = Managed.reflectionDataStoreRoot; Managed.reflectionDataStoreRoot = store; reflectionData.ExecuteFunctionPtr = store.CodeGenExecuteFunctionPtr; if (codegenCleanupDelegate != null) { reflectionData.CleanupFunctionPtr = store.CodeGenCleanupFunctionPtr; } #if ENABLE_UNITY_COLLECTIONS_CHECKS && !UNITY_DOTSRUNTIME_IL2CPP reflectionData.UnmanagedSize = codegenUnmanagedJobSize; if (codegenUnmanagedJobSize != -1) { reflectionData.MarshalToBurstFunctionPtr = store.CodeGenMarshalToBurstFunctionPtr; } #endif UnsafeUtility.CopyStructureToPtr(ref reflectionData, reflectionDataPtr); return((IntPtr)reflectionDataPtr); }
public unsafe JobScheduleParameters(void *jobData, ReflectionDataProxy *reflectionData, JobHandle jobDependency, ScheduleMode scheduleMode, int jobDataSize = 0, #if ENABLE_UNITY_COLLECTIONS_CHECKS int producerJobPreSchedule = 1, int userJobPreSchedule = 3, #endif int isBursted = 5) { // Synchronize with InterfaceGen.cs! #if ENABLE_UNITY_COLLECTIONS_CHECKS const int k_ProducerScheduleReturnValue = 4; const int k_UserScheduleReturnValue = 2; const int k_UserScheduleReturnValueNoParallel = -2; #endif const string k_PostFix = " Seeing this error indicates a bug in the dots compiler. We'd appreciate a bug report (About->Report a Bug...)."; // Default is 0; code-gen should set to a correct size. if (jobDataSize == 0) { throw new InvalidOperationException("JobScheduleParameters (size) should be set by code-gen." + k_PostFix); } #if ENABLE_UNITY_COLLECTIONS_CHECKS if (producerJobPreSchedule != k_ProducerScheduleReturnValue) { throw new InvalidOperationException( "JobScheduleParameter (which is the return code of ProducerScheduleFn_Gen) should be set by code-gen." + k_PostFix); } if (userJobPreSchedule != k_UserScheduleReturnValue && userJobPreSchedule != k_UserScheduleReturnValueNoParallel) { throw new InvalidOperationException( "JobScheduleParameter (which is the return code of PrepareJobAtPreScheduleTimeFn_Gen) should be set by code-gen." + k_PostFix); } #endif if (!(isBursted == 0 || isBursted == 1)) { throw new InvalidOperationException( "JobScheduleParameter (which is the return code of RunOnMainThread_Gen) should be set by code-gen." + k_PostFix); } int nWorkers = JobWorkerCount > 0 ? JobWorkerCount : 1; JobMetaData *mem = AllocateJobHeapMemory(jobDataSize, nWorkers); // A copy of the JobData is needed *for each worker thread* as it will // get mutated in unique ways (threadIndex, safety.) The jobIndex is passed // to the Execute method, so a thread can look up the correct jobData to use. // Cleanup is always called on jobIndex=0. for (int i = 0; i < nWorkers; i++) { UnsafeUtility.MemCpy(((byte *)mem + sizeof(JobMetaData) + jobDataSize * i), jobData, jobDataSize); } UnsafeUtility.AssertHeap(mem); JobMetaData jobMetaData = new JobMetaData(); jobMetaData.jobDataSize = jobDataSize; // Indicate parallel for is an error #if ENABLE_UNITY_COLLECTIONS_CHECKS if (userJobPreSchedule == k_UserScheduleReturnValueNoParallel) { jobMetaData.isParallelFor = -1; } #endif UnsafeUtility.CopyStructureToPtr(ref jobMetaData, mem); Dependency = jobDependency; JobDataPtr = mem; ReflectionData = reflectionData; #if UNITY_DOTSRUNTIME_MULTITHREAD_NOBURST // Allow debugging multithreaded code without burst when necessary ScheduleMode = scheduleMode; #else // Normally, only bursted methods run on worker threads if (isBursted != 0) { ScheduleMode = scheduleMode; } else { // Both main thread schedule modes run immediately - the difference is that scheduling returns a job handle // which must still be synced in order to maintain dependency safety, whereas run returns a default job handle // not needing completion. ScheduleMode = scheduleMode == ScheduleMode.Run ? ScheduleMode.RunOnMainThread : ScheduleMode.ScheduleOnMainThread; } #endif }