ogl_beamforming

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

Commit: fecdf9e1bae62c4807bbbfeafea40d8426765f75
Parent: 684ec5b99db42cf252db5032e618b0c79e4739e1
Author: Randy Palamar
Date:   Tue,  8 Oct 2024 14:23:30 -0600

remove raylib calls from platform layer

They complicate cross compilation and don't really offer anything.

Diffstat:
Mbeamformer.h | 20+-------------------
Mmain_generic.c | 3++-
Mos_unix.c | 63++++++++++++++++++++++++++++++++++++++++++---------------------
Mos_win32.c | 58++++++++++++++++++++++++++++++++++++----------------------
Mstatic.c | 26++++++++++++--------------
Mui.c | 2--
Mutil.c | 21+++++++++++++++++++++
Mutil.h | 23+++++++++++++++++++++--
8 files changed, 135 insertions(+), 81 deletions(-)

diff --git a/beamformer.h b/beamformer.h @@ -90,25 +90,6 @@ typedef struct { cuda_hilbert_fn *cuda_hilbert; } CudaLib; -#define PLATFORM_ALLOC_ARENA_FN(name) Arena name(Arena old, size capacity) -typedef PLATFORM_ALLOC_ARENA_FN(platform_alloc_arena_fn); - -#define PLATFORM_POLL_PIPE_FN(name) b32 name(Pipe p) -typedef PLATFORM_POLL_PIPE_FN(platform_poll_pipe_fn); - -#define PLATFORM_READ_PIPE_FN(name) size name(Pipe p, void *buf, size len) -typedef PLATFORM_READ_PIPE_FN(platform_read_pipe_fn); - -#define PLATFORM_WRITE_NEW_FILE_FN(name) b32 name(char *fname, s8 raw) -typedef PLATFORM_WRITE_NEW_FILE_FN(platform_write_new_file_fn); - -typedef struct { - platform_alloc_arena_fn *alloc_arena; - platform_poll_pipe_fn *poll_pipe; - platform_read_pipe_fn *read_pipe; - platform_write_new_file_fn *write_new_file; -} Platform; - #include "beamformer_parameters.h" typedef struct { BeamformerParameters raw; @@ -224,6 +205,7 @@ typedef struct { CudaLib cuda_lib; Platform platform; + Stream error_stream; BeamformerParametersFull *params; } BeamformerCtx; diff --git a/main_generic.c b/main_generic.c @@ -34,8 +34,9 @@ int main(void) { BeamformerCtx ctx = {0}; - Arena temp_memory = os_alloc_arena((Arena){0}, 8 * MEGABYTE); + Arena temp_memory = os_alloc_arena((Arena){0}, 16 * MEGABYTE); + ctx.error_stream = stream_alloc(&temp_memory, 1 * MEGABYTE); ctx.platform.alloc_arena = os_alloc_arena; ctx.platform.poll_pipe = os_poll_pipe; ctx.platform.read_pipe = os_read_pipe; diff --git a/os_unix.c b/os_unix.c @@ -8,12 +8,6 @@ #include <sys/stat.h> #include <unistd.h> -static void -os_write_err_msg(s8 msg) -{ - write(STDERR_FILENO, msg.data, msg.len); -} - static void __attribute__((noreturn)) os_fail(void) { @@ -21,6 +15,23 @@ os_fail(void) unreachable(); } +static b32 +os_write_file(iptr file, s8 raw) +{ + while (raw.len) { + size r = write(file, raw.data, raw.len); + if (r < 0) return 0; + raw = s8_cut_head(raw, r); + } + return 1; +} + +static void +os_write_err_msg(s8 msg) +{ + write(STDERR_FILENO, msg.data, msg.len); +} + static PLATFORM_ALLOC_ARENA_FN(os_alloc_arena) { Arena result; @@ -66,12 +77,12 @@ os_read_file(Arena *a, char *fname, size fsize) static PLATFORM_WRITE_NEW_FILE_FN(os_write_new_file) { - i32 fd = open(fname, O_WRONLY|O_TRUNC|O_CREAT, 0600); - if (fd < 0) + iptr fd = open(fname, O_WRONLY|O_TRUNC|O_CREAT, 0600); + if (fd == INVALID_FILE) return 0; - size wlen = write(fd, raw.data, raw.len); + b32 ret = os_write_file(fd, raw); close(fd); - return wlen == raw.len; + return ret; } static FileStats @@ -121,20 +132,19 @@ static PLATFORM_READ_PIPE_FN(os_read_pipe) return total_read; } -static BeamformerParametersFull * -os_open_shared_memory_area(char *name) +static void * +os_open_shared_memory_area(char *name, size cap) { i32 fd = shm_open(name, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR); if (fd == -1) return NULL; - if (ftruncate(fd, sizeof(BeamformerParametersFull)) == -1) { + if (ftruncate(fd, cap) == -1) { close(fd); return NULL; } - BeamformerParametersFull *new; - new = mmap(NULL, sizeof(*new), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + void *new = mmap(NULL, cap, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); close(fd); if (new == MAP_FAILED) @@ -180,15 +190,20 @@ ret: } static void * -os_load_library(char *name, char *temp_name) +os_load_library(char *name, char *temp_name, Stream *e) { if (temp_name) { if (os_copy_file(name, temp_name)) name = temp_name; } void *res = dlopen(name, RTLD_NOW|RTLD_LOCAL); - if (!res) - TraceLog(LOG_WARNING, "os_load_library(%s): %s\n", name, dlerror()); + if (!res && e) { + s8 errs[] = {s8("WARNING: os_load_library("), cstr_to_s8(name), s8("): "), + cstr_to_s8(dlerror()), s8("\n")}; + stream_append_s8_array(e, errs, ARRAY_COUNT(errs)); + os_write_err_msg(stream_to_s8(*e)); + e->widx = 0; + } if (temp_name) unlink(temp_name); @@ -197,13 +212,19 @@ os_load_library(char *name, char *temp_name) } static void * -os_lookup_dynamic_symbol(void *h, char *name) +os_lookup_dynamic_symbol(void *h, char *name, Stream *e) { if (!h) return 0; void *res = dlsym(h, name); - if (!res) - TraceLog(LOG_WARNING, "os_lookup_dynamic_symbol(%s): %s\n", name, dlerror()); + if (!res && e) { + s8 errs[] = {s8("WARNING: os_lookup_dynamic_symbol("), cstr_to_s8(name), s8("): "), + cstr_to_s8(dlerror()), s8("\n")}; + stream_append_s8_array(e, errs, ARRAY_COUNT(errs)); + os_write_err_msg(stream_to_s8(*e)); + e->widx = 0; + } + return res; } diff --git a/os_win32.c b/os_win32.c @@ -77,13 +77,20 @@ os_fail(void) unreachable(); } +static b32 +os_write_file(iptr file, s8 raw) +{ + i32 wlen; + WriteFile(file, raw.data, raw.len, &wlen, 0); + return raw.len == wlen; +} + static void os_write_err_msg(s8 msg) { if (!win32_stderr_handle) win32_stderr_handle = GetStdHandle(STD_ERROR_HANDLE); - i32 wlen; - WriteFile(win32_stderr_handle, msg.data, msg.len, &wlen, 0); + os_write_file(win32_stderr_handle, msg); } static PLATFORM_ALLOC_ARENA_FN(os_alloc_arena) @@ -118,8 +125,7 @@ os_read_file(Arena *a, char *fname, size fsize) return (s8){.len = -1}; if (fsize > (size)U32_MAX) { - os_write_err_msg(s8("os_read_file: Handling files >4GB is not yet handled" - "in win32 code\n")); + os_write_err_msg(s8("os_read_file: files >4GB are not yet handled on win32\n")); return (s8){.len = -1}; } @@ -141,7 +147,7 @@ os_read_file(Arena *a, char *fname, size fsize) static PLATFORM_WRITE_NEW_FILE_FN(os_write_new_file) { if (raw.len > (size)U32_MAX) { - os_write_err_msg(s8("os_write_file: writing files > 4GB is not yet support on win32\n")); + os_write_err_msg(s8("os_write_file: files >4GB are not yet handled on win32\n")); return 0; } @@ -149,10 +155,10 @@ static PLATFORM_WRITE_NEW_FILE_FN(os_write_new_file) if (h == INVALID_FILE) return 0; - i32 wlen; - WriteFile(h, raw.data, raw.len, &wlen, 0); + b32 ret = os_write_file(h, raw); CloseHandle(h); - return wlen == raw.len; + + return ret; } static FileStats @@ -203,18 +209,14 @@ static PLATFORM_READ_PIPE_FN(os_read_pipe) return total_read; } -static BeamformerParametersFull * -os_open_shared_memory_area(char *name) +static void * +os_open_shared_memory_area(char *name, size cap) { - iptr h = CreateFileMappingA(-1, 0, PAGE_READWRITE, 0, - sizeof(BeamformerParametersFull), name); + iptr h = CreateFileMappingA(-1, 0, PAGE_READWRITE, 0, cap, name); if (h == INVALID_FILE) return NULL; - BeamformerParametersFull *new; - new = MapViewOfFile(h, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(*new)); - - return new; + return MapViewOfFile(h, FILE_MAP_ALL_ACCESS, 0, 0, cap); } /* NOTE: closing the handle releases the memory and this happens when program terminates */ @@ -224,7 +226,7 @@ os_remove_shared_memory(char *name) } static void * -os_load_library(char *name, char *temp_name) +os_load_library(char *name, char *temp_name, Stream *e) { if (temp_name) { if (CopyFileA(name, temp_name, 0)) @@ -232,8 +234,14 @@ os_load_library(char *name, char *temp_name) } void *res = LoadLibraryA(name); - if (!res) - TraceLog(LOG_WARNING, "os_load_library(%s): %d\n", name, GetLastError()); + if (!res && e) { + s8 errs[] = {s8("WARNING: os_load_library("), cstr_to_s8(name), s8("): ")}; + stream_append_s8_array(e, errs, ARRAY_COUNT(errs)); + stream_append_i64(e, GetLastError()); + stream_append_s8(e, s8("\n")); + os_write_err_msg(stream_to_s8(*e)); + e->widx = 0; + } if (temp_name) DeleteFileA(temp_name); @@ -242,13 +250,19 @@ os_load_library(char *name, char *temp_name) } static void * -os_lookup_dynamic_symbol(void *h, char *name) +os_lookup_dynamic_symbol(void *h, char *name, Stream *e) { if (!h) return 0; void *res = GetProcAddress(h, name); - if (!res) - TraceLog(LOG_WARNING, "os_lookup_dynamic_symbol(%s): %d\n", name, GetLastError()); + if (!res && e) { + s8 errs[] = {s8("WARNING: os_lookup_dynamic_symbol("), cstr_to_s8(name), s8("): ")}; + stream_append_s8_array(e, errs, ARRAY_COUNT(errs)); + stream_append_i64(e, GetLastError()); + stream_append_s8(e, s8("\n")); + os_write_err_msg(stream_to_s8(*e)); + e->widx = 0; + } return res; } diff --git a/static.c b/static.c @@ -1,6 +1,4 @@ /* See LICENSE for license details. */ -#include "beamformer.h" - static s8 compute_shader_paths[CS_LAST] = { [CS_HADAMARD] = s8("shaders/hadamard.glsl"), [CS_HERCULES] = s8("shaders/hercules.glsl"), @@ -22,14 +20,14 @@ typedef void do_beamformer_fn(BeamformerCtx *, Arena); static do_beamformer_fn *do_beamformer; static void -do_debug(void) +do_debug(Stream *error_stream) { static f32 updated_time; FileStats test_stats = os_get_file_stats(OS_DEBUG_LIB_NAME); if (test_stats.filesize > 32 && test_stats.timestamp > updated_time) { os_unload_library(debug_lib); - debug_lib = os_load_library(OS_DEBUG_LIB_NAME, OS_DEBUG_LIB_TEMP_NAME); - do_beamformer = os_lookup_dynamic_symbol(debug_lib, "do_beamformer"); + debug_lib = os_load_library(OS_DEBUG_LIB_NAME, OS_DEBUG_LIB_TEMP_NAME, error_stream); + do_beamformer = os_lookup_dynamic_symbol(debug_lib, "do_beamformer", error_stream); updated_time = test_stats.timestamp; } } @@ -221,7 +219,7 @@ validate_cuda_lib(CudaLib *cl) } static void -check_and_load_cuda_lib(CudaLib *cl) +check_and_load_cuda_lib(CudaLib *cl, Stream *error_stream) { FileStats current = os_get_file_stats(OS_CUDA_LIB_NAME); if (cl->timestamp == current.timestamp || current.filesize < 32) @@ -231,12 +229,12 @@ check_and_load_cuda_lib(CudaLib *cl) cl->timestamp = current.timestamp; os_unload_library(cl->lib); - cl->lib = os_load_library(OS_CUDA_LIB_NAME, OS_CUDA_LIB_TEMP_NAME); + cl->lib = os_load_library(OS_CUDA_LIB_NAME, OS_CUDA_LIB_TEMP_NAME, error_stream); - cl->init_cuda_configuration = os_lookup_dynamic_symbol(cl->lib, "init_cuda_configuration"); - cl->register_cuda_buffers = os_lookup_dynamic_symbol(cl->lib, "register_cuda_buffers"); - cl->cuda_decode = os_lookup_dynamic_symbol(cl->lib, "cuda_decode"); - cl->cuda_hilbert = os_lookup_dynamic_symbol(cl->lib, "cuda_hilbert"); + cl->init_cuda_configuration = os_lookup_dynamic_symbol(cl->lib, "init_cuda_configuration", error_stream); + cl->register_cuda_buffers = os_lookup_dynamic_symbol(cl->lib, "register_cuda_buffers", error_stream); + cl->cuda_decode = os_lookup_dynamic_symbol(cl->lib, "cuda_decode", error_stream); + cl->cuda_hilbert = os_lookup_dynamic_symbol(cl->lib, "cuda_hilbert", error_stream); validate_cuda_lib(cl); } @@ -267,7 +265,7 @@ setup_beamformer(BeamformerCtx *ctx, Arena temp_memory) init_fragment_shader_ctx(&ctx->fsctx, ctx->out_data_dim); ctx->data_pipe = os_open_named_pipe(OS_PIPE_NAME); - ctx->params = os_open_shared_memory_area(OS_SMEM_NAME); + ctx->params = os_open_shared_memory_area(OS_SMEM_NAME, sizeof(ctx->params)); /* TODO: properly handle this? */ ASSERT(ctx->data_pipe.file != INVALID_FILE); ASSERT(ctx->params); @@ -304,9 +302,9 @@ setup_beamformer(BeamformerCtx *ctx, Arena temp_memory) static void do_program_step(BeamformerCtx *ctx, Arena temp_memory) { - do_debug(); + do_debug(&ctx->error_stream); if (ctx->gl.vendor_id == GL_VENDOR_NVIDIA) - check_and_load_cuda_lib(&ctx->cuda_lib); + check_and_load_cuda_lib(&ctx->cuda_lib, &ctx->error_stream); if (ctx->flags & RELOAD_SHADERS) { ctx->flags &= ~RELOAD_SHADERS; diff --git a/ui.c b/ui.c @@ -1,6 +1,4 @@ /* See LICENSE for license details. */ -#include "beamformer.h" - static void ui_start_compute(BeamformerCtx *ctx) { diff --git a/util.c b/util.c @@ -54,6 +54,16 @@ stream_append_s8(Stream *s, s8 str) } static void +stream_append_s8_array(Stream *s, s8 *strs, size count) +{ + while (count > 0) { + stream_append_s8(s, *strs); + strs++; + count--; + } +} + +static void stream_append_u64(Stream *s, u64 n) { u8 tmp[64]; @@ -110,6 +120,17 @@ cstr_to_s8(char *cstr) } static s8 +s8_cut_head(s8 s, size cut) +{ + s8 result = s; + if (cut > 0) { + result.data += cut; + result.len -= cut; + } + return result; +} + +static s8 s8alloc(Arena *a, size len) { return (s8){ .data = alloc(a, u8, len), .len = len }; diff --git a/util.h b/util.h @@ -135,12 +135,31 @@ typedef struct { #define ERROR_FILE_STATS (FileStats){.filesize = -1} typedef struct { - size widx; u8 *data; - size cap; + u32 widx; + u32 cap; b32 errors; } Stream; +#define PLATFORM_ALLOC_ARENA_FN(name) Arena name(Arena old, size capacity) +typedef PLATFORM_ALLOC_ARENA_FN(platform_alloc_arena_fn); + +#define PLATFORM_POLL_PIPE_FN(name) b32 name(Pipe p) +typedef PLATFORM_POLL_PIPE_FN(platform_poll_pipe_fn); + +#define PLATFORM_READ_PIPE_FN(name) size name(Pipe p, void *buf, size len) +typedef PLATFORM_READ_PIPE_FN(platform_read_pipe_fn); + +#define PLATFORM_WRITE_NEW_FILE_FN(name) b32 name(char *fname, s8 raw) +typedef PLATFORM_WRITE_NEW_FILE_FN(platform_write_new_file_fn); + +typedef struct { + platform_alloc_arena_fn *alloc_arena; + platform_poll_pipe_fn *poll_pipe; + platform_read_pipe_fn *read_pipe; + platform_write_new_file_fn *write_new_file; +} Platform; + #include "util.c" #endif /* _UTIL_H_ */