예제 #1
0
        // 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);
        }
예제 #2
0
        // Schedule all the jobs for the simulation step.
        // Enqueued callbacks can choose to inject additional jobs at defined sync points.
        public void ScheduleStepJobs(SimulationStepInput input, JobHandle inputDeps, out JobHandle finalSimulationJobHandle, out JobHandle finalJobHandle)
        {
            // Dispose event streams from previous frame
            DisposeEventStreams();

            m_Context = new Context();

            if (input.World.NumDynamicBodies == 0)
            {
                // No need to do anything, since nothing can move
                finalSimulationJobHandle = new JobHandle();
                finalJobHandle           = new JobHandle();
                return;
            }

            SimulationCallbacks callbacks = input.Callbacks ?? new SimulationCallbacks();
            JobHandle           handle    = inputDeps;

            // We need to make sure that broadphase tree building is done before we schedule FindOverlapsJobs.
            handle.Complete();

            // Find all body pairs that overlap in the broadphase
            handle = input.World.CollisionWorld.Broadphase.ScheduleFindOverlapsJobs(
                out BlockStream dynamicVsDynamicBroadphasePairsStream, out BlockStream staticVsDynamicBroadphasePairsStream, handle);
            handle.Complete();  // Need to know the total number of pairs before continuing

            // Create phased dispatch pairs for all interacting body pairs
            handle = m_Scheduler.ScheduleCreatePhasedDispatchPairsJob(
                ref input.World, ref dynamicVsDynamicBroadphasePairsStream, ref staticVsDynamicBroadphasePairsStream, ref m_Context, handle);
            handle.Complete();  // Need to know the total number of work items before continuing
            handle = callbacks.Execute(SimulationCallbacks.Phase.PostCreateDispatchPairs, this, handle);
            m_Context.CreateBodyPairsHandle = 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, handle);
            m_Context.CreateContactsHandle = handle;

            // Create contact Jacobians
            handle = Solver.ScheduleBuildContactJacobiansJobs(ref input.World.DynamicsWorld, input.TimeStep, ref m_Context, handle);
            handle = callbacks.Execute(SimulationCallbacks.Phase.PostCreateContactJacobians, this, handle);
            m_Context.CreateContactJacobiansHandle = handle;

            // Solve all Jacobians
            int numIterations = input.NumSolverIterations > 0 ? input.NumSolverIterations : 4;

            handle = Solver.ScheduleSolveJacobiansJobs(ref input.World.DynamicsWorld, input.TimeStep, input.Gravity, numIterations, ref m_Context, handle);
            handle = callbacks.Execute(SimulationCallbacks.Phase.PostSolveJacobians, this, handle);
            m_Context.SolveContactJacobiansHandle = handle;

            // Integration motions
            handle = Integrator.ScheduleIntegrateJobs(ref input.World.DynamicsWorld, input.TimeStep, input.Gravity, handle);
            handle = callbacks.Execute(SimulationCallbacks.Phase.PostIntegrateMotions, this, handle);
            m_Context.IntegrateMotionsHandle = handle;

            // Synchronize the collision world
            if (input.SynchronizeCollisionWorld)
            {
                handle = input.World.CollisionWorld.ScheduleUpdateDynamicLayer(ref input.World, input.TimeStep, input.ThreadCountHint, handle);  // TODO: timeStep = 0?
            }

            // Return the final simulation handle
            finalSimulationJobHandle = handle;

            // Return the final handle, which includes disposing temporary arrays
            finalJobHandle = JobHandle.CombineDependencies(finalSimulationJobHandle, m_Context.DisposeBroadphasePairs, m_Context.DisposeContacts);
            finalJobHandle = JobHandle.CombineDependencies(finalJobHandle, m_Context.DisposeJacobians, m_Context.DisposeJointJacobians);
            finalJobHandle = JobHandle.CombineDependencies(finalJobHandle, m_Context.DisposeSolverSchedulerData);
        }