ogl_beamforming

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

beamformer.h (7663B)


      1 /* See LICENSE for license details. */
      2 #ifndef _BEAMFORMER_H_
      3 #define _BEAMFORMER_H_
      4 
      5 #include <glad.h>
      6 
      7 #define GRAPHICS_API_OPENGL_43
      8 #include <raylib.h>
      9 #include <rlgl.h>
     10 
     11 #include "util.h"
     12 
     13 #define BG_COLOUR              (v4){.r = 0.15, .g = 0.12, .b = 0.13, .a = 1.0}
     14 #define FG_COLOUR              (v4){.r = 0.92, .g = 0.88, .b = 0.78, .a = 1.0}
     15 #define FOCUSED_COLOUR         (v4){.r = 0.86, .g = 0.28, .b = 0.21, .a = 1.0}
     16 #define HOVERED_COLOUR         (v4){.r = 0.11, .g = 0.50, .b = 0.59, .a = 1.0}
     17 #define RULER_COLOUR           (v4){.r = 1.00, .g = 0.70, .b = 0.00, .a = 1.0}
     18 
     19 #define INFO_COLUMN_WIDTH      560
     20 /* NOTE: extra space used for allowing mouse clicks after end of text */
     21 #define TEXT_BOX_EXTRA_X       10.0f
     22 
     23 #define TEXT_HOVER_SPEED       5.0f
     24 
     25 #define RECT_BTN_COLOUR        (Color){.r = 0x43, .g = 0x36, .b = 0x3a, .a = 0xff}
     26 #define RECT_BTN_BORDER_COLOUR (Color){.r = 0x00, .g = 0x00, .b = 0x00, .a = 0xCC}
     27 #define RECT_BTN_ROUNDNESS     0.3f
     28 #define RECT_BTN_BORDER_WIDTH  6.0f
     29 
     30 enum program_flags {
     31 	SHOULD_EXIT    = 1 << 0,
     32 	RELOAD_SHADERS = 1 << 1,
     33 	GEN_MIPMAPS    = 1 << 30,
     34 };
     35 
     36 enum gl_vendor_ids {
     37 	GL_VENDOR_AMD,
     38 	GL_VENDOR_ARM,
     39 	GL_VENDOR_INTEL,
     40 	GL_VENDOR_NVIDIA,
     41 };
     42 
     43 typedef struct {
     44 	u8   buf[64];
     45 	i32  buf_len;
     46 	i32  cursor;
     47 	f32  cursor_blink_t;
     48 	f32  cursor_blink_scale;
     49 } InputState;
     50 
     51 enum variable_flags {
     52 	V_CAUSES_COMPUTE = 1 << 29,
     53 	V_GEN_MIPMAPS    = 1 << 30,
     54 };
     55 
     56 enum interaction_states {
     57 	IS_NONE,
     58 	IS_NOP,
     59 	IS_SET,
     60 	IS_DRAG,
     61 	IS_SCROLL,
     62 	IS_TEXT,
     63 
     64 	IS_DISPLAY,
     65 	IS_SCALE_BAR,
     66 };
     67 
     68 typedef struct {
     69 	Variable hot;
     70 	Variable next_hot;
     71 	Variable active;
     72 	u32      hot_state;
     73 	u32      state;
     74 	v2       last_mouse_click_p;
     75 } InteractionState;
     76 
     77 typedef struct {
     78 	TempArena frame_temporary_arena;
     79 	Arena     arena_for_frame;
     80 
     81 	Font font;
     82 	Font small_font;
     83 
     84 	InteractionState interaction;
     85 	InputState       text_input_state;
     86 } BeamformerUI;
     87 
     88 #define MAX_FRAMES_IN_FLIGHT 3
     89 
     90 #define INIT_CUDA_CONFIGURATION_FN(name) void name(u32 *input_dims, u32 *decoded_dims, u16 *channel_mapping)
     91 typedef INIT_CUDA_CONFIGURATION_FN(init_cuda_configuration_fn);
     92 INIT_CUDA_CONFIGURATION_FN(init_cuda_configuration_stub) {}
     93 
     94 #define REGISTER_CUDA_BUFFERS_FN(name) void name(u32 *rf_data_ssbos, u32 rf_buffer_count, u32 raw_data_ssbo)
     95 typedef REGISTER_CUDA_BUFFERS_FN(register_cuda_buffers_fn);
     96 REGISTER_CUDA_BUFFERS_FN(register_cuda_buffers_stub) {}
     97 
     98 #define CUDA_DECODE_FN(name) void name(size_t input_offset, u32 output_buffer_idx, u32 rf_channel_offset)
     99 typedef CUDA_DECODE_FN(cuda_decode_fn);
    100 CUDA_DECODE_FN(cuda_decode_stub) {}
    101 
    102 #define CUDA_HILBERT_FN(name) void name(u32 input_buffer_idx, u32 output_buffer_idx)
    103 typedef CUDA_HILBERT_FN(cuda_hilbert_fn);
    104 CUDA_HILBERT_FN(cuda_hilbert_stub) {}
    105 
    106 #define CUDA_LIB_FNS               \
    107 	X(cuda_decode)             \
    108 	X(cuda_hilbert)            \
    109 	X(init_cuda_configuration) \
    110 	X(register_cuda_buffers)
    111 
    112 typedef struct {
    113 	void                       *lib;
    114 	u64                         timestamp;
    115 	#define X(name) name ## _fn *name;
    116 	CUDA_LIB_FNS
    117 	#undef X
    118 } CudaLib;
    119 
    120 #include "beamformer_parameters.h"
    121 typedef struct {
    122 	BeamformerParameters raw;
    123 	enum compute_shaders compute_stages[16];
    124 	u32                  compute_stages_count;
    125 	b32                  upload;
    126 	b32                  export_next_frame;
    127 	c8                   export_pipe_name[1024];
    128 } BeamformerParametersFull;
    129 
    130 #define CS_UNIFORMS                             \
    131 	X(CS_DAS,     volume_export_dim_offset) \
    132 	X(CS_DAS,     volume_export_pass)       \
    133 	X(CS_DAS,     xdc_index)                \
    134 	X(CS_DAS,     xdc_transform)            \
    135 	X(CS_DAS,     cycle_t)                  \
    136 	X(CS_MIN_MAX, mips_level)               \
    137 	X(CS_SUM,     sum_prescale)
    138 
    139 typedef struct {
    140 	u32 programs[CS_LAST];
    141 
    142 	u32    timer_index;
    143 	u32    timer_ids[MAX_FRAMES_IN_FLIGHT][CS_LAST];
    144 	b32    timer_active[MAX_FRAMES_IN_FLIGHT][CS_LAST];
    145 	GLsync timer_fences[MAX_FRAMES_IN_FLIGHT];
    146 	f32    last_frame_time[CS_LAST];
    147 
    148 	/* NOTE: the raw_data_ssbo is allocated at 3x the required size to allow for tiled
    149 	 * transfers when the GPU is running behind the CPU. It is not mapped on NVIDIA because
    150 	 * their drivers _will_ store the buffer in the system memory. This doesn't happen
    151 	 * for Intel or AMD and mapping the buffer is preferred. In either case incoming data can
    152 	 * be written to the arena at the appropriate offset for the current raw_data_index. An
    153 	 * additional BufferSubData is needed on NVIDIA to upload the data. */
    154 	GLsync raw_data_fences[MAX_FRAMES_IN_FLIGHT];
    155 	Arena  raw_data_arena;
    156 	u32    raw_data_ssbo;
    157 	u32    raw_data_index;
    158 
    159 	/* NOTE: Decoded data is only relevant in the context of a single frame. We use two
    160 	 * buffers so that they can be swapped when chaining multiple compute stages */
    161 	u32 rf_data_ssbos[2];
    162 	u32 last_output_ssbo_index;
    163 	u32 hadamard_ssbo;
    164 	uv2 hadamard_dim;
    165 
    166 	u32 shared_ubo;
    167 
    168 	uv4 dec_data_dim;
    169 	uv2 rf_raw_dim;
    170 
    171 	#define X(idx, name) i32 name ## _id;
    172 	CS_UNIFORMS
    173 	#undef X
    174 } ComputeShaderCtx;
    175 
    176 typedef struct {
    177 	Shader          shader;
    178 	RenderTexture2D output;
    179 	/* TODO: cleanup: X macro? */
    180 	i32             db_cutoff_id;
    181 	i32             threshold_id;
    182 	f32             db;
    183 	f32             threshold;
    184 } FragmentShaderCtx;
    185 
    186 typedef struct {
    187 	/* NOTE: we always have one extra texture to sum into; thus the final output data
    188 	 * is always found in textures[dim.w - 1] */
    189 	u32 textures[MAX_MULTI_XDC_COUNT + 1];
    190 	uv4 dim;
    191 	u32 mips;
    192 } BeamformFrame;
    193 
    194 typedef struct {
    195 	BeamformFrame frame;
    196 	u32 timer_ids[2];
    197 	f32 runtime;
    198 	u32 rf_data_ssbo;
    199 	u32 shader;
    200 	u32 dispatch_index;
    201 	b32 timer_active;
    202 } PartialComputeCtx;
    203 
    204 typedef struct {
    205 	enum gl_vendor_ids vendor_id;
    206 	i32  version_major;
    207 	i32  version_minor;
    208 	i32  max_2d_texture_dim;
    209 	i32  max_3d_texture_dim;
    210 	i32  max_ssbo_size;
    211 	i32  max_ubo_size;
    212 } GLParams;
    213 
    214 enum beamform_work {
    215 	BW_FULL_COMPUTE,
    216 	BW_RECOMPUTE,
    217 	BW_PARTIAL_COMPUTE,
    218 	BW_SAVE_FRAME,
    219 	BW_SEND_FRAME,
    220 	BW_SSBO_COPY,
    221 };
    222 
    223 typedef struct {
    224 	u32 source_ssbo;
    225 	u32 dest_ssbo;
    226 } BeamformSSBOCopy;
    227 
    228 typedef struct {
    229 	BeamformFrame *frame;
    230 	iptr export_handle;
    231 	u32  raw_data_ssbo_index;
    232 	b32  first_pass;
    233 } BeamformCompute;
    234 
    235 typedef struct {
    236 	BeamformFrame *frame;
    237 	iptr output_handle;
    238 } BeamformOutputFrame;
    239 
    240 /* NOTE: discriminated union based on type */
    241 typedef struct BeamformWork {
    242 	struct BeamformWork *next;
    243 	union {
    244 		BeamformSSBOCopy    ssbo_copy_ctx;
    245 		BeamformCompute     compute_ctx;
    246 		BeamformOutputFrame output_frame_ctx;
    247 	};
    248 	u32 type;
    249 } BeamformWork;
    250 
    251 typedef struct {
    252 	BeamformWork *first;
    253 	BeamformWork *last;
    254 	BeamformWork *next_free;
    255 	i32 compute_in_flight;
    256 	b32 did_compute_this_frame;
    257 } BeamformWorkQueue;
    258 
    259 typedef struct {
    260 	BeamformFrame *frames;
    261 	u32 capacity;
    262 	u32 offset;
    263 	u32 cursor;
    264 	u32 needed_frames;
    265 } BeamformFrameIterator;
    266 
    267 typedef struct BeamformerCtx {
    268 	GLParams gl;
    269 
    270 	uv2 window_size;
    271 	u32 flags;
    272 
    273 	Arena ui_backing_store;
    274 	BeamformerUI *ui;
    275 
    276 	BeamformFrame beamform_frames[MAX_BEAMFORMED_SAVED_FRAMES];
    277 	u32 displayed_frame_index;
    278 
    279 	/* NOTE: this will only be used when we are averaging */
    280 	BeamformFrame averaged_frame;
    281 	ComputeShaderCtx  csctx;
    282 	FragmentShaderCtx fsctx;
    283 	PartialComputeCtx partial_compute_ctx;
    284 
    285 	Arena export_buffer;
    286 
    287 	CudaLib  cuda_lib;
    288 	Platform platform;
    289 	Stream   error_stream;
    290 
    291 	BeamformWorkQueue beamform_work_queue;
    292 
    293 	BeamformerParametersFull *params;
    294 } BeamformerCtx;
    295 
    296 #define LABEL_GL_OBJECT(type, id, s) {s8 _s = (s); glObjectLabel(type, id, _s.len, (c8 *)_s.data);}
    297 
    298 #define BEAMFORMER_FRAME_STEP_FN(name) void name(BeamformerCtx *ctx, Arena *arena, \
    299                                                  BeamformerInput *input)
    300 typedef BEAMFORMER_FRAME_STEP_FN(beamformer_frame_step_fn);
    301 
    302 #endif /*_BEAMFORMER_H_ */