ogl_beamforming

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

decode.glsl (3073B)


      1 /* See LICENSE for license details. */
      2 
      3 /* NOTE(rnp): invoked with samples x channels x transmits
      4  * Each instance extracts a single time sample from a single channel for all transmits
      5  * and does a dot product with the appropriate row of the bound hadamard matrix
      6  * (unless decode_mode == DECODE_MODE_NONE). The result of this dot product is stored in the
      7  * output. In bulk this has the effect of computing a matrix multiply of the
      8  * sample-transmit plane with the bound hadamard matrix.
      9  */
     10 
     11 #if   defined(INPUT_DATA_TYPE_FLOAT)
     12 	#define INPUT_DATA_TYPE      float
     13 	#define RF_SAMPLES_PER_INDEX 1
     14 	#define RESULT_TYPE_CAST(x)  vec4((x), 0, 0, 0)
     15 	#define SAMPLE_DATA_TYPE     float
     16 	#define SAMPLE_TYPE_CAST(x)  (x)
     17 #elif defined(INPUT_DATA_TYPE_FLOAT_COMPLEX)
     18 	#define INPUT_DATA_TYPE      vec2
     19 	#define RF_SAMPLES_PER_INDEX 1
     20 	#define RESULT_TYPE_CAST(x)  vec4((x), 0, 0)
     21 	#define SAMPLE_DATA_TYPE     vec2
     22 	#define SAMPLE_TYPE_CAST(x)  (x)
     23 #else
     24 	#define INPUT_DATA_TYPE      int
     25 	#define RF_SAMPLES_PER_INDEX 2
     26 	#define RESULT_TYPE_CAST(x)  (x)
     27 	#define SAMPLE_DATA_TYPE     vec4
     28 	/* NOTE(rnp): for i16 rf_data we decode 2 samples at once */
     29 	#define SAMPLE_TYPE_CAST(x)  vec4(((x) << 16) >> 16, 0, (x) >> 16, 0)
     30 #endif
     31 
     32 layout(std430, binding = 1) readonly restrict buffer buffer_1 {
     33 	INPUT_DATA_TYPE rf_data[];
     34 };
     35 
     36 layout(std430, binding = 2) writeonly restrict buffer buffer_2 {
     37 	INPUT_DATA_TYPE out_rf_data[];
     38 };
     39 
     40 layout(std430, binding = 3) writeonly restrict buffer buffer_3 {
     41 	vec2 out_data[];
     42 };
     43 
     44 layout(r8i,  binding = 0) readonly restrict uniform iimage2D hadamard;
     45 layout(r16i, binding = 1) readonly restrict uniform iimage1D channel_mapping;
     46 
     47 SAMPLE_DATA_TYPE sample_rf_data(uint index)
     48 {
     49 	SAMPLE_DATA_TYPE result = SAMPLE_TYPE_CAST(rf_data[index]);
     50 	return result;
     51 }
     52 
     53 void main()
     54 {
     55 	uint time_sample = gl_GlobalInvocationID.x * RF_SAMPLES_PER_INDEX;
     56 	uint channel     = gl_GlobalInvocationID.y;
     57 	uint transmit    = gl_GlobalInvocationID.z;
     58 
     59 	uint rf_offset = (channel * rf_raw_dim.x + time_sample * dec_data_dim.z) / RF_SAMPLES_PER_INDEX;
     60 	if (u_first_pass) {
     61 		int  rf_channel = imageLoad(channel_mapping, int(channel)).x;
     62 		uint in_off     = rf_channel * rf_raw_dim.x + transmit * dec_data_dim.x + time_sample;
     63 		out_rf_data[rf_offset + transmit] = rf_data[in_off / RF_SAMPLES_PER_INDEX];
     64 	} else {
     65 		/* NOTE(rnp): stores output as a 3D matrix with ordering of {samples, channels, transmits} */
     66 		uint out_off = dec_data_dim.x * dec_data_dim.y * transmit + dec_data_dim.x * channel + time_sample;
     67 
     68 		vec4 result = vec4(0);
     69 		switch (decode) {
     70 		case DECODE_MODE_NONE: {
     71 			result = RESULT_TYPE_CAST(sample_rf_data(rf_offset + transmit));
     72 		} break;
     73 		case DECODE_MODE_HADAMARD: {
     74 			SAMPLE_DATA_TYPE sum = SAMPLE_DATA_TYPE(0);
     75 			for (int i = 0; i < dec_data_dim.z; i++)
     76 				sum += imageLoad(hadamard, ivec2(i, transmit)).x * sample_rf_data(rf_offset++);
     77 			result = RESULT_TYPE_CAST(sum) / float(dec_data_dim.z);
     78 		} break;
     79 		}
     80 		out_data[out_off + 0] = result.xy;
     81 		#if RF_SAMPLES_PER_INDEX == 2
     82 		out_data[out_off + 1] = result.zw;
     83 		#endif
     84 	}
     85 }