ogl_beamforming

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

Commit: 2236c1d733d7fca11793307b2680239c8084a080
Parent: 39bef936bf5e1bf778684cb7d5b24eddc8900140
Author: Randy Palamar
Date:   Mon, 31 Aug 2026 06:41:49 -0700

core/shaders: store pointers into temp arena as offsets from a base pointer

This somewhat simplifies the planning code and reduces the size of
the bake parameters. It is also maybe more explicit to the shader
compiler that it can share the base pointer for all of these and
just use an offset but it might have already seen that.

Diffstat:
Mbeamformer.meta | 16++++++++--------
Mbeamformer_core.c | 168+++++++++++++++++++++++++++++++++++++------------------------------------------
Mbeamformer_internal.h | 4+++-
Mgenerated/beamformer.c | 90++++++++++++++++++++++++++++++++++++++++----------------------------------------
Mshaders/coherency_weighting.glsl | 4++--
Mshaders/das.glsl | 18++++++++++++------
Mshaders/decode.glsl | 6+++---
Mshaders/filter.glsl | 2+-
8 files changed, 153 insertions(+), 155 deletions(-)

diff --git a/beamformer.meta b/beamformer.meta @@ -324,7 +324,7 @@ @Bake { - [Hadamard U64] + [Hadamard U32] [DecodeMode U32] [OutputChannelStride U32] [OutputSampleStride U32] @@ -356,7 +356,7 @@ @Bake { - [FilterCoefficients U64] + [FilterCoefficients U32] [FilterLength U32] [SamplingFrequency F32] [DemodulationFrequency F32] @@ -395,11 +395,11 @@ @Bake { [RFData U64] - [FocalVectors U64] - [Hadamard U64] - [IncoherentFrame U64] - [SparseElements U64] - [TransmitReceiveOrientations U64] + [FocalVectors U32] + [Hadamard U32] + [IncoherentFrame U32] + [SparseElements U32] + [TransmitReceiveOrientations U32] [AcquisitionKind U32] [AcquisitionCount S32] @@ -452,7 +452,7 @@ @Bake { - [IncoherentSum U64] + [IncoherentSum U32] [Scale F32] [OutputVoxels U32] } diff --git a/beamformer_core.c b/beamformer_core.c @@ -64,8 +64,6 @@ #include "beamformer_internal.h" #define GPU_RESOURCE_HASH_TABLE_COUNT 256 -typedef struct U64ReferenceNode U64ReferenceNode; -struct U64ReferenceNode {u64 *v; U64ReferenceNode *next;}; typedef struct GPUResource GPUResource; struct GPUResource { @@ -78,8 +76,6 @@ struct GPUResource { u64 hash; - U64ReferenceNode *pointer_store_list; - GPUResource *next; GPUResource *hash_next, *hash_prev; }; @@ -221,7 +217,6 @@ typedef struct { str8 name; u64 align; u64 size; - u64 *store; void *data; } GPUResourcePushInfo; #define gpu_resource_push(rb, t, count, ...) gpu_resource_push_(rb, (GPUResourcePushInfo){\ @@ -229,10 +224,10 @@ typedef struct { .size = sizeof(t) * count, \ __VA_ARGS__}) -function void +function u32 gpu_resource_push_(GPUResourceBuilder *rb, GPUResourcePushInfo info) { - assert(info.store && info.size > 0 && info.name.length > 0 && IsPowerOfTwo(info.align)); + assert(info.size > 0 && info.name.length > 0 && IsPowerOfTwo(info.align)); u64 hash = u64_hash_from_str8(info.name); GPUResource *r = gpu_resource_from_hash(rb, hash); @@ -241,24 +236,23 @@ gpu_resource_push_(GPUResourceBuilder *rb, GPUResourcePushInfo info) GPUResourceHashBucket *hb = rb->hash_table + (hash % GPU_RESOURCE_HASH_TABLE_COUNT); DLLInsert(0, hb->first, hb->last, r, hash_next, hash_prev); SLLStackPush(rb->resource_list, r, next); + + r->hash = hash; + r->name = info.name; + r->alignment = Max(16, info.align); + r->offset = AlignUpPowerOfTwo(rb->position, r->alignment); + r->size = info.size; + rb->position = r->offset + r->size; } - r->hash = hash; - r->name = info.name; - r->alignment = Max(16, info.align); - r->offset = AlignUpPowerOfTwo(rb->position, r->alignment); - r->size = info.size; + u32 result = r->offset; // NOTE(rnp): if this is a new resource and no data is provided it is likely // a temporary GPU side buffer. if this is not a new resource and no data - // is provided then maybe it is shared and someone else already provided it + // is provided then maybe it is shared and someone else will provide it if (info.data) r->data = info.data; - U64ReferenceNode *output = push_struct(rb->arena, U64ReferenceNode); - output->v = info.store; - SLLStackPush(r->pointer_store_list, output, next); - - rb->position = r->offset + r->size; + return result; } function GPUResourceBuilder * @@ -282,12 +276,6 @@ gpu_resource_build_end(GPUResourceBuilder *rb, GPUBuffer *buffer) } ////////////////////////////////////// - // NOTE(rnp): fill in pointer outputs - for (GPUResource *r = rb->resource_list; r; r = r->next) - for (U64ReferenceNode *op = r->pointer_store_list; op; op = op->next) - *op->v = buffer->gpu_pointer + r->offset; - - ////////////////////////////////////// // NOTE(rnp): upload data for (GPUResource *r = rb->resource_list; r; r = r->next) if (r->data) @@ -830,11 +818,11 @@ plan_compute_pipeline(BeamformerComputePlan *cp, BeamformerParameterBlock *pb, A sd->dispatch.z = 1; } + sd->uses_heap = 1; u32 order = pb->parameters.acquisition_count; - gpu_resource_push(resource_builder, f16, order * order, - .data = make_hadamard_transpose(scratch, order, use_coop_matrix), - .name = str8("hadamard"), - .store = &db->Hadamard); + db->Hadamard = gpu_resource_push(resource_builder, f16, order * order, + .data = make_hadamard_transpose(scratch, order, use_coop_matrix), + .name = str8("hadamard")); }break; case BeamformerShaderKind_Demodulate: @@ -850,11 +838,11 @@ plan_compute_pipeline(BeamformerComputePlan *cp, BeamformerParameterBlock *pb, A BeamformerFilterBakeParameters *fb = &sd->bake.Filter; + sd->uses_heap = 1; fb->FilterLength = (u32)f->length; - gpu_resource_push(resource_builder, f32, f->length * (f->parameters.complex ? 2 : 1), - .data = f->data, - .name = push_str8_f(scratch, "filter_%u", sp->filter_slot), - .store = &fb->FilterCoefficients); + fb->FilterCoefficients = gpu_resource_push(resource_builder, f32, f->length * (f->parameters.complex ? 2 : 1), + .data = f->data, + .name = push_str8_f(scratch, "filter_%u", sp->filter_slot)); fb->SampleCount = input_sample_count; fb->DecimationRate = demod ? decimation_rate : 1; @@ -940,40 +928,40 @@ plan_compute_pipeline(BeamformerComputePlan *cp, BeamformerParameterBlock *pb, A sd->dispatch = dispatch_for_output(sd->layout, cp->output_points); if (id != BeamformerAcquisitionKind_UFORCES && id != BeamformerAcquisitionKind_FORCES && !single_focus) { - gpu_resource_push(resource_builder, v2, db->AcquisitionCount, - .store = &db->FocalVectors, - .data = pb->focal_vectors, - .name = str8("focal_vectors")); + db->FocalVectors = gpu_resource_push(resource_builder, v2, db->AcquisitionCount, + .data = pb->focal_vectors, + .name = str8("focal_vectors")); + sd->uses_heap = 1; } if (id != BeamformerAcquisitionKind_UFORCES && id != BeamformerAcquisitionKind_FORCES && !single_orientation) { - gpu_resource_push(resource_builder, u8, db->AcquisitionCount, - .store = &db->TransmitReceiveOrientations, - .data = pb->transmit_receive_orientations, - .name = str8("transmit_receive_orientations")); + db->TransmitReceiveOrientations = gpu_resource_push(resource_builder, u8, db->AcquisitionCount, + .data = pb->transmit_receive_orientations, + .name = str8("transmit_receive_orientations")); + sd->uses_heap = 1; } if (sparse) { - gpu_resource_push(resource_builder, i16, db->AcquisitionCount, - .store = &db->SparseElements, - .data = pb->sparse_elements, - .name = str8("sparse_elements")); + db->SparseElements = gpu_resource_push(resource_builder, i16, db->AcquisitionCount, + .data = pb->sparse_elements, + .name = str8("sparse_elements")); + sd->uses_heap = 1; } if (pb->parameters.coherency_weighting) { - gpu_resource_push(resource_builder, u32, 0, - .store = &db->IncoherentFrame, - .size = beamformer_incoherent_frame_byte_size(cp->output_points, das_data_kind), - .name = str8("incoherent_buffer")); + db->IncoherentFrame = gpu_resource_push(resource_builder, u32, 0, + .size = beamformer_incoherent_frame_byte_size(cp->output_points, das_data_kind), + .name = str8("incoherent_buffer")); + sd->uses_heap = 1; } cp->readi_group = pb->parameters.readi_group; if (db->ReadiGroupCount > 1) { u32 order = db->ReadiGroupCount; - gpu_resource_push(resource_builder, f16, order * order, - .store = &db->Hadamard, - .data = make_hadamard_transpose(scratch, order, 0), - .name = str8("readi_hadamard")); + db->Hadamard = gpu_resource_push(resource_builder, f16, order * order, + .data = make_hadamard_transpose(scratch, order, 0), + .name = str8("readi_hadamard")); + sd->uses_heap = 1; } }break; @@ -984,12 +972,12 @@ plan_compute_pipeline(BeamformerComputePlan *cp, BeamformerParameterBlock *pb, A sd->dispatch = dispatch_for_output(sd->layout, cp->output_points); BeamformerCoherencyWeightingBakeParameters *cw = &sd->bake.CoherencyWeighting; - cw->Scale = 1.f; - cw->OutputVoxels = cp->output_points.x * cp->output_points.y * cp->output_points.z; - gpu_resource_push(resource_builder, u32, 0, - .store = &cw->IncoherentSum, - .size = beamformer_incoherent_frame_byte_size(cp->output_points, das_data_kind), - .name = str8("incoherent_buffer")); + cw->Scale = 1.f; + cw->OutputVoxels = cp->output_points.x * cp->output_points.y * cp->output_points.z; + cw->IncoherentSum = gpu_resource_push(resource_builder, u32, 0, + .size = beamformer_incoherent_frame_byte_size(cp->output_points, das_data_kind), + .name = str8("incoherent_buffer")); + sd->uses_heap = 1; }break; case BeamformerShaderKind_Reshape:{ @@ -1051,7 +1039,7 @@ plan_compute_pipeline(BeamformerComputePlan *cp, BeamformerParameterBlock *pb, A } function void -stream_append_shader_header(Stream *s, i32 reloadable_index, BeamformerShaderDescriptor *sd, uv3 layout) +stream_append_shader_header(Stream *s, i32 reloadable_index, u64 gpu_heap_pointer, BeamformerShaderDescriptor *sd, uv3 layout) { stream_append_str8(s, str8("#version 460 core\n\n" "#extension GL_EXT_buffer_reference : require\n" @@ -1098,6 +1086,12 @@ stream_append_shader_header(Stream *s, i32 reloadable_index, BeamformerShaderDes stream_append_byte(s, '\n'); } + if (gpu_heap_pointer) { + stream_append_str8(s, str8("#define HeapBase u64(0x")); + stream_append_hex_u64(s, gpu_heap_pointer); + stream_append_str8(s, str8("ul)\n")); + } + if (sd) { BeamformerDataKind data_kinds[] = {sd->input_data_kind, sd->output_data_kind}; str8 line_prefixes[] = {str8_comp("Input"), str8_comp("Output")}; @@ -1155,7 +1149,8 @@ beamformer_reload_pipeline(VulkanHandle *pipeline, BeamformerShaderReloadInfo *s if (i == 0) push_constants_size = beamformer_shader_push_constant_sizes[reloadable_index]; else assert(push_constants_size == beamformer_shader_push_constant_sizes[reloadable_index]); - stream_append_shader_header(&shader_stream, reloadable_index, sris[i].shader_descriptor, sris[i].layout); + stream_append_shader_header(&shader_stream, reloadable_index, sris[i].gpu_heap_pointer, + sris[i].shader_descriptor, sris[i].layout); str8 shader_text; if (BakeShaders) { @@ -1210,23 +1205,6 @@ beamformer_reload_render_pipeline(VulkanHandle *pipeline, BeamformerShaderKind s } function void -beamformer_reload_compute_pipeline(VulkanHandle *pipeline, BeamformerShaderKind shader, - BeamformerShaderDescriptor *shader_descriptor, Arena *scratch) -{ - i32 index = beamformer_shader_reloadable_index_by_shader[shader]; - uv3 layout = shader_descriptor ? shader_descriptor->layout : (uv3){{gpu_info()->subgroup_size, 1, 1}}; - BeamformerShaderReloadInfo info = { - .shader = shader, - .shader_kind = VulkanShaderKind_Compute, - .shader_descriptor = shader_descriptor, - .filename_or_data = BakeShaders ? beamformer_shader_data[index][0] - : beamformer_reloadable_shader_files[index][0], - .layout = layout, - }; - beamformer_reload_pipeline(pipeline, &info, 1, scratch); -} - -function void beamformer_commit_parameter_block(BeamformerCtx *ctx, BeamformerComputePlan *cp, u32 block, Arena *scratch) { BeamformerParameterBlock *pb; @@ -1246,10 +1224,16 @@ beamformer_commit_parameter_block(BeamformerCtx *ctx, BeamformerComputePlan *cp, plan_compute_pipeline(cp, pb, scratch); + b32 heap_pointer_updated = cp->last_gpu_heap_pointer != cp->gpu_temp_arena.gpu_pointer; + cp->last_gpu_heap_pointer = cp->gpu_temp_arena.gpu_pointer; + for (u32 shader_slot = 0; shader_slot < cp->pipeline.shader_count; shader_slot++) { u128 hash = u128_hash_from_data(cp->shader_descriptors + shader_slot, sizeof(BeamformerShaderDescriptor)); - if (!u128_equal(hash, cp->shader_hashes[shader_slot])) + if (!u128_equal(hash, cp->shader_hashes[shader_slot]) || + (cp->shader_descriptors[shader_slot].uses_heap && heap_pointer_updated)) + { cp->dirty_programs |= 1 << shader_slot; + } cp->shader_hashes[shader_slot] = hash; } @@ -1482,11 +1466,22 @@ complete_queue(BeamformerCtx *ctx, BeamformWorkQueue *q, Arena *arena) if unlikely(dirty_programs) { for EachBit(dirty_programs, slot) { assert(slot < BeamformerMaxComputeShaderStages); - Temp scratch = temp_begin(arena); - beamformer_reload_compute_pipeline(cp->vulkan_pipelines + slot, - cp->pipeline.shaders[slot], - cp->shader_descriptors + slot, arena); - temp_end(scratch); + Temp scratch; + DeferLoop(scratch = temp_begin(arena), temp_end(scratch)) + { + u64 gpu_heap_pointer = cp->gpu_temp_arena.gpu_pointer; + i32 index = beamformer_shader_reloadable_index_by_shader[cp->pipeline.shaders[slot]]; + BeamformerShaderReloadInfo info = { + .shader = cp->pipeline.shaders[slot], + .shader_kind = VulkanShaderKind_Compute, + .shader_descriptor = cp->shader_descriptors + slot, + .gpu_heap_pointer = cp->shader_descriptors[slot].uses_heap ? gpu_heap_pointer : 0, + .filename_or_data = BakeShaders ? beamformer_shader_data[index][0] + : beamformer_reloadable_shader_files[index][0], + .layout = cp->shader_descriptors[slot].layout, + }; + beamformer_reload_pipeline(cp->vulkan_pipelines + slot, &info, 1, arena); + } } } @@ -1526,7 +1521,7 @@ complete_queue(BeamformerCtx *ctx, BeamformWorkQueue *q, Arena *arena) BeamformerCoherencyWeightingBakeParameters *cw = &cp->shader_descriptors[coherency_weighting].bake.CoherencyWeighting; GPUBuffer *gpu_arena = &cp->gpu_temp_arena; u64 coherent_size = beamformer_incoherent_frame_byte_size(frame->points, frame->data_kind); - gpu_command_clear_buffer(cmd, gpu_arena, cw->IncoherentSum - gpu_arena->gpu_pointer, coherent_size, 0); + gpu_command_clear_buffer(cmd, gpu_arena, cw->IncoherentSum, coherent_size, 0); } BeamformerRFBuffer *rf = &cs->rf_buffer; @@ -1826,11 +1821,6 @@ beamformer_process_input_events(BeamformerCtx *ctx, BeamformerInput *input, case BeamformerInputEventKind_FileEvent:{ BeamformerFileReloadContext *frc = event->file_watch_user_context; switch (frc->kind) { - case BeamformerFileReloadKind_ComputeInternalShader:{ - // TODO(rnp): this could stall, better to push it onto compute once queue is better - beamformer_reload_compute_pipeline(frc->shader_reload.pipeline, frc->shader_reload.shader, 0, ctx->arena); - }break; - case BeamformerFileReloadKind_ComputeShader:{ for EachElement(ctx->compute_context.compute_plans, block) { BeamformerComputePlan *cp = ctx->compute_context.compute_plans[block]; diff --git a/beamformer_internal.h b/beamformer_internal.h @@ -272,6 +272,7 @@ typedef struct { uv3 layout; uv3 dispatch; u32 compile_flags; + b32 uses_heap; BeamformerDataKind input_data_kind; BeamformerDataKind output_data_kind; BeamformerShaderBakeParameters bake; @@ -311,6 +312,7 @@ struct BeamformerComputePlan { u32 readi_group; + u64 last_gpu_heap_pointer; GPUBuffer gpu_temp_arena; BeamformerFilterParameters filter_parameters[BeamformerFilterSlots]; @@ -635,7 +637,6 @@ typedef struct { } BeamformerCtx; typedef enum { - BeamformerFileReloadKind_ComputeInternalShader, BeamformerFileReloadKind_ComputeShader, BeamformerFileReloadKind_RenderShader, } BeamformerFileReloadKind; @@ -654,6 +655,7 @@ typedef struct { BeamformerShaderDescriptor *shader_descriptor; + u64 gpu_heap_pointer; uv3 layout; } BeamformerShaderReloadInfo; diff --git a/generated/beamformer.c b/generated/beamformer.c @@ -159,7 +159,7 @@ typedef enum { } BeamformerShaderKind; typedef struct { - u64 Hadamard; + u32 Hadamard; u32 DecodeMode; u32 OutputChannelStride; u32 OutputSampleStride; @@ -173,7 +173,7 @@ typedef struct { } BeamformerDecodeBakeParameters; typedef struct { - u64 FilterCoefficients; + u32 FilterCoefficients; u32 FilterLength; f32 SamplingFrequency; f32 DemodulationFrequency; @@ -190,11 +190,11 @@ typedef struct { typedef struct { u64 RFData; - u64 FocalVectors; - u64 Hadamard; - u64 IncoherentFrame; - u64 SparseElements; - u64 TransmitReceiveOrientations; + u32 FocalVectors; + u32 Hadamard; + u32 IncoherentFrame; + u32 SparseElements; + u32 TransmitReceiveOrientations; u32 AcquisitionKind; i32 AcquisitionCount; i32 ReceiveChannelCount; @@ -216,7 +216,7 @@ typedef struct { } BeamformerDASBakeParameters; typedef struct { - u64 IncoherentSum; + u32 IncoherentSum; f32 Scale; u32 OutputVoxels; } BeamformerCoherencyWeightingBakeParameters; @@ -577,7 +577,8 @@ typedef enum { read_only global MetaStructMember *meta_struct_members_by_id[] = { (MetaStructMember []){ - {17, 0, 1, 0}, + {18, 0, 1, 0}, + {18, 4, 1, 0}, {18, 8, 1, 0}, {18, 12, 1, 0}, {18, 16, 1, 0}, @@ -587,13 +588,13 @@ read_only global MetaStructMember *meta_struct_members_by_id[] = { {18, 32, 1, 0}, {18, 36, 1, 0}, {18, 40, 1, 0}, - {18, 44, 1, 0}, }, (MetaStructMember []){ - {17, 0, 1, 0}, - {18, 8, 1, 0}, + {18, 0, 1, 0}, + {18, 4, 1, 0}, + {8, 8, 1, 0}, {8, 12, 1, 0}, - {8, 16, 1, 0}, + {18, 16, 1, 0}, {18, 20, 1, 0}, {18, 24, 1, 0}, {18, 28, 1, 0}, @@ -602,38 +603,37 @@ read_only global MetaStructMember *meta_struct_members_by_id[] = { {18, 40, 1, 0}, {18, 44, 1, 0}, {18, 48, 1, 0}, - {18, 52, 1, 0}, - }, - (MetaStructMember []){ - {17, 0, 1, 0}, - {17, 8, 1, 0}, - {17, 16, 1, 0}, - {17, 24, 1, 0}, - {17, 32, 1, 0}, - {17, 40, 1, 0}, - {18, 48, 1, 0}, - {10, 52, 1, 0}, - {10, 56, 1, 0}, - {10, 60, 1, 0}, - {10, 64, 1, 0}, - {8, 68, 1, 0}, - {8, 72, 1, 0}, - {8, 76, 1, 0}, - {8, 80, 1, 0}, - {18, 84, 1, 0}, - {8, 88, 1, 0}, - {18, 92, 1, 0}, - {8, 96, 1, 0}, - {8, 100, 1, 0}, - {18, 104, 1, 0}, - {18, 108, 1, 0}, - {18, 112, 1, 0}, - {18, 116, 1, 0}, }, (MetaStructMember []){ {17, 0, 1, 0}, - {8, 8, 1, 0}, + {18, 8, 1, 0}, {18, 12, 1, 0}, + {18, 16, 1, 0}, + {18, 20, 1, 0}, + {18, 24, 1, 0}, + {18, 28, 1, 0}, + {10, 32, 1, 0}, + {10, 36, 1, 0}, + {10, 40, 1, 0}, + {10, 44, 1, 0}, + {8, 48, 1, 0}, + {8, 52, 1, 0}, + {8, 56, 1, 0}, + {8, 60, 1, 0}, + {18, 64, 1, 0}, + {8, 68, 1, 0}, + {18, 72, 1, 0}, + {8, 76, 1, 0}, + {8, 80, 1, 0}, + {18, 84, 1, 0}, + {18, 88, 1, 0}, + {18, 92, 1, 0}, + {18, 96, 1, 0}, + }, + (MetaStructMember []){ + {18, 0, 1, 0}, + {8, 4, 1, 0}, + {18, 8, 1, 0}, }, (MetaStructMember []){ {18, 0, 1, 0}, @@ -722,10 +722,10 @@ read_only global str8 *meta_struct_member_names_by_id[] = { }; read_only global MetaStructInfo meta_struct_info_by_id[] = { - {str8_comp("DecodeBakeParameters"), 11, 48, 0}, - {str8_comp("FilterBakeParameters"), 13, 56, 0}, - {str8_comp("DASBakeParameters"), 24, 120, 0}, - {str8_comp("CoherencyWeightingBakeParameters"), 3, 16, 0}, + {str8_comp("DecodeBakeParameters"), 11, 44, 0}, + {str8_comp("FilterBakeParameters"), 13, 52, 0}, + {str8_comp("DASBakeParameters"), 24, 100, 0}, + {str8_comp("CoherencyWeightingBakeParameters"), 3, 12, 0}, {str8_comp("ReshapeBakeParameters"), 9, 36, 0}, }; diff --git a/shaders/coherency_weighting.glsl b/shaders/coherency_weighting.glsl @@ -17,10 +17,10 @@ layout(std430, buffer_reference, buffer_reference_align = 8) restrict buffer Flo #if InputDataKind == DataKind_Float32 #define COHERENT_SAMPLE(index) Float32(coherent_sum).values[index] - #define INCOHERENT_SAMPLE(index) Float32(IncoherentSum).values[index] + #define INCOHERENT_SAMPLE(index) Float32(HeapBase + IncoherentSum).values[index] #elif InputDataKind == DataKind_Float32Complex #define COHERENT_SAMPLE(index) Float32Complex(coherent_sum).values[index] - #define INCOHERENT_SAMPLE(index) Float32(IncoherentSum).values[index] + #define INCOHERENT_SAMPLE(index) Float32(HeapBase + IncoherentSum).values[index] #else #error DataKind unsupported for CoherencyWeighting #endif diff --git a/shaders/das.glsl b/shaders/das.glsl @@ -31,6 +31,12 @@ #define RESULT_STORE(a) (a) #endif +// NOTE(rnp): we don't want das to get recompiled when it isn't actually using the Heap +// but we also don't want to check everywhere in here for the existence of the Heap +#ifndef HeapBase + #define HeapBase u64(0) +#endif + layout(std430, buffer_reference) buffer Input { InputDataType x[]; }; layout(std430, buffer_reference) buffer Output { OutputDataType x[]; }; @@ -206,13 +212,13 @@ float cylindrical_wave_transmit_distance(const vec3 point, const float focal_dep u8 tx_rx_orientation_for_acquisition(const s32 acquisition) { u8 result = u8(TransmitReceiveOrientation); - if (!SingleOrientation) result = U8(TransmitReceiveOrientations).x[acquisition]; + if (!SingleOrientation) result = U8(HeapBase + TransmitReceiveOrientations).x[acquisition]; return result; } f32vec2 focal_vector_for_acquisition(const s32 acquisition) { - f32vec2 result = SingleFocus ? f32vec2(TransmitAngle, FocusDepth) : F32V2(FocalVectors).x[acquisition]; + f32vec2 result = SingleFocus ? f32vec2(TransmitAngle, FocusDepth) : F32V2(HeapBase + FocalVectors).x[acquisition]; return result; } @@ -291,7 +297,7 @@ RESULT_TYPE HERCULES(const vec3 world_point) rf_pointer -= InputDataKindByteSize * u32(InterpolationMode == InterpolationMode_Cubic); for (f32 transmit = f32(Sparse); transmit < f32(AcquisitionCount); transmit += 1.f) { - f32 tx_channel = Sparse ? f32(S16(SparseElements).x[s32(transmit) - s32(Sparse)]) : transmit; + f32 tx_channel = Sparse ? f32(S16(HeapBase + SparseElements).x[s32(transmit) - s32(Sparse)]) : transmit; f32 element_transmit_delta_squared = tx_world_point - tx_channel * tx_pitch; element_transmit_delta_squared *= element_transmit_delta_squared; @@ -337,7 +343,7 @@ RESULT_TYPE FORCES(const vec3 world_point) f32 receive_index = sample_index(sqrt(receive_x_delta * receive_x_delta + z_delta_squared)); f32 apodization = apodize(a_arg); for (f32 transmit = f32(Sparse); transmit < f32(AcquisitionCount); transmit += 1.f) { - f32 tx_channel = Sparse ? f32(S16(SparseElements).x[s32(transmit) - s32(Sparse)]) : transmit; + f32 tx_channel = Sparse ? f32(S16(HeapBase + SparseElements).x[s32(transmit) - s32(Sparse)]) : transmit; f32 transmit_x_delta = xdc_world_point.x - xdc_element_pitch.x * tx_channel; f32 transmit_index = sqrt(transmit_yz_squared + transmit_x_delta * transmit_x_delta) * SamplingFrequency / SpeedOfSound; @@ -381,7 +387,7 @@ RESULT_TYPE READI_FORCES(const vec3 world_point) // sequential elements. The first element in each group is beamformed using the first // acquisition, the second element in each group is beamformed using the second acquisition, etc. for (s32 tx_group = 0; tx_group < s32(ReadiGroupCount); tx_group++) { - f32 group_apodization = apodization * F16(Hadamard).x[hadamard_offset + tx_group]; + f32 group_apodization = apodization * F16(HeapBase + Hadamard).x[hadamard_offset + tx_group]; u64 rf_pointer = channel_rf_pointer; for (f32 tx_event = 0; tx_event < f32(AcquisitionCount); tx_event += 1.f) { @@ -434,7 +440,7 @@ void main() } #if CoherencyWeighting - IncoherentOutput(IncoherentFrame).x[out_index] += RESULT_INCOHERENT_CAST(sum); + IncoherentOutput(HeapBase + IncoherentFrame).x[out_index] += RESULT_INCOHERENT_CAST(sum); #endif Output(output_frame).x[out_index] += RESULT_COHERENT_CAST(sum); diff --git a/shaders/decode.glsl b/shaders/decode.glsl @@ -48,7 +48,7 @@ void run_decode_large(void) for (s32 i = 0; i < ToProcess; i++) result[i] = OutputDataType(0); - F16 h = F16(Hadamard); + F16 h = F16(HeapBase + Hadamard); for (s32 j = 0; j < TransmitCount; j++) { OutputDataType s = OutputDataType(rf[gl_LocalInvocationID.y][j]); for (s32 i = 0; i < ToProcess; i++) @@ -92,7 +92,7 @@ void run_decode_coop(void) u32 offset = ChunkChannelCount * TransmitCount * time_sample; - F16 h = F16(Hadamard); + F16 h = F16(HeapBase + Hadamard); for (u32 k = 0; k < TransmitCount; k += CooperativeMatrixK) { u32 rf_tile_row = CooperativeMatrixM * tile_index.y; u32 rf_tile_col = k; @@ -131,7 +131,7 @@ void run_decode_small(void) for (s32 j = 0; j < TransmitCount; j++) result[j] = OutputDataType(0); - F16 h = F16(Hadamard); + F16 h = F16(HeapBase + Hadamard); for (s32 i = 0; i < TransmitCount; i++) { OutputDataType s = OutputDataType(rf[i]); for (s32 j = 0; j < TransmitCount; j++) { diff --git a/shaders/filter.glsl b/shaders/filter.glsl @@ -106,7 +106,7 @@ void main() } barrier(); - Filter f = Filter(FilterCoefficients); + Filter f = Filter(HeapBase + FilterCoefficients); if (out_sample < SampleCount / DecimationRate) { RESULT_TYPE result = RESULT_TYPE(0); u32 offset = DecimationRate * thread_index;