ogl_beamforming

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

beamformer.h (6788B)


      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_extended.h>
      9 #include <rlgl.h>
     10 
     11 #include "util.h"
     12 
     13 enum gl_vendor_ids {
     14 	GL_VENDOR_AMD,
     15 	GL_VENDOR_ARM,
     16 	GL_VENDOR_INTEL,
     17 	GL_VENDOR_NVIDIA,
     18 };
     19 
     20 typedef struct {
     21 	b32  executable_reloaded;
     22 	b32  pipe_data_available;
     23 	iptr pipe_handle;
     24 
     25 	v2 mouse;
     26 	v2 last_mouse;
     27 } BeamformerInput;
     28 
     29 #define INIT_CUDA_CONFIGURATION_FN(name) void name(u32 *input_dims, u32 *decoded_dims, u16 *channel_mapping)
     30 typedef INIT_CUDA_CONFIGURATION_FN(init_cuda_configuration_fn);
     31 INIT_CUDA_CONFIGURATION_FN(init_cuda_configuration_stub) {}
     32 
     33 #define REGISTER_CUDA_BUFFERS_FN(name) void name(u32 *rf_data_ssbos, u32 rf_buffer_count, u32 raw_data_ssbo)
     34 typedef REGISTER_CUDA_BUFFERS_FN(register_cuda_buffers_fn);
     35 REGISTER_CUDA_BUFFERS_FN(register_cuda_buffers_stub) {}
     36 
     37 #define CUDA_DECODE_FN(name) void name(size_t input_offset, u32 output_buffer_idx, u32 rf_channel_offset)
     38 typedef CUDA_DECODE_FN(cuda_decode_fn);
     39 CUDA_DECODE_FN(cuda_decode_stub) {}
     40 
     41 #define CUDA_HILBERT_FN(name) void name(u32 input_buffer_idx, u32 output_buffer_idx)
     42 typedef CUDA_HILBERT_FN(cuda_hilbert_fn);
     43 CUDA_HILBERT_FN(cuda_hilbert_stub) {}
     44 
     45 #define CUDA_LIB_FNS               \
     46 	X(cuda_decode)             \
     47 	X(cuda_hilbert)            \
     48 	X(init_cuda_configuration) \
     49 	X(register_cuda_buffers)
     50 
     51 typedef struct {
     52 	void                       *lib;
     53 	u64                         timestamp;
     54 	#define X(name) name ## _fn *name;
     55 	CUDA_LIB_FNS
     56 	#undef X
     57 } CudaLib;
     58 
     59 #include "beamformer_parameters.h"
     60 
     61 typedef struct {
     62 	BeamformerParameters raw;
     63 	ComputeShaderID compute_stages[16];
     64 	u32             compute_stages_count;
     65 	b32             upload;
     66 	u32             raw_data_size;
     67 	b32             export_next_frame;
     68 	c8              export_pipe_name[1024];
     69 } BeamformerParametersFull;
     70 
     71 #define CS_UNIFORMS \
     72 	X(CS_DAS,     voxel_offset) \
     73 	X(CS_DAS,     cycle_t)      \
     74 	X(CS_MIN_MAX, mips_level)   \
     75 	X(CS_SUM,     sum_prescale)
     76 
     77 typedef struct {
     78 	u32 programs[CS_LAST];
     79 
     80 	/* NOTE: The raw data ssbo is not mapped on NVIDIA because their drivers _will_ store
     81 	 * the buffer in the system memory. This doesn't happen for other vendors and
     82 	 * mapping the buffer is preferred. In either case incoming data can be written to
     83 	 * the arena. An additional BufferSubData is needed on NVIDIA to upload the data. */
     84 	Arena raw_data_arena;
     85 	u32   raw_data_ssbo;
     86 
     87 	/* NOTE: Decoded data is only relevant in the context of a single frame. We use two
     88 	 * buffers so that they can be swapped when chaining multiple compute stages */
     89 	u32 rf_data_ssbos[2];
     90 	u32 last_output_ssbo_index;
     91 	u32 hadamard_texture;
     92 
     93 	u32 shared_ubo;
     94 
     95 	f32 processing_progress;
     96 	b32 processing_compute;
     97 
     98 	uv4 dec_data_dim;
     99 	u32 rf_raw_size;
    100 
    101 	#define X(idx, name) i32 name ## _id;
    102 	CS_UNIFORMS
    103 	#undef X
    104 } ComputeShaderCtx;
    105 
    106 typedef struct {
    107 	Shader shader;
    108 	b32    updated;
    109 	i32    db_cutoff_id;
    110 	i32    threshold_id;
    111 } FragmentShaderCtx;
    112 
    113 typedef enum {
    114 #define X(type, id, pretty, fixed_tx) DAS_ ##type = id,
    115 DAS_TYPES
    116 #undef X
    117 DAS_LAST
    118 } DASShaderID;
    119 
    120 typedef struct {
    121 	/* TODO(rnp): there is assumption here that each shader will occur only once
    122 	 * per compute. add an insertion index and change these to hold the max number
    123 	 * of executed compute stages */
    124 	u32 timer_ids[CS_LAST];
    125 	f32 times[CS_LAST];
    126 	b32 timer_active[CS_LAST];
    127 } ComputeShaderStats;
    128 
    129 typedef struct BeamformFrame {
    130 	uv3 dim;
    131 	u32 texture;
    132 
    133 	/* NOTE: for use when displaying either prebeamformed frames or on the current frame
    134 	 * when we intend to recompute on the next frame */
    135 	v4  min_coordinate;
    136 	v4  max_coordinate;
    137 
    138 	u32 mips;
    139 	b32 in_flight;
    140 	b32 ready_to_present;
    141 	DASShaderID das_shader_id;
    142 	u32 compound_count;
    143 	u32 id;
    144 
    145 	struct BeamformFrame *next;
    146 } BeamformFrame;
    147 
    148 typedef struct {
    149 	enum gl_vendor_ids vendor_id;
    150 	i32  version_major;
    151 	i32  version_minor;
    152 	i32  max_2d_texture_dim;
    153 	i32  max_3d_texture_dim;
    154 	i32  max_ssbo_size;
    155 	i32  max_ubo_size;
    156 	i32  max_server_wait_time;
    157 } GLParams;
    158 
    159 enum beamform_work {
    160 	BW_COMPUTE,
    161 	BW_LOAD_RF_DATA,
    162 	BW_RELOAD_SHADER,
    163 	BW_SAVE_FRAME,
    164 	BW_SEND_FRAME,
    165 };
    166 
    167 typedef struct {
    168 	void *beamformer_ctx;
    169 	s8    label;
    170 	s8    path;
    171 	ComputeShaderID shader;
    172 	b32   needs_header;
    173 } ComputeShaderReloadContext;
    174 
    175 typedef struct {
    176 	BeamformFrame      *store;
    177 	ComputeShaderStats *stats;
    178 } BeamformerWorkFrame;
    179 
    180 typedef struct {
    181 	BeamformerWorkFrame frame;
    182 	iptr                file_handle;
    183 } BeamformOutputFrameContext;
    184 
    185 /* NOTE: discriminated union based on type */
    186 typedef struct {
    187 	union {
    188 		iptr                        file_handle;
    189 		BeamformerWorkFrame         frame;
    190 		BeamformOutputFrameContext  output_frame_ctx;
    191 		ComputeShaderReloadContext *reload_shader_ctx;
    192 	};
    193 	u32 type;
    194 } BeamformWork;
    195 
    196 typedef struct {
    197 	union {
    198 		u64 queue;
    199 		struct {u32 widx, ridx;};
    200 	};
    201 	BeamformWork work_items[1 << 6];
    202 } BeamformWorkQueue;
    203 
    204 typedef struct {
    205 	BeamformFrame *frames;
    206 	u32 capacity;
    207 	u32 offset;
    208 	u32 cursor;
    209 	u32 needed_frames;
    210 } BeamformFrameIterator;
    211 
    212 typedef struct BeamformerCtx {
    213 	GLParams gl;
    214 
    215 	uv2 window_size;
    216 	b32 start_compute;
    217 	b32 should_exit;
    218 
    219 	/* TODO(rnp): is there a better way of tracking this? */
    220 	b32 ready_for_rf;
    221 
    222 	Arena  ui_backing_store;
    223 	void  *ui;
    224 	/* TODO(rnp): this is nasty and should be removed */
    225 	b32    ui_read_params;
    226 
    227 	BeamformFrame      beamform_frames[MAX_BEAMFORMED_SAVED_FRAMES];
    228 	ComputeShaderStats beamform_frame_compute_stats[MAX_BEAMFORMED_SAVED_FRAMES];
    229 	u32 next_render_frame_index;
    230 	u32 display_frame_index;
    231 
    232 	/* NOTE: this will only be used when we are averaging */
    233 	u32                averaged_frame_index;
    234 	BeamformFrame      averaged_frames[2];
    235 	ComputeShaderStats averaged_frame_compute_stats[2];
    236 
    237 	ComputeShaderCtx  csctx;
    238 	FragmentShaderCtx fsctx;
    239 
    240 	Arena export_buffer;
    241 
    242 	CudaLib cuda_lib;
    243 	OS      os;
    244 	Stream  error_stream;
    245 
    246 	BeamformWorkQueue *beamform_work_queue;
    247 
    248 	BeamformerParametersFull *params;
    249 } BeamformerCtx;
    250 
    251 #define LABEL_GL_OBJECT(type, id, s) {s8 _s = (s); glObjectLabel(type, id, _s.len, (c8 *)_s.data);}
    252 
    253 #define BEAMFORMER_FRAME_STEP_FN(name) void name(BeamformerCtx *ctx, Arena *arena, \
    254                                                  BeamformerInput *input)
    255 typedef BEAMFORMER_FRAME_STEP_FN(beamformer_frame_step_fn);
    256 
    257 #define BEAMFORMER_COMPLETE_COMPUTE_FN(name) void name(iptr user_context, Arena arena, iptr gl_context)
    258 typedef BEAMFORMER_COMPLETE_COMPUTE_FN(beamformer_complete_compute_fn);
    259 
    260 #define BEAMFORM_WORK_QUEUE_PUSH_FN(name) BeamformWork *name(BeamformWorkQueue *q)
    261 typedef BEAMFORM_WORK_QUEUE_PUSH_FN(beamform_work_queue_push_fn);
    262 
    263 #define BEAMFORM_WORK_QUEUE_PUSH_COMMIT_FN(name) void name(BeamformWorkQueue *q)
    264 typedef BEAMFORM_WORK_QUEUE_PUSH_COMMIT_FN(beamform_work_queue_push_commit_fn);
    265 
    266 #endif /*_BEAMFORMER_H_ */