Commit: f3fd61ef5a82e14f936b0fc854da1f7606e5213d
Parent: 20ab88cdec5da5c429ac14b297e54076564a6692
Author: Randy Palamar
Date: Fri, 4 Jul 2025 09:02:45 -0600
core/lib: add live imaging parameters sharing
Diffstat:
6 files changed, 110 insertions(+), 24 deletions(-)
diff --git a/beamformer_parameters.h b/beamformer_parameters.h
@@ -161,3 +161,14 @@ _Static_assert((offsetof(BeamformerParameters, output_min_coordinate) & 15) == 0
_Static_assert((sizeof(BeamformerParameters) & 15) == 0,
"sizeof(BeamformerParameters) must be a multiple of 16");
#endif
+
+#define BEAMFORMER_LIVE_IMAGING_DIRTY_FLAG_LIST \
+ X(ImagePlaneOffsets, 0) \
+ X(TransmitPower, 1)
+/* NOTE(rnp): if this exceeds 32 you need to fix the flag handling code */
+
+typedef struct {
+ uint32_t active;
+ float transmit_power;
+ float image_plane_offsets[BeamformerViewPlaneTag_Count];
+} BeamformerLiveImagingParameters;
diff --git a/beamformer_work_queue.h b/beamformer_work_queue.h
@@ -89,6 +89,10 @@ typedef BEAMFORM_WORK_QUEUE_PUSH_COMMIT_FN(beamform_work_queue_push_commit_fn);
#define BEAMFORMER_SCRATCH_SIZE (BEAMFORMER_SHARED_MEMORY_SIZE - BEAMFORMER_SCRATCH_OFF)
#define BEAMFORMER_MAX_RF_DATA_SIZE (BEAMFORMER_SCRATCH_SIZE)
+#define X(name, id) BeamformerLiveImagingDirtyFlags_##name = (1 << id),
+typedef enum {BEAMFORMER_LIVE_IMAGING_DIRTY_FLAG_LIST} BeamformerLiveImagingDirtyFlags;
+#undef X
+
typedef struct {
u32 version;
@@ -128,6 +132,9 @@ typedef struct {
/* TODO(rnp): this shouldn't be needed */
b32 export_next_frame;
+ BeamformerLiveImagingParameters live_imaging_parameters;
+ BeamformerLiveImagingDirtyFlags live_imaging_dirty_flags;
+
BeamformWorkQueue external_work_queue;
} BeamformerSharedMemory;
diff --git a/helpers/ogl_beamformer_lib.c b/helpers/ogl_beamformer_lib.c
@@ -44,8 +44,7 @@ os_open_shared_memory_area(char *name)
SharedMemoryRegion result = {0};
iptr h = OpenFileMappingA(FILE_MAP_ALL_ACCESS, 0, name);
if (h != INVALID_FILE) {
- void *new = MapViewOfFile(h, FILE_MAP_ALL_ACCESS, 0, 0,
- os_round_up_to_page_size(BEAMFORMER_SHARED_MEMORY_SIZE));
+ void *new = MapViewOfFile(h, FILE_MAP_ALL_ACCESS, 0, 0, BEAMFORMER_SHARED_MEMORY_SIZE);
if (new) {
u8 buffer[1024];
Stream sb = {.data = buffer, .cap = 1024};
@@ -422,3 +421,37 @@ beamformer_compute_timings(BeamformerComputeStatsTable *output, i32 timeout_ms)
}
return result;
}
+
+i32
+beamformer_live_parameters_get_dirty_flag(void)
+{
+ i32 result = -1;
+ if (check_shared_memory()) {
+ u32 flag = ctz_u32(g_bp->live_imaging_dirty_flags);
+ if (flag != 32) {
+ atomic_and_u32(&g_bp->live_imaging_dirty_flags, ~(1 << flag));
+ result = flag;
+ }
+ }
+ return result;
+}
+
+BeamformerLiveImagingParameters *
+beamformer_get_live_parameters(void)
+{
+ BeamformerLiveImagingParameters *result = 0;
+ if (check_shared_memory()) result = &g_bp->live_imaging_parameters;
+ return result;
+}
+
+b32
+beamformer_set_live_parameters(BeamformerLiveImagingParameters *new)
+{
+ b32 result = 0;
+ if (check_shared_memory()) {
+ mem_copy(&g_bp->live_imaging_parameters, new, sizeof(*new));
+ memory_write_barrier();
+ result = 1;
+ }
+ return result;
+}
diff --git a/helpers/ogl_beamformer_lib_base.h b/helpers/ogl_beamformer_lib_base.h
@@ -56,3 +56,9 @@ LIB_FN uint32_t beamformer_push_focal_vectors(float *vectors, uint32_t coun
LIB_FN uint32_t beamformer_push_parameters(BeamformerParameters *, int32_t timeout_ms);
LIB_FN uint32_t beamformer_push_parameters_ui(BeamformerUIParameters *, int32_t timeout_ms);
LIB_FN uint32_t beamformer_push_parameters_head(BeamformerParametersHead *, int32_t timeout_ms);
+
+//////////////////////////
+// Live Imaging Controls
+LIB_FN int32_t beamformer_live_parameters_get_dirty_flag(void);
+LIB_FN uint32_t beamformer_set_live_parameters(BeamformerLiveImagingParameters *);
+LIB_FN BeamformerLiveImagingParameters *beamformer_get_live_parameters(void);
diff --git a/intrinsics.c b/intrinsics.c
@@ -26,6 +26,8 @@
#define debugbreak() __debugbreak()
#define unreachable() __assume(0)
+ #define memory_write_barrier() _WriteBarrier()
+
#define atomic_store_u64(ptr, n) *((volatile u64 *)(ptr)) = (n)
#define atomic_store_u32(ptr, n) *((volatile u32 *)(ptr)) = (n)
#define atomic_load_u64(ptr) *((volatile u64 *)(ptr))
@@ -58,6 +60,8 @@
#endif
#define unreachable() __builtin_unreachable()
+ #define memory_write_barrier() asm volatile ("" ::: "memory")
+
#define atomic_store_u64(ptr, n) __atomic_store_n(ptr, n, __ATOMIC_RELEASE)
#define atomic_load_u64(ptr) __atomic_load_n(ptr, __ATOMIC_ACQUIRE)
#define atomic_add_u64(ptr, n) __atomic_fetch_add(ptr, n, __ATOMIC_ACQ_REL)
diff --git a/ui.c b/ui.c
@@ -237,7 +237,6 @@ typedef enum {
V_INPUT = 1 << 0,
V_TEXT = 1 << 1,
V_RADIO_BUTTON = 1 << 2,
- V_IMAGING_PARAM = 1 << 28,
V_CAUSES_COMPUTE = 1 << 29,
V_UPDATE_VIEW = 1 << 30,
} VariableFlags;
@@ -377,6 +376,10 @@ struct BeamformerUI {
b32 flush_params;
FrameViewRenderContext *frame_view_render_context;
+
+ /* TODO(rnp): hack? */
+ SharedMemoryRegion shared_memory;
+
OS *os;
};
@@ -1096,10 +1099,8 @@ add_beamformer_frame_view(BeamformerUI *ui, Variable *parent, Arena *arena,
resize_frame_view(bv, (uv2){{FRAME_VIEW_RENDER_TARGET_SIZE}}, 0);
glTextureParameteri(bv->textures[0], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTextureParameteri(bv->textures[0], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- fill_variable(bv->x_plane_shifts + 0, var, s8("XZ Shift"), V_INPUT|V_IMAGING_PARAM,
- VT_X_PLANE_SHIFT, ui->small_font);
- fill_variable(bv->x_plane_shifts + 1, var, s8("YZ Shift"), V_INPUT|V_IMAGING_PARAM,
- VT_X_PLANE_SHIFT, ui->small_font);
+ fill_variable(bv->x_plane_shifts + 0, var, s8("XZ Shift"), V_INPUT, VT_X_PLANE_SHIFT, ui->small_font);
+ fill_variable(bv->x_plane_shifts + 1, var, s8("YZ Shift"), V_INPUT, VT_X_PLANE_SHIFT, ui->small_font);
bv->demo = add_variable(ui, menu, arena, s8("Demo Mode"), V_INPUT|V_UPDATE_VIEW|V_RADIO_BUTTON,
VT_B32, ui->small_font);
}break;
@@ -1294,6 +1295,15 @@ x_plane_size(BeamformerUI *ui)
return result;
}
+function f32
+x_plane_rotation_for_view_plane(BeamformerFrameView *view, BeamformerViewPlaneTag tag)
+{
+ f32 result = view->rotation;
+ if (tag == BeamformerViewPlaneTag_YZ)
+ result += 0.25f;
+ return result;
+}
+
function v2
normalized_p_in_rect(Rect r, v2 p, b32 invert_y)
{
@@ -1313,6 +1323,18 @@ x_plane_position(BeamformerUI *ui)
}
function v3
+offset_x_plane_position(BeamformerUI *ui, BeamformerFrameView *view, BeamformerViewPlaneTag tag)
+{
+ BeamformerSharedMemory *sm = ui->shared_memory.region;
+ BeamformerLiveImagingParameters *li = &sm->live_imaging_parameters;
+ m4 x_rotation = m4_rotation_about_y(x_plane_rotation_for_view_plane(view, tag));
+ v3 Z = x_rotation.c[2].xyz;
+ v3 offset = v3_scale(Z, li->image_plane_offsets[tag]);
+ v3 result = v3_add(x_plane_position(ui), offset);
+ return result;
+}
+
+function v3
camera_for_x_plane_view(BeamformerUI *ui, BeamformerFrameView *view)
{
v3 size = x_plane_size(ui);
@@ -1370,15 +1392,6 @@ view_plane_tag_from_x_plane_shift(BeamformerFrameView *view, Variable *x_plane_s
return result;
}
-function f32
-x_plane_rotation_for_view_plane(BeamformerFrameView *view, BeamformerViewPlaneTag tag)
-{
- f32 result = view->rotation;
- if (tag == BeamformerViewPlaneTag_YZ)
- result += 0.25f;
- return result;
-}
-
function void
render_single_xplane(BeamformerUI *ui, BeamformerFrameView *view, Variable *x_plane_shift,
u32 program, f32 rotation_turns, v3 translate, BeamformerViewPlaneTag tag)
@@ -1433,11 +1446,14 @@ render_3D_xplane(BeamformerUI *ui, BeamformerFrameView *view, u32 program)
glProgramUniformMatrix4fv(program, FRAME_VIEW_VIEW_MATRIX_LOC, 1, 0, view_m.E);
glProgramUniformMatrix4fv(program, FRAME_VIEW_PROJ_MATRIX_LOC, 1, 0, projection.E);
- v3 model_translate = x_plane_position(ui);
- render_single_xplane(ui, view, view->x_plane_shifts + 0, program, view->rotation,
+ v3 model_translate = offset_x_plane_position(ui, view, BeamformerViewPlaneTag_XZ);
+ render_single_xplane(ui, view, view->x_plane_shifts + 0, program,
+ x_plane_rotation_for_view_plane(view, BeamformerViewPlaneTag_XZ),
model_translate, BeamformerViewPlaneTag_XZ);
+ model_translate = offset_x_plane_position(ui, view, BeamformerViewPlaneTag_YZ);
model_translate.y -= 0.0001;
- render_single_xplane(ui, view, view->x_plane_shifts + 1, program, view->rotation + 0.25f,
+ render_single_xplane(ui, view, view->x_plane_shifts + 1, program,
+ x_plane_rotation_for_view_plane(view, BeamformerViewPlaneTag_YZ),
model_translate, BeamformerViewPlaneTag_YZ);
}
@@ -2169,13 +2185,18 @@ draw_3D_xplane_frame_view(BeamformerUI *ui, Arena arena, Variable *var, Rect dis
i32 id = -1;
if (hover_interaction(ui, mouse, auto_interaction(vr, var))) {
ray mouse_ray = ray_for_x_plane_view(ui, view, normalized_p_in_rect(vr, mouse, 0));
- v3 x_position = x_plane_position(ui);
v3 x_size = v3_scale(x_plane_size(ui), 0.5f);
- m4 x_rotation = m4_rotation_about_y(view->rotation);
+
+ f32 rotation = x_plane_rotation_for_view_plane(view, BeamformerViewPlaneTag_XZ);
+ m4 x_rotation = m4_rotation_about_y(rotation);
+ v3 x_position = offset_x_plane_position(ui, view, BeamformerViewPlaneTag_XZ);
f32 test[2] = {0};
test[0] = obb_raycast(x_rotation, x_size, x_position, mouse_ray);
- x_rotation = m4_rotation_about_y(view->rotation + 0.25);
+
+ x_position = offset_x_plane_position(ui, view, BeamformerViewPlaneTag_YZ);
+ rotation = x_plane_rotation_for_view_plane(view, BeamformerViewPlaneTag_YZ);
+ x_rotation = m4_rotation_about_y(rotation);
test[1] = obb_raycast(x_rotation, x_size, x_position, mouse_ray);
if (test[0] >= 0 && test[1] >= 0) id = test[1] < test[0]? 1 : 0;
@@ -3259,9 +3280,12 @@ ui_end_interact(BeamformerUI *ui, v2 mouse)
m4 x_rotation = m4_rotation_about_y(rotation);
v3 Z = x_rotation.c[2].xyz;
f32 delta = v3_dot(Z, v3_sub(xp->end_point, xp->start_point));
- /* TODO(rnp): commit to image parameters shared memory */
- (void)delta;
xp->start_point = xp->end_point;
+
+ BeamformerSharedMemory *sm = ui->shared_memory.region;
+ BeamformerLiveImagingParameters *li = &sm->live_imaging_parameters;
+ li->image_plane_offsets[plane] += delta;
+ atomic_or_u32(&sm->live_imaging_dirty_flags, BeamformerLiveImagingDirtyFlags_ImagePlaneOffsets);
}break;
default:{}break;
}
@@ -3454,6 +3478,7 @@ ui_init(BeamformerCtx *ctx, Arena store)
ui->arena = store;
ui->frame_view_render_context = &ctx->frame_view_render_context;
ui->unit_cube_model = ctx->csctx.unit_cube_model;
+ ui->shared_memory = ctx->shared_memory;
/* TODO: build these into the binary */
/* TODO(rnp): better font, this one is jank at small sizes */