mirror of
https://github.com/OpenMW/openmw.git
synced 2025-05-01 03:11:23 +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/detournavigator/navigator.hpp>
|
||||||
|
|
||||||
|
#include <components/misc/frameratelimiter.hpp>
|
||||||
|
|
||||||
#include "mwinput/inputmanagerimp.hpp"
|
#include "mwinput/inputmanagerimp.hpp"
|
||||||
|
|
||||||
#include "mwgui/windowmanagerimp.hpp"
|
#include "mwgui/windowmanagerimp.hpp"
|
||||||
|
@ -918,13 +920,15 @@ void OMW::Engine::go()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the main rendering loop
|
// Start the main rendering loop
|
||||||
osg::Timer frameTimer;
|
|
||||||
double simulationTime = 0.0;
|
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())
|
while (!mViewer->done() && !mEnvironment.getStateManager()->hasQuitRequest())
|
||||||
{
|
{
|
||||||
double dt = frameTimer.time_s();
|
const double dt = std::chrono::duration_cast<std::chrono::duration<double>>(std::min(
|
||||||
frameTimer.setStartTick();
|
frameRateLimiter.getLastFrameDuration(),
|
||||||
dt = std::min(dt, 0.2);
|
maxSimulationInterval
|
||||||
|
)).count();
|
||||||
|
|
||||||
mViewer->advance(simulationTime);
|
mViewer->advance(simulationTime);
|
||||||
|
|
||||||
|
@ -960,7 +964,7 @@ void OMW::Engine::go()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mEnvironment.limitFrameRate(frameTimer.time_s());
|
frameRateLimiter.limit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save user settings
|
// Save user settings
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
#include "environment.hpp"
|
#include "environment.hpp"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <chrono>
|
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
#include <components/resource/resourcesystem.hpp>
|
#include <components/resource/resourcesystem.hpp>
|
||||||
|
|
||||||
|
@ -98,19 +96,6 @@ float MWBase::Environment::getFrameRateLimit() const
|
||||||
return mFrameRateLimit;
|
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
|
MWBase::World *MWBase::Environment::getWorld() const
|
||||||
{
|
{
|
||||||
assert (mWorld);
|
assert (mWorld);
|
||||||
|
|
|
@ -83,7 +83,6 @@ namespace MWBase
|
||||||
|
|
||||||
void setFrameRateLimit(float frameRateLimit);
|
void setFrameRateLimit(float frameRateLimit);
|
||||||
float getFrameRateLimit() const;
|
float getFrameRateLimit() const;
|
||||||
void limitFrameRate(double dt) const;
|
|
||||||
|
|
||||||
World *getWorld() const;
|
World *getWorld() const;
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,7 @@
|
||||||
#include <components/widgets/tags.hpp>
|
#include <components/widgets/tags.hpp>
|
||||||
|
|
||||||
#include <components/misc/resourcehelpers.hpp>
|
#include <components/misc/resourcehelpers.hpp>
|
||||||
|
#include <components/misc/frameratelimiter.hpp>
|
||||||
|
|
||||||
#include "../mwbase/inputmanager.hpp"
|
#include "../mwbase/inputmanager.hpp"
|
||||||
#include "../mwbase/statemanager.hpp"
|
#include "../mwbase/statemanager.hpp"
|
||||||
|
@ -710,12 +711,11 @@ namespace MWGui
|
||||||
|
|
||||||
if (block)
|
if (block)
|
||||||
{
|
{
|
||||||
osg::Timer frameTimer;
|
Misc::FrameRateLimiter frameRateLimiter = Misc::makeFrameRateLimiter(MWBase::Environment::get().getFrameRateLimit());
|
||||||
while (mMessageBoxManager->readPressedButton(false) == -1
|
while (mMessageBoxManager->readPressedButton(false) == -1
|
||||||
&& !MWBase::Environment::get().getStateManager()->hasQuitRequest())
|
&& !MWBase::Environment::get().getStateManager()->hasQuitRequest())
|
||||||
{
|
{
|
||||||
double dt = frameTimer.time_s();
|
const double dt = std::chrono::duration_cast<std::chrono::duration<double>>(frameRateLimiter.getLastFrameDuration()).count();
|
||||||
frameTimer.setStartTick();
|
|
||||||
|
|
||||||
mKeyboardNavigation->onFrame();
|
mKeyboardNavigation->onFrame();
|
||||||
mMessageBoxManager->onFrame(dt);
|
mMessageBoxManager->onFrame(dt);
|
||||||
|
@ -734,7 +734,7 @@ namespace MWGui
|
||||||
// refer to the advance() and frame() order in Engine::go()
|
// refer to the advance() and frame() order in Engine::go()
|
||||||
mViewer->advance(mViewer->getFrameStamp()->getSimulationTime());
|
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
|
~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())
|
while (mVideoWidget->update() && !MWBase::Environment::get().getStateManager()->hasQuitRequest())
|
||||||
{
|
{
|
||||||
double dt = frameTimer.time_s();
|
const double dt = std::chrono::duration_cast<std::chrono::duration<double>>(frameRateLimiter.getLastFrameDuration()).count();
|
||||||
frameTimer.setStartTick();
|
|
||||||
|
|
||||||
MWBase::Environment::get().getInputManager()->update(dt, true, false);
|
MWBase::Environment::get().getInputManager()->update(dt, true, false);
|
||||||
|
|
||||||
|
@ -1777,7 +1776,7 @@ namespace MWGui
|
||||||
// refer to the advance() and frame() order in Engine::go()
|
// refer to the advance() and frame() order in Engine::go()
|
||||||
mViewer->advance(mViewer->getFrameStamp()->getSimulationTime());
|
mViewer->advance(mViewer->getFrameStamp()->getSimulationTime());
|
||||||
|
|
||||||
MWBase::Environment::get().limitFrameRate(frameTimer.time_s());
|
frameRateLimiter.limit();
|
||||||
}
|
}
|
||||||
mVideoWidget->stop();
|
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