From 1b19ad889061b0bb7ae5e5cab436251ee3b4f692 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 16 Oct 2023 05:00:09 -0700 Subject: [PATCH] Frame skipping Skip up to 3 frames of rendering if the time between tics exceeds TICRATE. If rendering is a significant source of that slowdown, skipping some frames can speed up the game loop and improve input responsiveness. --- src/d_main.cpp | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index 2343a837c..32ee3bd4e 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -328,8 +328,9 @@ gamestate_t wipegamestate = GS_LEVEL; INT16 wipetypepre = -1; INT16 wipetypepost = -1; -static void D_Display(void) +static bool D_Display(void) { + bool ranwipe = false; boolean forcerefresh = false; static boolean wipe = false; INT32 wipedefindex = 0; @@ -340,7 +341,7 @@ static void D_Display(void) if (!dedicated) { if (nodrawers) - return; // for comparative timing/profiling + return false; // for comparative timing/profiling // Lactozilla: Switching renderers works by checking // if the game has to do it right when the frame @@ -409,6 +410,7 @@ static void D_Display(void) F_WipeColorFill(31); F_WipeEndScreen(); F_RunWipe(wipedefindex, wipetypepre, gamestate != GS_MENU, "FADEMAP0", false, false); + ranwipe = true; } if (G_GamestateUsesLevel() == false && rendermode != render_none) @@ -422,6 +424,7 @@ static void D_Display(void) else //dedicated servers { F_RunWipe(wipedefindex, wipedefs[wipedefindex], gamestate != GS_MENU, "FADEMAP0", false, false); + ranwipe = true; wipegamestate = gamestate; } @@ -431,7 +434,7 @@ static void D_Display(void) wipetypepre = -1; if (dedicated) //bail out after wipe logic - return; + return false; // Catch runaway clipping rectangles. V_ClearClipRect(); @@ -708,6 +711,7 @@ static void D_Display(void) F_WipeEndScreen(); F_RunWipe(wipedefindex, wipedefs[wipedefindex], gamestate != GS_MENU && gamestate != GS_TITLESCREEN, "FADEMAP0", true, false); + ranwipe = true; } // reset counters so timedemo doesn't count the wipe duration @@ -763,6 +767,8 @@ static void D_Display(void) I_FinishUpdate(); // page flip or blit buffer ps_swaptime = I_GetPreciseTime() - ps_swaptime; } + + return ranwipe; } // ========================================================================= @@ -779,6 +785,7 @@ void D_SRB2Loop(void) boolean interp = false; boolean doDisplay = false; + int frameskip = 0; if (dedicated) server = true; @@ -827,6 +834,8 @@ void D_SRB2Loop(void) capbudget = (precise_t) budget; } + bool ranwipe = false; + I_UpdateTime(cv_timescale.value); if (lastwipetic) @@ -923,9 +932,9 @@ void D_SRB2Loop(void) rendertimefrac_unpaused = FRACUNIT; } - if (interp || doDisplay) + if ((interp || doDisplay) && !frameskip) { - D_Display(); + ranwipe = D_Display(); } #ifdef HWRENDER @@ -976,6 +985,23 @@ void D_SRB2Loop(void) finishprecise = I_GetPreciseTime(); deltasecs = (double)((INT64)(finishprecise - enterprecise)) / I_GetPrecisePrecision(); deltatics = deltasecs * NEWTICRATE; + + // If time spent this game loop exceeds a single tic, + // it's probably because of rendering. + // + // Skip rendering the next frame, up to a limit of 3 + // frames before a frame is rendered no matter what. + // + // Wipes run an inner loop and artificially increase + // the measured time. + if (!ranwipe && frameskip < 3 && deltatics > 1.0) + { + frameskip++; + } + else + { + frameskip = 0; + } } }