ogl_beamforming

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

Commit: 005a95449bc29b51acc2060d53f71747319aa162
Parent: 332e2ccb9f5c5c406d9bb67fc45714c5a302c0c0
Author: Randy Palamar
Date:   Wed, 16 Oct 2024 15:59:08 -0600

drop uforces and lpf parameters from shaders

uforces can be calculated based on whether or not the
dec_data_dim.y == dec_data_dim.z and the lpf coefficients need to
be rethought to allow for more general filtering (we already never
use this shader for demodulation).

Diffstat:
Mbeamformer_parameters.h | 5+----
Mshaders/demod.glsl | 13++++++++-----
Mshaders/hadamard.glsl | 3---
Mshaders/hercules.glsl | 14++------------
Mshaders/uforces.glsl | 15+++------------
5 files changed, 14 insertions(+), 36 deletions(-)

diff --git a/beamformer_parameters.h b/beamformer_parameters.h @@ -16,7 +16,6 @@ enum compute_shaders { typedef struct { u16 channel_mapping[512]; /* Transducer Channel to Verasonics Channel */ u32 uforces_channels[128]; /* Channels used for virtual UFORCES elements */ - f32 lpf_coefficients[64]; /* Low Pass Filter Cofficients */ f32 xdc_origin[16]; /* [m] (4 v4s) Corner of transducer being treated as origin */ f32 xdc_corner1[16]; /* [m] (4 v4s) Corner of transducer along first axis (arbitrary) */ f32 xdc_corner2[16]; /* [m] (4 v4s) Corner of transducer along second axis (arbitrary) */ @@ -27,14 +26,12 @@ typedef struct { uv2 rf_raw_dim; /* Raw Data Dimensions */ u32 xdc_count; /* Number of Transducer Arrays (4 max) */ u32 channel_offset; /* Offset into channel_mapping: 0 or 128 (rows or columns) */ - u32 lpf_order; /* Order of Low Pass Filter */ f32 speed_of_sound; /* [m/s] */ f32 sampling_frequency; /* [Hz] */ f32 center_frequency; /* [Hz] */ f32 focal_depth; /* [m] */ f32 time_offset; /* pulse length correction time [s] */ - u32 uforces; /* mode is UFORCES (1) or FORCES (0) */ f32 off_axis_pos; /* [m] Position on screen normal to beamform in 2D HERCULES */ i32 beamform_plane; /* Plane to Beamform in 2D HERCULES */ - f32 _pad[3]; + f32 _pad[1]; } BeamformerParameters; diff --git a/shaders/demod.glsl b/shaders/demod.glsl @@ -10,10 +10,13 @@ layout(std430, binding = 2) writeonly restrict buffer buffer_2 { vec2 out_data[]; }; +layout(std430, binding = 3) readonly restrict buffer buffer_3 { + float filter_coefficients[]; +}; + layout(std140, binding = 0) uniform parameters { uvec4 channel_mapping[64]; /* Transducer Channel to Verasonics Channel */ uvec4 uforces_channels[32]; /* Channels used for virtual UFORCES elements */ - vec4 lpf_coefficients[16]; /* Low Pass Filter Cofficients */ vec4 xdc_origin[4]; /* [m] Corner of transducer being treated as origin */ vec4 xdc_corner1[4]; /* [m] Corner of transducer along first axis (arbitrary) */ vec4 xdc_corner2[4]; /* [m] Corner of transducer along second axis (arbitrary) */ @@ -24,17 +27,17 @@ layout(std140, binding = 0) uniform parameters { uvec2 rf_raw_dim; /* Raw Data Dimensions */ uint xdc_count; /* Number of Transducer Arrays (4 max) */ uint channel_offset; /* Offset into channel_mapping: 0 or 128 (rows or columns) */ - uint lpf_order; /* Order of Low Pass Filter */ float speed_of_sound; /* [m/s] */ float sampling_frequency; /* [Hz] */ float center_frequency; /* [Hz] */ float focal_depth; /* [m] */ float time_offset; /* pulse length correction time [s] */ - uint uforces; /* mode is UFORCES (1) or FORCES (0) */ float off_axis_pos; /* [m] Position on screen normal to beamform in 2D HERCULES */ int beamform_plane; /* Plane to Beamform in 2D HERCULES */ }; +layout(location = 0) uniform uint u_filter_order = 0; + void main() { uint time_sample = gl_GlobalInvocationID.x; @@ -50,12 +53,12 @@ void main() float arg_delta = radians(360) * center_frequency / sampling_frequency; vec2 sum = vec2(0); - for (int i = 0; i <= lpf_order; i++) { + for (int i = 0; i <= u_filter_order; i++) { vec2 data; /* NOTE: make sure data samples come from the same acquisition */ if (time_sample >= i) data = in_data[off - i].xx * vec2(cos(arg), sin(arg)); else data = vec2(0); - sum += lpf_coefficients[i / 4][i % 4] * data; + sum += filter_coefficients[i] * data; arg -= arg_delta; } out_data[off] = sum; diff --git a/shaders/hadamard.glsl b/shaders/hadamard.glsl @@ -17,7 +17,6 @@ layout(std430, binding = 3) readonly restrict buffer buffer_3 { layout(std140, binding = 0) uniform parameters { uvec4 channel_mapping[64]; /* Transducer Channel to Verasonics Channel */ uvec4 uforces_channels[32]; /* Channels used for virtual UFORCES elements */ - vec4 lpf_coefficients[16]; /* Low Pass Filter Cofficients */ vec4 xdc_origin[4]; /* [m] Corner of transducer being treated as origin */ vec4 xdc_corner1[4]; /* [m] Corner of transducer along first axis (arbitrary) */ vec4 xdc_corner2[4]; /* [m] Corner of transducer along second axis (arbitrary) */ @@ -28,13 +27,11 @@ layout(std140, binding = 0) uniform parameters { uvec2 rf_raw_dim; /* Raw Data Dimensions */ uint xdc_count; /* Number of Transducer Arrays (4 max) */ uint channel_offset; /* Offset into channel_mapping: 0 or 128 (rows or columns) */ - uint lpf_order; /* Order of Low Pass Filter */ float speed_of_sound; /* [m/s] */ float sampling_frequency; /* [Hz] */ float center_frequency; /* [Hz] */ float focal_depth; /* [m] */ float time_offset; /* pulse length correction time [s] */ - uint uforces; /* mode is UFORCES (1) or FORCES (0) */ float off_axis_pos; /* [m] Position on screen normal to beamform in 2D HERCULES */ int beamform_plane; /* Plane to Beamform in 2D HERCULES */ }; diff --git a/shaders/hercules.glsl b/shaders/hercules.glsl @@ -9,7 +9,6 @@ layout(std430, binding = 1) readonly restrict buffer buffer_1 { layout(std140, binding = 0) uniform parameters { uvec4 channel_mapping[64]; /* Transducer Channel to Verasonics Channel */ uvec4 uforces_channels[32]; /* Channels used for virtual UFORCES elements */ - vec4 lpf_coefficients[16]; /* Low Pass Filter Cofficients */ vec4 xdc_origin[4]; /* [m] Corner of transducer being treated as origin */ vec4 xdc_corner1[4]; /* [m] Corner of transducer along first axis (arbitrary) */ vec4 xdc_corner2[4]; /* [m] Corner of transducer along second axis (arbitrary) */ @@ -20,13 +19,11 @@ layout(std140, binding = 0) uniform parameters { uvec2 rf_raw_dim; /* Raw Data Dimensions */ uint xdc_count; /* Number of Transducer Arrays (4 max) */ uint channel_offset; /* Offset into channel_mapping: 0 or 128 (rows or columns) */ - uint lpf_order; /* Order of Low Pass Filter */ float speed_of_sound; /* [m/s] */ float sampling_frequency; /* [Hz] */ float center_frequency; /* [Hz] */ float focal_depth; /* [m] */ float time_offset; /* pulse length correction time [s] */ - uint uforces; /* mode is UFORCES (1) or FORCES (0) */ float off_axis_pos; /* [m] Position on screen normal to beamform in 2D HERCULES */ int beamform_plane; /* Plane to Beamform in 2D HERCULES */ }; @@ -109,9 +106,6 @@ void main() float f_num = 0.5; float apod_arg = f_num * 0.5 * radians(360) / abs(image_point.z); - /* NOTE: for I-Q data phase correction */ - float iq_time_scale = (lpf_order > 0)? radians(360) * center_frequency : 0; - /* NOTE: lerp along a line from one edge of the xdc to the other in the imaging plane */ vec3 delta = edge1 / float(dec_data_dim.y); vec3 xdc_start = xdc_origin[u_xdc_index].xyz; @@ -119,9 +113,6 @@ void main() vec3 starting_point = image_point - xdc_start; - /* NOTE: offset correcting for both pulse length and low pass filtering */ - float time_correction = time_offset + lpf_order / sampling_frequency; - vec2 sum = vec2(0); vec3 rdist = starting_point; @@ -148,7 +139,7 @@ void main() /* NOTE: For Each Virtual Source */ for (uint j = 0; j < dec_data_dim.y; j++) { float dist = transmit_dist + length(rdist); - float time = dist / speed_of_sound + time_correction; + float time = dist / speed_of_sound + time_offset; /* NOTE: apodization value for this transducer element */ float a = cos(clamp(abs(apod_arg * rdist.x), 0, 0.25 * radians(360))); @@ -157,8 +148,7 @@ void main() vec2 p = cubic(ridx, time * sampling_frequency); /* NOTE: tribal knowledge; this is a problem with the imaging sequence */ if (i == 0) p *= inversesqrt(128); - //p *= vec2(cos(iq_time_scale * time), sin(iq_time_scale * time)); - sum += p; + sum += p; rdist[direction] -= delta[direction]; ridx += dec_data_dim.x; diff --git a/shaders/uforces.glsl b/shaders/uforces.glsl @@ -9,7 +9,6 @@ layout(std430, binding = 1) readonly restrict buffer buffer_1 { layout(std140, binding = 0) uniform parameters { uvec4 channel_mapping[64]; /* Transducer Channel to Verasonics Channel */ uvec4 uforces_channels[32]; /* Channels used for virtual UFORCES elements */ - vec4 lpf_coefficients[16]; /* Low Pass Filter Cofficients */ vec4 xdc_origin[4]; /* [m] Corner of transducer being treated as origin */ vec4 xdc_corner1[4]; /* [m] Corner of transducer along first axis (arbitrary) */ vec4 xdc_corner2[4]; /* [m] Corner of transducer along second axis (arbitrary) */ @@ -20,13 +19,11 @@ layout(std140, binding = 0) uniform parameters { uvec2 rf_raw_dim; /* Raw Data Dimensions */ uint xdc_count; /* Number of Transducer Arrays (4 max) */ uint channel_offset; /* Offset into channel_mapping: 0 or 128 (rows or columns) */ - uint lpf_order; /* Order of Low Pass Filter */ float speed_of_sound; /* [m/s] */ float sampling_frequency; /* [Hz] */ float center_frequency; /* [Hz] */ float focal_depth; /* [m] */ float time_offset; /* pulse length correction time [s] */ - uint uforces; /* mode is UFORCES (1) or FORCES (0) */ float off_axis_pos; /* [m] Position on screen normal to beamform in 2D HERCULES */ int beamform_plane; /* Plane to Beamform in 2D HERCULES */ }; @@ -106,9 +103,6 @@ void main() float f_num = 0.5; float apod_arg = f_num * 0.5 * radians(360) / abs(image_point.z); - /* NOTE: for I-Q data phase correction */ - float iq_time_scale = (lpf_order > 0)? radians(360) * center_frequency : 0; - /* NOTE: lerp along a line from one edge of the xdc to the other in the imaging plane */ vec3 delta = edge1 / float(dec_data_dim.y); vec3 xdc_start = xdc_origin[u_xdc_index].xyz; @@ -116,14 +110,12 @@ void main() vec3 starting_point = image_point - xdc_start; - /* NOTE: offset correcting for both pulse length and low pass filtering */ - float time_correction = time_offset + lpf_order / sampling_frequency; - vec2 sum = vec2(0); /* NOTE: skip over channels corresponding to other arrays */ uint ridx = u_xdc_index * (dec_data_dim.y / xdc_count) * dec_data_dim.x * dec_data_dim.z; /* NOTE: skip first acquisition in uforces since its garbage */ - ridx += dec_data_dim.y * dec_data_dim.x * uforces; + uint uforces = uint(dec_data_dim.y != dec_data_dim.z); + ridx += dec_data_dim.y * dec_data_dim.x * uforces; for (uint i = uforces; i < dec_data_dim.z; i++) { uint base_idx = (i - uforces) / 4; uint sub_idx = (i - uforces) % 4; @@ -133,14 +125,13 @@ void main() vec3 rdist = starting_point; for (uint j = 0; j < dec_data_dim.y; j++) { float dist = transmit_dist + length(rdist); - float time = dist / speed_of_sound + time_correction; + float time = dist / speed_of_sound + time_offset; /* NOTE: apodization value for this transducer element */ float a = cos(clamp(abs(apod_arg * rdist.x), 0, 0.25 * radians(360))); a = a * a; vec2 p = cubic(ridx, time * sampling_frequency); - p *= vec2(cos(iq_time_scale * time), sin(iq_time_scale * time)); sum += p * a; rdist -= delta; ridx += dec_data_dim.x;