mirror of
https://github.com/jpd002/Play-.git
synced 2025-04-28 13:47:57 +03:00
Use the average frame time to limit frame rate.
Helps a lot with games that don't run at 60fps internally (ex.: FFX).
This commit is contained in:
parent
695cb21e06
commit
130dcb7d51
2 changed files with 23 additions and 3 deletions
|
@ -11,6 +11,10 @@ CFrameLimiter::CFrameLimiter()
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
timeBeginPeriod(1);
|
timeBeginPeriod(1);
|
||||||
#endif
|
#endif
|
||||||
|
for (uint32 i = 0; i < MAX_FRAMETIMES; i++)
|
||||||
|
{
|
||||||
|
m_frameTimes[i] = std::chrono::microseconds(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CFrameLimiter::~CFrameLimiter()
|
CFrameLimiter::~CFrameLimiter()
|
||||||
|
@ -32,9 +36,17 @@ void CFrameLimiter::EndFrame()
|
||||||
assert(m_frameStarted);
|
assert(m_frameStarted);
|
||||||
auto currentFrameTime = std::chrono::high_resolution_clock::now();
|
auto currentFrameTime = std::chrono::high_resolution_clock::now();
|
||||||
auto frameDuration = std::chrono::duration_cast<std::chrono::microseconds>(currentFrameTime - m_lastFrameTime);
|
auto frameDuration = std::chrono::duration_cast<std::chrono::microseconds>(currentFrameTime - m_lastFrameTime);
|
||||||
if(frameDuration < m_minFrameDuration)
|
m_frameTimes[m_frameTimeIndex++] = frameDuration;
|
||||||
|
m_frameTimeIndex %= MAX_FRAMETIMES;
|
||||||
|
std::chrono::microseconds averageFrameTime = std::chrono::microseconds(0);
|
||||||
|
for(uint32 i = 0; i < MAX_FRAMETIMES; i++)
|
||||||
{
|
{
|
||||||
auto delay = m_minFrameDuration - frameDuration;
|
averageFrameTime += m_frameTimes[i];
|
||||||
|
}
|
||||||
|
averageFrameTime /= MAX_FRAMETIMES;
|
||||||
|
if(averageFrameTime < m_minFrameDuration)
|
||||||
|
{
|
||||||
|
auto delay = m_minFrameDuration - averageFrameTime;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
{
|
{
|
||||||
LARGE_INTEGER ft = {};
|
LARGE_INTEGER ft = {};
|
||||||
|
@ -47,7 +59,7 @@ void CFrameLimiter::EndFrame()
|
||||||
}
|
}
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
//Sleeping for the whole delay on macOS/iOS doesn't provide a good enough resolution
|
//Sleeping for the whole delay on macOS/iOS doesn't provide a good enough resolution
|
||||||
while(frameDuration < m_minFrameDuration)
|
while(averageFrameTime < m_minFrameDuration)
|
||||||
{
|
{
|
||||||
std::this_thread::sleep_for(std::chrono::microseconds(250));
|
std::this_thread::sleep_for(std::chrono::microseconds(250));
|
||||||
currentFrameTime = std::chrono::high_resolution_clock::now();
|
currentFrameTime = std::chrono::high_resolution_clock::now();
|
||||||
|
|
|
@ -17,6 +17,14 @@ public:
|
||||||
private:
|
private:
|
||||||
typedef std::chrono::high_resolution_clock::time_point TimePoint;
|
typedef std::chrono::high_resolution_clock::time_point TimePoint;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
MAX_FRAMETIMES = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
std::chrono::microseconds m_frameTimes[MAX_FRAMETIMES];
|
||||||
|
uint32 m_frameTimeIndex = 0;
|
||||||
|
|
||||||
std::chrono::microseconds m_minFrameDuration = std::chrono::microseconds(0);
|
std::chrono::microseconds m_minFrameDuration = std::chrono::microseconds(0);
|
||||||
bool m_frameStarted = false;
|
bool m_frameStarted = false;
|
||||||
TimePoint m_lastFrameTime;
|
TimePoint m_lastFrameTime;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue