Reuse physics simulations buffer

To avoid redundant allocations.

Use 2 buffers to make sure there is no overlap between main and the background
threads.
crashfix_debugdraw
elsid 2 years ago
parent c4d357df0f
commit 277211c5b4
No known key found for this signature in database
GPG Key ID: 4DE04C198CBA7625

@ -3,6 +3,7 @@
#include <optional> #include <optional>
#include <shared_mutex> #include <shared_mutex>
#include <mutex> #include <mutex>
#include <cassert>
#include <BulletCollision/BroadphaseCollision/btDbvtBroadphase.h> #include <BulletCollision/BroadphaseCollision/btDbvtBroadphase.h>
#include <BulletCollision/CollisionShapes/btCollisionShape.h> #include <BulletCollision/CollisionShapes/btCollisionShape.h>
@ -410,8 +411,10 @@ namespace MWPhysics
return std::make_tuple(numSteps, actualDelta); return std::make_tuple(numSteps, actualDelta);
} }
void PhysicsTaskScheduler::applyQueuedMovements(float & timeAccum, std::vector<Simulation>&& simulations, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats) void PhysicsTaskScheduler::applyQueuedMovements(float& timeAccum, std::vector<Simulation>& simulations, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats)
{ {
assert(mSimulations != &simulations);
waitForWorkers(); waitForWorkers();
// This function run in the main thread. // This function run in the main thread.
@ -444,10 +447,10 @@ namespace MWPhysics
mRemainingSteps = numSteps; mRemainingSteps = numSteps;
mTimeAccum = timeAccum; mTimeAccum = timeAccum;
mPhysicsDt = newDelta; mPhysicsDt = newDelta;
mSimulations = std::move(simulations); mSimulations = &simulations;
mAdvanceSimulation = (mRemainingSteps != 0); mAdvanceSimulation = (mRemainingSteps != 0);
++mFrameCounter; ++mFrameCounter;
mNumJobs = mSimulations.size(); mNumJobs = mSimulations->size();
mNextLOS.store(0, std::memory_order_relaxed); mNextLOS.store(0, std::memory_order_relaxed);
mNextJob.store(0, std::memory_order_release); mNextJob.store(0, std::memory_order_release);
@ -478,7 +481,11 @@ namespace MWPhysics
MaybeExclusiveLock lock(mSimulationMutex, mNumThreads); MaybeExclusiveLock lock(mSimulationMutex, mNumThreads);
mBudget.reset(mDefaultPhysicsDt); mBudget.reset(mDefaultPhysicsDt);
mAsyncBudget.reset(0.0f); mAsyncBudget.reset(0.0f);
mSimulations.clear(); if (mSimulations != nullptr)
{
mSimulations->clear();
mSimulations = nullptr;
}
for (const auto& [_, actor] : actors) for (const auto& [_, actor] : actors)
{ {
actor->updatePosition(); actor->updatePosition();
@ -654,7 +661,7 @@ namespace MWPhysics
{ {
const Visitors::UpdatePosition impl{mCollisionWorld}; const Visitors::UpdatePosition impl{mCollisionWorld};
const Visitors::WithLockedPtr<Visitors::UpdatePosition, MaybeExclusiveLock> vis{impl, mCollisionWorldMutex, mNumThreads}; const Visitors::WithLockedPtr<Visitors::UpdatePosition, MaybeExclusiveLock> vis{impl, mCollisionWorldMutex, mNumThreads};
for (Simulation& sim : mSimulations) for (Simulation& sim : *mSimulations)
std::visit(vis, sim); std::visit(vis, sim);
} }
@ -682,7 +689,7 @@ namespace MWPhysics
const Visitors::Move impl{mPhysicsDt, mCollisionWorld, *mWorldFrameData}; const Visitors::Move impl{mPhysicsDt, mCollisionWorld, *mWorldFrameData};
const Visitors::WithLockedPtr<Visitors::Move, MaybeLock> vis{impl, mCollisionWorldMutex, mNumThreads}; const Visitors::WithLockedPtr<Visitors::Move, MaybeLock> vis{impl, mCollisionWorldMutex, mNumThreads};
while ((job = mNextJob.fetch_add(1, std::memory_order_relaxed)) < mNumJobs) while ((job = mNextJob.fetch_add(1, std::memory_order_relaxed)) < mNumJobs)
std::visit(vis, mSimulations[job]); std::visit(vis, (*mSimulations)[job]);
mPostStepBarrier->wait([this] { afterPostStep(); }); mPostStepBarrier->wait([this] { afterPostStep(); });
} }
@ -724,7 +731,11 @@ namespace MWPhysics
{ {
waitForWorkers(); waitForWorkers();
std::scoped_lock lock(mSimulationMutex, mUpdateAabbMutex); std::scoped_lock lock(mSimulationMutex, mUpdateAabbMutex);
mSimulations.clear(); if (mSimulations != nullptr)
{
mSimulations->clear();
mSimulations = nullptr;
}
mUpdateAabb.clear(); mUpdateAabb.clear();
} }
@ -735,7 +746,7 @@ namespace MWPhysics
return; return;
const Visitors::PreStep impl{mCollisionWorld}; const Visitors::PreStep impl{mCollisionWorld};
const Visitors::WithLockedPtr<Visitors::PreStep, MaybeExclusiveLock> vis{impl, mCollisionWorldMutex, mNumThreads}; const Visitors::WithLockedPtr<Visitors::PreStep, MaybeExclusiveLock> vis{impl, mCollisionWorldMutex, mNumThreads};
for (auto& sim : mSimulations) for (auto& sim : *mSimulations)
std::visit(vis, sim); std::visit(vis, sim);
} }
@ -767,9 +778,13 @@ namespace MWPhysics
void PhysicsTaskScheduler::syncWithMainThread() void PhysicsTaskScheduler::syncWithMainThread()
{ {
if (mSimulations == nullptr)
return;
const Visitors::Sync vis{mAdvanceSimulation, mTimeAccum, mPhysicsDt, this}; const Visitors::Sync vis{mAdvanceSimulation, mTimeAccum, mPhysicsDt, this};
for (auto& sim : mSimulations) for (auto& sim : *mSimulations)
std::visit(vis, sim); std::visit(vis, sim);
mSimulations->clear();
mSimulations = nullptr;
} }
// Attempt to acquire unique lock on mSimulationMutex while not all worker // Attempt to acquire unique lock on mSimulationMutex while not all worker

