From 993877b64175c556cf65fac7b6c3dd9c033f3be7 Mon Sep 17 00:00:00 2001 From: Josh Goebel Date: Sun, 28 Feb 2016 02:52:42 -0500 Subject: [PATCH] fix frame timing previosly timing was calculating the next frame based on now + duration when the correct timing should have been last_frame + duration. This would have the effect of slowing the game down the higher your CPU usage. A 0% CPU usage game would play at the request frame rate, but a 100% CPU usage game would play at only half the requested frame rate. (RR is render time below) Timing with the bug: 60FPs requested, 35FPs actual, 3 frames, 87ms. | 29ms | 29ms | 29ms | | RR 12ms + 17ms sleep | RR 12ms + 17ms sleep | RR 12ms + 17ms sleep | Timing after the fix: 60FPs, 60FPs actual, 3 frames, 51ms. | 17ms | 17ms | 17ms | | RR 12ms + sleep | RR 12ms + sleep | RR 12ms + sleep | After this fix you may need to change your games timing mechanics or adjust your frame rate (to slow things back down). Your game will run faster after this fix, even if you were using "100% CPU" before. --- src/Arduboy.cpp | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/Arduboy.cpp b/src/Arduboy.cpp index ec3ef6b..2da4d6c 100644 --- a/src/Arduboy.cpp +++ b/src/Arduboy.cpp @@ -106,12 +106,25 @@ bool Arduboy::nextFrame() // pre-render - // technically next frame should be last frame + each frame but if we're - // running a slow render we would constnatly be behind the clock - // keep an eye on this and see how it works. If it works well the - // lastFrameStart variable could be eliminated completely - nextFrameStart = now + eachFrameMillis; + // next frame should start from last frame start + frame duration + nextFrameStart = lastFrameStart + eachFrameMillis; + // If we're running CPU at 100%+ (too slow to complete each loop within + // the frame duration) then it's possible that we get "behind"... Say we + // took 5ms too long, resulting in nextFrameStart being 5ms in the PAST. + // In that case we simply schedule the next frame to start immediately. + // + // If we were to let the nextFrameStart slide further and further into + // the past AND eventually the CPU usage dropped then frame management + // would try to "catch up" (by speeding up the game) to make up for all + // that lost time. That would not be good. We allow frames to take too + // long (what choice do we have?), but we do not allow super-fast frames + // to make up for slow frames in the past. + if (nextFrameStart < now) { + nextFrameStart = now; + } + lastFrameStart = now; + post_render = true; return post_render; }