summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonAki <konaki@anokonaki.org>2026-10-10 23:29:00 +0800
committerKonAki <konaki@anokonaki.org>2026-10-10 23:29:00 +0800
commit438ad3a0bfe98dd3981f531f3d7bb45132166174 (patch)
tree502b604a68e2d05efbef5ccdb3155c4acb58adf9
parent6938842f479c6af0aaa6999f4dccf0da06a3f610 (diff)
program: time each part of the frame, cap fps instead of fixed sleep
-rw-r--r--kon/kondebug.c14
-rw-r--r--kon/kondebug.h4
-rw-r--r--kon/konprogram.c16
-rw-r--r--kon/konprogram.h1
4 files changed, 33 insertions, 2 deletions
diff --git a/kon/kondebug.c b/kon/kondebug.c
index a68ebcf..54e8d13 100644
--- a/kon/kondebug.c
+++ b/kon/kondebug.c
@@ -91,6 +91,7 @@ struct kon_debug {
double accumTime;
int accumFrames;
float fps;
+ double times[4]; /* update, draw, present, blit */
float graph[KON_DEBUG_GRAPH];
int graphHead;
};
@@ -607,6 +608,16 @@ void kon_debugFrame(kon_debug_t *d)
d->graphHead = (d->graphHead + 1) % KON_DEBUG_GRAPH;
}
+void kon_debugTimes(kon_debug_t *d, double update, double draw, double present, double blit)
+{
+ double in[4];
+ int i;
+
+ if (!d) return;
+ in[0] = update; in[1] = draw; in[2] = present; in[3] = blit;
+ for (i = 0; i < 4; i++) d->times[i] += (in[i] - d->times[i]) * 0.1;
+}
+
static void kon_debugBox_(const kon_debug_t *d, kon_framebuffer_t *fb, int x, int y, const char *s, uint32_t color)
{
int w = 0;
@@ -628,6 +639,9 @@ static void kon_debugDrawOverlay_(kon_debug_t *d, kon_framebuffer_t *fb)
y += d->lineH + 3;
if (d->overlay >= 1) {
+ snprintf(line, sizeof(line), "upd %.1f draw %.1f scale %.1f blit %.1f", d->times[0] * 1000.0, d->times[1] * 1000.0, d->times[2] * 1000.0, d->times[3] * 1000.0);
+ kon_debugBox_(d, fb, x, y, line, dim);
+ y += d->lineH + 3;
kon_fillRectangle(fb, x - 2, y - 2, KON_DEBUG_GRAPH + 4, 34, 0xB0000000);
for (i = 0; i < KON_DEBUG_GRAPH; i++) {
float ms = d->graph[(d->graphHead + i) % KON_DEBUG_GRAPH];
diff --git a/kon/kondebug.h b/kon/kondebug.h
index f17f0c2..0f32a0f 100644
--- a/kon/kondebug.h
+++ b/kon/kondebug.h
@@ -69,6 +69,9 @@ int kon_debugConsoleOpen(const kon_debug_t *debug);
void kon_debugFrame(kon_debug_t *debug);
void kon_debugDraw(kon_debug_t *debug, kon_framebuffer_t *fb);
+/* where the frame went, in seconds. shown under the fps when the overlay is on */
+void kon_debugTimes(kon_debug_t *debug, double update, double draw, double present, double blit);
+
float kon_debugFps(const kon_debug_t *debug);
/* set by the quit and exit commands, the game decides what to do with it */
@@ -87,6 +90,7 @@ static inline int kon_debugFeedEvent(kon_debug_t *debug, const kon_event_t *even
static inline int kon_debugConsoleOpen(const kon_debug_t *debug) { (void)debug; return 0; }
static inline void kon_debugFrame(kon_debug_t *debug) { (void)debug; }
static inline void kon_debugDraw(kon_debug_t *debug, kon_framebuffer_t *fb) { (void)debug; (void)fb; }
+static inline void kon_debugTimes(kon_debug_t *debug, double update, double draw, double present, double blit) { (void)debug; (void)update; (void)draw; (void)present; (void)blit; }
static inline float kon_debugFps(const kon_debug_t *debug) { (void)debug; return 0.0f; }
static inline int kon_debugQuitRequested(const kon_debug_t *debug) { (void)debug; return 0; }
diff --git a/kon/konprogram.c b/kon/konprogram.c
index 31fe7b6..a87aee8 100644
--- a/kon/konprogram.c
+++ b/kon/konprogram.c
@@ -110,7 +110,7 @@ static void kon_frame_(void *data) {
const kon_programConfig_t *config = &state->config;
kon_display_t *display = program->display;
kon_event_t ev;
- kon_time now, dt;
+ kon_time now, dt, t0, t1, t2, t3, t4, cap;
while (kon_pollEvent(program->window, &ev)) {
if (kon_debugFeedEvent(program->debug, &ev)) continue;
@@ -131,17 +131,29 @@ static void kon_frame_(void *data) {
else kon_setWindowPos(program->window, state->shakeX, state->shakeY);
}
+ t0 = kon_getTime();
if (config->update) config->update(program, dt, config->user);
+ t1 = kon_getTime();
kon_clearFramebuffer(display->game, KON_BACKGROUND_COLOR);
if (config->draw) config->draw(program, display->game, config->user);
+ t2 = kon_getTime();
kon_presentDisplay(display);
+ t3 = kon_getTime();
if (config->drawScreen) config->drawScreen(program, display->screen, config->user);
kon_debugFrame(program->debug);
if (kon_debugQuitRequested(program->debug)) kon_setShouldClose(program->window, true);
kon_debugDraw(program->debug, display->screen);
+ t4 = kon_getTime();
kon_blitPixels(program->window, display->screen->data, display->screen->width, display->screen->height);
- kon_sleep(0.008);
+ kon_debugTimes(program->debug, t1 - t0, t2 - t1, t3 - t2, kon_getTime() - t4);
+
+ /* only wait out what is left of the frame, a fixed sleep eats time the frame could use */
+ if (config->maxFps >= 0) {
+ cap = 1.0 / (config->maxFps > 0 ? config->maxFps : 120);
+ dt = kon_getTime() - now;
+ if (dt < cap) kon_sleep(cap - dt);
+ }
}
void kon_programQuit(kon_program_t *program) {
diff --git a/kon/konprogram.h b/kon/konprogram.h
index f0a29b3..04aef18 100644
--- a/kon/konprogram.h
+++ b/kon/konprogram.h
@@ -46,6 +46,7 @@ typedef struct kon_programConfig {
int windowWidth, windowHeight; /* 3 times the game size */
const char *assetDir; /* folder with loose files, "assets". only used with KON_DEVELOPER */
const char *packPath; /* pack file to read assets from, none if NULL */
+ int maxFps; /* frame cap, 120. -1 for none */
void *user; /* given back to every callback */
/* return 0 to quit before the loop starts */