Commit: 9fca71254e69efeddbcba0524a4662d6bcfbb446
Parent: 6b005a1202c2747d9f037a063a81ca69f75739bb
Author: Randy Palamar
Date: Mon, 20 Apr 2026 20:36:11 -0600
beamformer_shared_memory: extend dirty_regions to region_update_flags
Now arbitrary extra flags can also be included. This includes a
flag which is set in the library indicating that the UI should be
informed about a parameter set upload. This is the correct place
to decide when the UI should be informed, not in random places
based on broken heuristics.
Diffstat:
4 files changed, 53 insertions(+), 49 deletions(-)
diff --git a/beamformer_core.c b/beamformer_core.c
@@ -753,10 +753,14 @@ function void
beamformer_commit_parameter_block(BeamformerCtx *ctx, BeamformerComputePlan *cp, u32 block, Arena arena)
{
BeamformerParameterBlock *pb = beamformer_parameter_block_lock(ctx->shared_memory, block, -1);
- for EachBit(pb->dirty_regions, region) {
+ for EachBit(pb->region_update_flags, region) {
switch (region) {
- case BeamformerParameterBlockRegion_ComputePipeline:
- case BeamformerParameterBlockRegion_Parameters:
+ case BeamformerParameterRegionFlag_NotifyUI:{
+ atomic_store_u32(&ctx->ui_dirty_parameter_blocks, 1u << block);
+ }break;
+
+ case BeamformerParameterRegionFlag_ComputePipeline:
+ case BeamformerParameterRegionFlag_Parameters:
{
cp->output_points = das_valid_points(pb->parameters.output_points.xyz);
cp->average_frames = pb->parameters.output_points.E[3];
@@ -766,7 +770,7 @@ beamformer_commit_parameter_block(BeamformerCtx *ctx, BeamformerComputePlan *cp,
/* NOTE(rnp): these are both handled by plan_compute_pipeline() */
u32 mask = 1 << BeamformerParameterBlockRegion_ComputePipeline |
1 << BeamformerParameterBlockRegion_Parameters;
- pb->dirty_regions &= ~mask;
+ pb->region_update_flags &= ~mask;
for (u32 shader_slot = 0; shader_slot < cp->pipeline.shader_count; shader_slot++) {
u128 hash = u128_hash_from_data(cp->shader_descriptors + shader_slot, sizeof(BeamformerShaderDescriptor));
@@ -801,15 +805,15 @@ beamformer_commit_parameter_block(BeamformerCtx *ctx, BeamformerComputePlan *cp,
case BeamformerParameterBlockRegion_ChannelMapping:{
cuda_set_channel_mapping(pb->channel_mapping);
}break;
- case BeamformerParameterBlockRegion_FocalVectors:
- case BeamformerParameterBlockRegion_SparseElements:
- case BeamformerParameterBlockRegion_TransmitReceiveOrientations:
+ case BeamformerParameterRegionFlag_FocalVectors:
+ case BeamformerParameterRegionFlag_SparseElements:
+ case BeamformerParameterRegionFlag_TransmitReceiveOrientations:
{
BeamformerComputeTextureKind texture_kind = 0;
u32 pixel_type = 0, texture_format = 0;
switch (region) {
#define X(kind, _gl, tf, pt, ...) \
- case BeamformerParameterBlockRegion_## kind:{ \
+ case BeamformerParameterRegionFlag_##kind:{ \
texture_kind = BeamformerComputeTextureKind_## kind; \
texture_format = tf; \
pixel_type = pt; \
@@ -1109,7 +1113,6 @@ complete_queue(BeamformerCtx *ctx, BeamformWorkQueue *q, Arena *arena, iptr gl_c
if (beamformer_parameter_block_dirty(sm, work->compute_context.parameter_block)) {
u32 block = work->compute_context.parameter_block;
beamformer_commit_parameter_block(ctx, cp, block, *arena);
- atomic_store_u32(&ctx->ui_dirty_parameter_blocks, (u32)(ctx->beamform_work_queue != q) << block);
}
post_sync_barrier(ctx->shared_memory, work->lock);
diff --git a/beamformer_shared_memory.c b/beamformer_shared_memory.c
@@ -1,5 +1,5 @@
/* See LICENSE for license details. */
-#define BEAMFORMER_SHARED_MEMORY_VERSION (25UL)
+#define BEAMFORMER_SHARED_MEMORY_VERSION (26UL)
typedef struct BeamformerFrame BeamformerFrame;
@@ -80,7 +80,11 @@ typedef enum {BEAMFORMER_LIVE_IMAGING_DIRTY_FLAG_LIST} BeamformerLiveImagingDirt
X(FocalVectors, focal_vectors) \
X(Parameters, parameters) \
X(SparseElements, sparse_elements) \
- X(TransmitReceiveOrientations, transmit_receive_orientations)
+ X(TransmitReceiveOrientations, transmit_receive_orientations) \
+
+#define BEAMFORMER_PARAMETER_BLOCK_REGION_FLAG_LIST \
+ BEAMFORMER_PARAMETER_BLOCK_REGION_LIST \
+ X(NotifyUI) \
typedef enum {
#define X(k, ...) BeamformerParameterBlockRegion_##k,
@@ -89,6 +93,13 @@ typedef enum {
BeamformerParameterBlockRegion_Count
} BeamformerParameterBlockRegions;
+typedef enum {
+ #define X(k, ...) BeamformerParameterRegionFlag_##k,
+ BEAMFORMER_PARAMETER_BLOCK_REGION_FLAG_LIST
+ #undef X
+ BeamformerParameterRegionFlag_Count,
+} BeamformerParameterRegionFlags;
+
typedef union {
u8 filter_slot;
} BeamformerShaderParameters;
@@ -111,8 +122,8 @@ typedef struct {
};
/* NOTE(rnp): signals to the beamformer that a subregion of a block has been updated */
- u32 dirty_regions;
- static_assert(BeamformerParameterBlockRegion_Count <= 32, "only 32 parameter block regions supported");
+ u32 region_update_flags;
+ static_assert(BeamformerParameterRegionFlag_Count <= 32, "");
BeamformerComputePipeline pipeline;
@@ -247,7 +258,7 @@ beamformer_parameter_block(BeamformerSharedMemory *sm, u32 block)
function b32
beamformer_parameter_block_dirty(BeamformerSharedMemory *sm, u32 block)
{
- b32 result = beamformer_parameter_block(sm, block)->dirty_regions != 0;
+ b32 result = beamformer_parameter_block(sm, block)->region_update_flags != 0;
return result;
}
@@ -282,7 +293,7 @@ function void
mark_parameter_block_region_dirty(BeamformerSharedMemory *sm, u32 block, BeamformerParameterBlockRegions region)
{
BeamformerParameterBlock *pb = beamformer_parameter_block(sm, block);
- atomic_or_u32(&pb->dirty_regions, 1u << region);
+ atomic_or_u32(&pb->region_update_flags, 1u << region);
}
function void
diff --git a/lib/ogl_beamformer_lib.c b/lib/ogl_beamformer_lib.c
@@ -488,6 +488,10 @@ beamformer_push_parameters_at(BeamformerParameters *bp, u32 block)
BeamformerParameterBlockRegion_Parameters,
offsetof(BeamformerParameterBlock, parameters),
g_beamformer_library_context.timeout_ms);
+ if (result) {
+ BeamformerParameterBlock *pb = beamformer_parameter_block(g_beamformer_library_context.bp, block);
+ atomic_or_u32(&pb->region_update_flags, 1u << BeamformerParameterRegionFlag_NotifyUI);
+ }
}
return result;
}
diff --git a/ui.c b/ui.c
@@ -434,8 +434,6 @@ struct BeamformerUI {
b32 flush_params;
u32 selected_parameter_block;
- u64 parameters_update_timestamp;
- u64 das_transform_hash;
v2 min_coordinate;
v2 max_coordinate;
f32 off_axis_position;
@@ -4109,42 +4107,32 @@ draw_ui(BeamformerCtx *ctx, BeamformerInput *input, BeamformerFrame *frame_to_dr
atomic_and_u32(&ctx->ui_dirty_parameter_blocks, ~selected_mask);
beamformer_parameter_block_unlock(ui->shared_memory, selected_block);
- u64 timestamp = os_timer_count();
- f64 timestamp_delta = (f64)(timestamp - ui->parameters_update_timestamp)
- / os_system_info()->timer_frequency;
- ui->parameters_update_timestamp = timestamp;
+ BeamformerComputePlan *cp = ui->beamformer_context->compute_context.compute_plans[selected_block];
+ m4 identity = m4_identity();
+ b32 recompute = !m4_equal(identity, cp->ui_voxel_transform);
+ mem_copy(cp->ui_voxel_transform.E, identity.E, sizeof(identity));
- u64 das_transform_hash = u64_hash_from_s8(s8_struct(&das_transform));
- if (das_transform_hash != ui->das_transform_hash || timestamp_delta > 2.0) {
- ui->das_transform_hash = das_transform_hash;
-
- BeamformerComputePlan *cp = ui->beamformer_context->compute_context.compute_plans[selected_block];
- m4 identity = m4_identity();
- b32 recompute = !m4_equal(identity, cp->ui_voxel_transform);
- mem_copy(cp->ui_voxel_transform.E, identity.E, sizeof(identity));
-
- if (recompute) {
- mark_parameter_block_region_dirty(ui->shared_memory, selected_block,
- BeamformerParameterBlockRegion_Parameters);
- beamformer_queue_compute(ctx, frame_to_draw, selected_block);
- }
+ if (recompute) {
+ mark_parameter_block_region_dirty(ui->shared_memory, selected_block,
+ BeamformerParameterBlockRegion_Parameters);
+ beamformer_queue_compute(ctx, frame_to_draw, selected_block);
+ }
- v3 U = v3_normalize(das_transform.c[0].xyz);
- v3 V = v3_normalize(das_transform.c[1].xyz);
- v3 N = cross(V, U);
+ v3 U = v3_normalize(das_transform.c[0].xyz);
+ v3 V = v3_normalize(das_transform.c[1].xyz);
+ v3 N = cross(V, U);
- ui->off_axis_position = v3_dot(N, das_transform.c[3].xyz);
- ui->beamform_plane = 0;
+ ui->off_axis_position = v3_dot(N, das_transform.c[3].xyz);
+ ui->beamform_plane = 0;
- v3 min_coordinate = m4_mul_v3(das_transform, (v3){{0.0f, 0.0f, 0.0f}});
- v3 max_coordinate = m4_mul_v3(das_transform, (v3){{1.0f, 1.0f, 1.0f}});
+ v3 min_coordinate = m4_mul_v3(das_transform, (v3){{0.0f, 0.0f, 0.0f}});
+ v3 max_coordinate = m4_mul_v3(das_transform, (v3){{1.0f, 1.0f, 1.0f}});
- ui->min_coordinate.x = v3_dot(U, min_coordinate);
- ui->min_coordinate.y = v3_dot(V, min_coordinate);
+ ui->min_coordinate.x = v3_dot(U, min_coordinate);
+ ui->min_coordinate.y = v3_dot(V, min_coordinate);
- ui->max_coordinate.x = v3_dot(U, max_coordinate);
- ui->max_coordinate.y = v3_dot(V, max_coordinate);
- }
+ ui->max_coordinate.x = v3_dot(U, max_coordinate);
+ ui->max_coordinate.y = v3_dot(V, max_coordinate);
}
}
@@ -4202,8 +4190,6 @@ draw_ui(BeamformerCtx *ctx, BeamformerInput *input, BeamformerFrame *frame_to_dr
BeamformerParameterBlockRegion_Parameters);
beamformer_parameter_block_unlock(ui->shared_memory, selected_block);
- ui->parameters_update_timestamp = os_timer_count();
-
if (recompute)
beamformer_queue_compute(ctx, frame_to_draw, selected_block);
}