ogl_beamforming

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

Commit: 266448a5f5056b5cc502040a21f560bf1df35f75
Parent: 62b6d4a0d8638c532d4933a570f92e702bdf50c6
Author: Randy Palamar
Date:   Mon,  7 Oct 2024 13:10:12 -0600

remove many *printf calls and move remaining to util.c

Diffstat:
Mmain.c | 56+++++++++++++++++++++++++++++++++++---------------------
Mos_unix.c | 6++++++
Mos_win32.c | 17+++++++++++++++--
Mui.c | 87++++++++++++++++++++++++++++++++++++++++---------------------------------------
Mutil.c | 103++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Mutil.h | 8++++++++
6 files changed, 195 insertions(+), 82 deletions(-)

diff --git a/main.c b/main.c @@ -46,16 +46,20 @@ static void gl_debug_logger(u32 src, u32 type, u32 id, u32 lvl, i32 len, const char *msg, const void *userctx) { (void)src; (void)type; (void)id; (void)userctx; - fputs("[GL DEBUG ", stderr); + + u8 buf[128]; + Stream s = {.data = buf, .cap = ARRAY_COUNT(buf)}; + stream_append_s8(&s, s8("[GL DEBUG ")); switch (lvl) { - case GL_DEBUG_SEVERITY_HIGH: fputs("HIGH]: ", stderr); break; - case GL_DEBUG_SEVERITY_MEDIUM: fputs("MEDIUM]: ", stderr); break; - case GL_DEBUG_SEVERITY_LOW: fputs("LOW]: ", stderr); break; - case GL_DEBUG_SEVERITY_NOTIFICATION: fputs("NOTIFICATION]: ", stderr); break; - default: fputs("INVALID]: ", stderr); break; + case GL_DEBUG_SEVERITY_HIGH: stream_append_s8(&s, s8("HIGH]: ")); break; + case GL_DEBUG_SEVERITY_MEDIUM: stream_append_s8(&s, s8("MEDIUM]: ")); break; + case GL_DEBUG_SEVERITY_LOW: stream_append_s8(&s, s8("LOW]: ")); break; + case GL_DEBUG_SEVERITY_NOTIFICATION: stream_append_s8(&s, s8("NOTIFICATION]: ")); break; + default: stream_append_s8(&s, s8("INVALID]: ")); break; } - fwrite(msg, 1, len, stderr); - fputc('\n', stderr); + os_write_err_msg(stream_to_s8(s)); + os_write_err_msg((s8){.len = len, .data = (u8 *)msg}); + os_write_err_msg(s8("\n")); } static void @@ -88,22 +92,32 @@ validate_gl_requirements(GLParams *gl) } static void -dump_gl_params(GLParams *gl) +dump_gl_params(GLParams *gl, Arena a) { - (void)gl; + (void)gl; (void)a; #ifdef _DEBUG - fputs("---- GL Parameters ----\n", stdout); + Stream s = stream_alloc(&a, 1 * MEGABYTE); + stream_append_s8(&s, s8("---- GL Parameters ----\n")); switch (gl->vendor_id) { - case GL_VENDOR_AMD: fputs("Vendor: AMD\n", stdout); break; - case GL_VENDOR_INTEL: fputs("Vendor: Intel\n", stdout); break; - case GL_VENDOR_NVIDIA: fputs("Vendor: nVidia\n", stdout); break; + case GL_VENDOR_AMD: stream_append_s8(&s, s8("Vendor: AMD\n")); break; + case GL_VENDOR_INTEL: stream_append_s8(&s, s8("Vendor: Intel\n")); break; + case GL_VENDOR_NVIDIA: stream_append_s8(&s, s8("Vendor: nVidia\n")); break; } - printf("Version: %d.%d\n", gl->version_major, gl->version_minor); - printf("Max 1D/2D Texture Dimension: %d\n", gl->max_2d_texture_dim); - printf("Max 3D Texture Dimension: %d\n", gl->max_3d_texture_dim); - printf("Max SSBO Size: %d\n", gl->max_ssbo_size); - printf("Max UBO Size: %d\n", gl->max_ubo_size); - fputs("-----------------------\n", stdout); + stream_append_s8(&s, s8("Version: ")); + stream_append_i64(&s, gl->version_major); + stream_append_s8(&s, s8(".")); + stream_append_i64(&s, gl->version_minor); + stream_append_s8(&s, s8("\nMax 1D/2D Texture Dimension: ")); + stream_append_i64(&s, gl->max_2d_texture_dim); + stream_append_s8(&s, s8("\nMax 3D Texture Dimension: ")); + stream_append_i64(&s, gl->max_3d_texture_dim); + stream_append_s8(&s, s8("\nMax SSBO Size: ")); + stream_append_i64(&s, gl->max_ssbo_size); + stream_append_s8(&s, s8("\nMax UBO Size: ")); + stream_append_i64(&s, gl->max_ubo_size); + stream_append_s8(&s, s8("\n-----------------------\n")); + if (!s.errors) + os_write_err_msg(stream_to_s8(s)); #endif } @@ -238,7 +252,7 @@ main(void) /* NOTE: Gather information about the GPU */ get_gl_params(&ctx.gl); - dump_gl_params(&ctx.gl); + dump_gl_params(&ctx.gl, temp_memory); validate_gl_requirements(&ctx.gl); /* TODO: build these into the binary */ diff --git a/os_unix.c b/os_unix.c @@ -14,6 +14,12 @@ typedef struct { typedef void *os_library_handle; +static void +os_write_err_msg(s8 msg) +{ + write(STDERR_FILENO, msg.data, msg.len); +} + static Arena os_alloc_arena(Arena a, size capacity) { diff --git a/os_win32.c b/os_win32.c @@ -1,6 +1,9 @@ /* See LICENSE for license details. */ #include "util.h" +#define STD_OUTPUT_HANDLE -11 +#define STD_ERROR_HANDLE -12 + #define PAGE_READWRITE 0x04 #define MEM_COMMIT 0x1000 #define MEM_RESERVE 0x2000 @@ -56,6 +59,7 @@ W32(b32) FreeLibrary(void *); W32(b32) GetFileInformationByHandle(void *, void *); W32(i32) GetLastError(void); W32(void *) GetProcAddress(void *, c8 *); +W32(void *) GetStdHandle(i32); W32(void) GetSystemInfo(void *); W32(void *) LoadLibraryA(c8 *); W32(void *) MapViewOfFile(void *, u32, u32, u32, u64); @@ -74,6 +78,15 @@ typedef struct { typedef void *os_library_handle; +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); +} + static Arena os_alloc_arena(Arena a, size capacity) { @@ -122,7 +135,7 @@ static b32 os_write_file(char *fname, s8 raw) { if (raw.len > (size)U32_MAX) { - fputs("os_write_file: writing files > 4GB is not yet support on win32\n", stderr); + os_write_err_msg(s8("os_write_file: writing files > 4GB is not yet support on win32\n")); return 0; } @@ -146,7 +159,7 @@ os_get_file_stats(char *fname) w32_file_info fileinfo; if (!GetFileInformationByHandle(h, &fileinfo)) { - fputs("os_get_file_stats: couldn't get file info\n", stderr); + os_write_err_msg(s8("os_get_file_stats: couldn't get file info\n")); CloseHandle(h); return ERROR_FILE_STATS; } diff --git a/ui.c b/ui.c @@ -173,23 +173,17 @@ bmv_store_value(BeamformerCtx *ctx, BPModifiableValue *bmv, f32 new_val, b32 fro ctx->flags |= GEN_MIPMAPS; } -static s8 -bmv_sprint(BPModifiableValue *bmv, s8 buf) +static void +bmv_sprint(BPModifiableValue *bmv, Stream *s) { - s8 result = buf; if (bmv->flags & MV_FLOAT) { f32 *value = bmv->value; - size len = snprintf((char *)buf.data, buf.len, "%0.02f", *value * bmv->scale); - ASSERT(len <= buf.len); - result.len = len; + stream_append_f32(s, *value * bmv->scale); } else { ASSERT(bmv->flags & MV_INT); i32 *value = bmv->value; - size len = snprintf((char *)buf.data, buf.len, "%d", (i32)(*value * bmv->scale)); - ASSERT(len <= buf.len); - result.len = len; + stream_append_i64(s, *value * bmv->scale); } - return result; } static void @@ -313,8 +307,11 @@ set_text_input_idx(BeamformerCtx *ctx, BPModifiableValue bmv, Rect r, v2 mouse) if (ctx->is.store.value == NULL) return; - s8 ibuf = bmv_sprint(&bmv, (s8){.data = (u8 *)ctx->is.buf, .len = ARRAY_COUNT(ctx->is.buf)}); - ctx->is.buf_len = ibuf.len; + Stream s = {.cap = ARRAY_COUNT(ctx->is.buf), .data = (u8 *)ctx->is.buf}; + bmv_sprint(&bmv, &s); + ASSERT(!s.errors); + ctx->is.buf_len = s.widx; + ctx->is.buf[ctx->is.buf_len] = 0; ASSERT(CheckCollisionPointRec(mouse.rl, r.rl)); ctx->is.cursor_hover_p = CLAMP01((mouse.x - r.pos.x) / r.size.w); @@ -344,13 +341,13 @@ do_value_listing(s8 prefix, s8 suffix, f32 value, Font font, Arena a, Rect r) v2 suffix_s = measure_text(font, suffix); v2 suffix_p = {.x = r.pos.x + r.size.w - suffix_s.w, .y = r.pos.y}; - s8 txt = s8alloc(&a, 64); - txt.len = snprintf((char *)txt.data, txt.len, "%0.02f", value); + Stream buf = stream_alloc(&a, 64); + stream_append_f32(&buf, value); v2 txt_p = {.x = r.pos.x + LISTING_LEFT_COLUMN_WIDTH, .y = r.pos.y}; - draw_text(font, prefix, r.pos, 0, colour_from_normalized(FG_COLOUR)); - draw_text(font, txt, txt_p, 0, colour_from_normalized(FG_COLOUR)); - draw_text(font, suffix, suffix_p, 0, colour_from_normalized(FG_COLOUR)); + draw_text(font, prefix, r.pos, 0, colour_from_normalized(FG_COLOUR)); + draw_text(font, stream_to_s8(buf), txt_p, 0, colour_from_normalized(FG_COLOUR)); + draw_text(font, suffix, suffix_p, 0, colour_from_normalized(FG_COLOUR)); r.pos.y += suffix_s.h + LISTING_LINE_PAD; r.size.y -= suffix_s.h + LISTING_LINE_PAD; @@ -361,8 +358,7 @@ static Rect do_text_input_listing(s8 prefix, s8 suffix, BPModifiableValue bmv, BeamformerCtx *ctx, Arena a, Rect r, v2 mouse, f32 *hover_t) { - s8 buf = s8alloc(&a, 64); - s8 txt = buf; + Stream buf = stream_alloc(&a, 68); v2 txt_s; b32 bmv_active = bmv_equal(&bmv, &ctx->is.store); @@ -370,8 +366,8 @@ do_text_input_listing(s8 prefix, s8 suffix, BPModifiableValue bmv, BeamformerCtx txt_s = measure_text(ctx->font, (s8){.len = ctx->is.buf_len, .data = (u8 *)ctx->is.buf}); } else { - txt = bmv_sprint(&bmv, buf); - txt_s = measure_text(ctx->font, txt); + bmv_sprint(&bmv, &buf); + txt_s = measure_text(ctx->font, stream_to_s8(buf)); } Rect edit_rect = { @@ -387,13 +383,15 @@ do_text_input_listing(s8 prefix, s8 suffix, BPModifiableValue bmv, BeamformerCtx set_text_input_idx(ctx, (BPModifiableValue){0}, (Rect){0}, mouse); f32 old_val = bmv_scaled_value(&bmv); bmv_store_value(ctx, &bmv, old_val + mouse_scroll, 1); - txt = bmv_sprint(&bmv, buf); + buf.widx = 0; + bmv_sprint(&bmv, &buf); } } if (!hovering && bmv_equal(&bmv, &ctx->is.store) && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) { set_text_input_idx(ctx, (BPModifiableValue){0}, (Rect){0}, mouse); - txt = bmv_sprint(&bmv, buf); + buf.widx = 0; + bmv_sprint(&bmv, &buf); } if (hovering && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) @@ -402,7 +400,7 @@ do_text_input_listing(s8 prefix, s8 suffix, BPModifiableValue bmv, BeamformerCtx Color colour = colour_from_normalized(lerp_v4(FG_COLOUR, HOVERED_COLOUR, *hover_t)); if (!bmv_equal(&bmv, &ctx->is.store)) { - draw_text(ctx->font, txt, edit_rect.pos, 0, colour); + draw_text(ctx->font, stream_to_s8(buf), edit_rect.pos, 0, colour); } else { do_text_input(ctx, 7, edit_rect, colour); } @@ -596,8 +594,8 @@ draw_debug_overlay(BeamformerCtx *ctx, Arena arena, Rect r) ComputeShaderCtx *cs = &ctx->csctx; - s8 txt_buf = s8alloc(&arena, 64); - v2 pos = {.x = 20, .y = ws.h - 10}; + Stream buf = stream_alloc(&arena, 64); + v2 pos = {.x = 20, .y = ws.h - 10}; f32 compute_time_sum = 0; u32 stages = ctx->params->compute_stages_count; @@ -606,12 +604,12 @@ draw_debug_overlay(BeamformerCtx *ctx, Arena arena, Rect r) pos.y -= measure_text(ctx->font, labels[index]).y; draw_text(ctx->font, labels[index], pos, 0, colour_from_normalized(FG_COLOUR)); - s8 tmp = txt_buf; - tmp.len = snprintf((char *)txt_buf.data, txt_buf.len, "%0.02e [s]", - cs->last_frame_time[index]); - v2 txt_fs = measure_text(ctx->font, tmp); + buf.widx = 0; + stream_append_f32_e(&buf, cs->last_frame_time[index]); + stream_append_s8(&buf, s8(" [s]")); + v2 txt_fs = measure_text(ctx->font, stream_to_s8(buf)); v2 rpos = {.x = r.pos.x + r.size.w - txt_fs.w, .y = pos.y}; - draw_text(ctx->font, tmp, rpos, 0, colour_from_normalized(FG_COLOUR)); + draw_text(ctx->font, stream_to_s8(buf), rpos, 0, colour_from_normalized(FG_COLOUR)); compute_time_sum += cs->last_frame_time[index]; } @@ -622,11 +620,12 @@ draw_debug_overlay(BeamformerCtx *ctx, Arena arena, Rect r) pos.y -= measure_text(ctx->font, totals[i]).y; draw_text(ctx->font, totals[i], pos, 0, colour_from_normalized(FG_COLOUR)); - s8 tmp = txt_buf; - tmp.len = snprintf((char *)txt_buf.data, txt_buf.len, "%0.02e [s]", times[i]); - v2 txt_fs = measure_text(ctx->font, tmp); + buf.widx = 0; + stream_append_f32_e(&buf, times[i]); + stream_append_s8(&buf, s8(" [s]")); + v2 txt_fs = measure_text(ctx->font, stream_to_s8(buf)); v2 rpos = {.x = r.pos.x + r.size.w - txt_fs.w, .y = pos.y}; - draw_text(ctx->font, tmp, rpos, 0, colour_from_normalized(FG_COLOUR)); + draw_text(ctx->font, stream_to_s8(buf), rpos, 0, colour_from_normalized(FG_COLOUR)); } { @@ -683,10 +682,10 @@ draw_ui(BeamformerCtx *ctx, Arena arena) rr.pos.x = lr.pos.x + lr.size.w; if (output_dim.x > 1e-6 && output_dim.y > 1e-6) { - s8 txt = s8alloc(&arena, 64); - s8 tmp = txt; - tmp.len = snprintf((char *)txt.data, txt.len, "%+0.01f mm", -188.8f); - v2 txt_s = measure_text(ctx->small_font, tmp); + Stream buf = stream_alloc(&arena, 64); + stream_append_f32(&buf, -188.88f); + stream_append_s8(&buf, s8(" mm")); + v2 txt_s = measure_text(ctx->small_font, stream_to_s8(buf)); rr.pos.x += 0.02 * rr.size.w; rr.pos.y += 0.02 * rr.size.h; @@ -761,13 +760,15 @@ draw_ui(BeamformerCtx *ctx, Arena arena) Color txt_colour = colour_from_normalized(lerp_v4(FG_COLOUR, HOVERED_COLOUR, txt_colour_t[i])); - char *fmt[2] = {"%+0.01f mm", "%0.01f mm"}; f32 rot[2] = {90, 0}; for (u32 j = 0; j <= line_count; j++) { DrawLineEx(start_pos.rl, end_pos.rl, 3, colour_from_normalized(FG_COLOUR)); - s8 tmp = txt; - tmp.len = snprintf((char *)txt.data, txt.len, fmt[i], mm); - draw_text(ctx->small_font, tmp, txt_pos, rot[i], txt_colour); + buf.widx = 0; + if (i == 0 && mm > 0) stream_append_s8(&buf, s8("+")); + stream_append_f32(&buf, mm); + stream_append_s8(&buf, s8(" mm")); + draw_text(ctx->small_font, stream_to_s8(buf), txt_pos, + rot[i], txt_colour); start_pos.E[i] += inc; end_pos.E[i] += inc; txt_pos.E[i] += inc; diff --git a/util.c b/util.c @@ -3,18 +3,6 @@ #include <stdio.h> #include <stdlib.h> -static void __attribute__((noreturn)) -die(char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - - exit(1); -} - static void * mem_clear(u8 *p, u8 c, size len) { @@ -35,16 +23,99 @@ alloc_(Arena *a, size len, size align, size count) { size padding = -(uintptr_t)a->beg & (align - 1); size available = a->end - a->beg - padding; - if (available < 0 || count > available / len) { - ASSERT(0); - die("arena OOM\n"); - } + if (available < 0 || count > available / len) + ASSERT(0 && "arena OOM\n"); void *p = a->beg + padding; a->beg += padding + count * len; /* TODO: Performance? */ return mem_clear(p, 0, count * len); } +static Stream +stream_alloc(Arena *a, size cap) +{ + Stream result = {.cap = cap}; + result.data = alloc(a, u8, cap); + return result; +} + +static s8 +stream_to_s8(Stream s) +{ + ASSERT(!s.errors); + s8 result = {.len = s.widx, .data = s.data}; + return result; +} + +static void +stream_append_s8(Stream *s, s8 str) +{ + s->errors |= (s->cap - s->widx) <= str.len; + for (size i = 0; !s->errors && i < str.len; i++) + s->data[s->widx++] = str.data[i]; +} + +static void +stream_append_u64(Stream *s, u64 n) +{ + u8 tmp[64]; + u8 *end = tmp + sizeof(tmp); + u8 *beg = end; + do { *--beg = '0' + (n % 10); } while (n /= 10); + stream_append_s8(s, (s8){.len = end - beg, .data = beg}); +} + +static void +stream_append_i64(Stream *s, i64 n) +{ + if (n < 0) { + stream_append_s8(s, s8("-")); + n *= -1; + } + stream_append_u64(s, n); +} + +static void +stream_append_f32(Stream *s, f32 f) +{ + if (f < 0) { + stream_append_s8(s, s8("-")); + f *= -1; + } + /* TODO */ + size remaining = s->cap - s->widx; + s->errors |= remaining <= snprintf(0, 0, "%0.02f", f); + if (!s->errors) + s->widx += snprintf((char *)(s->data + s->widx), remaining, "%0.02f", f); +} + +static void +stream_append_f32_e(Stream *s, f32 f) +{ + if (f < 0) { + stream_append_s8(s, s8("-")); + f *= -1; + } + /* TODO */ + size remaining = s->cap - s->widx; + s->errors |= remaining <= snprintf(0, 0, "%0.02e", f); + if (!s->errors) + s->widx += snprintf((char *)(s->data + s->widx), remaining, "%0.02e", f); +} + + +static void __attribute__((noreturn)) +die(char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + + exit(1); +} + static s8 s8alloc(Arena *a, size len) { diff --git a/util.h b/util.h @@ -45,6 +45,7 @@ typedef int16_t i16; typedef uint16_t u16; typedef int32_t i32; typedef uint32_t u32; +typedef int64_t i64; typedef uint64_t u64; typedef uint32_t b32; typedef float f32; @@ -112,6 +113,13 @@ typedef struct { } FileStats; #define ERROR_FILE_STATS (FileStats){.filesize = -1} +typedef struct { + size widx; + u8 *data; + size cap; + b32 errors; +} Stream; + #include "beamformer_parameters.h" typedef struct { BeamformerParameters raw;