ogl_beamforming

Ultrasound Beamforming Implemented with OpenGL
git clone anongit@rnpnr.xyz:ogl_beamforming.git
Log | Files | Refs | Feed | Submodules | README | LICENSE

Commit: 14ea1604e894c655bf81b4540b2f02436a30edd1
Parent: f2766fe119cf7ccd086f17ad52e1443ecf9f4cc6
Author: Randy Palamar
Date:   Mon, 12 Oct 2026 12:47:27 -0600

meta: generate beamformer_data_strides() function

if we need to add more layouts modifying this function will be
annoying. We also might want access to these enumerations in the
library interface so moving it into beamformer.meta is a good idea.

Diffstat:
Mbeamformer.meta | 37+++++++++++++++++++++++++++++++++++++
Mbeamformer_core.c | 42------------------------------------------
Mbeamformer_core.meta | 16----------------
Mbuild.c | 4++--
Mgenerated/beamformer.c | 260++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Mgenerated/beamformer_core.c | 16----------------
6 files changed, 185 insertions(+), 190 deletions(-)

diff --git a/beamformer.meta b/beamformer.meta @@ -37,6 +37,28 @@ } @Expand(DataKindTable) @Enumeration(`$(name)`) DataKind +@Enumeration RFDimension +{ + Channels + Events + Samples + Frames +} + +@Table([name dim1 dim2 dim3]) DataLayoutTable +{ + [ChannelEventSample Channels Events Samples] + [ChannelSampleEvent Channels Samples Events ] + [EventChannelSample Events Channels Samples] + [SampleChannelEvent Samples Channels Events ] +} + +@Enumeration DataLayout +{ + @Expand(DataLayoutTable) `$(name)` + Image +} + @Table([name samples]) ContrastModeTable { [None 1] @@ -529,3 +551,18 @@ } } } + +@Emit +{ + `function uv3` + `beamformer_data_strides(BeamformerDataLayout layout, uv3 rf_dimensions)` + `{` + ` uv3 result = {0};` + ` switch (layout) {` + ` InvalidDefaultCase;` + ` case BeamformerDataLayout_Image:{}break;` + @Expand(DataLayoutTable) ` case BeamformerDataLayout_$(name):{$(|)result.E[BeamformerRFDimension_$(dim3)]$(|)= 1;$(|)result.E[BeamformerRFDimension_$(dim2)]$(|)= rf_dimensions.E[BeamformerRFDimension_$(dim3)];$(|)result.E[BeamformerRFDimension_$(dim1)]$(|)= rf_dimensions.E[BeamformerRFDimension_$(dim3)]$(|)* rf_dimensions.E[BeamformerRFDimension_$(dim2)];$(|)}break;` + ` }` + ` return result;` + `}` +} diff --git a/beamformer_core.c b/beamformer_core.c @@ -526,48 +526,6 @@ push_compute_graph_node(BeamformerComputeGraph *graph, BeamformerShaderKind kind return result; } -function uv3 -beamformer_data_strides(BeamformerDataLayout layout, uv3 rf_dimensions) -{ - u32 channel_count = rf_dimensions.E[BeamformerRFDimension_Channels]; - u32 event_count = rf_dimensions.E[BeamformerRFDimension_Events]; - u32 sample_count = rf_dimensions.E[BeamformerRFDimension_Samples]; - - uv3 result = {0}; - switch (layout) { - InvalidDefaultCase; - - case BeamformerDataLayout_Image:{}break; - - case BeamformerDataLayout_ChannelEventSample:{ - result.E[BeamformerRFDimension_Channels] = event_count * sample_count; - result.E[BeamformerRFDimension_Events] = sample_count; - result.E[BeamformerRFDimension_Samples] = 1; - }break; - - case BeamformerDataLayout_ChannelSampleEvent:{ - result.E[BeamformerRFDimension_Channels] = event_count * sample_count; - result.E[BeamformerRFDimension_Events] = 1; - result.E[BeamformerRFDimension_Samples] = event_count; - }break; - - case BeamformerDataLayout_EventChannelSample:{ - result.E[BeamformerRFDimension_Events] = channel_count * sample_count; - result.E[BeamformerRFDimension_Channels] = sample_count; - result.E[BeamformerRFDimension_Samples] = 1; - }break; - - case BeamformerDataLayout_SampleChannelEvent:{ - result.E[BeamformerRFDimension_Samples] = channel_count * event_count; - result.E[BeamformerRFDimension_Channels] = event_count; - result.E[BeamformerRFDimension_Events] = 1; - }break; - - } - - return result; -} - function void plan_compute_pipeline(BeamformerComputePlan *cp, BeamformerParameterBlock *pb, Arena *scratch) { diff --git a/beamformer_core.meta b/beamformer_core.meta @@ -1,20 +1,4 @@ // See LICENSE for license details. -@Enumeration DataLayout -{ - ChannelEventSample - ChannelSampleEvent - EventChannelSample - SampleChannelEvent - Image -} - -@Enumeration RFDimension -{ - Channels - Events - Samples -} - @Flags PanelFlags { List diff --git a/build.c b/build.c @@ -4137,8 +4137,6 @@ metagen_emit_c_code(MetaContext *ctx, Arena *arena) arena_clear(m->scratch); } - metagen_run_emit_set(m, ctx, ctx->emit_sets + MetaEmitLang_C, meta_kind_c_types); - // TODO(rnp): we may want this to include more than just the bake structs if (ctx->base_shader_count) DeferLoop(meta_begin_scope(m, str8("typedef enum {")), @@ -4350,6 +4348,8 @@ metagen_emit_c_code(MetaContext *ctx, Arena *arena) } } + metagen_run_emit_set(m, ctx, ctx->emit_sets + MetaEmitLang_C, meta_kind_c_types); + result = meta_write_and_reset(m, out); arena_clear(m->scratch); diff --git a/generated/beamformer.c b/generated/beamformer.c @@ -42,6 +42,23 @@ typedef enum { } BeamformerDataKind; typedef enum { + BeamformerRFDimension_Channels = 0, + BeamformerRFDimension_Events = 1, + BeamformerRFDimension_Samples = 2, + BeamformerRFDimension_Frames = 3, + BeamformerRFDimension_Count, +} BeamformerRFDimension; + +typedef enum { + BeamformerDataLayout_ChannelEventSample = 0, + BeamformerDataLayout_ChannelSampleEvent = 1, + BeamformerDataLayout_EventChannelSample = 2, + BeamformerDataLayout_SampleChannelEvent = 3, + BeamformerDataLayout_Image = 4, + BeamformerDataLayout_Count, +} BeamformerDataLayout; + +typedef enum { BeamformerContrastMode_None = 0, BeamformerContrastMode_A1S2 = 1, BeamformerContrastMode_Count, @@ -454,120 +471,6 @@ typedef union { BeamformerReshapeBakeParameters Reshape; } BeamformerShaderBakeParameters; -read_only u8 beamformer_data_kind_element_size[] = { - 2, - 2, - 4, - 4, - 2, - 2, -}; - -read_only u8 beamformer_data_kind_element_count[] = { - 1, - 2, - 1, - 2, - 1, - 2, -}; - -read_only u8 beamformer_data_kind_byte_size[] = { - 2 * 1, - 2 * 2, - 4 * 1, - 4 * 2, - 2 * 1, - 2 * 2, -}; - -read_only b8 beamformer_data_kind_complex[] = { - 0, - 1, - 0, - 1, - 0, - 1, -}; - -read_only str8 beamformer_data_kind_glsl_type[] = { - str8_comp("int16_t"), - str8_comp("i16vec2"), - str8_comp("float32_t"), - str8_comp("f32vec2"), - str8_comp("float16_t"), - str8_comp("f16vec2"), -}; - -read_only str8 beamformer_data_kind_str8[] = { - str8_comp("Int16"), - str8_comp("Int16Complex"), - str8_comp("Float32"), - str8_comp("Float32Complex"), - str8_comp("Float16"), - str8_comp("Float16Complex"), -}; - -read_only u8 beamformer_contrast_mode_samples[] = { - 1, - 3, -}; - -read_only str8 beamformer_contrast_mode_strings[] = { - str8_comp("None"), - str8_comp("A1S2"), -}; - -read_only str8 beamformer_view_plane_tag_strings[] = { - str8_comp("XZ"), - str8_comp("YZ"), - str8_comp("XY"), - str8_comp("Arbitrary"), -}; - -read_only u8 beamformer_acquisition_kind_has_fixed_transmits[] = { - 1, - 0, - 1, - 0, - 0, - 0, - 1, - 1, - 0, - 0, - 0, - 0, - 0, -}; - -read_only str8 beamformer_acquisition_kind_strings[] = { - str8_comp("FORCES"), - str8_comp("UFORCES"), - str8_comp("HERCULES"), - str8_comp("VLS"), - str8_comp("TPW"), - str8_comp("UHERCULES"), - str8_comp("RACES"), - str8_comp("EPIC-FORCES"), - str8_comp("EPIC-UFORCES"), - str8_comp("EPIC-UHERCULES"), - str8_comp("Flash"), - str8_comp("HERO-PA"), - str8_comp("ULM"), -}; - -read_only str8 beamformer_filter_kind_strings[] = { - str8_comp("Kaiser"), - str8_comp("MatchedChirp"), -}; - -read_only str8 beamformer_interpolation_mode_strings[] = { - str8_comp("Nearest"), - str8_comp("Linear"), - str8_comp("Cubic"), -}; - typedef enum { BeamformerStructKind_DecodeBakeParameters = 0, BeamformerStructKind_FilterBakeParameters = 1, @@ -1010,3 +913,132 @@ read_only u8 beamformer_shader_push_constant_sizes[] = { sizeof(BeamformerRenderBeamformedPushConstants), }; +read_only u8 beamformer_data_kind_element_size[] = { + 2, + 2, + 4, + 4, + 2, + 2, +}; + +read_only u8 beamformer_data_kind_element_count[] = { + 1, + 2, + 1, + 2, + 1, + 2, +}; + +read_only u8 beamformer_data_kind_byte_size[] = { + 2 * 1, + 2 * 2, + 4 * 1, + 4 * 2, + 2 * 1, + 2 * 2, +}; + +read_only b8 beamformer_data_kind_complex[] = { + 0, + 1, + 0, + 1, + 0, + 1, +}; + +read_only str8 beamformer_data_kind_glsl_type[] = { + str8_comp("int16_t"), + str8_comp("i16vec2"), + str8_comp("float32_t"), + str8_comp("f32vec2"), + str8_comp("float16_t"), + str8_comp("f16vec2"), +}; + +read_only str8 beamformer_data_kind_str8[] = { + str8_comp("Int16"), + str8_comp("Int16Complex"), + str8_comp("Float32"), + str8_comp("Float32Complex"), + str8_comp("Float16"), + str8_comp("Float16Complex"), +}; + +read_only u8 beamformer_contrast_mode_samples[] = { + 1, + 3, +}; + +read_only str8 beamformer_contrast_mode_strings[] = { + str8_comp("None"), + str8_comp("A1S2"), +}; + +read_only str8 beamformer_view_plane_tag_strings[] = { + str8_comp("XZ"), + str8_comp("YZ"), + str8_comp("XY"), + str8_comp("Arbitrary"), +}; + +read_only u8 beamformer_acquisition_kind_has_fixed_transmits[] = { + 1, + 0, + 1, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 0, +}; + +read_only str8 beamformer_acquisition_kind_strings[] = { + str8_comp("FORCES"), + str8_comp("UFORCES"), + str8_comp("HERCULES"), + str8_comp("VLS"), + str8_comp("TPW"), + str8_comp("UHERCULES"), + str8_comp("RACES"), + str8_comp("EPIC-FORCES"), + str8_comp("EPIC-UFORCES"), + str8_comp("EPIC-UHERCULES"), + str8_comp("Flash"), + str8_comp("HERO-PA"), + str8_comp("ULM"), +}; + +read_only str8 beamformer_filter_kind_strings[] = { + str8_comp("Kaiser"), + str8_comp("MatchedChirp"), +}; + +read_only str8 beamformer_interpolation_mode_strings[] = { + str8_comp("Nearest"), + str8_comp("Linear"), + str8_comp("Cubic"), +}; + +function uv3 +beamformer_data_strides(BeamformerDataLayout layout, uv3 rf_dimensions) +{ + uv3 result = {0}; + switch (layout) { + InvalidDefaultCase; + case BeamformerDataLayout_Image:{}break; + case BeamformerDataLayout_ChannelEventSample:{ result.E[BeamformerRFDimension_Samples] = 1; result.E[BeamformerRFDimension_Events] = rf_dimensions.E[BeamformerRFDimension_Samples]; result.E[BeamformerRFDimension_Channels] = rf_dimensions.E[BeamformerRFDimension_Samples] * rf_dimensions.E[BeamformerRFDimension_Events]; }break; + case BeamformerDataLayout_ChannelSampleEvent:{ result.E[BeamformerRFDimension_Events] = 1; result.E[BeamformerRFDimension_Samples] = rf_dimensions.E[BeamformerRFDimension_Events]; result.E[BeamformerRFDimension_Channels] = rf_dimensions.E[BeamformerRFDimension_Events] * rf_dimensions.E[BeamformerRFDimension_Samples]; }break; + case BeamformerDataLayout_EventChannelSample:{ result.E[BeamformerRFDimension_Samples] = 1; result.E[BeamformerRFDimension_Channels] = rf_dimensions.E[BeamformerRFDimension_Samples]; result.E[BeamformerRFDimension_Events] = rf_dimensions.E[BeamformerRFDimension_Samples] * rf_dimensions.E[BeamformerRFDimension_Channels]; }break; + case BeamformerDataLayout_SampleChannelEvent:{ result.E[BeamformerRFDimension_Events] = 1; result.E[BeamformerRFDimension_Channels] = rf_dimensions.E[BeamformerRFDimension_Events]; result.E[BeamformerRFDimension_Samples] = rf_dimensions.E[BeamformerRFDimension_Events] * rf_dimensions.E[BeamformerRFDimension_Channels]; }break; + } + return result; +} + diff --git a/generated/beamformer_core.c b/generated/beamformer_core.c @@ -3,22 +3,6 @@ // GENERATED CODE typedef enum { - BeamformerDataLayout_ChannelEventSample = 0, - BeamformerDataLayout_ChannelSampleEvent = 1, - BeamformerDataLayout_EventChannelSample = 2, - BeamformerDataLayout_SampleChannelEvent = 3, - BeamformerDataLayout_Image = 4, - BeamformerDataLayout_Count, -} BeamformerDataLayout; - -typedef enum { - BeamformerRFDimension_Channels = 0, - BeamformerRFDimension_Events = 1, - BeamformerRFDimension_Samples = 2, - BeamformerRFDimension_Count, -} BeamformerRFDimension; - -typedef enum { BeamformerPanelKind_Nil = 0, BeamformerPanelKind_Split = 1, BeamformerPanelKind_TabGroup = 2,