ogl_beamforming

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

Commit: 8b3e2ec9485c3171cf9f6ec7fce431d2eb4d284f
Parent: 547e619118f87af07b9e84a0defa25d3a360c40c
Author: Randy Palamar
Date:   Thu, 16 Oct 2025 15:52:47 -0600

core: ensure output image points are always valid

internally we expect that all dimensions are > 0 otherwise some
calculations are incorrect

also HERO_PA was missed in the voxel transform. perhaps that
requires generation as well

Diffstat:
Mbeamformer.c | 24+++++++++++++++---------
Mmath.c | 10++++++++++
2 files changed, 25 insertions(+), 9 deletions(-)

diff --git a/beamformer.c b/beamformer.c @@ -203,13 +203,20 @@ beamformer_frame_compatible(BeamformerFrame *f, iv3 dim, GLenum gl_kind) return result; } +function iv3 +make_valid_output_points(i32 points[3]) +{ + iv3 result; + result.E[0] = MAX(1, points[0]); + result.E[1] = MAX(1, points[1]); + result.E[2] = MAX(1, points[2]); + return result; +} + function void alloc_beamform_frame(GLParams *gp, BeamformerFrame *out, iv3 out_dim, GLenum gl_kind, s8 name, Arena arena) { - out->dim.x = MAX(1, out_dim.x); - out->dim.y = MAX(1, out_dim.y); - out->dim.z = MAX(1, out_dim.z); - + out->dim = make_valid_output_points(out_dim.E); if (gp) { out->dim.x = MIN(out->dim.x, gp->max_3d_texture_dim); out->dim.y = MIN(out->dim.y, gp->max_3d_texture_dim); @@ -407,7 +414,7 @@ das_voxel_transform_matrix(BeamformerParameters *bp) v3 min = v3_from_f32_array(bp->output_min_coordinate); v3 max = v3_from_f32_array(bp->output_max_coordinate); v3 extent = v3_abs(v3_sub(max, min)); - v3 points = {{(f32)bp->output_points[0], (f32)bp->output_points[1], (f32)bp->output_points[2]}}; + v3 points = v3_from_iv3(make_valid_output_points(bp->output_points)); m4 T1 = m4_translation(v3_scale(v3_sub(points, (v3){{1.0f, 1.0f, 1.0f}}), -0.5f)); m4 T2 = m4_translation(v3_add(min, v3_scale(extent, 0.5f))); @@ -423,6 +430,7 @@ das_voxel_transform_matrix(BeamformerParameters *bp) S.c[1].E[1] = 0; T2.c[3].E[1] = 0; }break; + case BeamformerAcquisitionKind_HERO_PA: case BeamformerAcquisitionKind_HERCULES: case BeamformerAcquisitionKind_UHERCULES: case BeamformerAcquisitionKind_RCA_TPW: @@ -806,10 +814,8 @@ beamformer_commit_parameter_block(BeamformerCtx *ctx, BeamformerComputePlan *cp, cp->min_coordinate = v3_from_f32_array(pb->parameters.output_min_coordinate); cp->max_coordinate = v3_from_f32_array(pb->parameters.output_max_coordinate); - cp->output_points.E[0] = MAX(pb->parameters.output_points[0], 1); - cp->output_points.E[1] = MAX(pb->parameters.output_points[1], 1); - cp->output_points.E[2] = MAX(pb->parameters.output_points[2], 1); - cp->average_frames = pb->parameters.output_points[3]; + cp->output_points = make_valid_output_points(pb->parameters.output_points); + cp->average_frames = pb->parameters.output_points[3]; GLenum gl_kind = cp->iq_pipeline ? GL_RG32F : GL_R32F; if (cp->average_frames > 1 && !beamformer_frame_compatible(ctx->averaged_frames + 0, cp->output_points, gl_kind)) { diff --git a/math.c b/math.c @@ -228,6 +228,16 @@ cross(v3 a, v3 b) } function v3 +v3_from_iv3(iv3 v) +{ + v3 result; + result.E[0] = (f32)v.E[0]; + result.E[1] = (f32)v.E[1]; + result.E[2] = (f32)v.E[2]; + return result; +} + +function v3 v3_from_f32_array(f32 v[3]) { v3 result;