Commit: 1ea96605d02f679311bd3e36b462a28c29de8eb5
Parent: 7d1c7212d386515488b5612e73055597a10f9b8a
Author: Randy Palamar
Date: Tue, 9 Sep 2025 20:21:08 -0600
lib: add beamformer_beamform_data (simple API)
I haven't yet thought of how to handle the filters in a way that is
easily manageable in toy languages such as matlab so for now they
still need to be setup via a separate function call
Diffstat:
9 files changed, 186 insertions(+), 98 deletions(-)
diff --git a/beamformer.c b/beamformer.c
@@ -398,18 +398,18 @@ das_voxel_transform_matrix(BeamformerParameters *bp)
m4 R;
switch (bp->das_shader_id) {
- case DASShaderKind_FORCES:
- case DASShaderKind_UFORCES:
- case DASShaderKind_Flash:
+ case BeamformerDASKind_FORCES:
+ case BeamformerDASKind_UFORCES:
+ case BeamformerDASKind_Flash:
{
R = m4_identity();
S.c[1].E[1] = 0;
T2.c[3].E[1] = 0;
}break;
- case DASShaderKind_HERCULES:
- case DASShaderKind_UHERCULES:
- case DASShaderKind_RCA_TPW:
- case DASShaderKind_RCA_VLS:
+ case BeamformerDASKind_HERCULES:
+ case BeamformerDASKind_UHERCULES:
+ case BeamformerDASKind_RCA_TPW:
+ case BeamformerDASKind_RCA_VLS:
{
R = m4_rotation_about_z(bp->beamform_plane ? 0.0f : 0.25f);
if (!(points.x > 1 && points.y > 1 && points.z > 1))
@@ -527,7 +527,7 @@ plan_compute_pipeline(BeamformerComputePlan *cp, BeamformerParameterBlock *pb)
i32 local_flags = 0;
if ((bp->shader_flags & BeamformerShaderDASFlags_CoherencyWeighting) == 0)
local_flags |= BeamformerShaderDASFlags_Fast;
- if (bp->shader_kind == DASShaderKind_UFORCES || bp->shader_kind == DASShaderKind_UHERCULES)
+ if (bp->shader_kind == BeamformerDASKind_UFORCES || bp->shader_kind == BeamformerDASKind_UHERCULES)
local_flags |= BeamformerShaderDASFlags_Sparse;
if (pb->parameters.interpolate)
local_flags |= BeamformerShaderDASFlags_Interpolate;
@@ -846,8 +846,8 @@ do_compute_shader(BeamformerCtx *ctx, BeamformerComputePlan *cp, BeamformerFrame
if (fast) {
i32 loop_end;
- if (ubo->shader_kind == DASShaderKind_RCA_VLS ||
- ubo->shader_kind == DASShaderKind_RCA_TPW)
+ if (ubo->shader_kind == BeamformerDASKind_RCA_VLS ||
+ ubo->shader_kind == BeamformerDASKind_RCA_TPW)
{
/* NOTE(rnp): to avoid repeatedly sampling the whole focal vectors
* texture we loop over transmits for VLS/TPW */
@@ -920,7 +920,7 @@ do_compute_shader(BeamformerCtx *ctx, BeamformerComputePlan *cp, BeamformerFrame
aframe->min_coordinate = frame->min_coordinate;
aframe->max_coordinate = frame->max_coordinate;
aframe->compound_count = frame->compound_count;
- aframe->das_shader_kind = frame->das_shader_kind;
+ aframe->das_kind = frame->das_kind;
}break;
InvalidDefaultCase;
}
@@ -1196,7 +1196,7 @@ complete_queue(BeamformerCtx *ctx, BeamformWorkQueue *q, Arena *arena, iptr gl_c
frame->min_coordinate = cp->min_coordinate;
frame->max_coordinate = cp->max_coordinate;
- frame->das_shader_kind = cp->das_ubo_data.shader_kind;
+ frame->das_kind = cp->das_ubo_data.shader_kind;
frame->compound_count = cp->das_ubo_data.acquisition_count;
BeamformerComputeContext *cc = &ctx->compute_context;
diff --git a/beamformer.h b/beamformer.h
@@ -260,13 +260,6 @@ typedef struct {
BeamformerRenderModel unit_cube_model;
} BeamformerComputeContext;
-typedef enum {
- #define X(type, id, ...) DASShaderKind_##type = id,
- DAS_SHADER_KIND_LIST
- #undef X
- DASShaderKind_Count
-} DASShaderKind;
-
typedef struct {
BeamformerComputeStatsTable table;
f32 average_times[BeamformerShaderKind_Count];
@@ -324,7 +317,7 @@ struct BeamformerFrame {
GLenum gl_kind;
u32 id;
u32 compound_count;
- DASShaderKind das_shader_kind;
+ BeamformerDASKind das_kind;
BeamformerViewPlaneTag view_plane_tag;
BeamformerFrame *next;
diff --git a/beamformer_parameters.h b/beamformer_parameters.h
@@ -20,6 +20,7 @@ typedef struct {
/* TODO(rnp): this is an absolute abuse of the preprocessor, but now is
* not a good time to write a full metaprogram */
#define BEAMFORMER_FILTER_KIND_LIST(type, _) \
+ X(Invalid, type unused) \
X(Kaiser, type cutoff_frequency _ type beta _ type length) \
X(MatchedChirp, type duration _ type min_frequency _ type max_frequency)
@@ -55,6 +56,13 @@ typedef enum {
X(EPIC_UHERCULES, 9, "EPIC-UHERCULES", 0) \
X(Flash, 10, "Flash", 0)
+typedef enum {
+ #define X(type, id, ...) BeamformerDASKind_##type = id,
+ DAS_SHADER_KIND_LIST
+ #undef X
+ BeamformerDASKind_Count
+} BeamformerDASKind;
+
#define FILTER_LOCAL_SIZE_X 64
#define FILTER_LOCAL_SIZE_Y 1
#define FILTER_LOCAL_SIZE_Z 1
@@ -84,37 +92,47 @@ typedef enum {
X(MaxRawDataFramesInFlight, 3) \
X(MaxSavedFrames, 16)
#define X(k, v, ...) Beamformer##k = v,
-enum {BEAMFORMER_CONSTANTS_LIST};
+typedef enum {BEAMFORMER_CONSTANTS_LIST} BeamformerConstants;
#undef X
-/* X(name, type, size, elements, comment) */
+/* X(name, type, size, matlab_type, elements, comment) */
#define BEAMFORMER_PARAMS_HEAD \
- X(xdc_transform, float, [16], 16, "IMPORTANT: column major order") \
- X(xdc_element_pitch, float, [2], 2, "[m] Transducer Element Pitch {row, col}") \
- X(raw_data_dimensions, uint32_t, [2], 2, "Raw Data Dimensions") \
- X(sample_count, uint32_t, , 1, "") \
- X(channel_count, uint32_t, , 1, "") \
- X(acquisition_count, uint32_t, , 1, "") \
- X(das_shader_id, uint32_t, , 1, "") \
- X(time_offset, float, , 1, "pulse length correction time [s]") \
- X(decode, uint8_t, , 1, "Decode or just reshape data") \
- X(transmit_mode, uint8_t, , 1, "Method/Orientation of Transmit") \
- X(receive_mode, uint8_t, , 1, "Method/Orientation of Receive") \
- X(sampling_mode, uint8_t, , 1, "")
+ X(xdc_transform, float, [16], single, 16, "IMPORTANT: column major order") \
+ X(xdc_element_pitch, float, [2], single, 2, "[m] Transducer Element Pitch {row, col}") \
+ X(raw_data_dimensions, uint32_t, [2], uint32, 2, "Raw Data Dimensions") \
+ X(sample_count, uint32_t, , uint32, 1, "") \
+ X(channel_count, uint32_t, , uint32, 1, "") \
+ X(acquisition_count, uint32_t, , uint32, 1, "") \
+ X(das_shader_id, uint32_t, , uint32, 1, "") \
+ X(time_offset, float, , single, 1, "pulse length correction time [s]") \
+ X(decode, uint8_t, , uint8, 1, "Decode or just reshape data") \
+ X(transmit_mode, uint8_t, , uint8, 1, "Method/Orientation of Transmit") \
+ X(receive_mode, uint8_t, , uint8, 1, "Method/Orientation of Receive") \
+ X(sampling_mode, uint8_t, , uint8, 1, "")
#define BEAMFORMER_UI_PARAMS \
- X(output_min_coordinate, float, [3], 3, "[m] Back-Top-Left corner of output region") \
- X(output_max_coordinate, float, [3], 3, "[m] Front-Bottom-Right corner of output region") \
- X(output_points, int32_t, [4], 4, "Width * Height * Depth * (Frame Average Count)") \
- X(sampling_frequency, float, , 1, "[Hz]") \
- X(demodulation_frequency, float, , 1, "[Hz]") \
- X(speed_of_sound, float, , 1, "[m/s]") \
- X(f_number, float, , 1, "F# (set to 0 to disable)") \
- X(off_axis_pos, float, , 1, "[m] Position on screen normal to beamform in TPW/VLS/HERCULES") \
- X(interpolate, uint32_t, , 1, "Perform Cubic Interpolation of RF Samples") \
- X(coherency_weighting, uint32_t, , 1, "Apply coherency weighting to output data") \
- X(beamform_plane, uint32_t, , 1, "Plane to Beamform in TPW/VLS/HERCULES") \
- X(decimation_rate, uint32_t, , 1, "Number of times to decimate")
+ X(output_min_coordinate, float, [3], single, 3, "[m] Back-Top-Left corner of output region") \
+ X(output_max_coordinate, float, [3], single, 3, "[m] Front-Bottom-Right corner of output region") \
+ X(output_points, int32_t, [4], int32, 4, "Width * Height * Depth * (Frame Average Count)") \
+ X(sampling_frequency, float, , single, 1, "[Hz]") \
+ X(demodulation_frequency, float, , single, 1, "[Hz]") \
+ X(speed_of_sound, float, , single, 1, "[m/s]") \
+ X(f_number, float, , single, 1, "F# (set to 0 to disable)") \
+ X(off_axis_pos, float, , single, 1, "[m] Position on screen normal to beamform in TPW/VLS/HERCULES") \
+ X(interpolate, uint32_t, , uint32, 1, "Perform Cubic Interpolation of RF Samples") \
+ X(coherency_weighting, uint32_t, , uint32, 1, "Apply coherency weighting to output data") \
+ X(beamform_plane, uint32_t, , uint32, 1, "Plane to Beamform in TPW/VLS/HERCULES") \
+ X(decimation_rate, uint32_t, , uint32, 1, "Number of times to decimate")
+
+#define BEAMFORMER_SIMPLE_PARAMS \
+ X(channel_mapping, int16_t, [BeamformerMaxChannelCount], int16, BeamformerMaxChannelCount) \
+ X(sparse_elements, int16_t, [BeamformerMaxChannelCount], int16, BeamformerMaxChannelCount) \
+ X(steering_angles, float, [BeamformerMaxChannelCount], single, BeamformerMaxChannelCount) \
+ X(focal_depths, float, [BeamformerMaxChannelCount], single, BeamformerMaxChannelCount) \
+ X(compute_stages, int32_t, [BeamformerMaxComputeShaderStages], int32, BeamformerMaxComputeShaderStages) \
+ X(compute_stage_parameters, int16_t, [BeamformerMaxComputeShaderStages], int16, BeamformerMaxComputeShaderStages) \
+ X(compute_stages_count, uint32_t, , uint32, 1) \
+ X(data_kind, int32_t, , int32, 1)
#define X(name, type, size, ...) type name size;
typedef struct {BEAMFORMER_PARAMS_HEAD} BeamformerParametersHead;
@@ -124,6 +142,12 @@ typedef struct {
BEAMFORMER_PARAMS_HEAD
BEAMFORMER_UI_PARAMS
} BeamformerParameters;
+
+typedef struct {
+ BEAMFORMER_PARAMS_HEAD
+ BEAMFORMER_UI_PARAMS
+ BEAMFORMER_SIMPLE_PARAMS
+} BeamformerSimpleParameters;
#undef X
#define BEAMFORMER_LIVE_IMAGING_DIRTY_FLAG_LIST \
diff --git a/beamformer_shared_memory.c b/beamformer_shared_memory.c
@@ -159,7 +159,7 @@ typedef struct {
/* NOTE(rnp): not used for locking on w32 but we can use these to peek at the status of
* the lock without leaving userspace. */
- i32 locks[BeamformerSharedMemoryLockKind_Count + BeamformerMaxParameterBlockSlots];
+ i32 locks[(u32)BeamformerSharedMemoryLockKind_Count + (u32)BeamformerMaxParameterBlockSlots];
/* NOTE(rnp): total number of parameter block regions the client has requested.
* used to calculate offset to scratch space and to track number of allocated
diff --git a/build.c b/build.c
@@ -792,12 +792,11 @@ meta_push_(MetaprogramContext *m, s8 *items, iz count)
meta_begin_matlab_class_1)(m, __VA_ARGS__)
function void
-meta_push_matlab_property(MetaprogramContext *m, s8 name, i64 length)
+meta_push_matlab_property(MetaprogramContext *m, s8 name, u64 length, s8 kind)
{
- meta_indent(m);
- stream_append_s8s(&m->stream, name, s8("(1,"));
- stream_append_i64(&m->stream, length);
- stream_append_s8(&m->stream, s8(")\n"));
+ meta_begin_line(m, name, s8("(1,"));
+ meta_push_u64(m, (u64)length);
+ meta_end_line(m, s8(")"), kind.len > 0 ? s8(" ") : s8(""), kind);
}
function void
@@ -2202,7 +2201,7 @@ metagen_emit_matlab_code(MetaContext *ctx, Arena arena)
#undef X
s8_list members = {0};
- for EachElement(filter_table, filter) {
+ for EachNonZeroEnumValue(BeamformerFilterKind, filter) {
typeof(*filter_table) *f = filter_table + filter;
members.count = 0;
s8_list_from_s8(&members, &m->scratch, f->args);
@@ -2210,7 +2209,7 @@ metagen_emit_matlab_code(MetaContext *ctx, Arena arena)
meta_begin_scope(m, s8("properties"));
for (iz it = 0; it < members.count; it++)
- meta_push_matlab_property(m, members.data[it], 1);
+ meta_push_matlab_property(m, members.data[it], 1, s8("single"));
meta_end_scope(m, s8("end"));
meta_begin_scope(m, s8("methods"));
@@ -2235,7 +2234,7 @@ metagen_emit_matlab_code(MetaContext *ctx, Arena arena)
meta_push_line(m, s8("out(i) = fields{i};"));
result &= meta_end_and_write_matlab(m, OUTPUT("matlab/+OGLBeamformerFilter/BaseFilter.m"));
- #define X(name, __t, __s, elements, ...) meta_push_line(m, s8(#name "(1," #elements ")"));
+ #define X(name, __t, __s, kind, elements, ...) meta_push_matlab_property(m, s8(#name), (u64)elements, s8(#kind));
meta_begin_matlab_class(m, "OGLBeamformerParameters");
meta_begin_scope(m, s8("properties"));
BEAMFORMER_PARAMS_HEAD
@@ -2251,9 +2250,16 @@ metagen_emit_matlab_code(MetaContext *ctx, Arena arena)
meta_begin_scope(m, s8("properties"));
BEAMFORMER_UI_PARAMS
result &= meta_end_and_write_matlab(m, OUTPUT("matlab/OGLBeamformerParametersUI.m"));
+
+ meta_begin_matlab_class(m, "OGLBeamformerSimpleParameters");
+ meta_begin_scope(m, s8("properties"));
+ BEAMFORMER_PARAMS_HEAD
+ BEAMFORMER_UI_PARAMS
+ BEAMFORMER_SIMPLE_PARAMS
+ result &= meta_end_and_write_matlab(m, OUTPUT("matlab/OGLBeamformerSimpleParameters.m"));
#undef X
- #define X(name, __t, __s, elements, ...) meta_push_matlab_property(m, s8(#name), elements);
+ #define X(name, __t, __s, elements, ...) meta_push_matlab_property(m, s8(#name), elements, s8(""));
meta_begin_matlab_class(m, "OGLBeamformerLiveImagingParameters");
meta_begin_scope(m, s8("properties"));
BEAMFORMER_LIVE_IMAGING_PARAMETERS_LIST
diff --git a/helpers/ogl_beamformer_lib.c b/helpers/ogl_beamformer_lib.c
@@ -228,10 +228,8 @@ beamformer_reserve_parameter_blocks(uint32_t count)
function b32
validate_pipeline(i32 *shaders, u32 shader_count, BeamformerDataKind data_kind)
{
- b32 result = 1;
- if (lib_error_check(shader_count <= BeamformerMaxComputeShaderStages,
- BF_LIB_ERR_KIND_COMPUTE_STAGE_OVERFLOW))
- {
+ b32 result = lib_error_check(shader_count <= BeamformerMaxComputeShaderStages, BF_LIB_ERR_KIND_COMPUTE_STAGE_OVERFLOW);
+ if (result) {
for (u32 i = 0; i < shader_count; i++)
result &= BETWEEN(shaders[i], BeamformerShaderKind_ComputeFirst, BeamformerShaderKind_ComputeLast);
if (!result) {
@@ -252,6 +250,18 @@ validate_pipeline(i32 *shaders, u32 shader_count, BeamformerDataKind data_kind)
}
function b32
+validate_simple_parameters(BeamformerSimpleParameters *bp)
+{
+ b32 result = check_shared_memory();
+ if (result) {
+ result &= bp->channel_count <= BeamformerMaxChannelCount;
+ if (!result)
+ g_beamformer_library_context.last_error = BF_LIB_ERR_KIND_INVALID_SIMPLE_PARAMETERS;
+ }
+ return result;
+}
+
+function b32
parameter_block_region_upload_explicit(void *data, u32 size, u32 block, BeamformerParameterBlockRegions region_id,
u32 block_offset, i32 timeout_ms)
{
@@ -301,7 +311,7 @@ b32
beamformer_push_pipeline_at(i32 *shaders, u32 shader_count, BeamformerDataKind data_kind, u32 block)
{
b32 result = 0;
- if (validate_pipeline(shaders, shader_count, data_kind)) {
+ if (check_shared_memory() && validate_pipeline(shaders, shader_count, data_kind)) {
i32 lock = BeamformerSharedMemoryLockKind_Count + (i32)block;
if (valid_parameter_block(block) && lib_try_lock(lock, g_beamformer_library_context.timeout_ms)) {
BeamformerParameterBlock *b = beamformer_parameter_block(g_beamformer_library_context.bp, block);
@@ -489,6 +499,35 @@ beamformer_push_parameters(BeamformerParameters *bp)
}
b32
+beamformer_push_simple_parameters_at(BeamformerSimpleParameters *bp, u32 block)
+{
+ b32 result = validate_simple_parameters(bp);
+ if (result) {
+ result &= beamformer_push_parameters_at((BeamformerParameters *)bp, block);
+ result &= beamformer_push_pipeline_at(bp->compute_stages, bp->compute_stages_count, (BeamformerDataKind)bp->data_kind, block);
+ result &= beamformer_push_channel_mapping_at(bp->channel_mapping, bp->channel_count, block);
+ if (bp->das_shader_id == BeamformerDASKind_UFORCES || bp->das_shader_id == BeamformerDASKind_UHERCULES)
+ result &= beamformer_push_sparse_elements_at(bp->sparse_elements, bp->acquisition_count, block);
+
+ alignas(64) v2 focal_vectors[countof(bp->steering_angles)];
+ for (u32 i = 0; i < countof(bp->steering_angles); i++)
+ focal_vectors[i] = (v2){{bp->steering_angles[i], bp->focal_depths[i]}};
+ result &= beamformer_push_focal_vectors_at((f32 *)focal_vectors, countof(focal_vectors), block);
+
+ for (u32 stage = 0; stage < bp->compute_stages_count; stage++)
+ result &= beamformer_set_pipeline_stage_parameters_at(stage, bp->compute_stage_parameters[stage], block);
+ }
+ return result;
+}
+
+b32
+beamformer_push_simple_parameters(BeamformerSimpleParameters *bp)
+{
+ b32 result = beamformer_push_simple_parameters_at(bp, 0);
+ return result;
+}
+
+b32
beamformer_push_parameters_ui(BeamformerUIParameters *bp)
{
b32 result = parameter_block_region_upload_explicit(bp, sizeof(*bp), 0, BeamformerParameterBlockRegion_Parameters,
@@ -537,23 +576,28 @@ beamformer_read_output(void *out, iz size, i32 timeout_ms)
}
b32
-beamform_data_synchronized(void *data, u32 data_size, i32 output_points[3], f32 *out_data, i32 timeout_ms)
+beamformer_beamform_data(BeamformerSimpleParameters *bp, void *data, uint32_t data_size,
+ void *out_data, int32_t timeout_ms)
{
- b32 result = 0;
- if (check_shared_memory()) {
- output_points[0] = MAX(1, output_points[0]);
- output_points[1] = MAX(1, output_points[1]);
- output_points[2] = MAX(1, output_points[2]);
+ b32 result = validate_simple_parameters(bp);
+ if (result) {
+ bp->output_points[0] = MAX(1, bp->output_points[0]);
+ bp->output_points[1] = MAX(1, bp->output_points[1]);
+ bp->output_points[2] = MAX(1, bp->output_points[2]);
+
+ beamformer_push_simple_parameters(bp);
- BeamformerParameterBlock *b = beamformer_parameter_block(g_beamformer_library_context.bp, 0);
- b->parameters.output_points[0] = output_points[0];
- b->parameters.output_points[1] = output_points[1];
- b->parameters.output_points[2] = output_points[2];
+ b32 complex = 0;
+ for (u32 stage = 0; stage < bp->compute_stages_count; stage++) {
+ BeamformerShaderKind shader = (BeamformerShaderKind)bp->compute_stages[stage];
+ complex |= shader == BeamformerShaderKind_Demodulate || shader == BeamformerShaderKind_CudaHilbert;
+ }
- iz output_size = output_points[0] * output_points[1] * output_points[2] * (i32)sizeof(f32) * 2;
+ iz output_size = bp->output_points[0] * bp->output_points[1] * bp->output_points[2] * (i32)sizeof(f32);
+ if (complex) output_size *= 2;
Arena scratch = beamformer_shared_memory_scratch_arena(g_beamformer_library_context.bp);
- if (lib_error_check(output_size <= arena_capacity(&scratch, u8), BF_LIB_ERR_KIND_EXPORT_SPACE_OVERFLOW)
+ if (result && lib_error_check(output_size <= arena_capacity(&scratch, u8), BF_LIB_ERR_KIND_EXPORT_SPACE_OVERFLOW)
&& beamformer_push_data_with_compute(data, data_size, 0, 0))
{
BeamformerExportContext export;
diff --git a/helpers/ogl_beamformer_lib_base.h b/helpers/ogl_beamformer_lib_base.h
@@ -25,7 +25,8 @@
X(SYNC_VARIABLE, 14, "failed to acquire lock within timeout period") \
X(INVALID_TIMEOUT, 15, "invalid timeout value") \
X(INVALID_FILTER_KIND, 16, "invalid filter kind") \
- X(INVALID_FILTER_PARAM_COUNT, 17, "invalid parameters count passed for filter")
+ X(INVALID_FILTER_PARAM_COUNT, 17, "invalid parameters count passed for filter") \
+ X(INVALID_SIMPLE_PARAMETERS, 18, "invalid simple parameters struct")
#define X(type, num, string) BF_LIB_ERR_KIND_ ##type = num,
typedef enum {BEAMFORMER_LIB_ERRORS} BeamformerLibErrorKind;
@@ -37,6 +38,20 @@ LIB_FN BeamformerLibErrorKind beamformer_get_last_error(void);
LIB_FN const char *beamformer_get_last_error_string(void);
LIB_FN const char *beamformer_error_string(BeamformerLibErrorKind kind);
+///////////////////////////
+// NOTE: Simple API
+/* Usage:
+ * - fill out a BeamformerSimpleParameters
+ * - filters need to be created with beamformer_create_filter, and the slot
+ * needs to be assigned in compute_stage_parameters
+ * - allocate a buffer with enough space for all Float32 or Float32Complex output points
+ * - pass the buffer along with the data and parameters to beamformer_beamform_data()
+ * - if the function was unsuccessful you can check the error with beamformer_get_last_error()
+ * or beamformer_get_last_error_string()
+ */
+LIB_FN uint32_t beamformer_beamform_data(BeamformerSimpleParameters *bp, void *data, uint32_t data_size,
+ void *out_data, int32_t timeout_ms);
+
/* NOTE: sets timeout for all functions which may timeout but don't
* take a timeout argument. The majority of such functions will not
* timeout in the normal case and so passing a timeout parameter around
@@ -47,10 +62,8 @@ LIB_FN const char *beamformer_error_string(BeamformerLibErrorKind kind);
* IMPORTANT: timeout of -1 will block forever */
LIB_FN uint32_t beamformer_set_global_timeout(int32_t timeout_ms);
-/* NOTE: sends data and waits for (complex) beamformed data to be returned.
- * out_data: must be allocated by the caller as 2 floats per output point. */
-LIB_FN uint32_t beamform_data_synchronized(void *data, uint32_t data_size, int32_t output_points[3],
- float *out_data, int32_t timeout_ms);
+///////////////////////////
+// NOTE: Advanced API
/* NOTE: downloads the last 32 frames worth of compute timings into output */
LIB_FN uint32_t beamformer_compute_timings(BeamformerComputeStatsTable *output, int32_t timeout_ms);
@@ -58,38 +71,46 @@ LIB_FN uint32_t beamformer_compute_timings(BeamformerComputeStatsTable *output,
/* NOTE: tells the beamformer to start beamforming */
LIB_FN uint32_t beamformer_start_compute(void);
-LIB_FN uint32_t beamformer_push_data_with_compute(void *data, uint32_t size,
- uint32_t image_plane_tag,
- uint32_t parameter_slot);
-
/* NOTE: waits for previously queued beamform to start or for timeout_ms */
LIB_FN uint32_t beamformer_wait_for_compute_dispatch(int32_t timeout_ms);
-/* NOTE: these functions only queue an upload; you must flush (start_compute) */
+/* NOTE: this function only queue an upload; you must flush (start_compute) */
LIB_FN uint32_t beamformer_push_data(void *data, uint32_t size);
-LIB_FN uint32_t beamformer_push_channel_mapping(int16_t *mapping, uint32_t count);
-LIB_FN uint32_t beamformer_push_sparse_elements(int16_t *elements, uint32_t count);
-LIB_FN uint32_t beamformer_push_focal_vectors(float *vectors, uint32_t count);
+
+/* NOTE: pushes data and tries to immediately starts a compute */
+LIB_FN uint32_t beamformer_push_data_with_compute(void *data, uint32_t size,
+ uint32_t image_plane_tag,
+ uint32_t parameter_slot);
///////////////////////////
// Parameter Configuration
LIB_FN uint32_t beamformer_reserve_parameter_blocks(uint32_t count);
LIB_FN uint32_t beamformer_set_pipeline_stage_parameters(uint32_t stage_index, int32_t parameter);
LIB_FN uint32_t beamformer_push_pipeline(int32_t *shaders, uint32_t shader_count, BeamformerDataKind data_kind);
-LIB_FN uint32_t beamformer_push_parameters(BeamformerParameters *);
-LIB_FN uint32_t beamformer_push_parameters_ui(BeamformerUIParameters *);
-LIB_FN uint32_t beamformer_push_parameters_head(BeamformerParametersHead *);
LIB_FN uint32_t beamformer_set_pipeline_stage_parameters_at(uint32_t stage_index,
int32_t parameter,
uint32_t parameter_slot);
LIB_FN uint32_t beamformer_push_pipeline_at(int32_t *shaders, uint32_t shader_count,
BeamformerDataKind data_kind, uint32_t parameter_slot);
+
+LIB_FN uint32_t beamformer_push_simple_parameters(BeamformerSimpleParameters *bp);
+LIB_FN uint32_t beamformer_push_simple_parameters_at(BeamformerSimpleParameters *bp, uint32_t parameter_slot);
+
+LIB_FN uint32_t beamformer_push_parameters(BeamformerParameters *);
+LIB_FN uint32_t beamformer_push_parameters_ui(BeamformerUIParameters *);
+LIB_FN uint32_t beamformer_push_parameters_head(BeamformerParametersHead *);
+
LIB_FN uint32_t beamformer_push_parameters_at(BeamformerParameters *, uint32_t parameter_slot);
-LIB_FN uint32_t beamformer_push_channel_mapping_at(int16_t *mapping, uint32_t count, uint32_t parameter_slot);
+LIB_FN uint32_t beamformer_push_channel_mapping(int16_t *mapping, uint32_t count);
+LIB_FN uint32_t beamformer_push_channel_mapping_at(int16_t *mapping, uint32_t count, uint32_t parameter_slot);
+
+LIB_FN uint32_t beamformer_push_sparse_elements(int16_t *elements, uint32_t count);
LIB_FN uint32_t beamformer_push_sparse_elements_at(int16_t *elements, uint32_t count, uint32_t parameter_slot);
-LIB_FN uint32_t beamformer_push_focal_vectors_at(float *vectors, uint32_t count, uint32_t parameter_slot);
+
+LIB_FN uint32_t beamformer_push_focal_vectors(float *vectors, uint32_t count);
+LIB_FN uint32_t beamformer_push_focal_vectors_at(float *vectors, uint32_t count, uint32_t parameter_slot);
////////////////////
// Filter Creation
diff --git a/static.c b/static.c
@@ -365,7 +365,7 @@ setup_beamformer(Arena *memory, BeamformerCtx **o_ctx, BeamformerInput **o_input
/* TODO(rnp): I'm not sure if its a good idea to pre-reserve a bunch of semaphores
* on w32 but thats what we are doing for now */
- u32 lock_count = BeamformerSharedMemoryLockKind_Count + BeamformerMaxParameterBlockSlots;
+ u32 lock_count = (u32)BeamformerSharedMemoryLockKind_Count + (u32)BeamformerMaxParameterBlockSlots;
ctx->shared_memory = os_create_shared_memory_area(memory, OS_SHARED_MEMORY_NAME, lock_count,
BEAMFORMER_SHARED_MEMORY_SIZE);
BeamformerSharedMemory *sm = ctx->shared_memory.region;
diff --git a/ui.c b/ui.c
@@ -657,20 +657,20 @@ stream_append_variable_group(Stream *s, Variable *var)
}
function s8
-push_das_shader_kind(Stream *s, DASShaderKind shader, u32 transmit_count)
+push_das_shader_kind(Stream *s, BeamformerDASKind shader, u32 transmit_count)
{
#define X(__1, __2, pretty, ...) s8_comp(pretty),
- read_only local_persist s8 pretty_names[DASShaderKind_Count + 1] = {
+ read_only local_persist s8 pretty_names[BeamformerDASKind_Count + 1] = {
DAS_SHADER_KIND_LIST
s8_comp("Invalid")
};
#undef X
#define X(__1, __2, __3, fixed_tx) fixed_tx,
- read_only local_persist u8 fixed_transmits[DASShaderKind_Count + 1] = {DAS_SHADER_KIND_LIST};
+ read_only local_persist u8 fixed_transmits[BeamformerDASKind_Count + 1] = {DAS_SHADER_KIND_LIST};
#undef X
- stream_append_s8(s, pretty_names[MIN(shader, DASShaderKind_Count)]);
- if (!fixed_transmits[MIN(shader, DASShaderKind_Count)]) {
+ stream_append_s8(s, pretty_names[MIN(shader, BeamformerDASKind_Count)]);
+ if (!fixed_transmits[MIN(shader, BeamformerDASKind_Count)]) {
stream_append_byte(s, '-');
stream_append_u64(s, transmit_count);
}
@@ -2571,7 +2571,7 @@ draw_beamformer_frame_view(BeamformerUI *ui, Arena a, Variable *var, Rect displa
{
Stream buf = arena_stream(a);
- s8 shader = push_das_shader_kind(&buf, frame->das_shader_kind, frame->compound_count);
+ s8 shader = push_das_shader_kind(&buf, frame->das_kind, frame->compound_count);
text_spec.font = &ui->font;
text_spec.limits.size.w -= 16;
v2 txt_s = measure_text(*text_spec.font, shader);