@ -40,7 +40,7 @@ namespace MWPhysics
/// @param timeAccum accumulated time from previous run to interpolate movements /// @param timeAccum accumulated time from previous run to interpolate movements
/// @param actorsData per actor data needed to compute new positions /// @param actorsData per actor data needed to compute new positions
/// @return new position of each actor /// @return new position of each actor
void applyQueuedMovements(float & timeAccum, std::vector<Simulation>&& simulations, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats); void applyQueuedMovements(float& timeAccum, std::vector<Simulation>& simulations, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats);
void resetSimulation(const ActorMap& actors); void resetSimulation(const ActorMap& actors);
@ -77,7 +77,7 @@ namespace MWPhysics
void waitForWorkers(); void waitForWorkers();
std::unique_ptr<WorldFrameData> mWorldFrameData; std::unique_ptr<WorldFrameData> mWorldFrameData;
std::vector<Simulation> mSimulations; std::vector<Simulation>* mSimulations = nullptr;
std::unordered_set<const btCollisionObject*> mCollisionObjects; std::unordered_set<const btCollisionObject*> mCollisionObjects;
float mDefaultPhysicsDt; float mDefaultPhysicsDt;
float mPhysicsDt; float mPhysicsDt;

@ -708,9 +708,9 @@ namespace MWPhysics
} }
} }
std::vector<Simulation> PhysicsSystem::prepareSimulation(bool willSimulate) void PhysicsSystem::prepareSimulation(bool willSimulate, std::vector<Simulation>& simulations)
{ {
std::vector<Simulation> simulations; assert(simulations.empty());
simulations.reserve(mActors.size() + mProjectiles.size()); simulations.reserve(mActors.size() + mProjectiles.size());
const MWBase::World *world = MWBase::Environment::get().getWorld(); const MWBase::World *world = MWBase::Environment::get().getWorld();
for (const auto& [ref, physicActor] : mActors) for (const auto& [ref, physicActor] : mActors)
@ -754,8 +754,6 @@ namespace MWPhysics
{ {
simulations.emplace_back(ProjectileSimulation{projectile, ProjectileFrameData{*projectile}}); simulations.emplace_back(ProjectileSimulation{projectile, ProjectileFrameData{*projectile}});
} }
return simulations;
} }
void PhysicsSystem::stepSimulation(float dt, bool skipSimulation, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats) void PhysicsSystem::stepSimulation(float dt, bool skipSimulation, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats)
@ -786,9 +784,10 @@ namespace MWPhysics
mTaskScheduler->resetSimulation(mActors); mTaskScheduler->resetSimulation(mActors);
else else
{ {
auto simulations = prepareSimulation(mTimeAccum >= mPhysicsDt); std::vector<Simulation>& simulations = mSimulations[mSimulationsCounter++ % mSimulations.size()];
prepareSimulation(mTimeAccum >= mPhysicsDt, simulations);
// modifies mTimeAccum // modifies mTimeAccum
mTaskScheduler->applyQueuedMovements(mTimeAccum, std::move(simulations), frameStart, frameNumber, stats); mTaskScheduler->applyQueuedMovements(mTimeAccum, simulations, frameStart, frameNumber, stats);
} }
} }

@ -289,7 +289,7 @@ namespace MWPhysics
void updateWater(); void updateWater();
std::vector<Simulation> prepareSimulation(bool willSimulate); void prepareSimulation(bool willSimulate, std::vector<Simulation>& simulations);
std::unique_ptr<btBroadphaseInterface> mBroadphase; std::unique_ptr<btBroadphaseInterface> mBroadphase;
std::unique_ptr<btDefaultCollisionConfiguration> mCollisionConfiguration; std::unique_ptr<btDefaultCollisionConfiguration> mCollisionConfiguration;
@ -333,6 +333,9 @@ namespace MWPhysics
DetourNavigator::CollisionShapeType mActorCollisionShapeType; DetourNavigator::CollisionShapeType mActorCollisionShapeType;
std::size_t mSimulationsCounter = 0;
std::array<std::vector<Simulation>, 2> mSimulations;
PhysicsSystem (const PhysicsSystem&); PhysicsSystem (const PhysicsSystem&);
PhysicsSystem& operator= (const PhysicsSystem&); PhysicsSystem& operator= (const PhysicsSystem&);
}; };

Loading…
Cancel
Save