diff --git a/src/client/renderingengine.cpp b/src/client/renderingengine.cpp index fe3c17936..807c5816a 100644 --- a/src/client/renderingengine.cpp +++ b/src/client/renderingengine.cpp @@ -50,8 +50,7 @@ void FpsControl::limit(IrrlichtDevice *device, f32 *dtime, bool assume_paused) if (busy_time < frametime_min) { sleep_time = frametime_min - busy_time; - if (sleep_time > 0) - sleep_us(sleep_time); + porting::preciseSleepUs(sleep_time); } else { sleep_time = 0; } diff --git a/src/porting.h b/src/porting.h index d6cec6c1a..8b753f518 100644 --- a/src/porting.h +++ b/src/porting.h @@ -32,12 +32,16 @@ #define sleep_ms(x) Sleep(x) #define sleep_us(x) Sleep((x)/1000) + #define SLEEP_ACCURACY_US 2000 + #define setenv(n,v,o) _putenv_s(n,v) #define unsetenv(n) _putenv_s(n,"") #else #include #include // setenv + #define SLEEP_ACCURACY_US 200 + #define sleep_ms(x) usleep((x)*1000) #define sleep_us(x) usleep(x) #endif @@ -220,6 +224,21 @@ inline u64 getDeltaMs(u64 old_time_ms, u64 new_time_ms) return (old_time_ms - new_time_ms); } +inline void preciseSleepUs(u64 sleep_time) +{ + if (sleep_time > 0) + { + u64 target_time = porting::getTimeUs() + sleep_time; + if (sleep_time > SLEEP_ACCURACY_US) + sleep_us(sleep_time - SLEEP_ACCURACY_US); + + // Busy-wait the remaining time to adjust for sleep inaccuracies + // The target - now > 0 construct will handle overflow gracefully (even though it should + // never happen) + while ((s64)(target_time - porting::getTimeUs()) > 0) {} + } +} + inline const char *getPlatformName() { return