Commit: d869fa9a2ae8f730205133bda65ae2ce8261e21f
Parent: 6ec7908d14402bbfa240372c5ee79f8eb2be67f2
Author: Randy Palamar
Date: Sat, 21 Jun 2025 16:21:58 -0600
core: store large backlog of compute timings
Diffstat:
M | beamformer.c | | | 129 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------- |
M | beamformer.h | | | 52 | ++++++++++++++++++++++++++++++++++++++++++---------- |
M | opengl.h | | | 3 | ++- |
M | static.c | | | 4 | +++- |
M | ui.c | | | 67 | ++++++++++++++++++++++++++++++------------------------------------- |
M | util.h | | | 4 | ++++ |
6 files changed, 182 insertions(+), 77 deletions(-)
diff --git a/beamformer.c b/beamformer.c
@@ -79,8 +79,7 @@ frame_next(ComputeFrameIterator *bfi)
}
function void
-alloc_beamform_frame(GLParams *gp, BeamformFrame *out, ComputeShaderStats *out_stats,
- uv3 out_dim, s8 name, Arena arena)
+alloc_beamform_frame(GLParams *gp, BeamformFrame *out, uv3 out_dim, s8 name, Arena arena)
{
out->dim.x = MAX(1, out_dim.x);
out->dim.y = MAX(1, out_dim.y);
@@ -107,11 +106,6 @@ alloc_beamform_frame(GLParams *gp, BeamformFrame *out, ComputeShaderStats *out_s
glCreateTextures(GL_TEXTURE_3D, 1, &out->texture);
glTextureStorage3D(out->texture, out->mips, GL_RG32F, out->dim.x, out->dim.y, out->dim.z);
LABEL_GL_OBJECT(GL_TEXTURE, out->texture, stream_to_s8(&label));
-
- if (out_stats) {
- glDeleteQueries(ARRAY_COUNT(out_stats->timer_ids), out_stats->timer_ids);
- glCreateQueries(GL_TIME_ELAPSED, ARRAY_COUNT(out_stats->timer_ids), out_stats->timer_ids);
- }
}
function void
@@ -159,6 +153,13 @@ alloc_shader_storage(BeamformerCtx *ctx, u32 rf_raw_size, Arena a)
}
}
+function void
+push_compute_timing_info(ComputeTimingTable *t, ComputeTimingInfo info)
+{
+ u32 index = atomic_add_u32(&t->write_index, 1) % countof(t->buffer);
+ t->buffer[index] = info;
+}
+
function b32
fill_frame_compute_work(BeamformerCtx *ctx, BeamformWork *work, ImagePlaneTag plane)
{
@@ -565,7 +566,14 @@ complete_queue(BeamformerCtx *ctx, BeamformWorkQueue *q, Arena arena, iptr gl_co
alloc_shader_storage(ctx, uc->size, arena);
}
buffer = cs->raw_data_ssbo;
- } break;
+
+ ComputeTimingInfo info = {0};
+ info.kind = ComputeTimingInfoKind_RF_Data;
+ /* TODO(rnp): this could stall. what should we do about it? */
+ glGetQueryObjectui64v(cs->rf_data_timestamp_query, GL_QUERY_RESULT, &info.timer_count);
+ glQueryCounter(cs->rf_data_timestamp_query, GL_TIMESTAMP);
+ push_compute_timing_info(ctx->compute_timing_table, info);
+ }break;
InvalidDefaultCase;
}
@@ -594,6 +602,9 @@ complete_queue(BeamformerCtx *ctx, BeamformWorkQueue *q, Arena arena, iptr gl_co
sm->locks, work->lock);
}
+ push_compute_timing_info(ctx->compute_timing_table,
+ (ComputeTimingInfo){.kind = ComputeTimingInfoKind_ComputeFrameBegin});
+
i32 mask = 1 << (BeamformerSharedMemoryLockKind_Parameters - 1);
if (sm->dirty_regions & mask) {
glNamedBufferSubData(cs->shared_ubo, 0, sizeof(sm->parameters), &sm->parameters);
@@ -606,16 +617,13 @@ complete_queue(BeamformerCtx *ctx, BeamformWorkQueue *q, Arena arena, iptr gl_co
BeamformComputeFrame *frame = work->frame;
uv3 try_dim = make_valid_test_dim(bp->output_points);
if (!uv3_equal(try_dim, frame->frame.dim))
- alloc_beamform_frame(&ctx->gl, &frame->frame, &frame->stats, try_dim,
- s8("Beamformed_Data"), arena);
+ alloc_beamform_frame(&ctx->gl, &frame->frame, try_dim, s8("Beamformed_Data"), arena);
if (bp->output_points[3] > 1) {
if (!uv3_equal(try_dim, ctx->averaged_frames[0].frame.dim)) {
alloc_beamform_frame(&ctx->gl, &ctx->averaged_frames[0].frame,
- &ctx->averaged_frames[0].stats,
try_dim, s8("Averaged Frame"), arena);
alloc_beamform_frame(&ctx->gl, &ctx->averaged_frames[1].frame,
- &ctx->averaged_frames[1].stats,
try_dim, s8("Averaged Frame"), arena);
}
}
@@ -631,8 +639,7 @@ complete_queue(BeamformerCtx *ctx, BeamformWorkQueue *q, Arena arena, iptr gl_co
ComputeShaderKind *stages = sm->compute_stages;
for (u32 i = 0; i < stage_count; i++) {
did_sum_shader |= stages[i] == ComputeShaderKind_Sum;
- frame->stats.timer_active[stages[i]] = 1;
- glBeginQuery(GL_TIME_ELAPSED, frame->stats.timer_ids[stages[i]]);
+ glBeginQuery(GL_TIME_ELAPSED, cs->shader_timer_ids[i]);
do_compute_shader(ctx, arena, frame, (ShaderKind)stages[i]);
glEndQuery(GL_TIME_ELAPSED);
}
@@ -640,29 +647,26 @@ complete_queue(BeamformerCtx *ctx, BeamformWorkQueue *q, Arena arena, iptr gl_co
glFinish();
cs->processing_progress = 1;
- for (u32 i = 0; i < ARRAY_COUNT(frame->stats.timer_ids); i++) {
- u64 ns = 0;
- if (frame->stats.timer_active[i]) {
- glGetQueryObjectui64v(frame->stats.timer_ids[i],
- GL_QUERY_RESULT, &ns);
- frame->stats.timer_active[i] = 0;
- }
- frame->stats.times[i] = (f32)ns / 1e9;
+ for (u32 i = 0; i < stage_count; i++) {
+ ComputeTimingInfo info = {0};
+ info.kind = ComputeTimingInfoKind_Shader;
+ info.shader = (ShaderKind)stages[i];
+ glGetQueryObjectui64v(cs->shader_timer_ids[i], GL_QUERY_RESULT, &info.timer_count);
+ push_compute_timing_info(ctx->compute_timing_table, info);
}
if (did_sum_shader) {
- u32 aframe_index = (ctx->averaged_frame_index %
- ARRAY_COUNT(ctx->averaged_frames));
+ u32 aframe_index = (ctx->averaged_frame_index % countof(ctx->averaged_frames));
ctx->averaged_frames[aframe_index].image_plane_tag = frame->image_plane_tag;
ctx->averaged_frames[aframe_index].ready_to_present = 1;
- /* TODO(rnp): not really sure what to do here */
- mem_copy(&ctx->averaged_frames[aframe_index].stats.times,
- &frame->stats.times, sizeof(frame->stats.times));
atomic_add_u32(&ctx->averaged_frame_index, 1);
}
frame->ready_to_present = 1;
cs->processing_compute = 0;
+ push_compute_timing_info(ctx->compute_timing_table,
+ (ComputeTimingInfo){.kind = ComputeTimingInfoKind_ComputeFrameEnd});
+
end_renderdoc_capture(gl_context);
} break;
case BW_SAVE_FRAME: {
@@ -684,6 +688,67 @@ complete_queue(BeamformerCtx *ctx, BeamformWorkQueue *q, Arena arena, iptr gl_co
}
}
+function void
+coalesce_timing_table(ComputeTimingTable *t, ComputeShaderStats *stats)
+{
+ /* TODO(rnp): we do not currently do anything to handle the potential for a half written
+ * info item. this could result in garbage entries but they shouldn't really matter */
+
+ u32 target = atomic_load_u32(&t->write_index);
+ u32 stats_index = (stats->latest_frame_index + 1) % countof(stats->times[0]);
+
+ static_assert(ShaderKind_Count + 1 <= 32, "timing coalescence bitfield test");
+ u32 seen_info_test = 0;
+
+ while (t->read_index != target) {
+ ComputeTimingInfo info = t->buffer[t->read_index++];
+ switch (info.kind) {
+ case ComputeTimingInfoKind_ComputeFrameBegin:{
+ assert(t->compute_frame_active == 0);
+ t->compute_frame_active = 1;
+ /* NOTE(rnp): allow multiple instances of same shader to accumulate */
+ for EachEnumValue(ShaderKind, shader)
+ stats->times[shader][stats_index] = 0;
+ }break;
+ case ComputeTimingInfoKind_ComputeFrameEnd:{
+ assert(t->compute_frame_active == 1);
+ t->compute_frame_active = 0;
+ stats->latest_frame_index = stats_index;
+ stats_index = (stats_index + 1) % countof(stats->times[0]);
+ }break;
+ case ComputeTimingInfoKind_Shader:{
+ stats->times[info.shader][stats_index] += (f32)info.timer_count / 1.0e9;
+ seen_info_test |= (1 << info.shader);
+ }break;
+ case ComputeTimingInfoKind_RF_Data:{
+ stats->latest_rf_index = (stats->latest_rf_index + 1) % countof(stats->rf_time_deltas);
+ f32 delta = (f32)(info.timer_count - stats->last_rf_timer_count) / 1.0e9;
+ stats->rf_time_deltas[stats->latest_rf_index] = delta;
+ stats->last_rf_timer_count = info.timer_count;
+ seen_info_test |= (1 << ShaderKind_Count);
+ }break;
+ }
+ }
+
+ if (seen_info_test) {
+ for EachEnumValue(ShaderKind, shader) {
+ if (seen_info_test & (1 << shader)) {
+ f32 sum = 0;
+ for EachElement(stats->times[shader], i)
+ sum += stats->times[shader][i];
+ stats->average_times[shader] = sum / countof(stats->times[shader]);
+ }
+ }
+
+ if (seen_info_test & (1 << ShaderKind_Count)) {
+ f32 sum = 0;
+ for EachElement(stats->rf_time_deltas, i)
+ sum += stats->rf_time_deltas[i];
+ stats->rf_time_delta_average = sum / countof(stats->rf_time_deltas);
+ }
+ }
+}
+
DEBUG_EXPORT BEAMFORMER_COMPUTE_SETUP_FN(beamformer_compute_setup)
{
BeamformerCtx *ctx = (BeamformerCtx *)user_context;
@@ -704,6 +769,12 @@ DEBUG_EXPORT BEAMFORMER_COMPUTE_SETUP_FN(beamformer_compute_setup)
LABEL_GL_OBJECT(GL_TEXTURE, cs->focal_vectors_texture, s8("Focal_Vectors"));
LABEL_GL_OBJECT(GL_TEXTURE, cs->sparse_elements_texture, s8("Sparse_Elements"));
LABEL_GL_OBJECT(GL_BUFFER, cs->shared_ubo, s8("Beamformer_Parameters"));
+
+ glCreateQueries(GL_TIME_ELAPSED, countof(cs->shader_timer_ids), cs->shader_timer_ids);
+ glCreateQueries(GL_TIMESTAMP, 1, &cs->rf_data_timestamp_query);
+
+ /* NOTE(rnp): start this here so we don't have to worry about it being started or not */
+ glQueryCounter(cs->rf_data_timestamp_query, GL_TIMESTAMP);
}
DEBUG_EXPORT BEAMFORMER_COMPLETE_COMPUTE_FN(beamformer_complete_compute)
@@ -725,6 +796,8 @@ DEBUG_EXPORT BEAMFORMER_FRAME_STEP_FN(beamformer_frame_step)
ctx->window_size.w = GetScreenWidth();
}
+ coalesce_timing_table(ctx->compute_timing_table, ctx->compute_shader_stats);
+
if (input->executable_reloaded) {
ui_init(ctx, ctx->ui_backing_store);
DEBUG_DECL(start_frame_capture = ctx->os.start_frame_capture);
@@ -784,7 +857,7 @@ DEBUG_EXPORT BEAMFORMER_FRAME_STEP_FN(beamformer_frame_step)
}
draw_ui(ctx, input, frame_to_draw->ready_to_present? &frame_to_draw->frame : 0,
- frame_to_draw->image_plane_tag, &frame_to_draw->stats);
+ frame_to_draw->image_plane_tag);
ctx->frame_view_render_context.updated = 0;
diff --git a/beamformer.h b/beamformer.h
@@ -95,6 +95,10 @@ typedef struct {
f32 processing_progress;
b32 processing_compute;
+ u32 rf_data_timestamp_query;
+
+ u32 shader_timer_ids[MAX_COMPUTE_SHADER_STAGES];
+
uv4 dec_data_dim;
u32 rf_raw_size;
} ComputeShaderCtx;
@@ -115,14 +119,40 @@ typedef enum {
} ShaderKind;
typedef struct {
- /* TODO(rnp): there is assumption here that each shader will occur only once
- * per compute. add an insertion index and change these to hold the max number
- * of executed compute stages */
- u32 timer_ids[ComputeShaderKind_Count];
- f32 times[ComputeShaderKind_Count];
- b32 timer_active[ComputeShaderKind_Count];
+ f32 times[ShaderKind_Count][32];
+ f32 average_times[ShaderKind_Count];
+
+ u64 last_rf_timer_count;
+ f32 rf_time_deltas[32];
+ f32 rf_time_delta_average;
+
+ u32 latest_frame_index;
+ u32 latest_rf_index;
} ComputeShaderStats;
+/* TODO(rnp): maybe this also gets used for CPU timing info as well */
+typedef enum {
+ ComputeTimingInfoKind_ComputeFrameBegin,
+ ComputeTimingInfoKind_ComputeFrameEnd,
+ ComputeTimingInfoKind_Shader,
+ ComputeTimingInfoKind_RF_Data,
+} ComputeTimingInfoKind;
+
+typedef struct {
+ u64 timer_count;
+ ComputeTimingInfoKind kind;
+ union {
+ ShaderKind shader;
+ };
+} ComputeTimingInfo;
+
+typedef struct {
+ u32 write_index;
+ u32 read_index;
+ b32 compute_frame_active;
+ ComputeTimingInfo buffer[4096];
+} ComputeTimingTable;
+
typedef struct BeamformFrame {
uv3 dim;
u32 texture;
@@ -141,11 +171,10 @@ typedef struct BeamformFrame {
} BeamformFrame;
struct BeamformComputeFrame {
- BeamformFrame frame;
- ComputeShaderStats stats;
+ BeamformFrame frame;
ImagePlaneTag image_plane_tag;
- b32 in_flight;
- b32 ready_to_present;
+ b32 in_flight;
+ b32 ready_to_present;
};
#define GL_PARAMETERS \
@@ -199,6 +228,9 @@ typedef struct {
BeamformWorkQueue *beamform_work_queue;
+ ComputeShaderStats *compute_shader_stats;
+ ComputeTimingTable *compute_timing_table;
+
SharedMemoryRegion shared_memory;
} BeamformerCtx;
diff --git a/opengl.h b/opengl.h
@@ -50,6 +50,7 @@
#define GL_FRAMEBUFFER 0x8D40
#define GL_RENDERBUFFER 0x8D41
#define GL_RED_INTEGER 0x8D94
+#define GL_TIMESTAMP 0x8E28
#define GL_SHADER_STORAGE_BUFFER 0x90D2
#define GL_MAX_SHADER_STORAGE_BLOCK_SIZE 0x90DE
#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111
@@ -86,7 +87,6 @@ typedef uint64_t GLuint64;
X(glDebugMessageCallback, void, (void (*)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *user), void *user)) \
X(glDeleteBuffers, void, (GLsizei n, const GLuint *buffers)) \
X(glDeleteProgram, void, (GLuint program)) \
- X(glDeleteQueries, void, (GLsizei n, const GLuint *ids)) \
X(glDeleteShader, void, (GLuint shader)) \
X(glDispatchCompute, void, (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z)) \
X(glEndQuery, void, (GLenum target)) \
@@ -113,6 +113,7 @@ typedef uint64_t GLuint64;
X(glProgramUniform3iv, void, (GLuint program, GLint location, GLsizei count, const GLint *value)) \
X(glProgramUniform4fv, void, (GLuint program, GLint location, GLsizei count, const GLfloat *value)) \
X(glProgramUniformMatrix4fv, void, (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)) \
+ X(glQueryCounter, void, (GLuint id, GLenum target)) \
X(glShaderSource, void, (GLuint shader, GLsizei count, const GLchar **strings, const GLint *lengths)) \
X(glTextureParameteri, void, (GLuint texture, GLenum pname, GLint param)) \
X(glTextureParameterfv, void, (GLuint texture, GLenum pname, const GLfloat *param)) \
diff --git a/static.c b/static.c
@@ -277,7 +277,9 @@ setup_beamformer(BeamformerCtx *ctx, BeamformerInput *input, Arena *memory)
glfwMakeContextCurrent(raylib_window_handle);
- ctx->beamform_work_queue = push_struct(memory, BeamformWorkQueue);
+ 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->shared_memory = os_create_shared_memory_area(memory, OS_SHARED_MEMORY_NAME,
BeamformerSharedMemoryLockKind_Count,
diff --git a/ui.c b/ui.c
@@ -136,7 +136,6 @@ typedef enum {
VT_BEAMFORMER_VARIABLE,
VT_BEAMFORMER_FRAME_VIEW,
VT_COMPUTE_STATS_VIEW,
- VT_COMPUTE_LATEST_STATS_VIEW,
VT_COMPUTE_PROGRESS_BAR,
VT_SCALE_BAR,
VT_UI_BUTTON,
@@ -221,7 +220,6 @@ struct Variable {
void *generic;
BeamformerVariable beamformer_variable;
ComputeProgressBar compute_progress_bar;
- ComputeStatsView compute_stats_view;
RegionSplit region_split;
ScaleBar scale_bar;
UIButtonID button;
@@ -331,8 +329,7 @@ struct BeamformerUI {
v2_sll *scale_bar_savepoint_freelist;
- BeamformFrame *latest_plane[IPT_LAST + 1];
- ComputeShaderStats *latest_compute_stats;
+ BeamformFrame *latest_plane[IPT_LAST + 1];
BeamformerUIParameters params;
b32 flush_params;
@@ -1196,7 +1193,7 @@ ui_copy_frame(BeamformerUI *ui, Variable *view, RegionSplitDirection direction)
mem_copy(bv->frame, old->frame, sizeof(*bv->frame));
bv->frame->texture = 0;
bv->frame->next = 0;
- alloc_beamform_frame(0, bv->frame, 0, old->frame->dim, s8("Frame Copy: "), ui->arena);
+ alloc_beamform_frame(0, bv->frame, old->frame->dim, s8("Frame Copy: "), ui->arena);
glCopyImageSubData(old->frame->texture, GL_TEXTURE_3D, 0, 0, 0, 0,
bv->frame->texture, GL_TEXTURE_3D, 0, 0, 0, 0,
@@ -1321,13 +1318,8 @@ function s8
push_custom_view_title(Stream *s, Variable *var)
{
switch (var->type) {
- case VT_COMPUTE_STATS_VIEW:
- case VT_COMPUTE_LATEST_STATS_VIEW: {
- stream_append_s8(s, s8("Compute Stats"));
- if (var->type == VT_COMPUTE_LATEST_STATS_VIEW)
- stream_append_s8(s, s8(": Live"));
- } break;
- case VT_COMPUTE_PROGRESS_BAR: {
+ case VT_COMPUTE_STATS_VIEW:{ stream_append_s8(s, s8("Compute Stats (Average)")); } break;
+ case VT_COMPUTE_PROGRESS_BAR:{
stream_append_s8(s, s8("Compute Progress: "));
stream_append_f64(s, 100 * *var->compute_progress_bar.progress, 100);
stream_append_byte(s, '%');
@@ -2038,30 +2030,35 @@ draw_compute_progress_bar(BeamformerUI *ui, Arena arena, ComputeProgressBar *sta
}
function v2
-draw_compute_stats_view(BeamformerCtx *ctx, Arena arena, ComputeShaderStats *stats, Rect r)
+draw_compute_stats_view(BeamformerCtx *ctx, Arena arena, Rect r)
{
#define X(e, n, s, h, pn) [ComputeShaderKind_##e] = s8_comp(pn ":"),
read_only local_persist s8 labels[ComputeShaderKind_Count] = {COMPUTE_SHADERS};
#undef X
- BeamformerSharedMemory *sm = ctx->shared_memory.region;
+ BeamformerSharedMemory *sm = ctx->shared_memory.region;
+ ComputeShaderStats *stats = ctx->compute_shader_stats;
BeamformerUI *ui = ctx->ui;
f32 compute_time_sum = 0;
u32 stages = sm->compute_stages_count;
TextSpec text_spec = {.font = &ui->font, .colour = FG_COLOUR, .flags = TF_LIMITED};
- Table *table = table_new(&arena, stages + 1, TextAlignment_Left, TextAlignment_Left, TextAlignment_Left);
+ static_assert(ShaderKind_Count <= 32, "shader kind bitfield test");
+ u32 seen_shaders = 0;
+ Table *table = table_new(&arena, stages + 2, TextAlignment_Left, TextAlignment_Left, TextAlignment_Left);
for (u32 i = 0; i < stages; i++) {
TableCell *cells = table_push_row(table, &arena, TRK_CELLS)->data;
Stream sb = arena_stream(arena);
ShaderKind index = (ShaderKind)sm->compute_stages[i];
- compute_time_sum += stats->times[index];
- stream_append_f64_e(&sb, stats->times[index]);
-
- cells[0].text = labels[index];
- cells[1].text = arena_stream_commit(&arena, &sb);
- cells[2].text = s8("[s]");
+ if ((seen_shaders & (1 << index)) == 0) {
+ compute_time_sum += stats->average_times[index];
+ stream_append_f64_e(&sb, stats->average_times[index]);
+ seen_shaders |= (1 << index);
+ cells[0].text = labels[index];
+ cells[1].text = arena_stream_commit(&arena, &sb);
+ cells[2].text = s8("[s]");
+ }
}
TableCell *cells = table_push_row(table, &arena, TRK_CELLS)->data;
@@ -2071,6 +2068,13 @@ draw_compute_stats_view(BeamformerCtx *ctx, Arena arena, ComputeShaderStats *sta
cells[1].text = arena_stream_commit(&arena, &sb);
cells[2].text = s8("[s]");
+ cells = table_push_row(table, &arena, TRK_CELLS)->data;
+ sb = arena_stream(arena);
+ stream_append_f64_e(&sb, stats->rf_time_delta_average);
+ cells[0].text = s8("RF Upload Delta:");
+ cells[1].text = arena_stream_commit(&arena, &sb);
+ cells[2].text = s8("[s]");
+
table_extent(table, arena, text_spec.font);
return draw_table(ui, arena, table, r, text_spec, (v2){0}, 0);
}
@@ -2268,13 +2272,7 @@ draw_ui_view(BeamformerUI *ui, Variable *ui_view, Rect r, v2 mouse, TextSpec tex
case VT_COMPUTE_PROGRESS_BAR: {
size = draw_compute_progress_bar(ui, ui->arena, &var->compute_progress_bar, r);
} break;
- case VT_COMPUTE_LATEST_STATS_VIEW:
- case VT_COMPUTE_STATS_VIEW: {
- ComputeShaderStats *stats = var->compute_stats_view.stats;
- if (var->type == VT_COMPUTE_LATEST_STATS_VIEW)
- stats = *(ComputeShaderStats **)stats;
- size = draw_compute_stats_view(var->compute_stats_view.ctx, ui->arena, stats, r);
- } break;
+ case VT_COMPUTE_STATS_VIEW:{ size = draw_compute_stats_view(var->generic, ui->arena, r); }break;
InvalidDefaultCase;
}
@@ -2971,12 +2969,9 @@ ui_init(BeamformerCtx *ctx, Arena store)
split = split->region_split.right;
split->region_split.left = add_compute_progress_bar(split, ctx);
- split->region_split.right = add_compute_stats_view(ui, split, &ui->arena,
- VT_COMPUTE_LATEST_STATS_VIEW);
-
- ComputeStatsView *compute_stats = &split->region_split.right->group.first->compute_stats_view;
- compute_stats->ctx = ctx;
- compute_stats->stats = &ui->latest_compute_stats;
+ split->region_split.right = add_compute_stats_view(ui, split, &ui->arena, VT_COMPUTE_STATS_VIEW);
+ /* TODO(rnp): refactor to not need the beamformer ctx */
+ split->region_split.right->group.first->generic = ctx;
ctx->ui_read_params = 1;
@@ -2994,15 +2989,13 @@ validate_ui_parameters(BeamformerUIParameters *p)
}
function void
-draw_ui(BeamformerCtx *ctx, BeamformerInput *input, BeamformFrame *frame_to_draw, ImagePlaneTag frame_plane,
- ComputeShaderStats *latest_compute_stats)
+draw_ui(BeamformerCtx *ctx, BeamformerInput *input, BeamformFrame *frame_to_draw, ImagePlaneTag frame_plane)
{
BeamformerUI *ui = ctx->ui;
BeamformerSharedMemory *sm = ctx->shared_memory.region;
ui->latest_plane[IPT_LAST] = frame_to_draw;
ui->latest_plane[frame_plane] = frame_to_draw;
- ui->latest_compute_stats = latest_compute_stats;
/* TODO(rnp): there should be a better way of detecting this */
if (ctx->ui_read_params) {
diff --git a/util.h b/util.h
@@ -70,6 +70,10 @@
#define SIGN(x) ((x) < 0? -1 : 1)
#define swap(a, b) do {typeof(a) __tmp = (a); (a) = (b); (b) = __tmp;} while(0)
+#define EachElement(array, it) (u64 it = 0; it < countof(array); it += 1)
+#define EachEnumValue(type, it) (type it = (type)0; it < type##_Count; it = (type)(it + 1))
+#define EachNonZeroEnumValue(type, it) (type it = (type)1; it < type##_Count; it = (type)(it + 1))
+
/* NOTE(rnp): no guarantees about actually getting an element */
#define SLLPop(list) list; list = list ? list->next : 0
#define SLLPush(v, list) do { \