ogl_beamforming

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

Commit: 95b319ebf6d812636e292454c121b347e9cf6f2e
Parent: c52cee3a74e9ea982371d75b58c36f78bb3e05fb
Author: Randy Palamar
Date:   Mon, 10 Mar 2025 18:36:59 -0600

core: do more compute shader preprocessing

This will aid in minimizing the number of places we need to modify
to add new DAS IDs and other things.

Diffstat:
Mbeamformer.c | 45+++++++++++++++++++++++++++++++++++----------
Mbeamformer.h | 14+++++++-------
Mbeamformer_parameters.h | 50++++++++++++++++----------------------------------
Mhelpers/ogl_beamformer_lib.c | 12++++++------
Mshaders/das.glsl | 2--
Mutil.h | 4++++
6 files changed, 68 insertions(+), 59 deletions(-)

diff --git a/beamformer.c b/beamformer.c @@ -362,7 +362,7 @@ compute_cursor_finished(struct compute_cursor *cursor) } static void -do_compute_shader(BeamformerCtx *ctx, Arena arena, BeamformFrame *frame, enum compute_shaders shader) +do_compute_shader(BeamformerCtx *ctx, Arena arena, BeamformFrame *frame, ComputeShaderID shader) { ComputeShaderCtx *csctx = &ctx->csctx; @@ -511,6 +511,37 @@ link_program(Platform *platform, Arena a, u32 shader_id) return result; } +static s8 +push_compute_shader_header(Arena *a, ComputeShaderID shader) +{ + s8 result = {.data = a->beg}; + push_s8(a, s8(COMPUTE_SHADER_HEADER)); + switch (shader) { + case CS_DAS: { + push_s8(a, s8("layout(" + "local_size_x = " str(DAS_LOCAL_SIZE_X) ", " + "local_size_y = " str(DAS_LOCAL_SIZE_Y) ", " + "local_size_z = " str(DAS_LOCAL_SIZE_Z) ") " + "in;\n\n")); + #define X(type, id, pretty) push_s8(a, s8("#define DAS_ID_" #type " " #id "\n")); + DAS_TYPES + #undef X + } break; + case CS_DECODE_FLOAT: { + push_s8(a, s8("#define INPUT_DATA_TYPE_FLOAT\n\n")); + } /* FALLTHROUGH */ + case CS_DECODE: { + #define X(type, id, pretty) push_s8(a, s8("#define DECODE_MODE_" #type " " #id "\n")); + DECODE_TYPES + #undef X + } break; + default: break; + } + s8 end = push_s8(a, s8("\n#line 1\n")); + result.len = end.data + end.len - result.data; + return result; +} + static void reload_compute_shader(BeamformerCtx *ctx, s8 path, ComputeShaderReloadContext *csr, Arena tmp) { @@ -518,14 +549,8 @@ reload_compute_shader(BeamformerCtx *ctx, s8 path, ComputeShaderReloadContext *c /* NOTE: arena works as stack (since everything here is 1 byte aligned) */ s8 header = {.data = tmp.beg}; - if (csr->needs_header) { - header = push_s8(&tmp, s8(COMPUTE_SHADER_HEADER)); - if (csr->shader == CS_DECODE_FLOAT) { - s8 extra = push_s8(&tmp, s8(COMPUTE_FLOAT_DECODE_HEADER)); - ASSERT(extra.data == header.data + header.len); - header.len += extra.len; - } - } + if (csr->needs_header) + header = push_compute_shader_header(&tmp, csr->shader); s8 shader_text = ctx->platform.read_whole_file(&tmp, (c8 *)path.data); shader_text.data -= header.len; @@ -644,7 +669,7 @@ DEBUG_EXPORT BEAMFORMER_COMPLETE_COMPUTE_FN(beamformer_complete_compute) frame->max_coordinate = ctx->params->raw.output_max_coordinate; u32 stage_count = ctx->params->compute_stages_count; - enum compute_shaders *stages = ctx->params->compute_stages; + ComputeShaderID *stages = ctx->params->compute_stages; for (u32 i = 0; i < stage_count; i++) { frame->timer_active[stages[i]] = 1; glBeginQuery(GL_TIME_ELAPSED, frame->timer_ids[stages[i]]); diff --git a/beamformer.h b/beamformer.h @@ -142,12 +142,12 @@ typedef struct { typedef struct { BeamformerParameters raw; - enum compute_shaders compute_stages[16]; - u32 compute_stages_count; - b32 upload; - u32 raw_data_size; - b32 export_next_frame; - c8 export_pipe_name[1024]; + ComputeShaderID compute_stages[16]; + u32 compute_stages_count; + b32 upload; + u32 raw_data_size; + b32 export_next_frame; + c8 export_pipe_name[1024]; } BeamformerParametersFull; typedef struct { @@ -267,7 +267,7 @@ typedef struct { void *beamformer_ctx; s8 label; s8 path; - u32 shader; + ComputeShaderID shader; b32 needs_header; } ComputeShaderReloadContext; diff --git a/beamformer_parameters.h b/beamformer_parameters.h @@ -11,21 +11,27 @@ X(MIN_MAX, 6, "min_max", 0, "Min/Max") \ X(SUM, 7, "sum", 0, "Sum") -enum compute_shaders { +typedef enum { #define X(e, n, s, h, pn) CS_ ##e = n, COMPUTE_SHADERS #undef X CS_LAST -}; +} ComputeShaderID; -#define DECODE_MODE_NONE 0 -#define DECODE_MODE_HADAMARD 1 +#define DECODE_TYPES \ + X(NONE, 0, "None") \ + X(HADAMARD, 1, "Hadamard") -#define DAS_ID_FORCES 0 -#define DAS_ID_UFORCES 1 -#define DAS_ID_HERCULES 2 -#define DAS_ID_RCA_VLS 3 -#define DAS_ID_RCA_TPW 4 +#define DAS_TYPES \ + X(FORCES, 0, "FORCES") \ + X(UFORCES, 1, "UFORCES") \ + X(HERCULES, 2, "HERCULES") \ + X(RCA_VLS, 3, "VLS") \ + X(RCA_TPW, 4, "TPW") + +#define DAS_LOCAL_SIZE_X 32 +#define DAS_LOCAL_SIZE_Y 1 +#define DAS_LOCAL_SIZE_Z 32 #define MAX_BEAMFORMED_SAVED_FRAMES 16 /* NOTE: This struct follows the OpenGL std140 layout. DO NOT modify unless you have @@ -77,10 +83,6 @@ _Static_assert((offsetof(BeamformerParameters, output_min_coordinate) & 15) == 0 _Static_assert((sizeof(BeamformerParameters) & 15) == 0, "sizeof(BeamformerParameters) must be a multiple of 16"); -/* NOTE: garbage to get the prepocessor to properly stringize the value of a macro */ -#define str_(x) #x -#define str(x) str_(x) - #define COMPUTE_SHADER_HEADER "\ #version 460 core\n\ \n\ @@ -108,24 +110,4 @@ layout(std140, binding = 0) uniform parameters {\n\ float f_number; /* F# (set to 0 to disable) */\n\ uint readi_group_id; /* Which readi group this data is from */\n\ uint readi_group_size; /* Size of readi transmit group */\n\ -};\n\ -\n\ -#define DECODE_MODE_NONE " str(DECODE_MODE_NONE) "\n\ -#define DECODE_MODE_HADAMARD " str(DECODE_MODE_HADAMARD) "\n\ -\n\ -#define DAS_ID_FORCES " str(DAS_ID_FORCES) "\n\ -#define DAS_ID_UFORCES " str(DAS_ID_UFORCES) "\n\ -#define DAS_ID_HERCULES " str(DAS_ID_HERCULES) "\n\ -#define DAS_ID_RCA_VLS " str(DAS_ID_RCA_VLS) "\n\ -#define DAS_ID_RCA_TPW " str(DAS_ID_RCA_TPW) "\n\ -\n\ -#line 1\n" - -#define COMPUTE_FLOAT_DECODE_HEADER "\ -#define INPUT_DATA_TYPE_FLOAT\n\ -#line 1\n" - -/* TODO(rnp): bake this into the das shader header */ -#define DAS_LOCAL_SIZE_X 32 -#define DAS_LOCAL_SIZE_Y 1 -#define DAS_LOCAL_SIZE_Z 32 +};\n\n" diff --git a/helpers/ogl_beamformer_lib.c b/helpers/ogl_beamformer_lib.c @@ -3,12 +3,12 @@ typedef struct { BeamformerParameters raw; - enum compute_shaders compute_stages[16]; - u32 compute_stages_count; - b32 upload; - u32 raw_data_size; - b32 export_next_frame; - c8 export_pipe_name[1024]; + ComputeShaderID compute_stages[16]; + u32 compute_stages_count; + b32 upload; + u32 raw_data_size; + b32 export_next_frame; + c8 export_pipe_name[1024]; } BeamformerParametersFull; typedef struct { diff --git a/shaders/das.glsl b/shaders/das.glsl @@ -1,6 +1,4 @@ /* See LICENSE for license details. */ -layout(local_size_x = 32, local_size_y = 1, local_size_z = 32) in; - layout(std430, binding = 1) readonly restrict buffer buffer_1 { vec2 rf_data[]; }; diff --git a/util.h b/util.h @@ -39,6 +39,10 @@ #define static_assert _Static_assert +/* NOTE: garbage to get the prepocessor to properly stringize the value of a macro */ +#define str_(x) #x +#define str(x) str_(x) + #define ARRAY_COUNT(a) (sizeof(a) / sizeof(*a)) #define ABS(x) ((x) < 0 ? (-x) : (x)) #define BETWEEN(x, a, b) ((x) >= (a) && (x) <= (b))