ogl_beamforming

Ultrasound Beamforming Implemented with OpenGL
git clone anongit@rnpnr.xyz:ogl_beamforming.git
Log | Files | Refs | Feed | Submodules | README | LICENSE

Commit: 57358dab72f75f60ffbe7362a6c80c8f63654d87
Parent: 7a81806f8d70ccd79c06c3170c2644eddfe56207
Author: Randy Palamar
Date:   Sun,  9 Nov 2025 09:32:51 -0700

os: make os struct a platform specific global

Diffstat:
Mbeamformer.c | 14+++++++-------
Mbeamformer.h | 12++++++++++--
Mmain_linux.c | 15+++++++--------
Mmain_w32.c | 24++++++++++++------------
Mos_linux.c | 31++++++++++++++++++++-----------
Mos_win32.c | 43++++++++++++++++++++++---------------------
Mstatic.c | 94++++++++++++++++++++++++++++++++++++++++---------------------------------------
Mtests/throughput.c | 6++----
Mui.c | 2+-
Mutil.c | 8+-------
Mutil.h | 30+++++++++---------------------
Mutil_gl.c | 14+++++++-------
12 files changed, 146 insertions(+), 147 deletions(-)

diff --git a/beamformer.c b/beamformer.c @@ -748,7 +748,7 @@ load_compute_shader(BeamformerCtx *ctx, BeamformerComputePlan *cp, u32 shader_sl BeamformerShaderKind base_shader = beamformer_reloadable_shader_kinds[reloadable_index]; s8 path; if (!BakeShaders) - path = push_s8_from_parts(&arena, ctx->os.path_separator, s8("shaders"), + path = push_s8_from_parts(&arena, os_path_separator(), s8("shaders"), beamformer_reloadable_shader_files[reloadable_index]); Stream shader_stream = arena_stream(arena); @@ -812,7 +812,7 @@ load_compute_shader(BeamformerCtx *ctx, BeamformerComputePlan *cp, u32 shader_sl /* TODO(rnp): instance name */ s8 shader_name = beamformer_shader_names[shader]; - program = load_shader(&ctx->os, arena, &shader_text, (u32 []){GL_COMPUTE_SHADER}, 1, shader_name); + program = load_shader(arena, &shader_text, (u32 []){GL_COMPUTE_SHADER}, 1, shader_name); } glDeleteProgram(cp->programs[shader_slot]); @@ -1134,7 +1134,7 @@ DEBUG_EXPORT BEAMFORMER_RELOAD_SHADER_FN(beamformer_reload_shader) u32 *shader = &ctx->frame_view_render_context.shader; glDeleteProgram(*shader); - *shader = load_shader(&ctx->os, arena, shader_texts, shader_types, shader_count, shader_name); + *shader = load_shader(arena, shader_texts, shader_types, shader_count, shader_name); ctx->frame_view_render_context.updated = 1; return 1; @@ -1480,15 +1480,15 @@ DEBUG_EXPORT BEAMFORMER_FRAME_STEP_FN(beamformer_frame_step) if (input->executable_reloaded) { ui_init(ctx, ctx->ui_backing_store); - DEBUG_DECL(start_frame_capture = ctx->os.start_frame_capture); - DEBUG_DECL(end_frame_capture = ctx->os.end_frame_capture); + DEBUG_DECL(start_frame_capture = ctx->start_frame_capture); + DEBUG_DECL(end_frame_capture = ctx->end_frame_capture); } BeamformerSharedMemory *sm = ctx->shared_memory.region; if (atomic_load_u32(sm->locks + BeamformerSharedMemoryLockKind_UploadRF)) - os_wake_waiters(&ctx->os.upload_worker.sync_variable); + os_wake_waiters(&ctx->upload_worker.sync_variable); if (atomic_load_u32(sm->locks + BeamformerSharedMemoryLockKind_DispatchCompute)) - os_wake_waiters(&ctx->os.compute_worker.sync_variable); + os_wake_waiters(&ctx->compute_worker.sync_variable); BeamformerFrame *frame = ctx->latest_frame; BeamformerViewPlaneTag tag = frame? frame->view_plane_tag : 0; diff --git a/beamformer.h b/beamformer.h @@ -13,6 +13,8 @@ /////////////////// // REQUIRED OS API +function iptr os_error_handle(void); +function s8 os_path_separator(void); function OS_READ_WHOLE_FILE_FN(os_read_whole_file); function OS_SHARED_MEMORY_LOCK_REGION_FN(os_shared_memory_region_lock); function OS_SHARED_MEMORY_UNLOCK_REGION_FN(os_shared_memory_region_unlock); @@ -325,7 +327,6 @@ typedef struct { * destroying itself on hot-reload */ FrameViewRenderContext frame_view_render_context; - OS os; Stream error_stream; BeamformWorkQueue *beamform_work_queue; @@ -343,6 +344,13 @@ typedef struct { /* NOTE: this will only be used when we are averaging */ u32 averaged_frame_index; BeamformerFrame averaged_frames[2]; + + FileWatchDirectoryList file_watch_list; + GLWorkerThreadContext upload_worker; + GLWorkerThreadContext compute_worker; + + DEBUG_DECL(renderdoc_start_frame_capture_fn *start_frame_capture;) + DEBUG_DECL(renderdoc_end_frame_capture_fn *end_frame_capture;) } BeamformerCtx; typedef struct ShaderReloadContext ShaderReloadContext; @@ -363,7 +371,7 @@ typedef BEAMFORMER_COMPLETE_COMPUTE_FN(beamformer_complete_compute_fn); #define BEAMFORMER_RF_UPLOAD_FN(name) void name(BeamformerUploadThreadContext *ctx, Arena arena) typedef BEAMFORMER_RF_UPLOAD_FN(beamformer_rf_upload_fn); -#define BEAMFORMER_RELOAD_SHADER_FN(name) b32 name(OS *os, s8 path, ShaderReloadContext *src, \ +#define BEAMFORMER_RELOAD_SHADER_FN(name) b32 name(s8 path, ShaderReloadContext *src, \ Arena arena, s8 shader_name) typedef BEAMFORMER_RELOAD_SHADER_FN(beamformer_reload_shader_fn); diff --git a/main_linux.c b/main_linux.c @@ -35,15 +35,14 @@ os_gl_proc_address(char *name) #include "static.c" function void -dispatch_file_watch_events(OS *os, Arena arena) +dispatch_file_watch_events(FileWatchDirectoryList *fwctx, Arena arena) { - FileWatchContext *fwctx = &os->file_watch_context; u8 *mem = arena_alloc(&arena, 4096, 16, 1); Stream path = stream_alloc(&arena, 256); struct inotify_event *event; iz rlen; - while ((rlen = read((i32)fwctx->handle, mem, 4096)) > 0) { + while ((rlen = read(os_linux_context.inotify_handle, mem, 4096)) > 0) { for (u8 *data = mem; data < mem + rlen; data += sizeof(*event) + event->len) { event = (struct inotify_event *)data; for (u32 i = 0; i < fwctx->count; i++) { @@ -59,8 +58,7 @@ dispatch_file_watch_events(OS *os, Arena arena) stream_append_s8s(&path, dir->name, s8("/"), file); stream_append_byte(&path, 0); stream_commit(&path, -1); - fw->callback(os, stream_to_s8(&path), - fw->user_data, arena); + fw->callback(stream_to_s8(&path), fw->user_data, arena); stream_reset(&path, 0); break; } @@ -78,18 +76,19 @@ main(void) BeamformerCtx *ctx = 0; BeamformerInput *input = 0; + os_linux_context.inotify_handle = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); + setup_beamformer(&program_memory, &ctx, &input); - os_wake_waiters(&ctx->os.compute_worker.sync_variable); struct pollfd fds[1] = {{0}}; - fds[0].fd = (i32)ctx->os.file_watch_context.handle; + fds[0].fd = os_linux_context.inotify_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, program_memory); + dispatch_file_watch_events(&ctx->file_watch_list, program_memory); u64 now = os_get_timer_counter(); input->last_mouse = input->mouse; diff --git a/main_w32.c b/main_w32.c @@ -33,7 +33,7 @@ os_gl_proc_address(char *name) #include "static.c" function void -dispatch_file_watch(OS *os, FileWatchDirectory *fw_dir, u8 *buf, Arena arena) +dispatch_file_watch(FileWatchDirectory *fw_dir, u8 *buf, Arena arena) { i64 offset = 0; TempArena save_point = {0}; @@ -48,7 +48,7 @@ dispatch_file_watch(OS *os, FileWatchDirectory *fw_dir, u8 *buf, Arena arena) stream_append_s8(&path, s8("unknown file watch event: ")); stream_append_u64(&path, fni->action); stream_append_byte(&path, '\n'); - os_write_file(os->error_handle, stream_to_s8(&path)); + os_write_file(os_error_handle(), stream_to_s8(&path)); stream_reset(&path, 0); } @@ -65,7 +65,7 @@ dispatch_file_watch(OS *os, FileWatchDirectory *fw_dir, u8 *buf, Arena arena) for (u32 i = 0; i < fw_dir->count; i++) { FileWatch *fw = fw_dir->data + i; if (fw->hash == hash) { - fw->callback(os, stream_to_s8(&path), fw->user_data, arena); + fw->callback(stream_to_s8(&path), fw->user_data, arena); break; } } @@ -76,11 +76,9 @@ dispatch_file_watch(OS *os, FileWatchDirectory *fw_dir, u8 *buf, Arena arena) } function void -clear_io_queue(OS *os, BeamformerInput *input, Arena arena) +clear_io_queue(BeamformerInput *input, Arena arena) { - w32_context *ctx = (w32_context *)os->context; - - iptr handle = ctx->io_completion_handle; + iptr handle = os_w32_context.io_completion_handle; w32_overlapped *overlapped; u32 bytes_read; uptr user_data; @@ -89,7 +87,7 @@ clear_io_queue(OS *os, BeamformerInput *input, Arena arena) switch (event->tag) { case W32_IO_FILE_WATCH: { FileWatchDirectory *dir = (FileWatchDirectory *)event->context; - dispatch_file_watch(os, dir, dir->buffer.beg, arena); + dispatch_file_watch(dir, dir->buffer.beg, arena); zero_struct(overlapped); ReadDirectoryChangesW(dir->handle, dir->buffer.beg, 4096, 0, FILE_NOTIFY_CHANGE_LAST_WRITE, 0, overlapped, 0); @@ -107,18 +105,20 @@ main(void) BeamformerCtx *ctx = 0; BeamformerInput *input = 0; + os_w32_context.error_handle = GetStdHandle(STD_ERROR_HANDLE); + os_w32_context.io_completion_handle = CreateIoCompletionPort(INVALID_FILE, 0, 0, 0); + os_w32_context.timer_frequency = os_get_timer_frequency(); + setup_beamformer(&program_memory, &ctx, &input); - os_wake_waiters(&ctx->os.compute_worker.sync_variable); - w32_context *w32_ctx = (w32_context *)ctx->os.context; u64 last_time = os_get_timer_counter(); while (!ctx->should_exit) { - clear_io_queue(&ctx->os, input, program_memory); + clear_io_queue(input, program_memory); u64 now = os_get_timer_counter(); input->last_mouse = input->mouse; input->mouse.rl = GetMousePosition(); - input->dt = (f32)((f64)(now - last_time) / (f64)w32_ctx->timer_frequency); + input->dt = (f32)((f64)(now - last_time) / (f64)os_w32_context.timer_frequency); last_time = now; beamformer_frame_step(ctx, input); diff --git a/os_linux.c b/os_linux.c @@ -21,6 +21,11 @@ #include <sys/syscall.h> #include <unistd.h> +typedef struct { + i32 inotify_handle; +} OS_LinuxContext; +global OS_LinuxContext os_linux_context; + /* NOTE(rnp): hidden behind feature flags -> screw compiler/standards idiots */ #ifndef CLOCK_MONOTONIC #define CLOCK_MONOTONIC 1 @@ -67,6 +72,18 @@ os_fatal(s8 msg) unreachable(); } +function iptr +os_error_handle(void) +{ + return STDERR_FILENO; +} + +function s8 +os_path_separator(void) +{ + return s8("/"); +} + function u64 os_get_timer_frequency(void) { @@ -223,19 +240,18 @@ os_unload_library(void *h) function OS_ADD_FILE_WATCH_FN(os_add_file_watch) { s8 directory = path; - directory.len = s8_scan_backwards(path, OS_PATH_SEPARATOR_CHAR); + directory.len = s8_scan_backwards(path, '/'); assert(directory.len > 0); u64 hash = u64_hash_from_s8(directory); - FileWatchContext *fwctx = &os->file_watch_context; FileWatchDirectory *dir = lookup_file_watch_directory(fwctx, hash); if (!dir) { - assert(path.data[directory.len] == OS_PATH_SEPARATOR_CHAR); + assert(path.data[directory.len] == '/'); dir = da_push(a, fwctx); dir->hash = hash; dir->name = push_s8(a, directory); u32 mask = IN_MOVED_TO|IN_CLOSE_WRITE; - dir->handle = inotify_add_watch((i32)fwctx->handle, (c8 *)dir->name.data, mask); + dir->handle = inotify_add_watch(os_linux_context.inotify_handle, (c8 *)dir->name.data, mask); } FileWatch *fw = da_push(a, dir); @@ -293,10 +309,3 @@ function OS_SHARED_MEMORY_UNLOCK_REGION_FN(os_shared_memory_region_unlock) atomic_store_u32(lock, 0); os_wake_waiters(lock); } - -function void -os_init(OS *os, Arena *program_memory) -{ - os->file_watch_context.handle = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); - os->error_handle = STDERR_FILENO; -} diff --git a/os_win32.c b/os_win32.c @@ -66,11 +66,6 @@ typedef struct { iptr event_handle; } w32_overlapped; -typedef struct { - iptr io_completion_handle; - u64 timer_frequency; -} w32_context; - typedef enum { W32_IO_FILE_WATCH, W32_IO_PIPE, @@ -120,6 +115,13 @@ W32(iptr) wglGetProcAddress(c8 *); W32(b32) WriteFile(iptr, u8 *, i32, i32 *, void *); W32(void *) VirtualAlloc(u8 *, iz, u32, u32); +typedef struct { + iptr error_handle; + iptr io_completion_handle; + u64 timer_frequency; +} OS_W32Context; +global OS_W32Context os_w32_context; + #ifdef _DEBUG function void * os_get_module(char *name, Stream *e) @@ -156,6 +158,18 @@ os_fatal(s8 msg) unreachable(); } +function iptr +os_error_handle(void) +{ + return os_w32_context.error_handle; +} + +function s8 +os_path_separator(void) +{ + return s8("\\"); +} + function u64 os_get_timer_frequency(void) { @@ -338,14 +352,13 @@ os_unload_library(void *h) function OS_ADD_FILE_WATCH_FN(os_add_file_watch) { s8 directory = path; - directory.len = s8_scan_backwards(path, OS_PATH_SEPARATOR_CHAR); + directory.len = s8_scan_backwards(path, '\\'); assert(directory.len > 0); u64 hash = u64_hash_from_s8(directory); - FileWatchContext *fwctx = &os->file_watch_context; FileWatchDirectory *dir = lookup_file_watch_directory(fwctx, hash); if (!dir) { - assert(path.data[directory.len] == OS_PATH_SEPARATOR_CHAR); + assert(path.data[directory.len] == '\\'); dir = da_push(a, fwctx); dir->hash = hash; @@ -354,11 +367,10 @@ 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; w32_io_completion_event *event = push_struct(a, typeof(*event)); event->tag = W32_IO_FILE_WATCH; event->context = (iptr)dir; - CreateIoCompletionPort(dir->handle, ctx->io_completion_handle, (uptr)event, 0); + CreateIoCompletionPort(dir->handle, os_w32_context.io_completion_handle, (uptr)event, 0); dir->buffer = sub_arena(a, 4096 + sizeof(w32_overlapped), 64); w32_overlapped *overlapped = (w32_overlapped *)(dir->buffer.beg + 4096); @@ -410,14 +422,3 @@ function OS_SHARED_MEMORY_UNLOCK_REGION_FN(os_shared_memory_region_unlock) os_wake_waiters(locks + lock_index); ReleaseSemaphore(ctx->semaphores[lock_index], 1, 0); } - -function void -os_init(OS *os, Arena *program_memory) -{ - w32_context *ctx = push_struct(program_memory, typeof(*ctx)); - ctx->io_completion_handle = CreateIoCompletionPort(INVALID_FILE, 0, 0, 0); - ctx->timer_frequency = os_get_timer_frequency(); - - os->error_handle = GetStdHandle(STD_ERROR_HANDLE); - os->context = (iptr)ctx; -} diff --git a/static.c b/static.c @@ -24,15 +24,21 @@ global void *debug_lib; DEBUG_ENTRY_POINTS #undef X +struct debug_context { + BeamformerInput *input; + b32 *compute_worker_asleep; + b32 *upload_worker_asleep; +}; + function FILE_WATCH_CALLBACK_FN(debug_reload) { - BeamformerInput *input = (BeamformerInput *)user_data; - Stream err = arena_stream(arena); + struct debug_context *ctx = (struct debug_context *)user_data; + Stream err = arena_stream(arena); /* NOTE(rnp): spin until compute thread finishes its work (we will probably * never reload while compute is in progress but just incase). */ - spin_wait(!atomic_load_u32(&os->compute_worker.asleep)); - spin_wait(!atomic_load_u32(&os->upload_worker.asleep)); + spin_wait(!atomic_load_u32(ctx->compute_worker_asleep)); + spin_wait(!atomic_load_u32(ctx->upload_worker_asleep)); os_unload_library(debug_lib); debug_lib = os_load_library(OS_DEBUG_LIB_NAME, OS_DEBUG_LIB_TEMP_NAME, &err); @@ -42,18 +48,22 @@ function FILE_WATCH_CALLBACK_FN(debug_reload) #undef X stream_append_s8(&err, s8("Reloaded Main Executable\n")); - os_write_file(os->error_handle, stream_to_s8(&err)); + os_write_file(os_error_handle(), stream_to_s8(&err)); - input->executable_reloaded = 1; + ctx->input->executable_reloaded = 1; return 1; } function void -debug_init(OS *os, iptr input, Arena *arena) +debug_init(BeamformerCtx *ctx, BeamformerInput *input, Arena *arena) { - os_add_file_watch(os, arena, s8(OS_DEBUG_LIB_NAME), debug_reload, input); - debug_reload(os, s8(""), input, *arena); + struct debug_context *dctx = push_struct(arena, struct debug_context); + dctx->input = input; + dctx->compute_worker_asleep = &ctx->compute_worker.asleep; + dctx->upload_worker_asleep = &ctx->upload_worker.asleep; + os_add_file_watch(&ctx->file_watch_list, arena, s8(OS_DEBUG_LIB_NAME), debug_reload, (iptr)dctx); + debug_reload(s8(""), (iptr)dctx, *arena); Stream err = arena_stream(*arena); void *rdoc = os_get_module(OS_RENDERDOC_SONAME, 0); @@ -62,30 +72,24 @@ debug_init(OS *os, iptr input, Arena *arena) if (get_api) { RenderDocAPI *api = 0; if (get_api(10600, (void **)&api)) { - os->start_frame_capture = RENDERDOC_START_FRAME_CAPTURE(api); - os->end_frame_capture = RENDERDOC_END_FRAME_CAPTURE(api); + ctx->start_frame_capture = RENDERDOC_START_FRAME_CAPTURE(api); + ctx->end_frame_capture = RENDERDOC_END_FRAME_CAPTURE(api); stream_append_s8(&err, s8("loaded: " OS_RENDERDOC_SONAME "\n")); } } } - os_write_file(os->error_handle, stream_to_s8(&err)); + os_write_file(os_error_handle(), stream_to_s8(&err)); } #endif /* _DEBUG */ -struct gl_debug_ctx { - Stream stream; - iptr os_error_handle; -}; - function void gl_debug_logger(u32 src, u32 type, u32 id, u32 lvl, i32 len, const char *msg, const void *userctx) { - struct gl_debug_ctx *ctx = (struct gl_debug_ctx *)userctx; - Stream *e = &ctx->stream; + Stream *e = (Stream *)userctx; stream_append_s8s(e, s8("[OpenGL] "), (s8){.len = len, .data = (u8 *)msg}, s8("\n")); - os_write_file(ctx->os_error_handle, stream_to_s8(e)); + os_write_file(os_error_handle(), stream_to_s8(e)); stream_reset(e, 0); } @@ -135,7 +139,7 @@ validate_gl_requirements(GLParams *gl, Arena a) } function void -dump_gl_params(GLParams *gl, Arena a, OS *os) +dump_gl_params(GLParams *gl, Arena a) { #ifdef _DEBUG s8 vendor = s8("vendor:"); @@ -164,7 +168,7 @@ dump_gl_params(GLParams *gl, Arena a, OS *os) GL_PARAMETERS #undef X stream_append_s8(&s, s8("-----------------------\n")); - os_write_file(os->error_handle, stream_to_s8(&s)); + os_write_file(os_error_handle(), stream_to_s8(&s)); #endif } @@ -172,7 +176,7 @@ function FILE_WATCH_CALLBACK_FN(reload_shader) { ShaderReloadContext *ctx = (typeof(ctx))user_data; BeamformerShaderKind kind = beamformer_reloadable_shader_kinds[ctx->reloadable_info_index]; - return beamformer_reload_shader(os, path, ctx, arena, beamformer_shader_names[kind]); + return beamformer_reload_shader(path, ctx, arena, beamformer_shader_names[kind]); } typedef struct { @@ -189,7 +193,7 @@ function FILE_WATCH_CALLBACK_FN(reload_shader_indirect) work->kind = BeamformerWorkKind_ReloadShader, work->reload_shader = rsi->shader; beamform_work_queue_push_commit(ctx->beamform_work_queue); - os_wake_waiters(&os->compute_worker.sync_variable); + os_wake_waiters(&ctx->compute_worker.sync_variable); } return 1; } @@ -213,7 +217,7 @@ function FILE_WATCH_CALLBACK_FN(load_cuda_library) CUDALibraryProcedureList #undef X - os_write_file(os->error_handle, stream_to_s8(&err)); + os_write_file(os_error_handle(), stream_to_s8(&err)); } #define X(name, symname) if (!cuda_## name) cuda_## name = cuda_ ## name ## _stub; @@ -343,14 +347,12 @@ setup_beamformer(Arena *memory, BeamformerCtx **o_ctx, BeamformerInput **o_input ctx->ui_backing_store = ui_arena; input->executable_reloaded = 1; - os_init(&ctx->os, memory); - ctx->os.path_separator = s8(OS_PATH_SEPARATOR); - ctx->os.compute_worker.arena = compute_arena; - ctx->os.compute_worker.asleep = 1; - ctx->os.upload_worker.arena = upload_arena; - ctx->os.upload_worker.asleep = 1; + ctx->compute_worker.arena = compute_arena; + ctx->compute_worker.asleep = 1; + ctx->upload_worker.arena = upload_arena; + ctx->upload_worker.asleep = 1; - debug_init(&ctx->os, (iptr)input, memory); + debug_init(ctx, input, memory); SetConfigFlags(FLAG_VSYNC_HINT|FLAG_WINDOW_ALWAYS_RUN); InitWindow(ctx->window_size.w, ctx->window_size.h, "OGL Beamformer"); @@ -366,7 +368,7 @@ setup_beamformer(Arena *memory, BeamformerCtx **o_ctx, BeamformerInput **o_input #undef X /* NOTE: Gather information about the GPU */ get_gl_params(&ctx->gl, &ctx->error_stream); - dump_gl_params(&ctx->gl, *memory, &ctx->os); + dump_gl_params(&ctx->gl, *memory); validate_gl_requirements(&ctx->gl, *memory); ctx->beamform_work_queue = push_struct(memory, BeamformWorkQueue); @@ -387,34 +389,34 @@ setup_beamformer(Arena *memory, BeamformerCtx **o_ctx, BeamformerInput **o_input BeamformerComputeContext *cs = &ctx->compute_context; - GLWorkerThreadContext *worker = &ctx->os.compute_worker; + GLWorkerThreadContext *worker = &ctx->compute_worker; /* TODO(rnp): we should lock this down after we have something working */ worker->user_context = (iptr)ctx; worker->window_handle = glfwCreateWindow(1, 1, "", 0, raylib_window_handle); worker->handle = os_create_thread(*memory, (iptr)worker, s8("[compute]"), compute_worker_thread_entry_point); - GLWorkerThreadContext *upload = &ctx->os.upload_worker; + GLWorkerThreadContext *upload = &ctx->upload_worker; BeamformerUploadThreadContext *upctx = push_struct(memory, typeof(*upctx)); upload->user_context = (iptr)upctx; upctx->rf_buffer = &cs->rf_buffer; upctx->shared_memory = &ctx->shared_memory; upctx->compute_timing_table = ctx->compute_timing_table; - upctx->compute_worker_sync = &ctx->os.compute_worker.sync_variable; + upctx->compute_worker_sync = &ctx->compute_worker.sync_variable; upload->window_handle = glfwCreateWindow(1, 1, "", 0, raylib_window_handle); upload->handle = os_create_thread(*memory, (iptr)upload, s8("[upload]"), upload_worker_thread_entry_point); glfwMakeContextCurrent(raylib_window_handle); - if (load_cuda_library(&ctx->os, s8(OS_CUDA_LIB_NAME), (iptr)&ctx->gl, *memory)) - os_add_file_watch(&ctx->os, memory, s8(OS_CUDA_LIB_NAME), load_cuda_library, (iptr)&ctx->gl); + if (load_cuda_library(s8(OS_CUDA_LIB_NAME), (iptr)&ctx->gl, *memory)) + os_add_file_watch(&ctx->file_watch_list, memory, s8(OS_CUDA_LIB_NAME), + load_cuda_library, (iptr)&ctx->gl); /* NOTE: set up OpenGL debug logging */ - struct gl_debug_ctx *gl_debug_ctx = push_struct(memory, typeof(*gl_debug_ctx)); - gl_debug_ctx->stream = stream_alloc(memory, 1024); - gl_debug_ctx->os_error_handle = ctx->os.error_handle; - glDebugMessageCallback(gl_debug_logger, gl_debug_ctx); + Stream *gl_error_stream = push_struct(memory, Stream); + *gl_error_stream = stream_alloc(memory, 1024); + glDebugMessageCallback(gl_debug_logger, gl_error_stream); #ifdef _DEBUG glEnable(GL_DEBUG_OUTPUT); #endif @@ -430,8 +432,8 @@ setup_beamformer(Arena *memory, BeamformerCtx **o_ctx, BeamformerInput **o_input BeamformerShaderReloadIndirectContext *rsi = push_struct(memory, typeof(*rsi)); rsi->beamformer = ctx; rsi->shader = beamformer_reloadable_shader_kinds[index]; - os_add_file_watch(&ctx->os, memory, file, reload_shader_indirect, (iptr)rsi); - reload_shader_indirect(&ctx->os, file, (iptr)rsi, *memory); + os_add_file_watch(&ctx->file_watch_list, memory, file, reload_shader_indirect, (iptr)rsi); + reload_shader_indirect(file, (iptr)rsi, *memory); } os_wake_waiters(&worker->sync_variable); } @@ -506,9 +508,9 @@ setup_beamformer(Arena *memory, BeamformerCtx **o_ctx, BeamformerInput **o_input if (!BakeShaders) { render_file = push_s8_from_parts(&scratch, s8(OS_PATH_SEPARATOR), s8("shaders"), beamformer_reloadable_shader_files[render_rsi_index]); - os_add_file_watch(&ctx->os, memory, render_file, reload_shader, (iptr)render_3d); + os_add_file_watch(&ctx->file_watch_list, memory, render_file, reload_shader, (iptr)render_3d); } - reload_shader(&ctx->os, render_file, (iptr)render_3d, *memory); + reload_shader(render_file, (iptr)render_3d, *memory); f32 unit_cube_vertices[] = { 0.5f, 0.5f, -0.5f, diff --git a/tests/throughput.c b/tests/throughput.c @@ -111,18 +111,16 @@ os_read_file_simp(char *fname) #elif OS_WINDOWS -global w32_context os_context; - function void os_init_timer(void) { - os_context.timer_frequency = os_get_timer_frequency(); + os_w32_context.timer_frequency = os_get_timer_frequency(); } function f64 os_get_time(void) { - f64 result = (f64)os_get_timer_counter() / (f64)os_context.timer_frequency; + f64 result = (f64)os_get_timer_counter() / (f64)os_w32_context.timer_frequency; return result; } diff --git a/ui.c b/ui.c @@ -4017,7 +4017,7 @@ draw_ui(BeamformerCtx *ctx, BeamformerInput *input, BeamformerFrame *frame_to_dr if (fill_frame_compute_work(ctx, work, tag, selected_block, 0)) beamform_work_queue_push_commit(ctx->beamform_work_queue); } - os_wake_waiters(&ctx->os.compute_worker.sync_variable); + os_wake_waiters(&ctx->compute_worker.sync_variable); } } } diff --git a/util.c b/util.c @@ -74,12 +74,6 @@ arena_alloc(Arena *a, iz len, uz align, iz count) enum { DA_INITIAL_CAP = 16 }; -#define DA_STRUCT(kind, name) typedef struct { \ - kind *data; \ - iz count; \ - iz capacity; \ -} name ##List; - #define da_index(it, s) ((it) - (s)->data) #define da_reserve(a, s, n) \ (s)->data = da_reserve_((a), (s)->data, &(s)->capacity, (s)->count + n, \ @@ -685,7 +679,7 @@ parse_f64(s8 s) } function FileWatchDirectory * -lookup_file_watch_directory(FileWatchContext *ctx, u64 hash) +lookup_file_watch_directory(FileWatchDirectoryList *ctx, u64 hash) { FileWatchDirectory *result = 0; for (u32 i = 0; i < ctx->count; i++) { diff --git a/util.h b/util.h @@ -99,6 +99,12 @@ #define spin_wait(c) while ((c)) cpu_yield() +#define DA_STRUCT(kind, name) typedef struct { \ + kind *data; \ + iz count; \ + iz capacity; \ +} name ##List; + /* NOTE(rnp): no guarantees about actually getting an element */ #define SLLPop(list) list; list = list ? list->next : 0 #define SLLPush(v, list) do { \ @@ -282,7 +288,7 @@ typedef struct { b32 asleep; } GLWorkerThreadContext; -#define FILE_WATCH_CALLBACK_FN(name) b32 name(OS *os, s8 path, iptr user_data, Arena arena) +#define FILE_WATCH_CALLBACK_FN(name) b32 name(s8 path, iptr user_data, Arena arena) typedef FILE_WATCH_CALLBACK_FN(file_watch_callback); typedef struct { @@ -301,13 +307,7 @@ typedef struct { iz capacity; Arena buffer; } FileWatchDirectory; - -typedef struct { - FileWatchDirectory *data; - iz count; - iz capacity; - iptr handle; -} FileWatchContext; +DA_STRUCT(FileWatchDirectory, FileWatchDirectory); typedef struct { void *region; @@ -317,7 +317,7 @@ typedef struct { #define OS_ALLOC_ARENA_FN(name) Arena name(iz capacity) typedef OS_ALLOC_ARENA_FN(os_alloc_arena_fn); -#define OS_ADD_FILE_WATCH_FN(name) void name(OS *os, Arena *a, s8 path, \ +#define OS_ADD_FILE_WATCH_FN(name) void name(FileWatchDirectoryList *fwctx, Arena *a, s8 path, \ file_watch_callback *callback, iptr user_data) typedef OS_ADD_FILE_WATCH_FN(os_add_file_watch_fn); @@ -362,18 +362,6 @@ typedef alignas(16) u8 RenderDocAPI[216]; #define RENDERDOC_START_FRAME_CAPTURE(a) (renderdoc_start_frame_capture_fn *)RENDERDOC_API_FN_ADDR(a, 152) #define RENDERDOC_END_FRAME_CAPTURE(a) (renderdoc_end_frame_capture_fn *) RENDERDOC_API_FN_ADDR(a, 168) -struct OS { - FileWatchContext file_watch_context; - iptr context; - iptr error_handle; - s8 path_separator; - - GLWorkerThreadContext compute_worker; - GLWorkerThreadContext upload_worker; - - DEBUG_DECL(renderdoc_start_frame_capture_fn *start_frame_capture;) - DEBUG_DECL(renderdoc_end_frame_capture_fn *end_frame_capture;) -}; #define LABEL_GL_OBJECT(type, id, s) {s8 _s = (s); glObjectLabel(type, id, (i32)_s.len, (c8 *)_s.data);} diff --git a/util_gl.c b/util_gl.c @@ -1,6 +1,6 @@ /* See LICENSE for license details. */ function u32 -compile_shader(OS *os, Arena a, u32 type, s8 shader, s8 name) +compile_shader(Arena a, u32 type, s8 shader, s8 name) { u32 sid = glCreateShader(type); glShaderSource(sid, 1, (const char **)&shader.data, (int *)&shader.len); @@ -18,7 +18,7 @@ compile_shader(OS *os, Arena a, u32 type, s8 shader, s8 name) glGetShaderInfoLog(sid, len, &out_len, (char *)(buf.data + buf.widx)); stream_commit(&buf, out_len); glDeleteShader(sid); - os_write_file(os->error_handle, stream_to_s8(&buf)); + os_write_file(os_error_handle(), stream_to_s8(&buf)); sid = 0; } @@ -27,7 +27,7 @@ compile_shader(OS *os, Arena a, u32 type, s8 shader, s8 name) } function u32 -link_program(OS *os, Arena a, u32 *shader_ids, i32 shader_id_count) +link_program(Arena a, u32 *shader_ids, i32 shader_id_count) { i32 success = 0; u32 result = glCreateProgram(); @@ -42,7 +42,7 @@ link_program(OS *os, Arena a, u32 *shader_ids, i32 shader_id_count) glGetProgramInfoLog(result, buf.cap - buf.widx, &len, (c8 *)(buf.data + buf.widx)); stream_reset(&buf, len); stream_append_byte(&buf, '\n'); - os_write_file(os->error_handle, stream_to_s8(&buf)); + os_write_file(os_error_handle(), stream_to_s8(&buf)); glDeleteProgram(result); result = 0; } @@ -50,17 +50,17 @@ link_program(OS *os, Arena a, u32 *shader_ids, i32 shader_id_count) } function u32 -load_shader(OS *os, Arena arena, s8 *shader_texts, u32 *shader_types, i32 count, s8 name) +load_shader(Arena arena, s8 *shader_texts, u32 *shader_types, i32 count, s8 name) { u32 result = 0; u32 *ids = push_array(&arena, u32, count); b32 valid = 1; for (i32 i = 0; i < count; i++) { - ids[i] = compile_shader(os, arena, shader_types[i], shader_texts[i], name); + ids[i] = compile_shader(arena, shader_types[i], shader_texts[i], name); valid &= ids[i] != 0; } - if (valid) result = link_program(os, arena, ids, count); + if (valid) result = link_program(arena, ids, count); for (i32 i = 0; i < count; i++) glDeleteShader(ids[i]); if (result) glObjectLabel(GL_PROGRAM, result, (i32)name.len, (c8 *)name.data);