ogl_beamforming

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

beamformer.h (8271B)


      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 RULER_TEXT_PAD         10.0f
     26 #define RULER_TICK_LENGTH      20.0f
     27 
     28 #define RECT_BTN_COLOUR        (Color){.r = 0x43, .g = 0x36, .b = 0x3a, .a = 0xff}
     29 #define RECT_BTN_BORDER_COLOUR (Color){.r = 0x00, .g = 0x00, .b = 0x00, .a = 0xCC}
     30 #define RECT_BTN_ROUNDNESS     0.3f
     31 #define RECT_BTN_BORDER_WIDTH  6.0f
     32 
     33 /* TODO: multiple views */
     34 #define MAX_DISPLAYS 1
     35 
     36 enum program_flags {
     37 	SHOULD_EXIT    = 1 << 0,
     38 	START_COMPUTE  = 1 << 1,
     39 };
     40 
     41 enum gl_vendor_ids {
     42 	GL_VENDOR_AMD,
     43 	GL_VENDOR_ARM,
     44 	GL_VENDOR_INTEL,
     45 	GL_VENDOR_NVIDIA,
     46 };
     47 
     48 typedef struct {
     49 	u8   buf[64];
     50 	i32  buf_len;
     51 	i32  cursor;
     52 	f32  cursor_blink_t;
     53 	f32  cursor_blink_scale;
     54 } InputState;
     55 
     56 enum variable_flags {
     57 	V_CAUSES_COMPUTE = 1 << 29,
     58 	V_GEN_MIPMAPS    = 1 << 30,
     59 };
     60 
     61 enum interaction_states {
     62 	IS_NONE,
     63 	IS_NOP,
     64 	IS_SET,
     65 	IS_DRAG,
     66 	IS_SCROLL,
     67 	IS_TEXT,
     68 
     69 	IS_DISPLAY,
     70 	IS_SCALE_BAR,
     71 };
     72 
     73 enum ruler_state {
     74 	RS_NONE,
     75 	RS_START,
     76 	RS_HOLD,
     77 };
     78 
     79 enum scale_bar_directions {
     80 	SB_LATERAL,
     81 	SB_AXIAL,
     82 };
     83 
     84 typedef struct {
     85 	Variable hot;
     86 	Variable next_hot;
     87 	Variable active;
     88 	u32      hot_state;
     89 	u32      state;
     90 } InteractionState;
     91 
     92 typedef struct v2_sll {
     93 	struct v2_sll *next;
     94 	v2             v;
     95 } v2_sll;
     96 
     97 typedef struct {
     98 	f32    *min_value, *max_value;
     99 	v2_sll *savepoint_stack;
    100 	v2      zoom_starting_point;
    101 	v2      screen_offset;
    102 	v2      screen_space_to_value;
    103 	f32     hover_t;
    104 	b32     scroll_both;
    105 } ScaleBar;
    106 
    107 typedef struct {
    108 	TempArena frame_temporary_arena;
    109 	Arena     arena_for_frame;
    110 
    111 	Font font;
    112 	Font small_font;
    113 	f32  font_height;
    114 	f32  small_font_height;
    115 
    116 	InteractionState interaction;
    117 	InputState       text_input_state;
    118 
    119 	ScaleBar scale_bars[MAX_DISPLAYS][2];
    120 	v2_sll   *scale_bar_savepoint_freelist;
    121 
    122 	v2  ruler_start_p;
    123 	v2  ruler_stop_p;
    124 	u32 ruler_state;
    125 } BeamformerUI;
    126 
    127 #define MAX_FRAMES_IN_FLIGHT 3
    128 
    129 #define INIT_CUDA_CONFIGURATION_FN(name) void name(u32 *input_dims, u32 *decoded_dims, u16 *channel_mapping)
    130 typedef INIT_CUDA_CONFIGURATION_FN(init_cuda_configuration_fn);
    131 INIT_CUDA_CONFIGURATION_FN(init_cuda_configuration_stub) {}
    132 
    133 #define REGISTER_CUDA_BUFFERS_FN(name) void name(u32 *rf_data_ssbos, u32 rf_buffer_count, u32 raw_data_ssbo)
    134 typedef REGISTER_CUDA_BUFFERS_FN(register_cuda_buffers_fn);
    135 REGISTER_CUDA_BUFFERS_FN(register_cuda_buffers_stub) {}
    136 
    137 #define CUDA_DECODE_FN(name) void name(size_t input_offset, u32 output_buffer_idx, u32 rf_channel_offset)
    138 typedef CUDA_DECODE_FN(cuda_decode_fn);
    139 CUDA_DECODE_FN(cuda_decode_stub) {}
    140 
    141 #define CUDA_HILBERT_FN(name) void name(u32 input_buffer_idx, u32 output_buffer_idx)
    142 typedef CUDA_HILBERT_FN(cuda_hilbert_fn);
    143 CUDA_HILBERT_FN(cuda_hilbert_stub) {}
    144 
    145 #define CUDA_LIB_FNS               \
    146 	X(cuda_decode)             \
    147 	X(cuda_hilbert)            \
    148 	X(init_cuda_configuration) \
    149 	X(register_cuda_buffers)
    150 
    151 typedef struct {
    152 	void                       *lib;
    153 	u64                         timestamp;
    154 	#define X(name) name ## _fn *name;
    155 	CUDA_LIB_FNS
    156 	#undef X
    157 } CudaLib;
    158 
    159 #include "beamformer_parameters.h"
    160 typedef struct {
    161 	BeamformerParameters raw;
    162 	enum compute_shaders compute_stages[16];
    163 	u32                  compute_stages_count;
    164 	b32                  upload;
    165 	b32                  export_next_frame;
    166 	c8                   export_pipe_name[1024];
    167 } BeamformerParametersFull;
    168 
    169 #define CS_UNIFORMS                             \
    170 	X(CS_DAS,     volume_export_dim_offset) \
    171 	X(CS_DAS,     volume_export_pass)       \
    172 	X(CS_DAS,     cycle_t)                  \
    173 	X(CS_MIN_MAX, mips_level)               \
    174 	X(CS_SUM,     sum_prescale)
    175 
    176 typedef struct {
    177 	u32 programs[CS_LAST];
    178 
    179 	u32    timer_index;
    180 	u32    timer_ids[MAX_FRAMES_IN_FLIGHT][CS_LAST];
    181 	b32    timer_active[MAX_FRAMES_IN_FLIGHT][CS_LAST];
    182 	GLsync timer_fences[MAX_FRAMES_IN_FLIGHT];
    183 	f32    last_frame_time[CS_LAST];
    184 
    185 	/* NOTE: the raw_data_ssbo is allocated at 3x the required size to allow for tiled
    186 	 * transfers when the GPU is running behind the CPU. It is not mapped on NVIDIA because
    187 	 * their drivers _will_ store the buffer in the system memory. This doesn't happen
    188 	 * for Intel or AMD and mapping the buffer is preferred. In either case incoming data can
    189 	 * be written to the arena at the appropriate offset for the current raw_data_index. An
    190 	 * additional BufferSubData is needed on NVIDIA to upload the data. */
    191 	GLsync raw_data_fences[MAX_FRAMES_IN_FLIGHT];
    192 	Arena  raw_data_arena;
    193 	u32    raw_data_ssbo;
    194 	u32    raw_data_index;
    195 
    196 	/* NOTE: Decoded data is only relevant in the context of a single frame. We use two
    197 	 * buffers so that they can be swapped when chaining multiple compute stages */
    198 	u32 rf_data_ssbos[2];
    199 	u32 last_output_ssbo_index;
    200 	u32 hadamard_texture;
    201 
    202 	u32 shared_ubo;
    203 
    204 	uv4 dec_data_dim;
    205 	uv2 rf_raw_dim;
    206 
    207 	#define X(idx, name) i32 name ## _id;
    208 	CS_UNIFORMS
    209 	#undef X
    210 } ComputeShaderCtx;
    211 
    212 typedef struct {
    213 	Shader          shader;
    214 	RenderTexture2D output;
    215 	/* TODO: cleanup: X macro? */
    216 	i32             db_cutoff_id;
    217 	i32             threshold_id;
    218 	f32             db;
    219 	f32             threshold;
    220 	b32             gen_mipmaps;
    221 } FragmentShaderCtx;
    222 
    223 typedef struct {
    224 	uv3 dim;
    225 	u32 texture;
    226 
    227 	/* NOTE: for use when displaying either prebeamformed frames or on the current frame
    228 	 * when we intend to recompute on the next frame */
    229 	v4  min_coordinate;
    230 	v4  max_coordinate;
    231 
    232 	u32 mips;
    233 } BeamformFrame;
    234 
    235 typedef struct {
    236 	BeamformFrame frame;
    237 	u32 timer_ids[2];
    238 	f32 runtime;
    239 	u32 rf_data_ssbo;
    240 	u32 shader;
    241 	u32 dispatch_index;
    242 	b32 timer_active;
    243 } PartialComputeCtx;
    244 
    245 typedef struct {
    246 	enum gl_vendor_ids vendor_id;
    247 	i32  version_major;
    248 	i32  version_minor;
    249 	i32  max_2d_texture_dim;
    250 	i32  max_3d_texture_dim;
    251 	i32  max_ssbo_size;
    252 	i32  max_ubo_size;
    253 } GLParams;
    254 
    255 enum beamform_work {
    256 	BW_FULL_COMPUTE,
    257 	BW_RECOMPUTE,
    258 	BW_PARTIAL_COMPUTE,
    259 	BW_SAVE_FRAME,
    260 	BW_SEND_FRAME,
    261 	BW_SSBO_COPY,
    262 };
    263 
    264 typedef struct {
    265 	u32 source_ssbo;
    266 	u32 dest_ssbo;
    267 } BeamformSSBOCopy;
    268 
    269 typedef struct {
    270 	BeamformFrame *frame;
    271 	iptr export_handle;
    272 	u32  raw_data_ssbo_index;
    273 	b32  first_pass;
    274 } BeamformCompute;
    275 
    276 typedef struct {
    277 	BeamformFrame *frame;
    278 	iptr output_handle;
    279 } BeamformOutputFrame;
    280 
    281 /* NOTE: discriminated union based on type */
    282 typedef struct BeamformWork {
    283 	struct BeamformWork *next;
    284 	union {
    285 		BeamformSSBOCopy    ssbo_copy_ctx;
    286 		BeamformCompute     compute_ctx;
    287 		BeamformOutputFrame output_frame_ctx;
    288 	};
    289 	u32 type;
    290 } BeamformWork;
    291 
    292 typedef struct {
    293 	BeamformWork *first;
    294 	BeamformWork *last;
    295 	BeamformWork *next_free;
    296 	i32 compute_in_flight;
    297 	b32 did_compute_this_frame;
    298 } BeamformWorkQueue;
    299 
    300 typedef struct {
    301 	BeamformFrame *frames;
    302 	u32 capacity;
    303 	u32 offset;
    304 	u32 cursor;
    305 	u32 needed_frames;
    306 } BeamformFrameIterator;
    307 
    308 typedef struct BeamformerCtx {
    309 	GLParams gl;
    310 
    311 	uv2 window_size;
    312 	u32 flags;
    313 
    314 	Arena ui_backing_store;
    315 	BeamformerUI *ui;
    316 
    317 	BeamformFrame beamform_frames[MAX_BEAMFORMED_SAVED_FRAMES];
    318 	u32 displayed_frame_index;
    319 
    320 	/* NOTE: this will only be used when we are averaging */
    321 	BeamformFrame averaged_frame;
    322 	ComputeShaderCtx  csctx;
    323 	FragmentShaderCtx fsctx;
    324 	PartialComputeCtx partial_compute_ctx;
    325 
    326 	Arena export_buffer;
    327 
    328 	CudaLib  cuda_lib;
    329 	Platform platform;
    330 	Stream   error_stream;
    331 
    332 	BeamformWorkQueue beamform_work_queue;
    333 
    334 	BeamformerParametersFull *params;
    335 } BeamformerCtx;
    336 
    337 #define LABEL_GL_OBJECT(type, id, s) {s8 _s = (s); glObjectLabel(type, id, _s.len, (c8 *)_s.data);}
    338 
    339 #define BEAMFORMER_FRAME_STEP_FN(name) void name(BeamformerCtx *ctx, Arena *arena, \
    340                                                  BeamformerInput *input)
    341 typedef BEAMFORMER_FRAME_STEP_FN(beamformer_frame_step_fn);
    342 
    343 #endif /*_BEAMFORMER_H_ */