|
@@ -344,9 +344,9 @@ void PhysicsSystem::Update(float inDeltaTime, int inCollisionSteps, int inIntegr
|
|
step.mBodySetIslandIndex.RemoveDependency();
|
|
step.mBodySetIslandIndex.RemoveDependency();
|
|
}, num_find_collisions_jobs + 2); // depends on: find collisions, build islands from constraints, finish building jobs
|
|
}, num_find_collisions_jobs + 2); // depends on: find collisions, build islands from constraints, finish building jobs
|
|
|
|
|
|
- // Unblock previous jobs (find collisions last since it will use up all CPU cores)
|
|
|
|
|
|
+ // Unblock previous job
|
|
|
|
+ // Note: technically we could release find collisions here but we don't want to because that could make them run before 'setup velocity constraints' which means that job won't have a thread left
|
|
step.mBuildIslandsFromConstraints.RemoveDependency();
|
|
step.mBuildIslandsFromConstraints.RemoveDependency();
|
|
- JobHandle::sRemoveDependencies(step.mFindCollisions);
|
|
|
|
|
|
|
|
// This job will call the contact removed callbacks
|
|
// This job will call the contact removed callbacks
|
|
step.mContactRemovedCallbacks = inJobSystem->CreateJob("ContactRemovedCallbacks", cColorContactRemovedCallbacks, [&context, &step]()
|
|
step.mContactRemovedCallbacks = inJobSystem->CreateJob("ContactRemovedCallbacks", cColorContactRemovedCallbacks, [&context, &step]()
|
|
@@ -433,8 +433,12 @@ void PhysicsSystem::Update(float inDeltaTime, int inCollisionSteps, int inIntegr
|
|
// Unblock previous jobs
|
|
// Unblock previous jobs
|
|
if (is_first_sub_step)
|
|
if (is_first_sub_step)
|
|
{
|
|
{
|
|
- step.mFinalizeIslands.RemoveDependency();
|
|
|
|
|
|
+ // Kick find collisions after setup velocity constraints because the former job will use up all CPU cores
|
|
step.mSetupVelocityConstraints.RemoveDependency();
|
|
step.mSetupVelocityConstraints.RemoveDependency();
|
|
|
|
+ JobHandle::sRemoveDependencies(step.mFindCollisions);
|
|
|
|
+
|
|
|
|
+ // Finalize islands is a dependency on find collisions so it can go last
|
|
|
|
+ step.mFinalizeIslands.RemoveDependency();
|
|
}
|
|
}
|
|
else
|
|
else
|
|
{
|
|
{
|
|
@@ -530,7 +534,7 @@ void PhysicsSystem::Update(float inDeltaTime, int inCollisionSteps, int inIntegr
|
|
JPH_PROFILE("Build job barrier");
|
|
JPH_PROFILE("Build job barrier");
|
|
|
|
|
|
StaticArray<JobHandle, cMaxPhysicsJobs> handles;
|
|
StaticArray<JobHandle, cMaxPhysicsJobs> handles;
|
|
- for (PhysicsUpdateContext::Step &step : context.mSteps)
|
|
|
|
|
|
+ for (const PhysicsUpdateContext::Step &step : context.mSteps)
|
|
{
|
|
{
|
|
if (step.mBroadPhasePrepare.IsValid())
|
|
if (step.mBroadPhasePrepare.IsValid())
|
|
handles.push_back(step.mBroadPhasePrepare);
|
|
handles.push_back(step.mBroadPhasePrepare);
|
|
@@ -548,7 +552,7 @@ void PhysicsSystem::Update(float inDeltaTime, int inCollisionSteps, int inIntegr
|
|
handles.push_back(step.mBuildIslandsFromConstraints);
|
|
handles.push_back(step.mBuildIslandsFromConstraints);
|
|
handles.push_back(step.mFinalizeIslands);
|
|
handles.push_back(step.mFinalizeIslands);
|
|
handles.push_back(step.mBodySetIslandIndex);
|
|
handles.push_back(step.mBodySetIslandIndex);
|
|
- for (PhysicsUpdateContext::SubStep &sub_step : step.mSubSteps)
|
|
|
|
|
|
+ for (const PhysicsUpdateContext::SubStep &sub_step : step.mSubSteps)
|
|
{
|
|
{
|
|
for (const JobHandle &h : sub_step.mSolveVelocityConstraints)
|
|
for (const JobHandle &h : sub_step.mSolveVelocityConstraints)
|
|
handles.push_back(h);
|
|
handles.push_back(h);
|
|
@@ -639,7 +643,7 @@ void PhysicsSystem::JobStepListeners(PhysicsUpdateContext::Step *ioStep)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-void PhysicsSystem::JobDetermineActiveConstraints(PhysicsUpdateContext::Step *ioStep)
|
|
|
|
|
|
+void PhysicsSystem::JobDetermineActiveConstraints(PhysicsUpdateContext::Step *ioStep) const
|
|
{
|
|
{
|
|
#ifdef JPH_ENABLE_ASSERTS
|
|
#ifdef JPH_ENABLE_ASSERTS
|
|
// No body access
|
|
// No body access
|
|
@@ -672,7 +676,7 @@ void PhysicsSystem::JobDetermineActiveConstraints(PhysicsUpdateContext::Step *io
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-void PhysicsSystem::JobApplyGravity(PhysicsUpdateContext *ioContext, PhysicsUpdateContext::Step *ioStep)
|
|
|
|
|
|
+void PhysicsSystem::JobApplyGravity(const PhysicsUpdateContext *ioContext, PhysicsUpdateContext::Step *ioStep)
|
|
{
|
|
{
|
|
#ifdef JPH_ENABLE_ASSERTS
|
|
#ifdef JPH_ENABLE_ASSERTS
|
|
// We update velocities and need the rotation to do so
|
|
// We update velocities and need the rotation to do so
|
|
@@ -703,7 +707,7 @@ void PhysicsSystem::JobApplyGravity(PhysicsUpdateContext *ioContext, PhysicsUpda
|
|
// Process the batch
|
|
// Process the batch
|
|
while (active_body_idx < active_body_idx_end)
|
|
while (active_body_idx < active_body_idx_end)
|
|
{
|
|
{
|
|
- Body &body = mBodyManager.GetBody(active_bodies[active_body_idx]);
|
|
|
|
|
|
+ const Body &body = mBodyManager.GetBody(active_bodies[active_body_idx]);
|
|
if (body.IsDynamic())
|
|
if (body.IsDynamic())
|
|
body.GetMotionProperties()->ApplyForceTorqueAndDragInternal(body.GetRotation(), mGravity, delta_time);
|
|
body.GetMotionProperties()->ApplyForceTorqueAndDragInternal(body.GetRotation(), mGravity, delta_time);
|
|
active_body_idx++;
|
|
active_body_idx++;
|
|
@@ -738,7 +742,7 @@ void PhysicsSystem::JobBuildIslandsFromConstraints(PhysicsUpdateContext *ioConte
|
|
mConstraintManager.BuildIslands(ioStep->mContext->mActiveConstraints, ioStep->mNumActiveConstraints, mIslandBuilder, mBodyManager);
|
|
mConstraintManager.BuildIslands(ioStep->mContext->mActiveConstraints, ioStep->mNumActiveConstraints, mIslandBuilder, mBodyManager);
|
|
}
|
|
}
|
|
|
|
|
|
-void PhysicsSystem::TrySpawnJobFindCollisions(PhysicsUpdateContext::Step *ioStep)
|
|
|
|
|
|
+void PhysicsSystem::TrySpawnJobFindCollisions(PhysicsUpdateContext::Step *ioStep) const
|
|
{
|
|
{
|
|
// Get how many jobs we can spawn and check if we can spawn more
|
|
// Get how many jobs we can spawn and check if we can spawn more
|
|
uint max_jobs = ioStep->mBodyPairQueues.size();
|
|
uint max_jobs = ioStep->mBodyPairQueues.size();
|
|
@@ -862,7 +866,7 @@ void PhysicsSystem::JobFindCollisions(PhysicsUpdateContext::Step *ioStep, int in
|
|
mBroadPhase->FindCollidingPairs(active_bodies, batch_size, mPhysicsSettings.mSpeculativeContactDistance, mObjectVsBroadPhaseLayerFilter, mObjectLayerPairFilter, add_pair);
|
|
mBroadPhase->FindCollidingPairs(active_bodies, batch_size, mPhysicsSettings.mSpeculativeContactDistance, mObjectVsBroadPhaseLayerFilter, mObjectLayerPairFilter, add_pair);
|
|
|
|
|
|
// Check if we have enough pairs in the buffer to start a new job
|
|
// Check if we have enough pairs in the buffer to start a new job
|
|
- PhysicsUpdateContext::BodyPairQueue &queue = ioStep->mBodyPairQueues[inJobIndex];
|
|
|
|
|
|
+ const PhysicsUpdateContext::BodyPairQueue &queue = ioStep->mBodyPairQueues[inJobIndex];
|
|
uint32 body_pairs_in_queue = queue.mWriteIdx - queue.mReadIdx;
|
|
uint32 body_pairs_in_queue = queue.mWriteIdx - queue.mReadIdx;
|
|
if (body_pairs_in_queue >= cNarrowPhaseBatchSize)
|
|
if (body_pairs_in_queue >= cNarrowPhaseBatchSize)
|
|
TrySpawnJobFindCollisions(ioStep);
|
|
TrySpawnJobFindCollisions(ioStep);
|
|
@@ -871,7 +875,7 @@ void PhysicsSystem::JobFindCollisions(PhysicsUpdateContext::Step *ioStep, int in
|
|
else
|
|
else
|
|
{
|
|
{
|
|
// Lockless loop to get the next body pair from the pairs buffer
|
|
// Lockless loop to get the next body pair from the pairs buffer
|
|
- PhysicsUpdateContext *context = ioStep->mContext;
|
|
|
|
|
|
+ const PhysicsUpdateContext *context = ioStep->mContext;
|
|
int first_read_queue_idx = read_queue_idx;
|
|
int first_read_queue_idx = read_queue_idx;
|
|
for (;;)
|
|
for (;;)
|
|
{
|
|
{
|
|
@@ -903,7 +907,7 @@ void PhysicsSystem::JobFindCollisions(PhysicsUpdateContext::Step *ioStep, int in
|
|
}
|
|
}
|
|
|
|
|
|
// Copy the body pair out of the buffer
|
|
// Copy the body pair out of the buffer
|
|
- BodyPair bp = context->mBodyPairs[read_queue_idx * ioStep->mMaxBodyPairsPerQueue + pair_idx % ioStep->mMaxBodyPairsPerQueue];
|
|
|
|
|
|
+ const BodyPair bp = context->mBodyPairs[read_queue_idx * ioStep->mMaxBodyPairsPerQueue + pair_idx % ioStep->mMaxBodyPairsPerQueue];
|
|
|
|
|
|
// Mark this pair as taken
|
|
// Mark this pair as taken
|
|
if (queue.mReadIdx.compare_exchange_strong(pair_idx, pair_idx + 1))
|
|
if (queue.mReadIdx.compare_exchange_strong(pair_idx, pair_idx + 1))
|
|
@@ -1546,7 +1550,7 @@ inline static PhysicsUpdateContext::SubStep::CCDBody *sGetCCDBody(const Body &in
|
|
return ccd_body;
|
|
return ccd_body;
|
|
}
|
|
}
|
|
|
|
|
|
-void PhysicsSystem::JobFindCCDContacts(PhysicsUpdateContext *ioContext, PhysicsUpdateContext::SubStep *ioSubStep)
|
|
|
|
|
|
+void PhysicsSystem::JobFindCCDContacts(const PhysicsUpdateContext *ioContext, PhysicsUpdateContext::SubStep *ioSubStep)
|
|
{
|
|
{
|
|
#ifdef JPH_ENABLE_ASSERTS
|
|
#ifdef JPH_ENABLE_ASSERTS
|
|
// We only read positions, but the validate callback may read body positions and velocities
|
|
// We only read positions, but the validate callback may read body positions and velocities
|
|
@@ -1776,10 +1780,10 @@ void PhysicsSystem::JobFindCCDContacts(PhysicsUpdateContext *ioContext, PhysicsU
|
|
float mDeltaTime;
|
|
float mDeltaTime;
|
|
};
|
|
};
|
|
|
|
|
|
- // Check if we collide with any other body
|
|
|
|
|
|
+ // Check if we collide with any other body. Note that we use the non-locking interface as we know the broadphase cannot be modified at this point.
|
|
ShapeCast shape_cast(body.GetShape(), Vec3::sReplicate(1.0f), body.GetCenterOfMassTransform(), ccd_body.mDeltaPosition);
|
|
ShapeCast shape_cast(body.GetShape(), Vec3::sReplicate(1.0f), body.GetCenterOfMassTransform(), ccd_body.mDeltaPosition);
|
|
CCDBroadPhaseCollector bp_collector(ccd_body, body, shape_cast, settings, np_collector, mBodyManager, ioSubStep, ioContext->mSubStepDeltaTime);
|
|
CCDBroadPhaseCollector bp_collector(ccd_body, body, shape_cast, settings, np_collector, mBodyManager, ioSubStep, ioContext->mSubStepDeltaTime);
|
|
- mBroadPhase->CastAABox({ shape_cast.mShapeWorldBounds, shape_cast.mDirection }, bp_collector, broadphase_layer_filter, object_layer_filter);
|
|
|
|
|
|
+ mBroadPhase->CastAABoxNoLock({ shape_cast.mShapeWorldBounds, shape_cast.mDirection }, bp_collector, broadphase_layer_filter, object_layer_filter);
|
|
|
|
|
|
// Check if there was a hit
|
|
// Check if there was a hit
|
|
if (ccd_body.mFractionPlusSlop < 1.0f)
|
|
if (ccd_body.mFractionPlusSlop < 1.0f)
|
|
@@ -2177,7 +2181,7 @@ bool PhysicsSystem::RestoreState(StateRecorder &inStream)
|
|
|
|
|
|
// Update bounding boxes for all bodies in the broadphase
|
|
// Update bounding boxes for all bodies in the broadphase
|
|
vector<BodyID> bodies;
|
|
vector<BodyID> bodies;
|
|
- for (Body *b : mBodyManager.GetBodies())
|
|
|
|
|
|
+ for (const Body *b : mBodyManager.GetBodies())
|
|
if (BodyManager::sIsValidBodyPointer(b) && b->IsInBroadPhase())
|
|
if (BodyManager::sIsValidBodyPointer(b) && b->IsInBroadPhase())
|
|
bodies.push_back(b->GetID());
|
|
bodies.push_back(b->GetID());
|
|
if (!bodies.empty())
|
|
if (!bodies.empty())
|