aboutsummaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2026-05-02 14:59:18 -0700
committer3gg <3gg@shellblade.net>2026-05-02 14:59:18 -0700
commit456d7f883ca34ec83692ff3879ca5f5717e82b33 (patch)
tree9bc29d8aa999d98d220419bbf87a02e9639afc64 /app
parent5c7204d7b334855b18761ba95f61fea0aefddd52 (diff)
Use the simloop libraryHEADmain
Diffstat (limited to 'app')
-rw-r--r--app/CMakeLists.txt1
-rw-r--r--app/demo/main.c11
-rw-r--r--app/include/gfx/app.h54
-rw-r--r--app/src/app.c46
4 files changed, 51 insertions, 61 deletions
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index 021a77d..b88219a 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -12,6 +12,7 @@ target_link_libraries(gfx-app PUBLIC
12 glad 12 glad
13 glfw 13 glfw
14 log 14 log
15 simloop
15 timer) 16 timer)
16 17
17add_subdirectory(demo) 18add_subdirectory(demo)
diff --git a/app/demo/main.c b/app/demo/main.c
index 0aa4e34..2efca7c 100644
--- a/app/demo/main.c
+++ b/app/demo/main.c
@@ -2,10 +2,11 @@
2 2
3#include <assert.h> 3#include <assert.h>
4 4
5const int WIDTH = 960; 5const int WIDTH = 960;
6const int HEIGHT = 600; 6const int HEIGHT = 600;
7const int MAX_FPS = 60; 7const int UPDATE_FPS = 60;
8const char* TITLE = "iso3d"; 8const int MAX_FPS = 60;
9const char* TITLE = "iso3d";
9 10
10typedef struct GfxAppState { 11typedef struct GfxAppState {
11 int unused; 12 int unused;
@@ -47,4 +48,4 @@ void Resize(GfxApp* app, GfxAppState* state, int width, int height) {
47 (void)height; 48 (void)height;
48} 49}
49 50
50GFX_APP_MAIN(WIDTH, HEIGHT, MAX_FPS, TITLE) 51GFX_APP_MAIN(WIDTH, HEIGHT, UPDATE_FPS, MAX_FPS, TITLE)
diff --git a/app/include/gfx/app.h b/app/include/gfx/app.h
index 3017707..42fccec 100644
--- a/app/include/gfx/app.h
+++ b/app/include/gfx/app.h
@@ -5,13 +5,13 @@ typedef struct GfxAppState GfxAppState;
5 5
6/// Application settings. 6/// Application settings.
7typedef struct GfxAppDesc { 7typedef struct GfxAppDesc {
8 int argc; // Number of application arguments. 8 int argc; // Number of application arguments.
9 const char** argv; // Application arguments. 9 const char** argv; // Application arguments.
10 int width; // Window width. 10 int width; // Window width.
11 int height; // Window height. 11 int height; // Window height.
12 int max_fps; // Desired maximum display framerate. 0 to disable. 12 int update_fps; // Desired frame update frequency.
13 double update_delta_time; // Desired delta time between frame updates. 13 int max_render_fps; // Desired maximum render frame rate. 0 to disable.
14 const char* title; // Window title. 14 const char* title; // Window title.
15 GfxAppState* app_state; 15 GfxAppState* app_state;
16} GfxAppDesc; 16} GfxAppDesc;
17 17
@@ -88,24 +88,24 @@ bool gfx_app_is_key_pressed(GfxApp*, Key);
88 88
89/// Define a main function that initializes and puts the application in a loop. 89/// Define a main function that initializes and puts the application in a loop.
90/// See also: gfx_app_run(). 90/// See also: gfx_app_run().
91#define GFX_APP_MAIN(WIDTH, HEIGHT, MAX_FPS, TITLE) \ 91#define GFX_APP_MAIN(WIDTH, HEIGHT, UPDATE_FPS, MAX_RENDER_FPS, TITLE) \
92 int main(int argc, const char** argv) { \ 92 int main(int argc, const char** argv) { \
93 GfxAppState app_state = {0}; \ 93 GfxAppState app_state = {0}; \
94 gfx_app_run( \ 94 gfx_app_run( \
95 &(GfxAppDesc){ \ 95 &(GfxAppDesc){ \
96 .argc = argc, \ 96 .argc = argc, \
97 .argv = argv, \ 97 .argv = argv, \
98 .width = WIDTH, \ 98 .width = WIDTH, \
99 .height = HEIGHT, \ 99 .height = HEIGHT, \
100 .max_fps = MAX_FPS, \ 100 .update_fps = UPDATE_FPS, \
101 .update_delta_time = MAX_FPS > 0 ? 1.0 / (double)MAX_FPS : 0.0, \ 101 .max_render_fps = MAX_RENDER_FPS, \
102 .title = TITLE, \ 102 .title = TITLE, \
103 .app_state = &app_state, \ 103 .app_state = &app_state, \
104 }, \ 104 }, \
105 &(GfxAppCallbacks){.init = Init, \ 105 &(GfxAppCallbacks){.init = Init, \
106 .shutdown = Shutdown, \ 106 .shutdown = Shutdown, \
107 .update = Update, \ 107 .update = Update, \
108 .render = Render, \ 108 .render = Render, \
109 .resize = Resize}); \ 109 .resize = Resize}); \
110 return 0; \ 110 return 0; \
111 } 111 }
diff --git a/app/src/app.c b/app/src/app.c
index 8262378..c056ddd 100644
--- a/app/src/app.c
+++ b/app/src/app.c
@@ -4,6 +4,7 @@
4 4
5#include <GLFW/glfw3.h> 5#include <GLFW/glfw3.h>
6#include <log/log.h> 6#include <log/log.h>
7#include <simloop.h>
7#include <timer.h> 8#include <timer.h>
8 9
9#include <assert.h> 10#include <assert.h>
@@ -13,9 +14,8 @@
13typedef struct GfxApp { 14typedef struct GfxApp {
14 GfxAppState* app_state; 15 GfxAppState* app_state;
15 GfxAppCallbacks callbacks; 16 GfxAppCallbacks callbacks;
16 int max_fps;
17 double update_delta_time;
18 GLFWwindow* window; 17 GLFWwindow* window;
18 Simloop simloop;
19} GfxApp; 19} GfxApp;
20 20
21/// Storing the application state in a global variable so that we can call the 21/// Storing the application state in a global variable so that we can call the
@@ -32,17 +32,9 @@ static void loop(GfxApp* app) {
32 assert(app); 32 assert(app);
33 assert(app->window); 33 assert(app->window);
34 34
35 const time_delta min_frame_time = 35 time_delta time = 0;
36 app->max_fps > 0 ? time_delta_from_sec(1.0 / (double)(app->max_fps)) : 0; 36 Timer timer = timer_make();
37 const time_delta update_dt = time_delta_from_sec(app->update_delta_time); 37 SimloopOut simout = {};
38 time_delta time = 0;
39 time_delta time_budget = 0;
40 Timer timer = timer_make();
41
42 // Warm up the update to initialize the application's state.
43 (*app->callbacks.update)(
44 app, app->app_state, time_delta_to_sec(time),
45 time_delta_to_sec(update_dt));
46 38
47 // Warm up the rendering before entering the main loop. A renderer can 39 // Warm up the rendering before entering the main loop. A renderer can
48 // compile shaders and do other initialization the first time it renders a 40 // compile shaders and do other initialization the first time it renders a
@@ -53,25 +45,21 @@ static void loop(GfxApp* app) {
53 timer_start(&timer); 45 timer_start(&timer);
54 while (!glfwWindowShouldClose(app->window)) { 46 while (!glfwWindowShouldClose(app->window)) {
55 timer_tick(&timer); 47 timer_tick(&timer);
56 time_budget += timer.delta_time; 48 simloop_update(&app->simloop, timer.delta_time, &simout);
49
50 glfwPollEvents();
57 51
58 while (time_budget >= update_dt) { 52 if (simout.should_update) {
59 (*app->callbacks.update)( 53 (*app->callbacks.update)(
60 app, app->app_state, time_delta_to_sec(time), 54 app, app->app_state, time_delta_to_sec(time),
61 time_delta_to_sec(update_dt)); 55 time_delta_to_sec(simout.update_dt));
62
63 time += update_dt;
64 time_budget -= update_dt;
65 } 56 }
66 57
67 (*app->callbacks.render)(app, app->app_state); 58 (*app->callbacks.render)(app, app->app_state);
68 glfwSwapBuffers(app->window); 59 glfwSwapBuffers(app->window);
69 glfwPollEvents();
70 60
71 const time_point frame_end = time_now(); 61 if (simout.throttle > 0) {
72 const time_delta frame_time = time_diff(timer.last_tick, frame_end); 62 time_sleep(simout.throttle);
73 if ((min_frame_time > 0) && (frame_time < min_frame_time)) {
74 time_sleep(min_frame_time - frame_time);
75 } 63 }
76 } 64 }
77} 65}
@@ -82,11 +70,9 @@ bool gfx_app_run(const GfxAppDesc* desc, const GfxAppCallbacks* callbacks) {
82 70
83 bool success = false; 71 bool success = false;
84 72
85 g_gfx_app.app_state = desc->app_state; 73 g_gfx_app.app_state = desc->app_state;
86 g_gfx_app.callbacks = *callbacks; 74 g_gfx_app.callbacks = *callbacks;
87 g_gfx_app.max_fps = desc->max_fps; 75 g_gfx_app.window = nullptr;
88 g_gfx_app.update_delta_time = desc->update_delta_time;
89 g_gfx_app.window = nullptr;
90 76
91 if (!glfwInit()) { 77 if (!glfwInit()) {
92 LOGE("glfwInit() failed"); 78 LOGE("glfwInit() failed");
@@ -138,6 +124,8 @@ bool gfx_app_run(const GfxAppDesc* desc, const GfxAppCallbacks* callbacks) {
138 // Set GLFW callbacks now that the application has been initialized. 124 // Set GLFW callbacks now that the application has been initialized.
139 glfwSetWindowSizeCallback(g_gfx_app.window, on_resize); 125 glfwSetWindowSizeCallback(g_gfx_app.window, on_resize);
140 126
127 g_gfx_app.simloop = simloop_make(&(SimloopArgs){
128 .update_fps = desc->update_fps, .max_render_fps = desc->max_render_fps});
141 loop(&g_gfx_app); 129 loop(&g_gfx_app);
142 130
143 (*g_gfx_app.callbacks.shutdown)(&g_gfx_app, g_gfx_app.app_state); 131 (*g_gfx_app.callbacks.shutdown)(&g_gfx_app, g_gfx_app.app_state);