diff options
| author | 3gg <3gg@shellblade.net> | 2026-04-11 12:27:23 -0700 |
|---|---|---|
| committer | 3gg <3gg@shellblade.net> | 2026-04-11 12:27:23 -0700 |
| commit | 879e5af4eb1a8972fc944853a515e1003f94bd7c (patch) | |
| tree | 136864b506276998047374c28e5b24e3a5463b39 /simloop/include/simloop.h | |
| parent | af26c0503d698b7824055dc98207d6252d9875cf (diff) | |
Fix simloop divergence
Diffstat (limited to 'simloop/include/simloop.h')
| -rw-r--r-- | simloop/include/simloop.h | 38 |
1 files changed, 36 insertions, 2 deletions
diff --git a/simloop/include/simloop.h b/simloop/include/simloop.h index f267d40..6ee3b98 100644 --- a/simloop/include/simloop.h +++ b/simloop/include/simloop.h | |||
| @@ -3,6 +3,37 @@ | |||
| 3 | * This implements a simulation loop but in a way that the client retains | 3 | * This implements a simulation loop but in a way that the client retains |
| 4 | * control flow. The client steps the loop and then checks whether the | 4 | * control flow. The client steps the loop and then checks whether the |
| 5 | * simulation must be updated and/or the result rendered. | 5 | * simulation must be updated and/or the result rendered. |
| 6 | * | ||
| 7 | * If the simulation's update cannot keep up with the desired frame rate, then | ||
| 8 | * the loop degrades to match the simulation's rate by requesting a single | ||
| 9 | * update. | ||
| 10 | * | ||
| 11 | * Under a variable time delta, the loop could simply update the simulation | ||
| 12 | * with a large delta that puts the simulation back into the current clock | ||
| 13 | * time. Under a fixed time delta this isn't possible, and we seem to have two | ||
| 14 | * choices instead: | ||
| 15 | * | ||
| 16 | * a) Queue as many updates as necessary to bring the simulation back to the | ||
| 17 | * current clock time (time_diff / fixed_delta). | ||
| 18 | * | ||
| 19 | * b) Queue a single update. | ||
| 20 | * | ||
| 21 | * The issue with (a) is that the number of requested updates diverges and | ||
| 22 | * eventually the simulation appears to freeze. At every loop, the number of | ||
| 23 | * queued updates increases with respect to the last iteration as the | ||
| 24 | * simulation fails to keep up with the desired frame rate. Example: | ||
| 25 | * | ||
| 26 | * desired delta = 10ms (100 fps) | ||
| 27 | * actual delta = 20ms ( 50 fps) | ||
| 28 | * --------------------------- | ||
| 29 | * iter, sim time, clock time | ||
| 30 | * --------------------------- | ||
| 31 | * 0, 0, 0, initial state | ||
| 32 | * 1, 0, 10, queue 1 update | ||
| 33 | * 2, 10, 30, queue (30-10)/10 = 2 updates | ||
| 34 | * 3, 30, 70, queue (70-30)/10 = 4 updates | ||
| 35 | * 4, 70, 150, queue (150-70)/10 = 8 updates | ||
| 36 | * ... | ||
| 6 | */ | 37 | */ |
| 7 | #pragma once | 38 | #pragma once |
| 8 | 39 | ||
| @@ -21,8 +52,8 @@ typedef struct SimloopOut { | |||
| 21 | time_delta render_elapsed; ///< Amount of time elapsed in the rendering. | 52 | time_delta render_elapsed; ///< Amount of time elapsed in the rendering. |
| 22 | time_delta update_elapsed; ///< Amount of time elapsed in the simulation. | 53 | time_delta update_elapsed; ///< Amount of time elapsed in the simulation. |
| 23 | time_delta update_dt; ///< Delta time for simulation updates. | 54 | time_delta update_dt; ///< Delta time for simulation updates. |
| 24 | int updates_pending; ///< Number of frames the simulation should produce. | 55 | bool should_update; ///< Whether the simulation should update. |
| 25 | bool should_render; ///< Whether the simulation should be rendered. | 56 | bool should_render; ///< Whether the simulation should be rendered. |
| 26 | } SimloopOut; | 57 | } SimloopOut; |
| 27 | 58 | ||
| 28 | typedef struct SimloopTimeline { | 59 | typedef struct SimloopTimeline { |
| @@ -35,10 +66,13 @@ typedef struct Simloop { | |||
| 35 | SimloopTimeline render; ///< Render timeline. | 66 | SimloopTimeline render; ///< Render timeline. |
| 36 | uint64_t frame; ///< Frame counter. | 67 | uint64_t frame; ///< Frame counter. |
| 37 | Timer* timer; | 68 | Timer* timer; |
| 69 | bool first_iter; | ||
| 38 | } Simloop; | 70 | } Simloop; |
| 39 | 71 | ||
| 40 | /// Create a simulation loop. | 72 | /// Create a simulation loop. |
| 41 | Simloop simloop_make(const SimloopArgs*); | 73 | Simloop simloop_make(const SimloopArgs*); |
| 42 | 74 | ||
| 43 | /// Step the simulation loop. | 75 | /// Step the simulation loop. |
| 76 | /// | ||
| 77 | /// The simulation always triggers a render of the initial state of simulation. | ||
| 44 | void simloop_update(Simloop*, SimloopOut*); | 78 | void simloop_update(Simloop*, SimloopOut*); |
