add stats with f4 toggle

This commit is contained in:
asrael 2026-02-06 00:35:52 -06:00
parent a29a6018b8
commit 8c0777b547
7 changed files with 88 additions and 36 deletions

View file

@ -39,8 +39,6 @@
(var camera nil) (var camera nil)
(var ceiling-tex nil) (var ceiling-tex nil)
(var floor-tex nil) (var floor-tex nil)
(var fps-avg 0)
(var fps-sample-count 0)
(var grounded true) (var grounded true)
(var land-squash 0) (var land-squash 0)
(var last-dt 0.016) (var last-dt 0.016)
@ -178,14 +176,6 @@
(fn update [dt] (fn update [dt]
(set last-dt dt) (set last-dt dt)
(let [fps (pxl8.get_fps)]
(set fps-sample-count (+ fps-sample-count 1))
(set fps-avg (+ (* fps-avg (/ (- fps-sample-count 1) fps-sample-count))
(/ fps fps-sample-count)))
(when (>= fps-sample-count 120)
(set fps-sample-count 0)
(set fps-avg 0)))
(setup-materials) (setup-materials)
(when (> portal-cooldown 0) (when (> portal-cooldown 0)
@ -380,15 +370,9 @@
(let [cx (/ (pxl8.get_width) 2) (let [cx (/ (pxl8.get_width) 2)
cy (/ (pxl8.get_height) 2) cy (/ (pxl8.get_height) 2)
crosshair-size 4 crosshair-size 4
crosshair-color 240 crosshair-color 240]
text-color 251]
(pxl8.line (- cx crosshair-size) cy (+ cx crosshair-size) cy crosshair-color) (pxl8.line (- cx crosshair-size) cy (+ cx crosshair-size) cy crosshair-color)
(pxl8.line cx (- cy crosshair-size) cx (+ cy crosshair-size) crosshair-color) (pxl8.line cx (- cy crosshair-size) cx (+ cy crosshair-size) crosshair-color))
(pxl8.text (.. "fps: " (string.format "%.0f" fps-avg)) 5 5 text-color)
(pxl8.text (.. "pos: " (string.format "%.0f" cam-x) ","
(string.format "%.0f" cam-y) ","
(string.format "%.0f" cam-z)) 5 15 text-color))
(pxl8.pop_target))))) (pxl8.pop_target)))))
{:preload preload {:preload preload

View file

@ -335,13 +335,10 @@ pxl8_result pxl8_update(pxl8* sys) {
game->last_time = current_time; game->last_time = current_time;
game->time += dt; game->time += dt;
game->fps_accumulator += dt; game->dt = dt;
game->fps_frame_count++;
if (game->fps_accumulator >= 1.0f) { if (pxl8_key_pressed(&game->input, "f4")) {
game->fps = (f32)game->fps_frame_count / game->fps_accumulator; game->debug_stats = !game->debug_stats;
game->fps_accumulator = 0.0f;
game->fps_frame_count = 0;
} }
#ifndef NDEBUG #ifndef NDEBUG
@ -450,10 +447,41 @@ pxl8_result pxl8_frame(pxl8* sys) {
} }
} }
if (game->debug_stats) {
const pxl8_gfx_stats* stats = pxl8_gfx_get_stats(game->gfx);
char buf[64];
i32 y = 4;
if (stats) {
snprintf(buf, sizeof(buf), "FPS: %.0f", stats->fps);
pxl8_2d_text(game->gfx, buf, 4, y, 15);
y += 10;
pxl8_sim_entity* player = pxl8_world_local_player(game->world);
if (player) {
snprintf(buf, sizeof(buf), "Pos: %.0f,%.0f,%.0f",
player->pos.x, player->pos.y, player->pos.z);
pxl8_2d_text(game->gfx, buf, 4, y, 15);
y += 10;
}
snprintf(buf, sizeof(buf), "Draw: %llu Tri: %llu",
(unsigned long long)stats->draw_calls,
(unsigned long long)stats->triangles);
pxl8_2d_text(game->gfx, buf, 4, y, 15);
y += 10;
snprintf(buf, sizeof(buf), "Raster: %.2fms", stats->raster_ms);
pxl8_2d_text(game->gfx, buf, 4, y, 15);
}
}
pxl8_gfx_set_viewport(game->gfx, pxl8_gfx_viewport(bounds, pxl8_gfx_get_width(game->gfx), pxl8_gfx_get_height(game->gfx))); pxl8_gfx_set_viewport(game->gfx, pxl8_gfx_viewport(bounds, pxl8_gfx_get_width(game->gfx), pxl8_gfx_get_height(game->gfx)));
pxl8_gfx_upload_framebuffer(game->gfx); pxl8_gfx_upload_framebuffer(game->gfx);
pxl8_gfx_present(game->gfx); pxl8_gfx_present(game->gfx);
pxl8_gfx_update_stats(game->gfx, game->dt);
memset(game->input.keys_pressed, 0, sizeof(game->input.keys_pressed)); memset(game->input.keys_pressed, 0, sizeof(game->input.keys_pressed));
memset(game->input.keys_released, 0, sizeof(game->input.keys_released)); memset(game->input.keys_released, 0, sizeof(game->input.keys_released));
memset(game->input.mouse_buttons_pressed, 0, sizeof(game->input.mouse_buttons_pressed)); memset(game->input.mouse_buttons_pressed, 0, sizeof(game->input.mouse_buttons_pressed));
@ -531,7 +559,9 @@ pxl8_world* pxl8_get_world(pxl8* sys) {
} }
f32 pxl8_get_fps(const pxl8* sys) { f32 pxl8_get_fps(const pxl8* sys) {
return (sys && sys->game) ? sys->game->fps : 0.0f; if (!sys || !sys->game) return 0.0f;
const pxl8_gfx_stats* stats = pxl8_gfx_get_stats(sys->game->gfx);
return stats ? stats->fps : 0.0f;
} }
pxl8_gfx* pxl8_get_gfx(const pxl8* sys) { pxl8_gfx* pxl8_get_gfx(const pxl8* sys) {

View file

@ -15,9 +15,8 @@ typedef struct pxl8_game {
pxl8_replay* debug_replay; pxl8_replay* debug_replay;
#endif #endif
f32 fps; bool debug_stats;
f32 fps_accumulator; f32 dt;
i32 fps_frame_count;
i32 frame_count; i32 frame_count;
pxl8_gfx* gfx; pxl8_gfx* gfx;
pxl8_input_state input; pxl8_input_state input;

View file

@ -19,6 +19,9 @@
#include "pxl8_sys.h" #include "pxl8_sys.h"
#include "pxl8_types.h" #include "pxl8_types.h"
void pxl8_renderer_update_stats(pxl8_renderer* r, f32 dt);
pxl8_gfx_stats* pxl8_renderer_get_stats(pxl8_renderer* r);
#define PXL8_MAX_TARGET_STACK 8 #define PXL8_MAX_TARGET_STACK 8
typedef struct pxl8_sprite_cache_entry { typedef struct pxl8_sprite_cache_entry {
@ -1043,3 +1046,11 @@ bool pxl8_gfx_get_wireframe(const pxl8_gfx* gfx) {
u8 pxl8_gfx_get_ambient(const pxl8_gfx* gfx) { u8 pxl8_gfx_get_ambient(const pxl8_gfx* gfx) {
return gfx ? gfx->frame.uniforms.ambient : 0; return gfx ? gfx->frame.uniforms.ambient : 0;
} }
const pxl8_gfx_stats* pxl8_gfx_get_stats(const pxl8_gfx* gfx) {
return gfx ? pxl8_renderer_get_stats(gfx->renderer) : NULL;
}
void pxl8_gfx_update_stats(pxl8_gfx* gfx, f32 dt) {
if (gfx) pxl8_renderer_update_stats(gfx->renderer, dt);
}

View file

@ -13,15 +13,12 @@ typedef struct pxl8_gfx pxl8_gfx;
typedef struct pxl8_gfx_stats { typedef struct pxl8_gfx_stats {
u64 draw_calls; u64 draw_calls;
u64 triangles; f32 dt_accumulator;
u64 clipped_triangles; f32 fps;
u64 depth_tests; u32 frame_count;
u64 depth_passes; f32 raster_ms;
u64 shader_calls;
u64 pixels_written;
u64 submit_ns;
u64 execute_draw_ns;
u64 raster_ns; u64 raster_ns;
u64 triangles;
} pxl8_gfx_stats; } pxl8_gfx_stats;
typedef enum pxl8_gfx_effect { typedef enum pxl8_gfx_effect {
@ -77,6 +74,9 @@ u8 pxl8_gfx_ui_color(pxl8_gfx* gfx, u8 index);
void pxl8_gfx_set_wireframe(pxl8_gfx* gfx, bool enabled); void pxl8_gfx_set_wireframe(pxl8_gfx* gfx, bool enabled);
bool pxl8_gfx_get_wireframe(const pxl8_gfx* gfx); bool pxl8_gfx_get_wireframe(const pxl8_gfx* gfx);
const pxl8_gfx_stats* pxl8_gfx_get_stats(const pxl8_gfx* gfx);
void pxl8_gfx_update_stats(pxl8_gfx* gfx, f32 dt);
u8 pxl8_gfx_get_ambient(const pxl8_gfx* gfx); u8 pxl8_gfx_get_ambient(const pxl8_gfx* gfx);
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -740,6 +740,7 @@ struct pxl8_renderer {
u32 scissor_w, scissor_h; u32 scissor_w, scissor_h;
pxl8_shader_fn shader; pxl8_shader_fn shader;
pxl8_gfx_stats stats;
}; };
struct pxl8_gfx_cmdbuf { struct pxl8_gfx_cmdbuf {
@ -782,6 +783,28 @@ void pxl8_renderer_set_shader(pxl8_renderer* r, pxl8_shader_fn fn) {
if (r) r->shader = fn; if (r) r->shader = fn;
} }
void pxl8_renderer_update_stats(pxl8_renderer* r, f32 dt) {
if (!r) return;
r->stats.dt_accumulator += dt;
r->stats.frame_count++;
if (r->stats.frame_count >= 60) {
r->stats.fps = (f32)r->stats.frame_count / r->stats.dt_accumulator;
r->stats.raster_ms = ((f32)r->stats.raster_ns / (f32)r->stats.frame_count) / 1000000.0f;
r->stats.dt_accumulator = 0.0f;
r->stats.raster_ns = 0;
r->stats.frame_count = 0;
}
r->stats.draw_calls = 0;
r->stats.triangles = 0;
}
pxl8_gfx_stats* pxl8_renderer_get_stats(pxl8_renderer* r) {
return r ? &r->stats : NULL;
}
static u32 texture_byte_size(pxl8_gfx_texture_format fmt, u32 w, u32 h) { static u32 texture_byte_size(pxl8_gfx_texture_format fmt, u32 w, u32 h) {
switch (fmt) { switch (fmt) {
case PXL8_GFX_FORMAT_INDEXED8: return w * h; case PXL8_GFX_FORMAT_INDEXED8: return w * h;
@ -1090,6 +1113,7 @@ static void execute_draw(
pxl8_renderer* r, pxl8_renderer* r,
const pxl8_gfx_cmd_draw* cmd const pxl8_gfx_cmd_draw* cmd
) { ) {
r->stats.draw_calls++;
if (!VALID_BUF(r, cmd->vertex_buffer)) return; if (!VALID_BUF(r, cmd->vertex_buffer)) return;
bool use_indices = pxl8_gfx_handle_valid(cmd->index_buffer) && VALID_BUF(r, cmd->index_buffer); bool use_indices = pxl8_gfx_handle_valid(cmd->index_buffer) && VALID_BUF(r, cmd->index_buffer);
if (!VALID_PASS(r, r->current_pass)) return; if (!VALID_PASS(r, r->current_pass)) return;
@ -1186,6 +1210,7 @@ static void execute_draw(
bool is_wireframe = pip->desc.rasterizer.fill == PXL8_GFX_FILL_WIREFRAME; bool is_wireframe = pip->desc.rasterizer.fill == PXL8_GFX_FILL_WIREFRAME;
for (u32 i = cmd->first_index; i < cmd->first_index + cmd->index_count; i += 3) { for (u32 i = cmd->first_index; i < cmd->first_index + cmd->index_count; i += 3) {
r->stats.triangles++;
u16 i0, i1, i2; u16 i0, i1, i2;
if (use_indices) { if (use_indices) {
@ -1295,8 +1320,10 @@ static void execute_draw(
continue; continue;
} }
u64 raster_start = pxl8_get_ticks_ns();
rasterize_triangle(&setup, fb, zb, fb_w, shader, &pip->desc, rasterize_triangle(&setup, fb, zb, fb_w, shader, &pip->desc,
&shader_bindings, &shader_uniforms); &shader_bindings, &shader_uniforms);
r->stats.raster_ns += pxl8_get_ticks_ns() - raster_start;
} }
} }
} }

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "pxl8_colormap.h" #include "pxl8_colormap.h"
#include "pxl8_gfx.h"
#include "pxl8_render_types.h" #include "pxl8_render_types.h"
#include "pxl8_shader.h" #include "pxl8_shader.h"