smoother timing in frame limiter

This commit is contained in:
water
2022-06-04 13:50:49 -04:00
parent 0c16d3c3d8
commit e1211aebc3
6 changed files with 67 additions and 58 deletions
+38 -44
View File
@@ -1,5 +1,7 @@
#include "FrameLimiter.h"
#include "common/common_types.h"
#include <thread>
#include <stdio.h>
double FrameLimiter::round_to_nearest_60fps(double current) {
double one_frame = 1.f / 60.f;
@@ -16,31 +18,16 @@ FrameLimiter::FrameLimiter() {}
FrameLimiter::~FrameLimiter() {}
void FrameLimiter::run(double target_fps,
bool experimental_accurate_lag,
bool do_sleeps,
double engine_time) {
double target_seconds;
if (experimental_accurate_lag) {
target_seconds = round_to_nearest_60fps(engine_time);
} else {
target_seconds = 1.f / target_fps;
}
double remaining_time = target_seconds - m_timer.getSeconds();
if (do_sleeps && remaining_time > 0.001) {
std::this_thread::sleep_for(std::chrono::microseconds(int((remaining_time - 0.001) * 1e6)));
}
while (remaining_time > 0) {
remaining_time = target_seconds - m_timer.getSeconds();
}
m_timer.start();
void sleep_us(u64 us) {
std::this_thread::sleep_for(std::chrono::microseconds(us));
}
#else
void sleep_us(u64 us) {
Sleep(us);
}
#define NOMINMAX
#include <Windows.h>
@@ -52,27 +39,34 @@ FrameLimiter::~FrameLimiter() {
timeEndPeriod(0);
}
void FrameLimiter::run(double target_fps,
bool experimental_accurate_lag,
bool do_sleeps,
double engine_time) {
double target_seconds;
if (experimental_accurate_lag) {
target_seconds = round_to_nearest_60fps(engine_time);
} else {
target_seconds = 1.f / target_fps;
}
double remaining_time = target_seconds - m_timer.getSeconds();
if (do_sleeps && remaining_time > 0.001) {
Sleep((remaining_time * 1000) - 1);
}
while (remaining_time > 0) {
remaining_time = target_seconds - m_timer.getSeconds();
}
m_timer.start();
}
#endif
void FrameLimiter::run(double target_fps, bool do_sleeps, double engine_time) {
// we want to exit this function when the current time reaches m_us_target.
// and update m_us_target for the next frame.
constexpr s64 max_lag_us = 20000;
constexpr s64 max_ahead_us = 50000;
s64 entry_time = m_timer.getUs();
// first, see if we're lagging too far behind:
if (entry_time > m_us_target + max_lag_us) {
m_us_target = entry_time - max_lag_us;
}
// see if we're too far ahead
if (m_us_target > entry_time + max_ahead_us) {
m_us_target = entry_time + max_ahead_us;
}
// sleep!
s64 remaining = m_us_target - entry_time;
if (do_sleeps && remaining > 1000) {
sleep_us(remaining - 1000);
}
while (m_timer.getUs() < m_us_target) {
// wait....
}
// now update the next target...
m_us_target += 1e6 * round_to_nearest_60fps(engine_time) * 60 / target_fps;
}