mirror of
https://github.com/OpenMW/openmw.git
synced 2025-06-19 15:11:33 +00:00
Reuse physics simulations buffer
To avoid redundant allocations. Use 2 buffers to make sure there is no overlap between main and the background threads.
This commit is contained in:
parent
c4d357df0f
commit
277211c5b4
4 changed files with 35 additions and 18 deletions
|
@ -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…
Reference in a new issue