ogl_beamforming

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

Commit: 0598a1525477862827cf97f6f1a708d34dfa6574
Parent: 54c1819ec4335515573858c1473f7a38a1513a07
Author: Randy Palamar
Date:   Tue, 30 Dec 2025 15:32:22 -0700

os: remove platform layer's knowledge of BeamformerCtx

Too much platform stuff was sneaking into the beamformer. File
watch data belongs in the platform layer, as does checking when
the application should close. The beamformer only cares that it
can watch a file for changes, how that happens is a concern for
the platform code to handle.

Diffstat:
Mbeamformer.c | 4+---
Mbeamformer.h | 10+++++-----
Mmain_linux.c | 30++++++++++++++++--------------
Mmain_w32.c | 51+++++++++++++++++++++++++++------------------------
Mos_linux.c | 37+++++++++++++++++++++++++++++++------
Mos_win32.c | 68+++++++++++++++++++++++++++++++++++++++++++++++---------------------
Mstatic.c | 58+++++++++++++++++++++++++++++-----------------------------
Mutil.c | 88++++++++++++++++++++++++++++++++++++++++----------------------------------------
Mutil.h | 15+--------------
9 files changed, 201 insertions(+), 160 deletions(-)

diff --git a/beamformer.c b/beamformer.c @@ -1472,6 +1472,7 @@ DEBUG_EXPORT BEAMFORMER_RF_UPLOAD_FN(beamformer_rf_upload) DEBUG_EXPORT BEAMFORMER_FRAME_STEP_FN(beamformer_frame_step) { + BeamformerCtx *ctx = BeamformerContextMemory(memory); dt_for_frame = input->dt; if (IsWindowResized()) { @@ -1498,9 +1499,6 @@ DEBUG_EXPORT BEAMFORMER_FRAME_STEP_FN(beamformer_frame_step) draw_ui(ctx, input, frame, tag); ctx->frame_view_render_context.updated = 0; - - if (WindowShouldClose()) - ctx->should_exit = 1; } /* NOTE(rnp): functions defined in these shouldn't be visible to the whole program */ diff --git a/beamformer.h b/beamformer.h @@ -26,10 +26,10 @@ function OS_WRITE_FILE_FN(os_write_file); #include "util_gl.c" typedef struct { + f64 dt; v2 mouse; v2 last_mouse; b32 executable_reloaded; - f32 dt; } BeamformerInput; #define CUDA_INIT_FN(name) void name(u32 *input_dims, u32 *decoded_dims) @@ -290,8 +290,8 @@ struct BeamformerFrame { typedef struct { iv2 window_size; - b32 should_exit; + Arena arena; Arena ui_backing_store; void *ui; u32 ui_dirty_parameter_blocks; @@ -320,13 +320,13 @@ typedef struct { 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; +#define BeamformerContextMemory(a) (BeamformerCtx *)arena_aligned_start(a, alignof(BeamformerCtx)) typedef struct ShaderReloadContext ShaderReloadContext; struct ShaderReloadContext { @@ -337,7 +337,7 @@ struct ShaderReloadContext { i32 reloadable_info_index; }; -#define BEAMFORMER_FRAME_STEP_FN(name) void name(BeamformerCtx *ctx, BeamformerInput *input) +#define BEAMFORMER_FRAME_STEP_FN(name) void name(Arena memory, BeamformerInput *input) typedef BEAMFORMER_FRAME_STEP_FN(beamformer_frame_step_fn); #define BEAMFORMER_COMPLETE_COMPUTE_FN(name) void name(iptr user_context, Arena *arena, iptr gl_context) @@ -350,7 +350,7 @@ typedef BEAMFORMER_RF_UPLOAD_FN(beamformer_rf_upload_fn); Arena arena, s8 shader_name) typedef BEAMFORMER_RELOAD_SHADER_FN(beamformer_reload_shader_fn); -#define BEAMFORMER_DEBUG_UI_DEINIT_FN(name) void name(BeamformerCtx *ctx) +#define BEAMFORMER_DEBUG_UI_DEINIT_FN(name) void name(Arena memory) typedef BEAMFORMER_DEBUG_UI_DEINIT_FN(beamformer_debug_ui_deinit_fn); #endif /*_BEAMFORMER_H_ */ diff --git a/main_linux.c b/main_linux.c @@ -35,8 +35,10 @@ os_gl_proc_address(char *name) #include "static.c" function void -dispatch_file_watch_events(FileWatchDirectoryList *fwctx, Arena arena) +dispatch_file_watch_events(void) { + OSLinux_FileWatchDirectoryList *fwctx = &os_linux_context.file_watch_list; + Arena arena = os_linux_context.arena; u8 *mem = arena_alloc(&arena, 4096, 16, 1); Stream path = stream_alloc(&arena, 256); struct inotify_event *event; @@ -46,7 +48,7 @@ dispatch_file_watch_events(FileWatchDirectoryList *fwctx, Arena arena) 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++) { - FileWatchDirectory *dir = fwctx->data + i; + OSLinux_FileWatchDirectory *dir = fwctx->data + i; if (event->wd != dir->handle) continue; @@ -73,40 +75,40 @@ main(void) { os_common_init(); - Arena program_memory = os_alloc_arena(MB(16) + KB(4)); + Arena program_memory = os_alloc_arena(MB(16) + KB(16)); - BeamformerCtx *ctx = 0; - BeamformerInput *input = 0; - - os_linux_context.arena = sub_arena(&program_memory, KB(4), KB(4)); + os_linux_context.arena = sub_arena(&program_memory, KB(16), KB(4)); os_linux_context.inotify_handle = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); - setup_beamformer(&program_memory, &ctx, &input); + + BeamformerInput *input = push_struct(&program_memory, BeamformerInput); + input->executable_reloaded = 1; + beamformer_init(program_memory, input); struct pollfd fds[1] = {{0}}; fds[0].fd = os_linux_context.inotify_handle; fds[0].events = POLLIN; u64 last_time = os_get_timer_counter(); - while (!ctx->should_exit) { + while (!WindowShouldClose()) { poll(fds, countof(fds), 0); if (fds[0].revents & POLLIN) - dispatch_file_watch_events(&ctx->file_watch_list, program_memory); + dispatch_file_watch_events(); Vector2 new_mouse = GetMousePosition(); u64 now = os_get_timer_counter(); input->last_mouse = input->mouse; input->mouse = (v2){{new_mouse.x, new_mouse.y}}; - input->dt = (f32)((f64)(now - last_time) / (f64)os_get_timer_frequency()); + input->dt = (f64)(now - last_time) / (f64)os_get_timer_frequency(); last_time = now; - beamformer_frame_step(ctx, input); + beamformer_frame_step(program_memory, input); input->executable_reloaded = 0; } - beamformer_invalidate_shared_memory(ctx); - beamformer_debug_ui_deinit(ctx); + beamformer_invalidate_shared_memory(program_memory); + beamformer_debug_ui_deinit(program_memory); /* NOTE: make sure this will get cleaned up after external * programs release their references */ diff --git a/main_w32.c b/main_w32.c @@ -33,11 +33,12 @@ os_gl_proc_address(char *name) #include "static.c" function void -dispatch_file_watch(FileWatchDirectory *fw_dir, u8 *buf, Arena arena) +dispatch_file_watch(OSW32_FileWatchDirectory *fw_dir, Arena arena) { - i64 offset = 0; TempArena save_point = {0}; - w32_file_notify_info *fni = (w32_file_notify_info *)buf; + i64 offset = 0; + + w32_file_notify_info *fni = (w32_file_notify_info *)fw_dir->buffer; do { end_temp_arena(save_point); save_point = begin_temp_arena(&arena); @@ -48,7 +49,7 @@ dispatch_file_watch(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_w32_context.error_handle, stream_to_s8(&path)); stream_reset(&path, 0); } @@ -85,14 +86,13 @@ clear_io_queue(BeamformerInput *input, Arena arena) while (GetQueuedCompletionStatus(handle, &bytes_read, &user_data, &overlapped, 0)) { w32_io_completion_event *event = (w32_io_completion_event *)user_data; switch (event->tag) { - case W32_IO_FILE_WATCH: { - FileWatchDirectory *dir = (FileWatchDirectory *)event->context; - 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); - } break; - case W32_IO_PIPE: break; + case W32IOEvent_FileWatch:{ + OSW32_FileWatchDirectory *dir = (OSW32_FileWatchDirectory *)event->context; + dispatch_file_watch(dir, arena); + zero_struct(&dir->overlapped); + ReadDirectoryChangesW(dir->handle, dir->buffer, OSW32_FileWatchDirectoryBufferSize, 0, + FILE_NOTIFY_CHANGE_LAST_WRITE, 0, &dir->overlapped, 0); + }break; } } } @@ -102,33 +102,36 @@ main(void) { os_common_init(); - Arena program_memory = os_alloc_arena(MB(16) + KB(4)); - - BeamformerCtx *ctx = 0; - BeamformerInput *input = 0; + Arena program_memory = os_alloc_arena(MB(16) + MB(2)); - os_w32_context.arena = sub_arena(&program_memory, KB(4), KB(4)); + os_w32_context.arena = sub_arena(&program_memory, MB(2), KB(4)); os_w32_context.error_handle = GetStdHandle(STD_ERROR_HANDLE); os_w32_context.io_completion_handle = CreateIoCompletionPort(INVALID_FILE, 0, 0, 0); - setup_beamformer(&program_memory, &ctx, &input); + BeamformerInput *input = push_struct(&program_memory, BeamformerInput); + input->executable_reloaded = 1; + beamformer_init(program_memory, input); u64 last_time = os_get_timer_counter(); - while (!ctx->should_exit) { - clear_io_queue(input, program_memory); + while (!WindowShouldClose()) { + DeferLoop(os_take_lock(&os_w32_context.arena_lock, -1), + os_release_lock(&os_w32_context.arena_lock)) + { + clear_io_queue(input, os_w32_context.arena); + } Vector2 new_mouse = GetMousePosition(); u64 now = os_get_timer_counter(); input->last_mouse = input->mouse; input->mouse = (v2){{new_mouse.x, new_mouse.y}}; - input->dt = (f32)((f64)(now - last_time) / (f64)os_w32_context.timer_frequency); + input->dt = (f64)(now - last_time) / (f64)os_w32_context.timer_frequency; last_time = now; - beamformer_frame_step(ctx, input); + beamformer_frame_step(program_memory, input); input->executable_reloaded = 0; } - beamformer_invalidate_shared_memory(ctx); - beamformer_debug_ui_deinit(ctx); + beamformer_invalidate_shared_memory(program_memory); + beamformer_debug_ui_deinit(program_memory); } diff --git a/os_linux.c b/os_linux.c @@ -23,12 +23,25 @@ #include <unistd.h> typedef struct { + u64 hash; + iptr handle; + s8 name; + + FileWatch *data; + iz count; + iz capacity; +} OSLinux_FileWatchDirectory; +DA_STRUCT(OSLinux_FileWatchDirectory, OSLinux_FileWatchDirectory); + +typedef struct { Arena arena; i32 arena_lock; i32 inotify_handle; OS_SystemInfo system_info; -} OS_LinuxContext; -global OS_LinuxContext os_linux_context; + + OSLinux_FileWatchDirectoryList file_watch_list; +} OSLinux_Context; +global OSLinux_Context os_linux_context; #ifdef _DEBUG function void * @@ -240,24 +253,36 @@ os_unload_library(void *h) dlclose(h); } +function OSLinux_FileWatchDirectory * +os_lookup_file_watch_directory(OSLinux_FileWatchDirectoryList *ctx, u64 hash) +{ + OSLinux_FileWatchDirectory *result = 0; + for (iz i = 0; !result && i < ctx->count; i++) + if (ctx->data[i].hash == hash) + result = ctx->data + i; + return result; +} + function OS_ADD_FILE_WATCH_FN(os_add_file_watch) { s8 directory = path; directory.len = s8_scan_backwards(path, '/'); assert(directory.len > 0); + OSLinux_FileWatchDirectoryList *fwctx = &os_linux_context.file_watch_list; + u64 hash = u64_hash_from_s8(directory); - FileWatchDirectory *dir = lookup_file_watch_directory(fwctx, hash); + OSLinux_FileWatchDirectory *dir = os_lookup_file_watch_directory(fwctx, hash); if (!dir) { assert(path.data[directory.len] == '/'); - dir = da_push(a, fwctx); + dir = da_push(&os_linux_context.arena, fwctx); dir->hash = hash; - dir->name = push_s8(a, directory); + dir->name = push_s8(&os_linux_context.arena, directory); u32 mask = IN_MOVED_TO|IN_CLOSE_WRITE; dir->handle = inotify_add_watch(os_linux_context.inotify_handle, (c8 *)dir->name.data, mask); } - FileWatch *fw = da_push(a, dir); + FileWatch *fw = da_push(&os_linux_context.arena, dir); fw->user_data = user_data; fw->callback = callback; fw->hash = u64_hash_from_s8(s8_cut_head(path, dir->name.len + 1)); diff --git a/os_win32.c b/os_win32.c @@ -89,9 +89,8 @@ typedef struct { } w32_overlapped; typedef enum { - W32_IO_FILE_WATCH, - W32_IO_PIPE, -} W32_IO_Event; + W32IOEvent_FileWatch, +} W32IOEvent; typedef struct { u64 tag; @@ -139,6 +138,23 @@ W32(iptr) wglGetProcAddress(c8 *); W32(b32) WriteFile(iptr, u8 *, i32, i32 *, void *); W32(void *) VirtualAlloc(u8 *, iz, u32, u32); +enum {OSW32_FileWatchDirectoryBufferSize = KB(4)}; +typedef struct { + u64 hash; + iptr handle; + s8 name; + + FileWatch *data; + iz count; + iz capacity; + + w32_overlapped overlapped; + w32_io_completion_event event; + + void *buffer; +} OSW32_FileWatchDirectory; +DA_STRUCT(OSW32_FileWatchDirectory, OSW32_FileWatchDirectory); + typedef struct { Arena arena; i32 arena_lock; @@ -146,8 +162,10 @@ typedef struct { iptr io_completion_handle; u64 timer_frequency; OS_SystemInfo system_info; -} OS_W32Context; -global OS_W32Context os_w32_context; + + OSW32_FileWatchDirectoryList file_watch_list; +} OSW32_Context; +global OSW32_Context os_w32_context; #ifdef _DEBUG function void * @@ -166,7 +184,7 @@ os_get_module(char *name, Stream *e) function OS_WRITE_FILE_FN(os_write_file) { i32 wlen = 0; - if (raw.len > 0 && raw.len <= U32_MAX) WriteFile(file, raw.data, (i32)raw.len, &wlen, 0); + if (raw.len > 0 && raw.len <= (iz)U32_MAX) WriteFile(file, raw.data, (i32)raw.len, &wlen, 0); return raw.len == wlen; } @@ -252,7 +270,7 @@ function OS_READ_WHOLE_FILE_FN(os_read_whole_file) if (h >= 0 && GetFileInformationByHandle(h, &fileinfo)) { iz filesize = (iz)fileinfo.nFileSizeHigh << 32; filesize |= (iz)fileinfo.nFileSizeLow; - if (filesize <= U32_MAX) { + if (filesize <= (iz)U32_MAX) { result = s8_alloc(arena, filesize); i32 rlen; if (!ReadFile(h, result.data, (i32)result.len, &rlen, 0) || rlen != result.len) @@ -373,38 +391,46 @@ os_unload_library(void *h) FreeLibrary(h); } +function OSW32_FileWatchDirectory * +os_lookup_file_watch_directory(OSW32_FileWatchDirectoryList *ctx, u64 hash) +{ + OSW32_FileWatchDirectory *result = 0; + for (iz i = 0; !result && i < ctx->count; i++) + if (ctx->data[i].hash == hash) + result = ctx->data + i; + return result; +} + function OS_ADD_FILE_WATCH_FN(os_add_file_watch) { s8 directory = path; directory.len = s8_scan_backwards(path, '\\'); assert(directory.len > 0); + OSW32_FileWatchDirectoryList *fwctx = &os_w32_context.file_watch_list; + u64 hash = u64_hash_from_s8(directory); - FileWatchDirectory *dir = lookup_file_watch_directory(fwctx, hash); + OSW32_FileWatchDirectory *dir = os_lookup_file_watch_directory(fwctx, hash); if (!dir) { assert(path.data[directory.len] == '\\'); - dir = da_push(a, fwctx); + dir = da_push(&os_w32_context.arena, fwctx); dir->hash = hash; - dir->name = push_s8(a, directory); + dir->name = push_s8(&os_w32_context.arena, directory); dir->handle = CreateFileA((c8 *)dir->name.data, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED, 0); - w32_io_completion_event *event = push_struct(a, typeof(*event)); - event->tag = W32_IO_FILE_WATCH; - event->context = (iptr)dir; - 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); - zero_struct(overlapped); + dir->event.tag = W32IOEvent_FileWatch; + dir->event.context = (iptr)dir; + CreateIoCompletionPort(dir->handle, os_w32_context.io_completion_handle, (uptr)&dir->event, 0); - ReadDirectoryChangesW(dir->handle, dir->buffer.beg, 4096, 0, - FILE_NOTIFY_CHANGE_LAST_WRITE, 0, overlapped, 0); + dir->buffer = arena_alloc(&os_w32_context.arena, OSW32_FileWatchDirectoryBufferSize, 8, 1); + ReadDirectoryChangesW(dir->handle, dir->buffer, OSW32_FileWatchDirectoryBufferSize, 0, + FILE_NOTIFY_CHANGE_LAST_WRITE, 0, &dir->overlapped, 0); } - FileWatch *fw = da_push(a, dir); + FileWatch *fw = da_push(&os_w32_context.arena, dir); fw->user_data = user_data; fw->callback = callback; fw->hash = u64_hash_from_s8(s8_cut_head(path, dir->name.len + 1)); diff --git a/static.c b/static.c @@ -62,7 +62,7 @@ debug_init(BeamformerCtx *ctx, BeamformerInput *input, Arena *arena) 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); + os_add_file_watch(s8(OS_DEBUG_LIB_NAME), debug_reload, (iptr)dctx); debug_reload(s8(""), (iptr)dctx, *arena); Stream err = arena_stream(*arena); @@ -329,18 +329,16 @@ function OS_THREAD_ENTRY_POINT_FN(beamformer_upload_entry_point) } function void -setup_beamformer(Arena *memory, BeamformerCtx **o_ctx, BeamformerInput **o_input) +beamformer_init(Arena memory, BeamformerInput *input) { - Arena compute_arena = sub_arena(memory, MB(2), KB(4)); - Arena upload_arena = sub_arena(memory, KB(4), KB(4)); - Stream error = stream_alloc(memory, MB(1)); - Arena ui_arena = sub_arena(memory, MB(2), KB(4)); + Arena compute_arena = sub_arena_end(&memory, MB(2), KB(4)); + Arena upload_arena = sub_arena_end(&memory, KB(4), KB(4)); + Arena ui_arena = sub_arena_end(&memory, MB(2), KB(4)); + Stream error = arena_stream(sub_arena_end(&memory, MB(1), 1)); + BeamformerCtx *ctx = push_struct(&memory, BeamformerCtx); - Arena scratch = {.beg = memory->end - 4096L, .end = memory->end}; - memory->end = scratch.beg; - - BeamformerCtx *ctx = *o_ctx = push_struct(memory, typeof(*ctx)); - BeamformerInput *input = *o_input = push_struct(memory, typeof(*input)); + Arena scratch = {.beg = memory.end - 4096L, .end = memory.end}; + memory.end = scratch.beg; ctx->window_size = (iv2){{1280, 840}}; ctx->error_stream = error; @@ -352,7 +350,7 @@ setup_beamformer(Arena *memory, BeamformerCtx **o_ctx, BeamformerInput **o_input ctx->upload_worker.arena = upload_arena; ctx->upload_worker.asleep = 1; - debug_init(ctx, 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"); @@ -365,14 +363,14 @@ setup_beamformer(Arena *memory, BeamformerCtx **o_ctx, BeamformerInput **o_input load_gl(&ctx->error_stream); - ctx->beamform_work_queue = push_struct(memory, BeamformWorkQueue); - ctx->compute_shader_stats = push_struct(memory, ComputeShaderStats); - ctx->compute_timing_table = push_struct(memory, ComputeTimingTable); + ctx->beamform_work_queue = push_struct(&memory, BeamformWorkQueue); + ctx->compute_shader_stats = push_struct(&memory, ComputeShaderStats); + ctx->compute_timing_table = push_struct(&memory, ComputeTimingTable); /* TODO(rnp): I'm not sure if its a good idea to pre-reserve a bunch of semaphores * on w32 but thats what we are doing for now */ u32 lock_count = (u32)BeamformerSharedMemoryLockKind_Count + (u32)BeamformerMaxParameterBlockSlots; - ctx->shared_memory = os_create_shared_memory_area(memory, OS_SHARED_MEMORY_NAME, lock_count, + ctx->shared_memory = os_create_shared_memory_area(&memory, OS_SHARED_MEMORY_NAME, lock_count, BEAMFORMER_SHARED_MEMORY_SIZE); BeamformerSharedMemory *sm = ctx->shared_memory.region; if (!sm) os_fatal(s8("Get more ram lol\n")); @@ -391,7 +389,7 @@ setup_beamformer(Arena *memory, BeamformerCtx **o_ctx, BeamformerInput **o_input os_set_thread_name(worker->handle, s8("[compute]")); GLWorkerThreadContext *upload = &ctx->upload_worker; - BeamformerUploadThreadContext *upctx = push_struct(memory, typeof(*upctx)); + BeamformerUploadThreadContext *upctx = push_struct(&memory, typeof(*upctx)); upload->user_context = (iptr)upctx; upctx->rf_buffer = &cs->rf_buffer; upctx->shared_memory = &ctx->shared_memory; @@ -403,12 +401,12 @@ setup_beamformer(Arena *memory, BeamformerCtx **o_ctx, BeamformerInput **o_input glfwMakeContextCurrent(raylib_window_handle); - if (load_cuda_library(s8(OS_CUDA_LIB_NAME), 0, *memory)) - os_add_file_watch(&ctx->file_watch_list, memory, s8(OS_CUDA_LIB_NAME), load_cuda_library, 0); + if (load_cuda_library(s8(OS_CUDA_LIB_NAME), 0, memory)) + os_add_file_watch(s8(OS_CUDA_LIB_NAME), load_cuda_library, 0); /* NOTE: set up OpenGL debug logging */ - Stream *gl_error_stream = push_struct(memory, Stream); - *gl_error_stream = stream_alloc(memory, 1024); + 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); @@ -422,11 +420,11 @@ setup_beamformer(Arena *memory, BeamformerCtx **o_ctx, BeamformerInput **o_input s8 file = push_s8_from_parts(&temp, s8(OS_PATH_SEPARATOR), s8("shaders"), beamformer_reloadable_shader_files[index]); - BeamformerShaderReloadIndirectContext *rsi = push_struct(memory, typeof(*rsi)); + BeamformerShaderReloadIndirectContext *rsi = push_struct(&memory, typeof(*rsi)); rsi->beamformer = ctx; rsi->shader = beamformer_reloadable_shader_kinds[index]; - os_add_file_watch(&ctx->file_watch_list, memory, file, reload_shader_indirect, (iptr)rsi); - reload_shader_indirect(file, (iptr)rsi, *memory); + os_add_file_watch(file, reload_shader_indirect, (iptr)rsi); + reload_shader_indirect(file, (iptr)rsi, memory); } os_wake_waiters(&worker->sync_variable); } @@ -447,7 +445,7 @@ setup_beamformer(Arena *memory, BeamformerCtx **o_ctx, BeamformerInput **o_input "only a single render shader is currently handled"); i32 render_rsi_index = beamformer_reloadable_render_shader_info_indices[0]; - Arena *arena = BakeShaders? &scratch : memory; + Arena *arena = BakeShaders? &scratch : &memory; ShaderReloadContext *render_3d = push_struct(arena, typeof(*render_3d)); render_3d->beamformer_context = ctx; render_3d->reloadable_info_index = render_rsi_index; @@ -501,9 +499,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->file_watch_list, memory, render_file, reload_shader, (iptr)render_3d); + os_add_file_watch(render_file, reload_shader, (iptr)render_3d); } - reload_shader(render_file, (iptr)render_3d, *memory); + reload_shader(render_file, (iptr)render_3d, memory); f32 unit_cube_vertices[] = { 0.5f, 0.5f, -0.5f, @@ -576,11 +574,12 @@ setup_beamformer(Arena *memory, BeamformerCtx **o_ctx, BeamformerInput **o_input sizeof(unit_cube_vertices), unit_cube_indices, countof(unit_cube_indices)); - memory->end = scratch.end; + memory.end = scratch.end; + ctx->arena = memory; } function void -beamformer_invalidate_shared_memory(BeamformerCtx *ctx) +beamformer_invalidate_shared_memory(Arena memory) { /* NOTE(rnp): work around pebkac when the beamformer is closed while we are doing live * imaging. if the verasonics is blocked in an external function (calling the library @@ -589,6 +588,7 @@ beamformer_invalidate_shared_memory(BeamformerCtx *ctx) * into an error state and release dispatch lock so that future calls will error instead * of blocking. */ + BeamformerCtx *ctx = BeamformerContextMemory(memory); BeamformerSharedMemory *sm = ctx->shared_memory.region; BeamformerSharedMemoryLockKind lock = BeamformerSharedMemoryLockKind_DispatchCompute; atomic_store_u32(&sm->invalid, 1); diff --git a/util.c b/util.c @@ -81,6 +81,50 @@ arena_alloc(Arena *a, iz len, uz align, iz count) return result; } +function Arena +sub_arena(Arena *a, iz len, uz align) +{ + Arena result = {0}; + + uz padding = -(uintptr_t)a->beg & (align - 1); + result.beg = a->beg + padding; + result.end = result.beg + len; + arena_commit(a, len + (iz)padding); + + return result; +} + +function Arena +sub_arena_end(Arena *a, iz len, uz align) +{ + Arena result; + result.beg = (u8 *)((uintptr_t)(a->end - len) & ~(align - 1)), + result.end = a->end, + + a->end = result.beg; + assert(a->end >= a->beg); + + return result; +} + +function TempArena +begin_temp_arena(Arena *a) +{ + TempArena result = {.arena = a, .old_beg = a->beg}; + return result; +} + +function void +end_temp_arena(TempArena ta) +{ + Arena *a = ta.arena; + if (a) { + assert(a->beg >= ta.old_beg); + a->beg = ta.old_beg; + } +} + + enum { DA_INITIAL_CAP = 16 }; #define da_index(it, s) ((it) - (s)->data) @@ -120,36 +164,6 @@ da_reserve_(Arena *a, void *data, iz *capacity, iz needed, uz align, iz size) return data; } -function Arena -sub_arena(Arena *a, iz len, uz align) -{ - Arena result = {0}; - - uz padding = -(uintptr_t)a->beg & (align - 1); - result.beg = a->beg + padding; - result.end = result.beg + len; - arena_commit(a, len + (iz)padding); - - return result; -} - -function TempArena -begin_temp_arena(Arena *a) -{ - TempArena result = {.arena = a, .old_beg = a->beg}; - return result; -} - -function void -end_temp_arena(TempArena ta) -{ - Arena *a = ta.arena; - if (a) { - assert(a->beg >= ta.old_beg); - a->beg = ta.old_beg; - } -} - function u32 utf8_encode(u8 *out, u32 cp) { @@ -719,17 +733,3 @@ parse_f64(s8 s) f64 result = (f64)integral.S64 + frac; return result; } - -function FileWatchDirectory * -lookup_file_watch_directory(FileWatchDirectoryList *ctx, u64 hash) -{ - FileWatchDirectory *result = 0; - for (u32 i = 0; i < ctx->count; i++) { - FileWatchDirectory *test = ctx->data + i; - if (test->hash == hash) { - result = test; - break; - } - } - return result; -} diff --git a/util.h b/util.h @@ -331,18 +331,6 @@ typedef struct { } FileWatch; typedef struct { - u64 hash; - iptr handle; - s8 name; - - FileWatch *data; - iz count; - iz capacity; - Arena buffer; -} FileWatchDirectory; -DA_STRUCT(FileWatchDirectory, FileWatchDirectory); - -typedef struct { void *region; iptr os_context; } SharedMemoryRegion; @@ -366,8 +354,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(FileWatchDirectoryList *fwctx, Arena *a, s8 path, \ - file_watch_callback *callback, iptr user_data) +#define OS_ADD_FILE_WATCH_FN(name) void name(s8 path, file_watch_callback *callback, iptr user_data) typedef OS_ADD_FILE_WATCH_FN(os_add_file_watch_fn); #define OS_WAKE_WORKER_FN(name) void name(GLWorkerThreadContext *ctx)