mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-21 08:39:45 +00:00
Merge branch 'fix_frame_rate_limit' into 'master'
Fix frame rate limit (#5686) See merge request OpenMW/openmw!603
This commit is contained in:
commit
2b144ff3dd
5 changed files with 72 additions and 29 deletions
|
@ -38,6 +38,8 @@
|
|||
|
||||
#include <components/detournavigator/navigator.hpp>
|
||||
|
||||
#include <components/misc/frameratelimiter.hpp>
|
||||
|
||||
#include "mwinput/inputmanagerimp.hpp"
|
||||
|
||||
#include "mwgui/windowmanagerimp.hpp"
|
||||
|
@ -918,13 +920,15 @@ void OMW::Engine::go()
|
|||
}
|
||||
|
||||
// Start the main rendering loop
|
||||
osg::Timer frameTimer;
|
||||
double simulationTime = 0.0;
|
||||
Misc::FrameRateLimiter frameRateLimiter = Misc::makeFrameRateLimiter(mEnvironment.getFrameRateLimit());
|
||||
const std::chrono::steady_clock::duration maxSimulationInterval(std::chrono::milliseconds(200));
|
||||
while (!mViewer->done() && !mEnvironment.getStateManager()->hasQuitRequest())
|
||||
{
|
||||
double dt = frameTimer.time_s();
|
||||
frameTimer.setStartTick();
|
||||
dt = std::min(dt, 0.2);
|
||||
const double dt = std::chrono::duration_cast<std::chrono::duration<double>>(std::min(
|
||||
frameRateLimiter.getLastFrameDuration(),
|
||||
maxSimulationInterval
|
||||
)).count();
|
||||
|
||||
mViewer->advance(simulationTime);
|
||||
|
||||
|
@ -960,7 +964,7 @@ void OMW::Engine::go()
|
|||
}
|
||||
}
|
||||
|
||||
mEnvironment.limitFrameRate(frameTimer.time_s());
|
||||
frameRateLimiter.limit();
|
||||
}
|
||||
|
||||
// Save user settings
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#include "environment.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
#include <components/resource/resourcesystem.hpp>
|
||||
|
||||
|
@ -98,19 +96,6 @@ float MWBase::Environment::getFrameRateLimit() const
|
|||
return mFrameRateLimit;
|
||||
}
|
||||
|
||||
void MWBase::Environment::limitFrameRate(double dt) const
|
||||
{
|
||||
if (mFrameRateLimit > 0.f)
|
||||
{
|
||||
double thisFrameTime = dt;
|
||||
double minFrameTime = 1.0 / static_cast<double>(mFrameRateLimit);
|
||||
if (thisFrameTime < minFrameTime)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::duration<double>(minFrameTime - thisFrameTime));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MWBase::World *MWBase::Environment::getWorld() const
|
||||
{
|
||||
assert (mWorld);
|
||||
|
|
|
@ -83,7 +83,6 @@ namespace MWBase
|
|||
|
||||
void setFrameRateLimit(float frameRateLimit);
|
||||
float getFrameRateLimit() const;
|
||||
void limitFrameRate(double dt) const;
|
||||
|
||||
World *getWorld() const;
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include <components/widgets/tags.hpp>
|
||||
|
||||
#include <components/misc/resourcehelpers.hpp>
|
||||
#include <components/misc/frameratelimiter.hpp>
|
||||
|
||||
#include "../mwbase/inputmanager.hpp"
|
||||
#include "../mwbase/statemanager.hpp"
|
||||
|
@ -710,12 +711,11 @@ namespace MWGui
|
|||
|
||||
if (block)
|
||||
{
|
||||
osg::Timer frameTimer;
|
||||
Misc::FrameRateLimiter frameRateLimiter = Misc::makeFrameRateLimiter(MWBase::Environment::get().getFrameRateLimit());
|
||||
while (mMessageBoxManager->readPressedButton(false) == -1
|
||||
&& !MWBase::Environment::get().getStateManager()->hasQuitRequest())
|
||||
{
|
||||
double dt = frameTimer.time_s();
|
||||
frameTimer.setStartTick();
|
||||
const double dt = std::chrono::duration_cast<std::chrono::duration<double>>(frameRateLimiter.getLastFrameDuration()).count();
|
||||
|
||||
mKeyboardNavigation->onFrame();
|
||||
mMessageBoxManager->onFrame(dt);
|
||||
|
@ -734,7 +734,7 @@ namespace MWGui
|
|||
// refer to the advance() and frame() order in Engine::go()
|
||||
mViewer->advance(mViewer->getFrameStamp()->getSimulationTime());
|
||||
|
||||
MWBase::Environment::get().limitFrameRate(frameTimer.time_s());
|
||||
frameRateLimiter.limit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1750,11 +1750,10 @@ namespace MWGui
|
|||
~MWSound::Type::Movie & MWSound::Type::Mask
|
||||
);
|
||||
|
||||
osg::Timer frameTimer;
|
||||
Misc::FrameRateLimiter frameRateLimiter = Misc::makeFrameRateLimiter(MWBase::Environment::get().getFrameRateLimit());
|
||||
while (mVideoWidget->update() && !MWBase::Environment::get().getStateManager()->hasQuitRequest())
|
||||
{
|
||||
double dt = frameTimer.time_s();
|
||||
frameTimer.setStartTick();
|
||||
const double dt = std::chrono::duration_cast<std::chrono::duration<double>>(frameRateLimiter.getLastFrameDuration()).count();
|
||||
|
||||
MWBase::Environment::get().getInputManager()->update(dt, true, false);
|
||||
|
||||
|
@ -1777,7 +1776,7 @@ namespace MWGui
|
|||
// refer to the advance() and frame() order in Engine::go()
|
||||
mViewer->advance(mViewer->getFrameStamp()->getSimulationTime());
|
||||
|
||||
MWBase::Environment::get().limitFrameRate(frameTimer.time_s());
|
||||
frameRateLimiter.limit();
|
||||
}
|
||||
mVideoWidget->stop();
|
||||
|
||||
|
|
56
components/misc/frameratelimiter.hpp
Normal file
56
components/misc/frameratelimiter.hpp
Normal file
|
@ -0,0 +1,56 @@
|
|||
#ifndef OPENMW_COMPONENTS_MISC_FRAMERATELIMITER_H
|
||||
#define OPENMW_COMPONENTS_MISC_FRAMERATELIMITER_H
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
namespace Misc
|
||||
{
|
||||
class FrameRateLimiter
|
||||
{
|
||||
public:
|
||||
template <class Rep, class Ratio>
|
||||
explicit FrameRateLimiter(std::chrono::duration<Rep, Ratio> maxFrameDuration,
|
||||
std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now())
|
||||
: mMaxFrameDuration(std::chrono::duration_cast<std::chrono::steady_clock::duration>(maxFrameDuration))
|
||||
, mLastMeasurement(now)
|
||||
{}
|
||||
|
||||
std::chrono::steady_clock::duration getLastFrameDuration() const
|
||||
{
|
||||
return mLastFrameDuration;
|
||||
}
|
||||
|
||||
void limit(std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now())
|
||||
{
|
||||
const auto passed = now - mLastMeasurement;
|
||||
const auto left = mMaxFrameDuration - passed;
|
||||
if (left > left.zero())
|
||||
{
|
||||
std::this_thread::sleep_for(left);
|
||||
mLastMeasurement = now + left;
|
||||
mLastFrameDuration = mMaxFrameDuration;
|
||||
}
|
||||
else
|
||||
{
|
||||
mLastMeasurement = now;
|
||||
mLastFrameDuration = passed;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::chrono::steady_clock::duration mMaxFrameDuration;
|
||||
std::chrono::steady_clock::time_point mLastMeasurement;
|
||||
std::chrono::steady_clock::duration mLastFrameDuration;
|
||||
};
|
||||
|
||||
inline Misc::FrameRateLimiter makeFrameRateLimiter(float frameRateLimit)
|
||||
{
|
||||
if (frameRateLimit > 0.0f)
|
||||
return Misc::FrameRateLimiter(std::chrono::duration<float>(1.0f / frameRateLimit));
|
||||
else
|
||||
return Misc::FrameRateLimiter(std::chrono::steady_clock::duration::zero());
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue