Commit: d3cfaa359b247baae041f266ecdb03d3874da76c
Parent: ea6a876212d30d4c6b91a6edb11b44ef94f5cf7e
Author: Randy Palamar
Date: Fri, 2 May 2025 07:56:19 -0600
util: rework arena string building
Diffstat:
M | beamformer.c | | | 73 | +++++++++++++++++++++++++++++++++---------------------------------------- |
M | build.c | | | 15 | +++++++-------- |
M | main_linux.c | | | 4 | +--- |
M | os_linux.c | | | 15 | ++++++--------- |
M | os_win32.c | | | 10 | ++++------ |
M | static.c | | | 46 | ++++++++++++++++++++-------------------------- |
M | ui.c | | | 74 | ++++++++++++++++++++++++++++++++++---------------------------------------- |
M | util.c | | | 64 | ++++++++++++++++++++++++++++++++++++++-------------------------- |
M | util_gl.c | | | 13 | +++++-------- |
9 files changed, 148 insertions(+), 166 deletions(-)
diff --git a/beamformer.c b/beamformer.c
@@ -89,7 +89,7 @@ alloc_beamform_frame(GLParams *gp, BeamformFrame *out, ComputeShaderStats *out_s
u32 max_dim = MAX(out->dim.x, MAX(out->dim.y, out->dim.z));
out->mips = ctz_u32(max_dim) + 1;
- Stream label = arena_stream(&arena);
+ Stream label = arena_stream(arena);
stream_append_s8(&label, name);
stream_append_byte(&label, '[');
stream_append_hex_u64(&label, out->id);
@@ -126,14 +126,13 @@ alloc_shader_storage(BeamformerCtx *ctx, u32 rf_raw_size, Arena a)
LABEL_GL_OBJECT(GL_BUFFER, cs->raw_data_ssbo, s8("Raw_RF_SSBO"));
iz rf_decoded_size = 2 * sizeof(f32) * cs->dec_data_dim.x * cs->dec_data_dim.y * cs->dec_data_dim.z;
- Stream label = stream_alloc(&a, 256);
+ Stream label = arena_stream(a);
stream_append_s8(&label, s8("Decoded_RF_SSBO_"));
u32 s_widx = label.widx;
for (u32 i = 0; i < ARRAY_COUNT(cs->rf_data_ssbos); i++) {
glNamedBufferStorage(cs->rf_data_ssbos[i], rf_decoded_size, 0, 0);
stream_append_u64(&label, i);
- s8 rf_label = stream_to_s8(&label);
- LABEL_GL_OBJECT(GL_BUFFER, cs->rf_data_ssbos[i], rf_label);
+ LABEL_GL_OBJECT(GL_BUFFER, cs->rf_data_ssbos[i], stream_to_s8(&label));
stream_reset(&label, s_widx);
}
@@ -392,57 +391,55 @@ do_compute_shader(BeamformerCtx *ctx, Arena arena, BeamformComputeFrame *frame,
function s8
push_compute_shader_header(Arena *a, b32 parameters, ComputeShaderID shader)
{
- s8 result = {.data = a->beg};
+ Stream sb = arena_stream(*a);
- push_s8(a, s8("#version 460 core\n\n"));
+ stream_append_s8(&sb, s8("#version 460 core\n\n"));
#define X(name, type, size, gltype, glsize, comment) "\t" #gltype " " #name #glsize "; " comment "\n"
if (parameters) {
- push_s8(a, s8("layout(std140, binding = 0) uniform parameters {\n"
- BEAMFORMER_PARAMS_HEAD
- BEAMFORMER_UI_PARAMS
- BEAMFORMER_PARAMS_TAIL
- "};\n\n"));
+ stream_append_s8(&sb, s8("layout(std140, binding = 0) uniform parameters {\n"
+ BEAMFORMER_PARAMS_HEAD
+ BEAMFORMER_UI_PARAMS
+ BEAMFORMER_PARAMS_TAIL
+ "};\n\n"));
}
#undef X
switch (shader) {
case CS_DAS: {
- push_s8(a, s8("layout("
- "local_size_x = " str(DAS_LOCAL_SIZE_X) ", "
- "local_size_y = " str(DAS_LOCAL_SIZE_Y) ", "
- "local_size_z = " str(DAS_LOCAL_SIZE_Z) ") "
- "in;\n\n"));
-
- push_s8(a, s8("layout(location = " str(DAS_VOXEL_OFFSET_UNIFORM_LOC) ") uniform ivec3 u_voxel_offset;\n"));
- push_s8(a, s8("layout(location = " str(DAS_CYCLE_T_UNIFORM_LOC) ") uniform uint u_cycle_t;\n\n"));
- #define X(type, id, pretty, fixed_tx) push_s8(a, s8("#define DAS_ID_" #type " " #id "\n"));
+ #define X(type, id, pretty, fixed_tx) "#define DAS_ID_" #type " " #id "\n"
+ stream_append_s8(&sb, s8(""
+ "layout(local_size_x = " str(DAS_LOCAL_SIZE_X) ", "
+ "local_size_y = " str(DAS_LOCAL_SIZE_Y) ", "
+ "local_size_z = " str(DAS_LOCAL_SIZE_Z) ") in;\n\n"
+ "layout(location = " str(DAS_VOXEL_OFFSET_UNIFORM_LOC) ") uniform ivec3 u_voxel_offset;\n"
+ "layout(location = " str(DAS_CYCLE_T_UNIFORM_LOC) ") uniform uint u_cycle_t;\n\n"
DAS_TYPES
+ ));
#undef X
} break;
case CS_DECODE_FLOAT:
case CS_DECODE_FLOAT_COMPLEX: {
- if (shader == CS_DECODE_FLOAT) push_s8(a, s8("#define INPUT_DATA_TYPE_FLOAT\n\n"));
- else push_s8(a, s8("#define INPUT_DATA_TYPE_FLOAT_COMPLEX\n\n"));
+ if (shader == CS_DECODE_FLOAT) stream_append_s8(&sb, s8("#define INPUT_DATA_TYPE_FLOAT\n\n"));
+ else stream_append_s8(&sb, s8("#define INPUT_DATA_TYPE_FLOAT_COMPLEX\n\n"));
} /* FALLTHROUGH */
case CS_DECODE: {
- #define X(type, id, pretty) push_s8(a, s8("#define DECODE_MODE_" #type " " #id "\n"));
+ #define X(type, id, pretty) stream_append_s8(&sb, s8("#define DECODE_MODE_" #type " " #id "\n"));
DECODE_TYPES
#undef X
} break;
case CS_MIN_MAX: {
- push_s8(a, s8("layout(location = " str(CS_MIN_MAX_MIPS_LEVEL_UNIFORM_LOC)
- ") uniform int u_mip_map;\n\n"));
+ stream_append_s8(&sb, s8("layout(location = " str(CS_MIN_MAX_MIPS_LEVEL_UNIFORM_LOC)
+ ") uniform int u_mip_map;\n\n"));
} break;
case CS_SUM: {
- push_s8(a, s8("layout(location = " str(CS_SUM_PRESCALE_UNIFORM_LOC)
- ") uniform float u_sum_prescale = 1.0;\n\n"));
+ stream_append_s8(&sb, s8("layout(location = " str(CS_SUM_PRESCALE_UNIFORM_LOC)
+ ") uniform float u_sum_prescale = 1.0;\n\n"));
} break;
default: break;
}
- s8 end = push_s8(a, s8("\n#line 1\n"));
- result.len = end.data + end.len - result.data;
- return result;
+ stream_append_s8(&sb, s8("\n#line 1\n"));
+ return arena_stream_commit(a, &sb);
}
static b32
@@ -458,10 +455,9 @@ reload_compute_shader(BeamformerCtx *ctx, s8 path, s8 extra, ComputeShaderReload
shader_text.len += header.len;
if (shader_text.data == header.data) {
- s8 info = {.data = tmp.beg};
- push_s8(&tmp, path);
- push_s8(&tmp, extra);
- info.len = tmp.beg - info.data;
+ Stream sb = arena_stream(tmp);
+ stream_append_s8s(&sb, path, extra);
+ s8 info = arena_stream_commit(&tmp, &sb);
u32 new_program = load_shader(&ctx->os, tmp, 1, (s8){0}, (s8){0}, shader_text,
info, csr->label);
if (new_program) {
@@ -471,12 +467,9 @@ reload_compute_shader(BeamformerCtx *ctx, s8 path, s8 extra, ComputeShaderReload
glBindBufferBase(GL_UNIFORM_BUFFER, 0, cs->shared_ubo);
}
} else {
- Stream buf = arena_stream(&tmp);
- stream_append_s8(&buf, s8("failed to load: "));
- stream_append_s8(&buf, path);
- stream_append_s8(&buf, extra);
- stream_append_byte(&buf, '\n');
- ctx->os.write_file(ctx->os.stderr, stream_to_s8(&buf));
+ Stream sb = arena_stream(tmp);
+ stream_append_s8s(&sb, s8("failed to load: "), path, extra, s8("\n"));
+ ctx->os.write_file(ctx->os.stderr, stream_to_s8(&sb));
}
return result;
diff --git a/build.c b/build.c
@@ -314,22 +314,21 @@ check_rebuild_self(Arena arena, i32 argc, char *argv[])
{
char *binary = shift(argv, argc);
if (needs_rebuild(binary, BUILD_DEPS)) {
- Stream name = stream_alloc(&arena, KB(1));
- stream_append_s8(&name, c_str_to_s8(binary));
- stream_append_s8(&name, s8(".old"));
- stream_append_byte(&name, 0);
+ Stream name_buffer = arena_stream(arena);
+ stream_append_s8s(&name_buffer, c_str_to_s8(binary), s8(".old"));
+ char *old_name = (char *)arena_stream_commit_zero(&arena, &name_buffer).data;
- if (!os_rename_file(binary, (char *)name.data))
- die("failed to move: %s -> %s\n", binary, (char *)name.data);
+ if (!os_rename_file(binary, old_name))
+ die("failed to move: %s -> %s\n", binary, old_name);
CommandList c = {0};
cmd_append(&arena, &c, BUILD_COMMAND(binary, __FILE__));
cmd_append(&arena, &c, "-O3", "-Wno-unused-function", (void *)0);
if (!run_synchronous(arena, &c)) {
- os_rename_file((char *)name.data, binary);
+ os_rename_file(old_name, binary);
die("failed to rebuild self\n");
}
- os_remove_file((char *)name.data);
+ os_remove_file(old_name);
c.count = 0;
cmd_append(&arena, &c, binary);
diff --git a/main_linux.c b/main_linux.c
@@ -43,9 +43,7 @@ dispatch_file_watch_events(OS *os, Arena arena)
for (u32 i = 0; i < dir->file_watch_count; i++) {
FileWatch *fw = dir->file_watches + i;
if (fw->hash == hash) {
- stream_append_s8(&path, dir->name);
- stream_append_byte(&path, '/');
- stream_append_s8(&path, file);
+ stream_append_s8s(&path, dir->name, s8("/"), file);
stream_append_byte(&path, 0);
stream_commit(&path, -1);
fw->callback(os, stream_to_s8(&path),
diff --git a/os_linux.c b/os_linux.c
@@ -26,9 +26,8 @@ os_get_module(char *name, Stream *e)
{
void *result = dlopen(name, RTLD_NOW|RTLD_LOCAL|RTLD_NOLOAD);
if (!result && e) {
- s8 errs[] = {s8("os_get_module(\""), c_str_to_s8(name), s8("\"): "),
- c_str_to_s8(dlerror()), s8("\n")};
- stream_append_s8_array(e, errs, ARRAY_COUNT(errs));
+ stream_append_s8s(e, s8("os_get_module(\""), c_str_to_s8(name), s8("\"): "),
+ c_str_to_s8(dlerror()), s8("\n"));
}
return result;
}
@@ -192,9 +191,8 @@ os_load_library(char *name, char *temp_name, Stream *e)
void *result = dlopen(name, RTLD_NOW|RTLD_LOCAL);
if (!result && e) {
- s8 errs[] = {s8("os_load_library(\""), c_str_to_s8(name), s8("\"): "),
- c_str_to_s8(dlerror()), s8("\n")};
- stream_append_s8_array(e, errs, ARRAY_COUNT(errs));
+ stream_append_s8s(e, s8("os_load_library(\""), c_str_to_s8(name), s8("\"): "),
+ c_str_to_s8(dlerror()), s8("\n"));
}
if (temp_name)
@@ -210,9 +208,8 @@ os_lookup_dynamic_symbol(void *h, char *name, Stream *e)
if (h) {
result = dlsym(h, name);
if (!result && e) {
- s8 errs[] = {s8("os_lookup_dynamic_symbol(\""), c_str_to_s8(name),
- s8("\"): "), c_str_to_s8(dlerror()), s8("\n")};
- stream_append_s8_array(e, errs, ARRAY_COUNT(errs));
+ stream_append_s8s(e, s8("os_lookup_dynamic_symbol(\""), c_str_to_s8(name),
+ s8("\"): "), c_str_to_s8(dlerror()), s8("\n"));
}
}
return result;
diff --git a/os_win32.c b/os_win32.c
@@ -126,8 +126,7 @@ os_get_module(char *name, Stream *e)
{
void *result = GetModuleHandleA(name);
if (!result && e) {
- s8 errs[] = {s8("os_get_module(\""), c_str_to_s8(name), s8("\"): ")};
- stream_append_s8_array(e, errs, ARRAY_COUNT(errs));
+ stream_append_s8s(e, s8("os_get_module(\""), c_str_to_s8(name), s8("\"): "));
stream_append_i64(e, GetLastError());
stream_append_byte(e, '\n');
}
@@ -269,8 +268,7 @@ os_load_library(char *name, char *temp_name, Stream *e)
void *result = LoadLibraryA(name);
if (!result && e) {
- s8 errs[] = {s8("os_load_library(\""), c_str_to_s8(name), s8("\"): ")};
- stream_append_s8_array(e, errs, ARRAY_COUNT(errs));
+ stream_append_s8s(e, s8("os_load_library(\""), c_str_to_s8(name), s8("\"): "));
stream_append_i64(e, GetLastError());
stream_append_byte(e, '\n');
}
@@ -288,8 +286,8 @@ os_lookup_dynamic_symbol(void *h, char *name, Stream *e)
if (h) {
result = GetProcAddress(h, name);
if (!result && e) {
- s8 errs[] = {s8("os_lookup_dynamic_symbol(\""), c_str_to_s8(name), s8("\"): ")};
- stream_append_s8_array(e, errs, ARRAY_COUNT(errs));
+ stream_append_s8s(e, s8("os_lookup_dynamic_symbol(\""), c_str_to_s8(name),
+ s8("\"): "));
stream_append_i64(e, GetLastError());
stream_append_byte(e, '\n');
}
diff --git a/static.c b/static.c
@@ -18,10 +18,10 @@ static void *debug_lib;
DEBUG_ENTRY_POINTS
#undef X
-static FILE_WATCH_CALLBACK_FN(debug_reload)
+function FILE_WATCH_CALLBACK_FN(debug_reload)
{
BeamformerInput *input = (BeamformerInput *)user_data;
- Stream err = arena_stream(&tmp);
+ Stream err = arena_stream(tmp);
/* NOTE(rnp): spin until compute thread finishes its work (we will probably
* never reload while compute is in progress but just incase). */
@@ -48,8 +48,7 @@ debug_init(OS *os, iptr input, Arena *arena)
os->add_file_watch(os, arena, s8(OS_DEBUG_LIB_NAME), debug_reload, input);
debug_reload(os, (s8){0}, input, *arena);
- Arena tmp = *arena;
- Stream err = arena_stream(&tmp);
+ Stream err = arena_stream(*arena);
void *rdoc = os_get_module(OS_RENDERDOC_SONAME, 0);
if (rdoc) {
renderdoc_get_api_fn *get_api = os_lookup_dynamic_symbol(rdoc, "RENDERDOC_GetAPI", &err);
@@ -114,9 +113,7 @@ get_gl_params(GLParams *gl, Stream *err)
/* NOTE(rnp): Microsoft Corporation - weird win32 thing (microsoft is just using mesa for the driver) */
case 'M': gl->vendor_id = GL_VENDOR_ARM; break;
default:
- stream_append_s8(err, s8("Unknown GL Vendor: "));
- stream_append_s8(err, c_str_to_s8(vendor));
- stream_append_byte(err, '\n');
+ stream_append_s8s(err, s8("Unknown GL Vendor: "), c_str_to_s8(vendor), s8("\n"));
os_fatal(stream_to_s8(err));
}
@@ -131,10 +128,10 @@ get_gl_params(GLParams *gl, Stream *err)
gl->version_minor = 5;
}
-static void
+function void
validate_gl_requirements(GLParams *gl, Arena a)
{
- Stream s = arena_stream(&a);
+ Stream s = arena_stream(a);
if (gl->max_ubo_size < sizeof(BeamformerParameters)) {
stream_append_s8(&s, s8("GPU must support UBOs of at least "));
@@ -160,9 +157,8 @@ dump_gl_params(GLParams *gl, Arena a, OS *os)
#undef X
max_width++;
- Stream s = arena_stream(&a);
- stream_append_s8(&s, s8("---- GL Parameters ----\n"));
- stream_append_s8(&s, vendor);
+ Stream s = arena_stream(a);
+ stream_append_s8s(&s, s8("---- GL Parameters ----\n"), vendor);
stream_pad(&s, ' ', max_width - vendor.len);
switch (gl->vendor_id) {
case GL_VENDOR_AMD: stream_append_s8(&s, s8("AMD\n")); break;
@@ -202,19 +198,17 @@ function FILE_WATCH_CALLBACK_FN(reload_render_shader)
"\tgl_Position = vec4(vertex_position, 0, 1);\n"
"}\n");
- Arena *a = &tmp;
- s8 header = {.data = a->beg};
- push_s8(a, s8("#version 460 core\n\n"));
- push_s8(a, s8("layout(location = 0) in vec2 fragment_texture_coordinate;\n"));
- push_s8(a, s8("layout(location = 0) out vec4 v_out_colour;\n\n"));
- push_s8(a, s8("layout(location = " str(FRAME_VIEW_RENDER_DYNAMIC_RANGE_LOC) ") uniform float u_db_cutoff = 60;\n"));
- push_s8(a, s8("layout(location = " str(FRAME_VIEW_RENDER_THRESHOLD_LOC) ") uniform float u_threshold = 40;\n"));
- push_s8(a, s8("layout(location = " str(FRAME_VIEW_RENDER_GAMMA_LOC) ") uniform float u_gamma = 1;\n"));
- push_s8(a, s8("layout(location = " str(FRAME_VIEW_RENDER_LOG_SCALE_LOC) ") uniform bool u_log_scale;\n"));
- push_s8(a, s8("\n#line 1\n"));
- header.len = a->beg - header.data;
-
- s8 fragment = os->read_whole_file(a, (c8 *)path.data);
+ s8 header = push_s8(&tmp, s8(""
+ "#version 460 core\n\n"
+ "layout(location = 0) in vec2 fragment_texture_coordinate;\n"
+ "layout(location = 0) out vec4 v_out_colour;\n\n"
+ "layout(location = " str(FRAME_VIEW_RENDER_DYNAMIC_RANGE_LOC) ") uniform float u_db_cutoff = 60;\n"
+ "layout(location = " str(FRAME_VIEW_RENDER_THRESHOLD_LOC) ") uniform float u_threshold = 40;\n"
+ "layout(location = " str(FRAME_VIEW_RENDER_GAMMA_LOC) ") uniform float u_gamma = 1;\n"
+ "layout(location = " str(FRAME_VIEW_RENDER_LOG_SCALE_LOC) ") uniform bool u_log_scale;\n"
+ "\n#line 1\n"));
+
+ s8 fragment = os->read_whole_file(&tmp, (c8 *)path.data);
fragment.data -= header.len;
fragment.len += header.len;
ASSERT(fragment.data == header.data);
@@ -248,7 +242,7 @@ static FILE_WATCH_CALLBACK_FN(load_cuda_lib)
CudaLib *cl = (CudaLib *)user_data;
b32 result = os_file_exists((c8 *)path.data);
if (result) {
- Stream err = arena_stream(&tmp);
+ Stream err = arena_stream(tmp);
stream_append_s8(&err, s8("loading CUDA lib: " OS_CUDA_LIB_NAME "\n"));
os_unload_library(cl->lib);
diff --git a/ui.c b/ui.c
@@ -654,11 +654,9 @@ function TableCell
table_variable_cell(Arena *a, Variable *var)
{
TableCell result = {.var = var, .kind = TCK_VARIABLE};
- Arena tmp = *a;
- Stream text = arena_stream(&tmp);
+ Stream text = arena_stream(*a);
stream_append_variable(&text, var);
- result.text = stream_to_s8(&text);
- arena_commit(a, text.widx);
+ result.text = arena_stream_commit(a, &text);
return result;
}
@@ -1487,8 +1485,9 @@ draw_title_bar(BeamformerUI *ui, Arena arena, Variable *ui_view, Rect r, v2 mous
s8 title = ui_view->name;
if (view->flags & UI_VIEW_CUSTOM_TEXT) {
- Stream buf = arena_stream(&arena);
- title = push_custom_view_title(&buf, ui_view->u.group.first);
+ Stream buf = arena_stream(arena);
+ push_custom_view_title(&buf, ui_view->u.group.first);
+ title = arena_stream_commit(&arena, &buf);
}
Rect result, title_rect;
@@ -1539,7 +1538,7 @@ draw_title_bar(BeamformerUI *ui, Arena arena, Variable *ui_view, Rect r, v2 mous
/* TODO(rnp): once this has more callers decide if it would be better for this to take
* an orientation rather than force CCW/right-handed */
function void
-draw_ruler(BeamformerUI *ui, Stream *buf, v2 start_point, v2 end_point,
+draw_ruler(BeamformerUI *ui, Arena arena, v2 start_point, v2 end_point,
f32 start_value, f32 end_value, f32 *markers, u32 marker_count,
u32 segments, s8 suffix, v4 marker_colour, v4 txt_colour)
{
@@ -1556,6 +1555,7 @@ draw_ruler(BeamformerUI *ui, Stream *buf, v2 start_point, v2 end_point,
f32 value_inc = (end_value - start_value) / segments;
f32 value = start_value;
+ Stream buf = arena_stream(arena);
v2 sp = {0}, ep = {.y = RULER_TICK_LENGTH};
v2 tp = {.x = ui->small_font.baseSize / 2, .y = ep.y + RULER_TEXT_PAD};
TextSpec text_spec = {.font = &ui->small_font, .rotation = 90, .colour = txt_colour, .flags = TF_ROTATED};
@@ -1563,11 +1563,11 @@ draw_ruler(BeamformerUI *ui, Stream *buf, v2 start_point, v2 end_point,
for (u32 j = 0; j <= segments; j++) {
DrawLineEx(sp.rl, ep.rl, 3, rl_txt_colour);
- stream_reset(buf, 0);
- if (draw_plus && value > 0) stream_append_byte(buf, '+');
- stream_append_f64(buf, value, 10);
- stream_append_s8(buf, suffix);
- draw_text(stream_to_s8(buf), tp, &text_spec);
+ stream_reset(&buf, 0);
+ if (draw_plus && value > 0) stream_append_byte(&buf, '+');
+ stream_append_f64(&buf, value, 10);
+ stream_append_s8(&buf, suffix);
+ draw_text(stream_to_s8(&buf), tp, &text_spec);
value += value_inc;
sp.x += inc;
@@ -1589,7 +1589,7 @@ draw_ruler(BeamformerUI *ui, Stream *buf, v2 start_point, v2 end_point,
}
function void
-do_scale_bar(BeamformerUI *ui, Stream *buf, Variable *scale_bar, v2 mouse, Rect draw_rect,
+do_scale_bar(BeamformerUI *ui, Arena arena, Variable *scale_bar, v2 mouse, Rect draw_rect,
f32 start_value, f32 end_value, s8 suffix)
{
ASSERT(scale_bar->type == VT_SCALE_BAR);
@@ -1628,11 +1628,11 @@ do_scale_bar(BeamformerUI *ui, Stream *buf, Variable *scale_bar, v2 mouse, Rect
if (hover_var(ui, mouse, tick_rect, scale_bar))
marker_count = 2;
- draw_ruler(ui, buf, start_pos, end_pos, start_value, end_value, markers, marker_count,
+ draw_ruler(ui, arena, start_pos, end_pos, start_value, end_value, markers, marker_count,
tick_count, suffix, RULER_COLOUR, lerp_v4(FG_COLOUR, HOVERED_COLOUR, scale_bar->hover_t));
}
-static v2
+function v2
draw_radio_button(BeamformerUI *ui, Variable *var, v2 at, v2 mouse, v4 base_colour, f32 size)
{
ASSERT(var->type == VT_B32 || var->type == VT_BEAMFORMER_VARIABLE);
@@ -1665,9 +1665,10 @@ draw_variable(BeamformerUI *ui, Arena arena, Variable *var, v2 at, v2 mouse, v4
if (var->flags & V_RADIO_BUTTON) {
result = draw_radio_button(ui, var, at, mouse, base_colour, text_spec.font->baseSize);
} else {
- Stream buf = arena_stream(&arena);
+ Stream buf = arena_stream(arena);
stream_append_variable(&buf, var);
- result = measure_text(*text_spec.font, stream_to_s8(&buf));
+ s8 text = arena_stream_commit(&arena, &buf);
+ result = measure_text(*text_spec.font, text);
if (var->flags & V_INPUT) {
Rect text_rect = {.pos = at, .size = result};
@@ -1677,7 +1678,7 @@ draw_variable(BeamformerUI *ui, Arena arena, Variable *var, v2 at, v2 mouse, v4
text_spec.colour = lerp_v4(base_colour, HOVERED_COLOUR, var->hover_t);
}
- draw_text(stream_to_s8(&buf), at, &text_spec);
+ draw_text(text, at, &text_spec);
}
return result;
}
@@ -1823,9 +1824,7 @@ draw_beamformer_frame_view(BeamformerUI *ui, Arena a, Variable *var, Rect displa
start_pos.y += vr.size.y;
if (vr.size.w > 0 && view->lateral_scale_bar_active->u.b32) {
- Arena tmp = a;
- Stream buf = arena_stream(&tmp);
- do_scale_bar(ui, &buf, &view->lateral_scale_bar, mouse,
+ do_scale_bar(ui, a, &view->lateral_scale_bar, mouse,
(Rect){.pos = start_pos, .size = vr.size},
*view->lateral_scale_bar.u.scale_bar.min_value * 1e3,
*view->lateral_scale_bar.u.scale_bar.max_value * 1e3, s8(" mm"));
@@ -1835,9 +1834,7 @@ draw_beamformer_frame_view(BeamformerUI *ui, Arena a, Variable *var, Rect displa
start_pos.x += vr.size.x;
if (vr.size.h > 0 && view->axial_scale_bar_active->u.b32) {
- Arena tmp = a;
- Stream buf = arena_stream(&tmp);
- do_scale_bar(ui, &buf, &view->axial_scale_bar, mouse,
+ do_scale_bar(ui, a, &view->axial_scale_bar, mouse,
(Rect){.pos = start_pos, .size = vr.size},
*view->axial_scale_bar.u.scale_bar.max_value * 1e3,
*view->axial_scale_bar.u.scale_bar.min_value * 1e3, s8(" mm"));
@@ -1855,8 +1852,7 @@ draw_beamformer_frame_view(BeamformerUI *ui, Arena a, Variable *var, Rect displa
v2 world = screen_point_to_world_2d(mouse, vr.pos, add_v2(vr.pos, vr.size),
XZ(view->min_coordinate),
XZ(view->max_coordinate));
- Arena tmp = a;
- Stream buf = arena_stream(&tmp);
+ Stream buf = arena_stream(a);
stream_append_v2(&buf, scale_v2(world, 1e3));
text_spec.limits.size.w -= 4;
@@ -1871,8 +1867,7 @@ draw_beamformer_frame_view(BeamformerUI *ui, Arena a, Variable *var, Rect displa
}
{
- Arena tmp = a;
- Stream buf = arena_stream(&tmp);
+ Stream buf = arena_stream(a);
s8 shader = push_das_shader_id(&buf, frame->das_shader_id, frame->compound_count);
text_spec.font = &ui->font;
text_spec.limits.size.w -= 16;
@@ -1910,8 +1905,7 @@ draw_beamformer_frame_view(BeamformerUI *ui, Arena a, Variable *var, Rect displa
DrawLineEx(end_p.rl, start_p.rl, 2, rl_colour);
DrawCircleV(end_p.rl, 3, rl_colour);
- Arena tmp = a;
- Stream buf = arena_stream(&tmp);
+ Stream buf = arena_stream(a);
stream_append_f64(&buf, 1e3 * magnitude_v2(m_delta), 100);
stream_append_s8(&buf, s8(" mm"));
@@ -1974,24 +1968,26 @@ draw_compute_stats_view(BeamformerCtx *ctx, Arena arena, ComputeShaderStats *sta
u32 stages = ctx->shared_memory->compute_stages_count;
TextSpec text_spec = {.font = &ui->font, .colour = FG_COLOUR, .flags = TF_LIMITED};
- Stream sb = stream_alloc(&arena, 256);
Table *table = table_new(&arena, stages + 1, 3, (TextAlignment []){TA_LEFT, TA_LEFT, TA_LEFT});
for (u32 i = 0; i < stages; i++) {
- u32 index = ctx->shared_memory->compute_stages[i];
+ TableCell *cells = table_push_row(table, &arena, TRK_CELLS)->data;
+
+ Stream sb = arena_stream(arena);
+ u32 index = ctx->shared_memory->compute_stages[i];
compute_time_sum += stats->times[index];
stream_append_f64_e(&sb, stats->times[index]);
- TableCell *cells = table_push_row(table, &arena, TRK_CELLS)->data;
cells[0].text = labels[index];
- cells[1].text = stream_chop_head(&sb);
+ cells[1].text = arena_stream_commit(&arena, &sb);
cells[2].text = s8("[s]");
}
- stream_append_f64_e(&sb, compute_time_sum);
TableCell *cells = table_push_row(table, &arena, TRK_CELLS)->data;
+ Stream sb = arena_stream(arena);
+ stream_append_f64_e(&sb, compute_time_sum);
cells[0].text = s8("Compute Total:");
- cells[1].text = stream_chop_head(&sb);
+ cells[1].text = arena_stream_commit(&arena, &sb);
cells[2].text = s8("[s]");
table_extent(table, arena, text_spec.font);
@@ -2042,8 +2038,7 @@ draw_ui_view_listing(BeamformerUI *ui, Variable *group, Arena arena, Rect r, v2
/* NOTE(rnp): assume the suffix is the same for all elements */
if (v) cells[2].text = v->u.beamformer_variable.suffix;
- Arena tmp = arena;
- Stream sb = arena_stream(&tmp);
+ Stream sb = arena_stream(arena);
switch (g->type) {
case VG_LIST: break;
case VG_V2:
@@ -2057,9 +2052,8 @@ draw_ui_view_listing(BeamformerUI *ui, Variable *group, Arena arena, Rect r, v2
stream_append_s8(&sb, s8("}"));
} break;
}
- arena_commit(&arena, sb.widx);
cells[1].kind = TCK_VARIABLE_GROUP;
- cells[1].text = stream_to_s8(&sb);
+ cells[1].text = arena_stream_commit(&arena, &sb);
cells[1].var = var;
var = var->next;
diff --git a/util.c b/util.c
@@ -204,17 +204,7 @@ utf16_encode(u16 *out, u32 cp)
return result;
}
-static Stream
-arena_stream(Arena *a)
-{
- Stream result = {0};
- result.data = a->beg;
- result.cap = a->end - a->beg;
- a->beg = a->end;
- return result;
-}
-
-static Stream
+function Stream
stream_alloc(Arena *a, iz cap)
{
Stream result = {.cap = cap};
@@ -222,20 +212,11 @@ stream_alloc(Arena *a, iz cap)
return result;
}
-static s8
-stream_to_s8(Stream *s)
-{
- s8 result = {.len = s->widx, .data = s->data};
- return result;
-}
-
function s8
-stream_chop_head(Stream *s)
+stream_to_s8(Stream *s)
{
- s8 result = stream_to_s8(s);
- s->cap -= s->widx;
- s->data += s->widx;
- s->widx = 0;
+ s8 result = {0};
+ if (!s->errors) result = (s8){.len = s->widx, .data = s->data};
return result;
}
@@ -283,8 +264,10 @@ stream_append_s8(Stream *s, s8 str)
stream_append(s, str.data, str.len);
}
-static void
-stream_append_s8_array(Stream *s, s8 *strs, iz count)
+#define stream_append_s8s(s, ...) stream_append_s8s_(s, (s8 []){__VA_ARGS__}, \
+ sizeof((s8 []){__VA_ARGS__}) / sizeof(s8))
+function void
+stream_append_s8s_(Stream *s, s8 *strs, iz count)
{
for (iz i = 0; i < count; i++)
stream_append(s, strs[i].data, strs[i].len);
@@ -400,8 +383,37 @@ stream_append_v2(Stream *s, v2 v)
stream_append_byte(s, '}');
}
+function Stream
+arena_stream(Arena a)
+{
+ Stream result = {0};
+ result.data = a.beg;
+ result.cap = a.end - a.beg;
+ return result;
+}
+
+function s8
+arena_stream_commit(Arena *a, Stream *s)
+{
+ ASSERT(s->data == a->beg);
+ s8 result = stream_to_s8(s);
+ arena_commit(a, result.len);
+ return result;
+}
+
+function s8
+arena_stream_commit_zero(Arena *a, Stream *s)
+{
+ b32 error = s->errors || s->widx == s->cap;
+ if (!error)
+ s->data[s->widx] = 0;
+ s8 result = stream_to_s8(s);
+ arena_commit(a, result.len + 1);
+ return result;
+}
+
/* NOTE(rnp): FNV-1a hash */
-static u64
+function u64
s8_hash(s8 v)
{
u64 h = 0x3243f6a8885a308d; /* digits of pi */
diff --git a/util_gl.c b/util_gl.c
@@ -10,9 +10,8 @@ compile_shader(OS *os, Arena a, u32 type, s8 shader, s8 name)
glGetShaderiv(sid, GL_COMPILE_STATUS, &res);
if (res == GL_FALSE) {
- Stream buf = arena_stream(&a);
- stream_append_s8(&buf, name);
- stream_append_s8(&buf, s8(": failed to compile\n"));
+ Stream buf = arena_stream(a);
+ stream_append_s8s(&buf, name, s8(": failed to compile\n"));
i32 len = 0, out_len = 0;
glGetShaderiv(sid, GL_INFO_LOG_LENGTH, &len);
@@ -38,7 +37,7 @@ link_program(OS *os, Arena a, u32 *shader_ids, u32 shader_id_count)
glGetProgramiv(result, GL_LINK_STATUS, &success);
if (success == GL_FALSE) {
i32 len = 0;
- Stream buf = arena_stream(&a);
+ Stream buf = arena_stream(a);
stream_append_s8(&buf, s8("shader link error: "));
glGetProgramInfoLog(result, buf.cap - buf.widx, &len, (c8 *)(buf.data + buf.widx));
stream_reset(&buf, len);
@@ -67,10 +66,8 @@ load_shader(OS *os, Arena arena, b32 compute, s8 vs_text, s8 fs_text, s8 cs_text
}
if (result) {
- Stream buf = arena_stream(&arena);
- stream_append_s8(&buf, s8("loaded: "));
- stream_append_s8(&buf, info_name);
- stream_append_byte(&buf, '\n');
+ Stream buf = arena_stream(arena);
+ stream_append_s8s(&buf, s8("loaded: "), info_name, s8("\n"));
os->write_file(os->stderr, stream_to_s8(&buf));
LABEL_GL_OBJECT(GL_PROGRAM, result, label);
}