ogl_beamforming

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

hadamard.glsl (2457B)


      1 /* See LICENSE for license details. */
      2 layout(local_size_x = 32, local_size_y = 32, local_size_z = 1) in;
      3 
      4 layout(std430, binding = 1) readonly restrict buffer buffer_1 {
      5 	int rf_data[];
      6 };
      7 
      8 layout(std430, binding = 2) writeonly restrict buffer buffer_2 {
      9 	vec2 out_data[];
     10 };
     11 
     12 layout(std430, binding = 3) readonly restrict buffer buffer_3 {
     13 	int hadamard[];
     14 };
     15 
     16 void main()
     17 {
     18 	/* NOTE: each invocation takes a time sample and a receive channel.
     19 	 * It first maps the column to the correct column in the rf data then
     20 	 * does the dot product with the equivalent row of the hadamard matrix.
     21 	 * The result is stored to the equivalent row, column index of the output.
     22 	 */
     23 	uint time_sample = gl_GlobalInvocationID.x;
     24 	uint channel     = gl_GlobalInvocationID.y;
     25 	uint acq         = gl_GlobalInvocationID.z;
     26 
     27 	/* NOTE: offsets for storing the results in the output data */
     28 	uint out_off = dec_data_dim.x * dec_data_dim.y * acq + dec_data_dim.x * channel + time_sample;
     29 
     30 	/* NOTE: channel mapping is stored as u16s so we must do this to extract the final value */
     31 	uint ch_array_idx = ((channel + channel_offset) / 8);
     32 	uint ch_vec_idx   = ((channel + channel_offset) % 8) / 2;
     33 	uint ch_elem_lfs  = ((channel + channel_offset) & 1u) * 16;
     34 	uint rf_channel   = (channel_mapping[ch_array_idx][ch_vec_idx] << ch_elem_lfs) >> 16;
     35 
     36 	/* NOTE: stride is the number of samples between acquistions; off is the
     37 	 * index of the first acquisition for this channel and time sample  */
     38 	uint rf_stride = dec_data_dim.x;
     39 	uint rf_off    = rf_raw_dim.x * rf_channel + time_sample;
     40 
     41 	/* NOTE: rf_data index and stride considering the data is i16 not i32 */
     42 	uint ridx       = rf_off / 2;
     43 	uint ridx_delta = rf_stride / 2;
     44 
     45 	/* NOTE: rf_data is i16 so each access grabs two time samples at time.
     46 	 * We need to shift arithmetically (maintaining the sign) to get the
     47 	 * desired element. If the time sample is even we take the upper half
     48 	 * and if its odd we take the lower half. */
     49 	uint lfs = ((~time_sample) & 1u) * 16;
     50 
     51 	/* NOTE: Compute N-D dot product */
     52 	int sum = 0;
     53 	if (decode == 1) {
     54 		/* NOTE: offset to get the correct column in hadamard matrix */
     55 		uint hoff = dec_data_dim.z * acq;
     56 
     57 		for (int i = 0; i < dec_data_dim.z; i++) {
     58 			int data = (rf_data[ridx] << lfs) >> 16;
     59 			sum  += hadamard[hoff + i] * data;
     60 			ridx += ridx_delta;
     61 		}
     62 	} else {
     63 		ridx += ridx_delta * acq;
     64 		sum   = (rf_data[ridx] << lfs) >> 16;
     65 	}
     66 	out_data[out_off] = vec2(float(sum), 0);
     67 }