ogl_beamforming

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

decode.glsl (2958B)


      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 	vec2 out_data[];
     38 };
     39 
     40 layout(r8i,  binding = 0) readonly restrict uniform iimage2D hadamard;
     41 layout(r16i, binding = 1) readonly restrict uniform iimage1D channel_mapping;
     42 
     43 SAMPLE_DATA_TYPE sample_rf_data(int index)
     44 {
     45 	SAMPLE_DATA_TYPE result = SAMPLE_TYPE_CAST(rf_data[index]);
     46 	return result;
     47 }
     48 
     49 void main()
     50 {
     51 	int time_sample = int(gl_GlobalInvocationID.x);
     52 	int channel     = int(gl_GlobalInvocationID.y);
     53 	int transmit    = int(gl_GlobalInvocationID.z);
     54 
     55 	/* NOTE(rnp): stores output as a 3D matrix with ordering of {samples, channels, transmits} */
     56 	uint out_off  = dec_data_dim.x * dec_data_dim.y * transmit + dec_data_dim.x * channel;
     57 	out_off      += RF_SAMPLES_PER_INDEX * time_sample;
     58 
     59 	int rf_channel = imageLoad(channel_mapping, channel).x;
     60 
     61 	/* NOTE(rnp): samples input as 2D matrix of {samples * transmits + padding, channels} */
     62 	int rf_stride = int(dec_data_dim.x) / RF_SAMPLES_PER_INDEX;
     63 	int rf_offset = (int(rf_raw_dim.x) * rf_channel) / RF_SAMPLES_PER_INDEX + time_sample;
     64 
     65 	vec4 result = vec4(0);
     66 	switch (decode) {
     67 	case DECODE_MODE_NONE: {
     68 		result = RESULT_TYPE_CAST(sample_rf_data(rf_offset + rf_stride * transmit));
     69 	} break;
     70 	case DECODE_MODE_HADAMARD: {
     71 		SAMPLE_DATA_TYPE sum = SAMPLE_DATA_TYPE(0);
     72 		for (int i = 0; i < dec_data_dim.z; i++) {
     73 			sum += imageLoad(hadamard, ivec2(i, transmit)).x * sample_rf_data(rf_offset);
     74 			rf_offset += rf_stride;
     75 		}
     76 		result = RESULT_TYPE_CAST(sum) / float(dec_data_dim.z);
     77 	} break;
     78 	}
     79 	out_data[out_off + 0] = result.xy;
     80 #if RF_SAMPLES_PER_INDEX == 2
     81 	out_data[out_off + 1] = result.zw;
     82 #endif
     83 }