public void ScheduleCreateThrows() { var list = new NativeList <int>(Allocator.Persistent); list.Add(2); BlockStream stream; var jobHandle = BlockStream.ScheduleConstruct(out stream, list, 0xd3e8afdd, default(JobHandle)); Assert.Throws <InvalidOperationException>(() => Debug.Log(stream.ForEachCount)); jobHandle.Complete(); Assert.AreEqual(1, stream.ForEachCount); stream.Dispose(); list.Dispose(); }
internal static JobHandle ScheduleProcessBodyPairsJobs(ref PhysicsWorld world, float timeStep, int numIterations, ref Simulation.Context context, JobHandle inputDeps) { var numWorkItems = context.SolverSchedulerInfo.NumWorkItems; var contactsHandle = BlockStream.ScheduleConstruct(out context.Contacts, numWorkItems, 0xcf97529c, inputDeps); var jointJacobiansHandle = BlockStream.ScheduleConstruct(out context.JointJacobians, numWorkItems, 0xd3185f82, inputDeps); var jacobiansHandle = BlockStream.ScheduleConstruct(out context.Jacobians, numWorkItems, 0x8d8f394d, inputDeps); var processHandle = new ProcessBodyPairsJob { World = world, TimeStep = timeStep, NumIterations = numIterations, PhasedDispatchPairs = context.PhasedDispatchPairs.AsDeferredJobArray(), SolverSchedulerInfo = context.SolverSchedulerInfo, ContactWriter = context.Contacts, JointJacobianWriter = context.JointJacobians, }.ScheduleUnsafeIndex0(numWorkItems, 1, JobHandle.CombineDependencies(contactsHandle, jointJacobiansHandle, jacobiansHandle)); context.DisposeProcessBodyPairs = NativeListUtilityTemp.DisposeHotFix(ref context.PhasedDispatchPairs, processHandle); return(processHandle); }
// Schedule a set of jobs which will write all overlapping body pairs to the given steam, // where at least one of the bodies is dynamic. The results are unsorted. internal JobHandle ScheduleFindOverlapsJobs(out BlockStream dynamicVsDynamicPairsStream, out BlockStream staticVsDynamicPairsStream, ref Simulation.Context context, JobHandle inputDeps) { var dynamicVsDynamicNodePairIndices = new NativeList <int2>(Allocator.TempJob); var staticVsDynamicNodePairIndices = new NativeList <int2>(Allocator.TempJob); JobHandle allocateDeps = new AllocateDynamicVsStaticNodePairs { dynamicVsDynamicNodePairIndices = dynamicVsDynamicNodePairIndices, staticVsDynamicNodePairIndices = staticVsDynamicNodePairIndices, dynamicBranchCount = m_DynamicTree.m_BranchCount, staticBranchCount = m_StaticTree.m_BranchCount }.Schedule(inputDeps); // Build pairs of branch node indices JobHandle dynamicVsDynamicPairs = new DynamicVsDynamicBuildBranchNodePairsJob { Ranges = m_DynamicTree.Ranges, NumBranches = m_DynamicTree.m_BranchCount, NodePairIndices = dynamicVsDynamicNodePairIndices.AsDeferredJobArray() }.Schedule(allocateDeps); JobHandle staticVsDynamicPairs = new StaticVsDynamicBuildBranchNodePairsJob { DynamicRanges = m_DynamicTree.Ranges, StaticRanges = m_StaticTree.Ranges, NumStaticBranches = m_StaticTree.m_BranchCount, NumDynamicBranches = m_DynamicTree.m_BranchCount, NodePairIndices = staticVsDynamicNodePairIndices.AsDeferredJobArray() }.Schedule(allocateDeps); //@TODO: We only need a dependency on allocateDeps, but the safety system doesn't understand that we can not change length list in DynamicVsDynamicBuildBranchNodePairsJob & StaticVsDynamicBuildBranchNodePairsJob // if this is a performance issue we can use [NativeDisableContainerSafetyRestriction] on DynamicVsDynamicBuildBranchNodePairsJob & StaticVsDynamicBuildBranchNodePairsJob JobHandle dynamicConstruct = BlockStream.ScheduleConstruct(out dynamicVsDynamicPairsStream, dynamicVsDynamicNodePairIndices, 0x0a542b34, dynamicVsDynamicPairs); JobHandle staticConstruct = BlockStream.ScheduleConstruct(out staticVsDynamicPairsStream, staticVsDynamicNodePairIndices, 0x0a542666, staticVsDynamicPairs); // Write all overlaps to the stream (also deallocates nodePairIndices) JobHandle dynamicVsDynamicHandle = new DynamicVsDynamicFindOverlappingPairsJob { DynamicNodes = m_DynamicTree.Nodes, BodyFilters = m_BodyFilters, DynamicNodeFilters = m_DynamicTree.NodeFilters, PairWriter = dynamicVsDynamicPairsStream, NodePairIndices = dynamicVsDynamicNodePairIndices.AsDeferredJobArray() }.Schedule(dynamicVsDynamicNodePairIndices, 1, JobHandle.CombineDependencies(dynamicVsDynamicPairs, dynamicConstruct)); // Write all overlaps to the stream (also deallocates nodePairIndices) JobHandle staticVsDynamicHandle = new StaticVsDynamicFindOverlappingPairsJob { StaticNodes = m_StaticTree.Nodes, DynamicNodes = m_DynamicTree.Nodes, BodyFilters = m_BodyFilters, StaticNodeFilters = m_StaticTree.NodeFilters, DynamicNodeFilters = m_DynamicTree.NodeFilters, PairWriter = staticVsDynamicPairsStream, NodePairIndices = staticVsDynamicNodePairIndices.AsDeferredJobArray() }.Schedule(staticVsDynamicNodePairIndices, 1, JobHandle.CombineDependencies(staticVsDynamicPairs, staticConstruct)); // Dispose node pair lists context.DisposeOverlapPairs0 = NativeListUtilityTemp.DisposeHotFix(ref dynamicVsDynamicNodePairIndices, dynamicVsDynamicHandle); context.DisposeOverlapPairs1 = NativeListUtilityTemp.DisposeHotFix(ref staticVsDynamicNodePairIndices, staticVsDynamicHandle); return(JobHandle.CombineDependencies(dynamicVsDynamicHandle, staticVsDynamicHandle)); }
// Schedule some jobs to solve the Jacobians stored in the simulation context internal static unsafe JobHandle ScheduleSolveJacobiansJobs(ref DynamicsWorld dynamicsWorld, float timestep, int numIterations, ref Simulation.Context context, JobHandle inputDeps) { JobHandle handle; int numPhases = context.SolverSchedulerInfo.NumPhases; // Use persistent allocator to allow these to live until the start of next step { NativeArray <int> workItemList = context.SolverSchedulerInfo.NumWorkItems; //TODO: Change this to Allocator.TempJob when https://github.com/Unity-Technologies/Unity.Physics/issues/7 is resolved JobHandle collisionEventStreamHandle = BlockStream.ScheduleConstruct(out context.CollisionEventStream, workItemList, 0xb17b474f, inputDeps, Allocator.Persistent); JobHandle triggerEventStreamHandle = BlockStream.ScheduleConstruct(out context.TriggerEventStream, workItemList, 0x43875d8f, inputDeps, Allocator.Persistent); handle = JobHandle.CombineDependencies(collisionEventStreamHandle, triggerEventStreamHandle); float invNumIterations = math.rcp(numIterations); var phaseInfoPtrs = (Scheduler.SolverSchedulerInfo.SolvePhaseInfo *)NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(context.SolverSchedulerInfo.PhaseInfo); for (int solverIterationId = 0; solverIterationId < numIterations; solverIterationId++) { bool lastIteration = solverIterationId == numIterations - 1; for (int phaseId = 0; phaseId < numPhases; phaseId++) { var job = new SolverJob { JacobianReader = context.Jacobians, PhaseIndex = phaseId, Phases = context.SolverSchedulerInfo.PhaseInfo, MotionVelocities = dynamicsWorld.MotionVelocities, StepInput = new StepInput { InvNumSolverIterations = invNumIterations, IsLastIteration = lastIteration, Timestep = timestep, InvTimestep = timestep > 0.0f ? 1.0f / timestep : 0.0f } }; // Only initialize event writers for last solver iteration jobs if (lastIteration) { job.CollisionEventsWriter = context.CollisionEventStream; job.TriggerEventsWriter = context.TriggerEventStream; } // NOTE: The last phase must be executed on a single job since it // int.MaxValue can't be used as batchSize since 19.1 overflows in that case... bool isLastPhase = phaseId == numPhases - 1; int batchSize = isLastPhase ? (int.MaxValue / 2) : 1; int *numWorkItems = &(phaseInfoPtrs[phaseId].NumWorkItems); handle = job.Schedule(numWorkItems, batchSize, handle); } } } // Dispose processed data context.DisposeJacobians = context.Jacobians.Dispose(handle); context.DisposeJointJacobians = context.JointJacobians.Dispose(handle); context.DisposeSolverSchedulerData = context.SolverSchedulerInfo.ScheduleDisposeJob(handle); return(handle); }