diff --git a/apps/openmw/mwphysics/mtphysics.cpp b/apps/openmw/mwphysics/mtphysics.cpp index 297f40c6a7..46c2574706 100644 --- a/apps/openmw/mwphysics/mtphysics.cpp +++ b/apps/openmw/mwphysics/mtphysics.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -410,8 +411,10 @@ namespace MWPhysics return std::make_tuple(numSteps, actualDelta); } - void PhysicsTaskScheduler::applyQueuedMovements(float & timeAccum, std::vector&& simulations, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats) + void PhysicsTaskScheduler::applyQueuedMovements(float& timeAccum, std::vector& simulations, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats) { + assert(mSimulations != &simulations); + waitForWorkers(); // This function run in the main thread. @@ -444,10 +447,10 @@ namespace MWPhysics mRemainingSteps = numSteps; mTimeAccum = timeAccum; mPhysicsDt = newDelta; - mSimulations = std::move(simulations); + mSimulations = &simulations; mAdvanceSimulation = (mRemainingSteps != 0); ++mFrameCounter; - mNumJobs = mSimulations.size(); + mNumJobs = mSimulations->size(); mNextLOS.store(0, std::memory_order_relaxed); mNextJob.store(0, std::memory_order_release); @@ -478,7 +481,11 @@ namespace MWPhysics MaybeExclusiveLock lock(mSimulationMutex, mNumThreads); mBudget.reset(mDefaultPhysicsDt); mAsyncBudget.reset(0.0f); - mSimulations.clear(); + if (mSimulations != nullptr) + { + mSimulations->clear(); + mSimulations = nullptr; + } for (const auto& [_, actor] : actors) { actor->updatePosition(); @@ -654,7 +661,7 @@ namespace MWPhysics { const Visitors::UpdatePosition impl{mCollisionWorld}; const Visitors::WithLockedPtr vis{impl, mCollisionWorldMutex, mNumThreads}; - for (Simulation& sim : mSimulations) + for (Simulation& sim : *mSimulations) std::visit(vis, sim); } @@ -682,7 +689,7 @@ namespace MWPhysics const Visitors::Move impl{mPhysicsDt, mCollisionWorld, *mWorldFrameData}; const Visitors::WithLockedPtr vis{impl, mCollisionWorldMutex, mNumThreads}; 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(); }); } @@ -724,7 +731,11 @@ namespace MWPhysics { waitForWorkers(); std::scoped_lock lock(mSimulationMutex, mUpdateAabbMutex); - mSimulations.clear(); + if (mSimulations != nullptr) + { + mSimulations->clear(); + mSimulations = nullptr; + } mUpdateAabb.clear(); } @@ -735,7 +746,7 @@ namespace MWPhysics return; const Visitors::PreStep impl{mCollisionWorld}; const Visitors::WithLockedPtr vis{impl, mCollisionWorldMutex, mNumThreads}; - for (auto& sim : mSimulations) + for (auto& sim : *mSimulations) std::visit(vis, sim); } @@ -767,9 +778,13 @@ namespace MWPhysics void PhysicsTaskScheduler::syncWithMainThread() { + if (mSimulations == nullptr) + return; const Visitors::Sync vis{mAdvanceSimulation, mTimeAccum, mPhysicsDt, this}; - for (auto& sim : mSimulations) + for (auto& sim : *mSimulations) std::visit(vis, sim); + mSimulations->clear(); + mSimulations = nullptr; } // Attempt to acquire unique lock on mSimulationMutex while not all worker diff --git a/apps/openmw/mwphysics/mtphysics.hpp b/apps/openmw/mwphysics/mtphysics.hpp index 74556ccd81..1e730a5801 100644 --- a/apps/openmw/mwphysics/mtphysics.hpp +++ b/apps/openmw/mwphysics/mtphysics.hpp @@ -40,7 +40,7 @@ namespace MWPhysics /// @param timeAccum accumulated time from previous run to interpolate movements /// @param actorsData per actor data needed to compute new positions /// @return new position of each actor - void applyQueuedMovements(float & timeAccum, std::vector&& simulations, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats); + void applyQueuedMovements(float& timeAccum, std::vector& simulations, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats); void resetSimulation(const ActorMap& actors); @@ -77,7 +77,7 @@ namespace MWPhysics void waitForWorkers(); std::unique_ptr mWorldFrameData; - std::vector mSimulations; + std::vector* mSimulations = nullptr; std::unordered_set mCollisionObjects; float mDefaultPhysicsDt; float mPhysicsDt; diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index df94d5cc1f..17ef53acd5 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -708,9 +708,9 @@ namespace MWPhysics } } - std::vector PhysicsSystem::prepareSimulation(bool willSimulate) + void PhysicsSystem::prepareSimulation(bool willSimulate, std::vector& simulations) { - std::vector simulations; + assert(simulations.empty()); simulations.reserve(mActors.size() + mProjectiles.size()); const MWBase::World *world = MWBase::Environment::get().getWorld(); for (const auto& [ref, physicActor] : mActors) @@ -754,8 +754,6 @@ namespace MWPhysics { 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) @@ -786,9 +784,10 @@ namespace MWPhysics mTaskScheduler->resetSimulation(mActors); else { - auto simulations = prepareSimulation(mTimeAccum >= mPhysicsDt); + std::vector& simulations = mSimulations[mSimulationsCounter++ % mSimulations.size()]; + prepareSimulation(mTimeAccum >= mPhysicsDt, simulations); // modifies mTimeAccum - mTaskScheduler->applyQueuedMovements(mTimeAccum, std::move(simulations), frameStart, frameNumber, stats); + mTaskScheduler->applyQueuedMovements(mTimeAccum, simulations, frameStart, frameNumber, stats); } } diff --git a/apps/openmw/mwphysics/physicssystem.hpp b/apps/openmw/mwphysics/physicssystem.hpp index dde2fc34c7..e8730a7dff 100644 --- a/apps/openmw/mwphysics/physicssystem.hpp +++ b/apps/openmw/mwphysics/physicssystem.hpp @@ -289,7 +289,7 @@ namespace MWPhysics void updateWater(); - std::vector prepareSimulation(bool willSimulate); + void prepareSimulation(bool willSimulate, std::vector& simulations); std::unique_ptr mBroadphase; std::unique_ptr mCollisionConfiguration; @@ -333,6 +333,9 @@ namespace MWPhysics DetourNavigator::CollisionShapeType mActorCollisionShapeType; + std::size_t mSimulationsCounter = 0; + std::array, 2> mSimulations; + PhysicsSystem (const PhysicsSystem&); PhysicsSystem& operator= (const PhysicsSystem&); };