Commit: 59fbe3b6b7927d78ed9243b6ce297dc9590bd30f
Parent: cd01e42f6d9bb69901d3e0d1b2599fb414de0f08
Author: Randy Palamar
Date: Sat, 7 Jun 2025 15:50:34 -0600
core: do our own frame timing
also add compiler agnostic `--time` option to build (report
removed since its not that useful)
Diffstat:
7 files changed, 67 insertions(+), 18 deletions(-)
diff --git a/beamformer.c b/beamformer.c
@@ -686,7 +686,7 @@ DEBUG_EXPORT BEAMFORMER_COMPLETE_COMPUTE_FN(beamformer_complete_compute)
DEBUG_EXPORT BEAMFORMER_FRAME_STEP_FN(beamformer_frame_step)
{
- dt_for_frame = GetFrameTime();
+ dt_for_frame = input->dt;
if (IsWindowResized()) {
ctx->window_size.h = GetScreenHeight();
diff --git a/beamformer.h b/beamformer.h
@@ -22,6 +22,7 @@ typedef struct {
v2 mouse;
v2 last_mouse;
b32 executable_reloaded;
+ f32 dt;
} BeamformerInput;
#define CUDA_INIT_FN(name) void name(u32 *input_dims, u32 *decoded_dims)
diff --git a/build.c b/build.c
@@ -109,8 +109,8 @@ typedef struct {
typedef struct {
b32 debug;
b32 generic;
- b32 report;
b32 sanitize;
+ b32 time;
} Options;
#define die(fmt, ...) die_("%s: " fmt, __FUNCTION__, ##__VA_ARGS__)
@@ -377,12 +377,6 @@ cmd_base(Arena *a, Options *o)
else printf("warning: santizers not supported with this compiler\n");
}
- if (o->report) {
- if (is_clang) cmd_append(a, &result, "-fproc-stat-report");
- else printf("warning: timing not supported with this compiler\n");
- /* TODO(rnp): basic timing */
- }
-
return result;
}
@@ -433,11 +427,11 @@ s8_equal(s8 a, s8 b)
function void
usage(char *argv0)
{
- die("%s [--debug] [--report] [--sanitize]\n"
+ die("%s [--debug] [--sanitize] [--time]\n"
" --debug: dynamically link and build with debug symbols\n"
" --generic: compile for a generic target (x86-64-v3 or armv8 with NEON)\n"
- " --report: print compilation stats (clang only)\n"
" --sanitize: build with ASAN and UBSAN\n"
+ " --time: print build time\n"
, argv0);
}
@@ -454,10 +448,10 @@ parse_options(i32 argc, char *argv[])
result.debug = 1;
} else if (s8_equal(str, s8("--generic"))) {
result.generic = 1;
- } else if (s8_equal(str, s8("--report"))) {
- result.report = 1;
} else if (s8_equal(str, s8("--sanitize"))) {
result.sanitize = 1;
+ } else if (s8_equal(str, s8("--time"))) {
+ result.time = 1;
} else {
usage(argv0);
}
@@ -626,6 +620,8 @@ build_beamformer_as_library(Arena arena, CommandList cc)
i32
main(i32 argc, char *argv[])
{
+ u64 start_time = os_get_timer_counter();
+
Arena arena = os_alloc_arena((Arena){0}, MB(8));
check_rebuild_self(arena, argc, argv);
@@ -662,5 +658,12 @@ main(i32 argc, char *argv[])
}
cmd_append(&arena, &c, (void *)0);
- return !run_synchronous(arena, &c);
+ i32 result = !run_synchronous(arena, &c);
+
+ if (options.time) {
+ f64 seconds = (f64)(os_get_timer_counter() - start_time) / os_get_timer_frequency();
+ printf("info: took %0.03f [s]\n", seconds);
+ }
+
+ return result;
}
diff --git a/main_linux.c b/main_linux.c
@@ -92,13 +92,17 @@ main(void)
fds[0].fd = ctx.os.file_watch_context.handle;
fds[0].events = POLLIN;
+ u64 last_time = os_get_timer_counter();
while (!ctx.should_exit) {
poll(fds, countof(fds), 0);
if (fds[0].revents & POLLIN)
dispatch_file_watch_events(&ctx.os, temp_memory);
+ u64 now = os_get_timer_counter();
input.last_mouse = input.mouse;
input.mouse.rl = GetMousePosition();
+ input.dt = (f64)(now - last_time) / os_get_timer_frequency();
+ last_time = now;
beamformer_frame_step(&ctx, &temp_memory, &input);
diff --git a/main_w32.c b/main_w32.c
@@ -73,7 +73,7 @@ dispatch_file_watch(OS *os, FileWatchDirectory *fw_dir, u8 *buf, Arena arena)
function void
clear_io_queue(OS *os, BeamformerInput *input, Arena arena)
{
- w32_context *ctx = (w32_context *)os->context;
+ os_w32_context *ctx = (os_w32_context *)os->context;
iptr handle = ctx->io_completion_handle;
w32_overlapped *overlapped;
@@ -109,8 +109,9 @@ main(void)
OS_FNS
#undef X
- w32_context w32_ctx = {0};
+ os_w32_context w32_ctx = {0};
w32_ctx.io_completion_handle = CreateIoCompletionPort(INVALID_FILE, 0, 0, 0);
+ w32_ctx.timer_frequency = os_get_timer_frequency();
ctx.os.context = (iptr)&w32_ctx;
ctx.os.compute_worker.asleep = 1;
@@ -121,11 +122,15 @@ main(void)
setup_beamformer(&ctx, &temp_memory);
os_wake_waiters(&ctx.os.compute_worker.sync_variable);
+ u64 last_time = os_get_timer_counter();
while (!ctx.should_exit) {
clear_io_queue(&ctx.os, &input, temp_memory);
+ u64 now = os_get_timer_counter();
input.last_mouse = input.mouse;
input.mouse.rl = GetMousePosition();
+ input.dt = (f64)(now - last_time) / w32_ctx.timer_frequency;
+ last_time = now;
beamformer_frame_step(&ctx, &temp_memory, &input);
diff --git a/os_linux.c b/os_linux.c
@@ -23,8 +23,12 @@
#include <unistd.h>
/* NOTE(rnp): hidden behind feature flags -> screw compiler/standards idiots */
+#ifndef CLOCK_MONOTONIC
+ #define CLOCK_MONOTONIC 1
+#endif
i32 ftruncate(i32, i64);
i64 syscall(i64, ...);
+i32 clock_gettime(i32, struct timespec *);
#ifdef _DEBUG
function void *
@@ -64,6 +68,21 @@ os_fatal(s8 msg)
unreachable();
}
+function u64
+os_get_timer_frequency(void)
+{
+ return 1000000000ULL;
+}
+
+function u64
+os_get_timer_counter(void)
+{
+ struct timespec time = {0};
+ clock_gettime(CLOCK_MONOTONIC, &time);
+ u64 result = time.tv_sec * 1000000000ULL + time.tv_nsec;
+ return result;
+}
+
function OS_ALLOC_ARENA_FN(os_alloc_arena)
{
Arena result;
diff --git a/os_win32.c b/os_win32.c
@@ -70,9 +70,8 @@ typedef struct {
typedef struct {
iptr io_completion_handle;
- u64 timer_start_time;
u64 timer_frequency;
-} w32_context;
+} os_w32_context;
typedef enum {
W32_IO_FILE_WATCH,
@@ -104,6 +103,8 @@ W32(iptr) GetStdHandle(i32);
W32(void) GetSystemInfo(void *);
W32(void *) LoadLibraryA(c8 *);
W32(void *) MapViewOfFile(iptr, u32, u32, u32, u64);
+W32(b32) QueryPerformanceCounter(u64 *);
+W32(b32) QueryPerformanceFrequency(u64 *);
W32(b32) ReadDirectoryChangesW(iptr, u8 *, u32, b32, u32, u32 *, void *, void *);
W32(b32) ReadFile(iptr, u8 *, i32, i32 *, void *);
W32(b32) ReleaseSemaphore(iptr, i64, i64 *);
@@ -150,6 +151,22 @@ os_fatal(s8 msg)
unreachable();
}
+function u64
+os_get_timer_frequency(void)
+{
+ u64 result;
+ QueryPerformanceFrequency(&result);
+ return result;
+}
+
+function u64
+os_get_timer_counter(void)
+{
+ u64 result;
+ QueryPerformanceCounter(&result);
+ return result;
+}
+
function OS_ALLOC_ARENA_FN(os_alloc_arena)
{
Arena result = old;
@@ -328,7 +345,7 @@ function OS_ADD_FILE_WATCH_FN(os_add_file_watch)
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED, 0);
- w32_context *ctx = (w32_context *)os->context;
+ os_w32_context *ctx = (os_w32_context *)os->context;
w32_io_completion_event *event = push_struct(a, typeof(*event));
event->tag = W32_IO_FILE_WATCH;
event->context = (iptr)dir;