]> git.0x19.co - doomgeneric-snom360/commitdiff
Only draw a new frame w/ a tic
authortechflashYT <officialTechflashYT@gmail.com>
Sun, 13 Jul 2025 12:31:16 +0000 (05:31 -0700)
committertechflashYT <officialTechflashYT@gmail.com>
Sun, 13 Jul 2025 12:41:18 +0000 (05:41 -0700)
Since TryRunTics() can absolutely return without running any gametic
(and it 100% will every-other time on fast enough hardware), it's a
waste of processing power to draw a new frame on every
doomgeneric_Tick().  This quick fix optimizes it down so it'll only try
to draw a new frame if TryRunTics() actually ran any gametics (and thus,
we have new frames to display).

In the best case scenario (the platform's DG_DrawFrame() is incredibly
fast), this will save a minute amount of processing power.
In the worst case scenario (the platform's DG_DrawFrame() is incredibly
slow), this can save several miliseconds of useless drawing, allowing
more actual gametics to be processed.  In fact, without this, slower
platforms can actually dig themselves into a hole that they can never
escape from.  It could start running behind on gametics due to the
useless render, which results in doing more work to catch back up in
every TryRunTics() call, further compounding the slowness.

doomgeneric/d_loop.c
doomgeneric/d_loop.h
doomgeneric/d_main.c

index 1939dbdc3d0f155e674485445caf5a79e0fbc902..bad699dd46f68c640f3c1f0d804b9e676715f431 100644 (file)
@@ -703,7 +703,7 @@ static void SinglePlayerClear(ticcmd_set_t *set)
 // TryRunTics
 //
 
-void TryRunTics (void)
+int TryRunTics (void)
 {
     int        i;
     int        lowtic;
@@ -712,11 +712,13 @@ void TryRunTics (void)
     int realtics;
     int        availabletics;
     int        counts;
+    int ticsRan;
 
     // get real tics
     entertic = I_GetTime() / ticdup;
     realtics = entertic - oldentertics;
     oldentertics = entertic;
+    ticsRan = 0;
 
     // in singletics mode, run a single tic every time this function
     // is called.
@@ -778,7 +780,7 @@ void TryRunTics (void)
 
        if (I_GetTime() / ticdup - entertic > 0)
        {
-           return;
+           return ticsRan;
        }
 
         I_Sleep(1);
@@ -791,7 +793,7 @@ void TryRunTics (void)
 
         if (!PlayersInGame())
         {
-            return;
+            return ticsRan;
         }
 
         set = &ticdata[(gametic / ticdup) % BACKUPTICS];
@@ -810,6 +812,7 @@ void TryRunTics (void)
 
             loop_interface->RunTic(set->cmds, set->ingame);
            gametic++;
+           ticsRan++;
 
            // modify command for duplicated tics
 
@@ -818,6 +821,7 @@ void TryRunTics (void)
 
        NetUpdate ();   // check for new console commands
     }
+    return ticsRan;
 }
 
 void D_RegisterLoopCallbacks(loop_interface_t *i)
index eb87d84888bd8cf90a374eb214462bd25a22ab80..486b3b55e425bab725fa2b30f059d08bbb11d71c 100644 (file)
@@ -59,7 +59,7 @@ void NetUpdate (void);
 void D_QuitNetGame (void);
 
 //? how many ticks to run?
-void TryRunTics (void);
+int TryRunTics (void);
 
 // Called at start of game loop to initialize timers
 void D_StartGameLoop(void);
index 9012e5f54086cb86aa6f5ab2d0aa7c7d11165ec8..bda9b71fe7ff1fcdd22a85f755f01aae4c6803ac 100644 (file)
@@ -404,15 +404,21 @@ boolean D_GrabMouseCallback(void)
 
 void doomgeneric_Tick()
 {
+    int ret;
     // frame syncronous IO operations
     I_StartFrame ();
 
-    TryRunTics (); // will run at least one tic
+    ret = TryRunTics (); // may run 0 tics if we're ahead of schedule
+                        // (and we are, on anything modern)
 
     S_UpdateSounds (players[consoleplayer].mo);// move positional sounds
 
     // Update display, next frame, with current state.
-    if (screenvisible)
+    //
+    // Don't bother displaying if we haven't ran any tics,
+    // since we'd just be painting the exact same image from
+    // last tic (waste of processing power)
+    if (screenvisible && ret > 0)
     {
         D_Display ();
     }