ogl_beamforming

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

Commit: 7a81806f8d70ccd79c06c3170c2644eddfe56207
Parent: 37b1ff9703fd28f875ffe27f6b48a46b2e0bef1b
Author: Randy Palamar
Date:   Sat,  8 Nov 2025 05:51:03 -0700

lib: add new error check for mismatched data size in push_data

Diffstat:
Mbeamformer_shared_memory.c | 2+-
Mhelpers/ogl_beamformer_lib.c | 120++++++++++++++++++++++++++++++++++++++-----------------------------------------
Mhelpers/ogl_beamformer_lib_base.h | 37+++++++++++++++++++------------------
3 files changed, 77 insertions(+), 82 deletions(-)

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 (18UL) +#define BEAMFORMER_SHARED_MEMORY_VERSION (19UL) typedef struct BeamformerFrame BeamformerFrame; diff --git a/helpers/ogl_beamformer_lib.c b/helpers/ogl_beamformer_lib.c @@ -370,28 +370,6 @@ beamformer_flush_commands(i32 timeout_ms) return result; } -function b32 -beamformer_compute_indirect(BeamformerViewPlaneTag tag, u32 block) -{ - b32 result = 0; - if (check_shared_memory() && - lib_error_check(tag < BeamformerViewPlaneTag_Count, BF_LIB_ERR_KIND_INVALID_IMAGE_PLANE) && - lib_error_check(block < g_beamformer_library_context.bp->reserved_parameter_blocks, - BF_LIB_ERR_KIND_PARAMETER_BLOCK_UNALLOCATED)) - { - BeamformWork *work = try_push_work_queue(); - if (work) { - work->kind = BeamformerWorkKind_ComputeIndirect; - work->compute_indirect_context.view_plane = tag; - work->compute_indirect_context.parameter_block = block; - beamform_work_queue_push_commit(&g_beamformer_library_context.bp->external_work_queue); - beamformer_flush_commands(0); - result = 1; - } - } - return result; -} - #define BEAMFORMER_UPLOAD_FNS \ X(channel_mapping, i16, 1, ChannelMapping) \ X(focal_vectors, f32, 2, FocalVectors) \ @@ -424,48 +402,48 @@ function b32 beamformer_push_data_base(void *data, u32 data_size, i32 timeout_ms, u32 block) { b32 result = 0; - if (check_shared_memory()) { - Arena scratch = beamformer_shared_memory_scratch_arena(g_beamformer_library_context.bp); - if (lib_error_check(data_size <= arena_capacity(&scratch, u8), BF_LIB_ERR_KIND_BUFFER_OVERFLOW)) { - if (lib_try_lock(BeamformerSharedMemoryLockKind_UploadRF, timeout_ms)) { - if (lib_try_lock(BeamformerSharedMemoryLockKind_ScratchSpace, 0)) { - BeamformerParameterBlock *b = beamformer_parameter_block(g_beamformer_library_context.bp, block); - BeamformerParameters *bp = &b->parameters; - BeamformerDataKind data_kind = b->pipeline.data_kind; - - // TODO(rnp): maybe make a mismatched size here an error - u32 size = bp->acquisition_count * bp->sample_count * bp->channel_count * beamformer_data_kind_byte_size[data_kind]; - - u32 channel_count = bp->channel_count; - u32 out_channel_stride = beamformer_data_kind_element_count[data_kind] * bp->sample_count * bp->acquisition_count; - u32 in_channel_stride = beamformer_data_kind_element_count[data_kind] * bp->raw_data_dimensions[0]; - - for (u32 channel = 0; channel < channel_count; channel++) { - u16 data_channel = (u16)b->channel_mapping[channel]; - u32 out_off = out_channel_stride * channel; - u32 in_off = in_channel_stride * data_channel; - for (u32 sample = 0; sample < out_channel_stride; sample++, out_off++, in_off++) { - switch (data_kind) { - case BeamformerDataKind_Int16: - case BeamformerDataKind_Int16Complex: - { - ((i16 *)scratch.beg)[out_off] = ((i16 *)data)[in_off]; - }break; - case BeamformerDataKind_Float32: - case BeamformerDataKind_Float32Complex: - { - ((f32 *)scratch.beg)[out_off] = ((f32 *)data)[in_off]; - }break; - InvalidDefaultCase; - } + Arena scratch = beamformer_shared_memory_scratch_arena(g_beamformer_library_context.bp); + BeamformerParameterBlock *b = beamformer_parameter_block(g_beamformer_library_context.bp, block); + BeamformerParameters *bp = &b->parameters; + BeamformerDataKind data_kind = b->pipeline.data_kind; + + u32 size = bp->acquisition_count * bp->sample_count * bp->channel_count * beamformer_data_kind_byte_size[data_kind]; + u32 raw_size = bp->raw_data_dimensions[0] * bp->raw_data_dimensions[1] * beamformer_data_kind_byte_size[data_kind]; + + if (lib_error_check(size <= arena_capacity(&scratch, u8), BF_LIB_ERR_KIND_BUFFER_OVERFLOW) && + lib_error_check(size <= data_size && data_size == raw_size, BF_LIB_ERR_KIND_DATA_SIZE_MISMATCH)) + { + if (lib_try_lock(BeamformerSharedMemoryLockKind_UploadRF, timeout_ms)) { + if (lib_try_lock(BeamformerSharedMemoryLockKind_ScratchSpace, 0)) { + u32 channel_count = bp->channel_count; + u32 out_channel_stride = beamformer_data_kind_element_count[data_kind] * bp->sample_count * bp->acquisition_count; + u32 in_channel_stride = beamformer_data_kind_element_count[data_kind] * bp->raw_data_dimensions[0]; + + for (u32 channel = 0; channel < channel_count; channel++) { + u16 data_channel = (u16)b->channel_mapping[channel]; + u32 out_off = out_channel_stride * channel; + u32 in_off = in_channel_stride * data_channel; + for (u32 sample = 0; sample < out_channel_stride; sample++, out_off++, in_off++) { + switch (data_kind) { + case BeamformerDataKind_Int16: + case BeamformerDataKind_Int16Complex: + { + ((i16 *)scratch.beg)[out_off] = ((i16 *)data)[in_off]; + }break; + case BeamformerDataKind_Float32: + case BeamformerDataKind_Float32Complex: + { + ((f32 *)scratch.beg)[out_off] = ((f32 *)data)[in_off]; + }break; + InvalidDefaultCase; } } - - lib_release_lock(BeamformerSharedMemoryLockKind_ScratchSpace); - /* TODO(rnp): need a better way to communicate this */ - atomic_store_u32(&g_beamformer_library_context.bp->scratch_rf_size, size); - result = 1; } + + lib_release_lock(BeamformerSharedMemoryLockKind_ScratchSpace); + /* TODO(rnp): need a better way to communicate this */ + atomic_store_u32(&g_beamformer_library_context.bp->scratch_rf_size, size); + result = 1; } } } @@ -475,8 +453,24 @@ beamformer_push_data_base(void *data, u32 data_size, i32 timeout_ms, u32 block) b32 beamformer_push_data_with_compute(void *data, u32 data_size, u32 image_plane_tag, u32 parameter_slot) { - b32 result = beamformer_push_data_base(data, data_size, g_beamformer_library_context.timeout_ms, parameter_slot); - if (result) result = beamformer_compute_indirect(image_plane_tag, parameter_slot); + b32 result = 0; + if (check_shared_memory()) { + u32 reserved_blocks = g_beamformer_library_context.bp->reserved_parameter_blocks; + if (lib_error_check(image_plane_tag < BeamformerViewPlaneTag_Count, BF_LIB_ERR_KIND_INVALID_IMAGE_PLANE) && + lib_error_check(parameter_slot < reserved_blocks, BF_LIB_ERR_KIND_PARAMETER_BLOCK_UNALLOCATED) && + beamformer_push_data_base(data, data_size, g_beamformer_library_context.timeout_ms, parameter_slot)) + { + BeamformWork *work = try_push_work_queue(); + if (work) { + work->kind = BeamformerWorkKind_ComputeIndirect; + work->compute_indirect_context.view_plane = image_plane_tag; + work->compute_indirect_context.parameter_block = parameter_slot; + beamform_work_queue_push_commit(&g_beamformer_library_context.bp->external_work_queue); + beamformer_flush_commands(0); + result = 1; + } + } + } return result; } diff --git a/helpers/ogl_beamformer_lib_base.h b/helpers/ogl_beamformer_lib_base.h @@ -9,24 +9,25 @@ #define BEAMFORMER_LIB_ERRORS \ X(NONE, 0, "None") \ - X(VERSION_MISMATCH, 1, "host-library version mismatch") \ - X(INVALID_ACCESS, 2, "library in invalid state") \ - X(PARAMETER_BLOCK_OVERFLOW, 3, "parameter block count overflow") \ - X(PARAMETER_BLOCK_UNALLOCATED, 4, "push to unallocated parameter block") \ - X(COMPUTE_STAGE_OVERFLOW, 5, "compute stage overflow") \ - X(INVALID_COMPUTE_STAGE, 6, "invalid compute shader stage") \ - X(INVALID_START_SHADER, 7, "starting shader not Decode or Demodulate") \ - X(INVALID_DEMOD_DATA_KIND, 8, "data kind for demodulation not Int16 or Float") \ - X(INVALID_IMAGE_PLANE, 9, "invalid image plane") \ - X(BUFFER_OVERFLOW, 10, "passed buffer size exceeds available space") \ - X(WORK_QUEUE_FULL, 11, "work queue full") \ - X(EXPORT_SPACE_OVERFLOW, 12, "not enough space for data export") \ - X(SHARED_MEMORY, 13, "failed to open shared memory region") \ - 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_SIMPLE_PARAMETERS, 18, "invalid simple parameters struct") + X(VERSION_MISMATCH, 1, "host-library version mismatch") \ + X(INVALID_ACCESS, 2, "library in invalid state") \ + X(PARAMETER_BLOCK_OVERFLOW, 3, "parameter block count overflow") \ + X(PARAMETER_BLOCK_UNALLOCATED, 4, "push to unallocated parameter block") \ + X(COMPUTE_STAGE_OVERFLOW, 5, "compute stage overflow") \ + X(INVALID_COMPUTE_STAGE, 6, "invalid compute shader stage") \ + X(INVALID_START_SHADER, 7, "starting shader not Decode or Demodulate") \ + X(INVALID_DEMOD_DATA_KIND, 8, "data kind for demodulation not Int16 or Float") \ + X(INVALID_IMAGE_PLANE, 9, "invalid image plane") \ + X(BUFFER_OVERFLOW, 10, "passed buffer size exceeds available space") \ + X(DATA_SIZE_MISMATCH, 11, "data size is less than specified from parameters") \ + X(WORK_QUEUE_FULL, 12, "work queue full") \ + X(EXPORT_SPACE_OVERFLOW, 13, "not enough space for data export") \ + X(SHARED_MEMORY, 14, "failed to open shared memory region") \ + X(SYNC_VARIABLE, 15, "failed to acquire lock within timeout period") \ + X(INVALID_TIMEOUT, 16, "invalid timeout value") \ + X(INVALID_FILTER_KIND, 17, "invalid filter kind") \ + X(INVALID_FILTER_PARAM_COUNT, 18, "invalid parameters count passed for filter") \ + X(INVALID_SIMPLE_PARAMETERS, 19, "invalid simple parameters struct") #define X(type, num, string) BF_LIB_ERR_KIND_ ##type = num, typedef enum {BEAMFORMER_LIB_ERRORS} BeamformerLibErrorKind;