ogl_beamforming

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

beamformer.h (12959B)


      1 /* See LICENSE for license details. */
      2 #ifndef _BEAMFORMER_H_
      3 #define _BEAMFORMER_H_
      4 
      5 #include <raylib_extended.h>
      6 #include <rlgl.h>
      7 
      8 #include "util.h"
      9 
     10 ///////////////////
     11 // REQUIRED OS API
     12 function OS_READ_WHOLE_FILE_FN(os_read_whole_file);
     13 function OS_SHARED_MEMORY_LOCK_REGION_FN(os_shared_memory_region_lock);
     14 function OS_SHARED_MEMORY_UNLOCK_REGION_FN(os_shared_memory_region_unlock);
     15 function OS_WAKE_WAITERS_FN(os_wake_waiters);
     16 function OS_WRITE_FILE_FN(os_write_file);
     17 
     18 #include "opengl.h"
     19 #include "util_gl.c"
     20 
     21 enum gl_vendor_ids {
     22 	GL_VENDOR_AMD,
     23 	GL_VENDOR_ARM,
     24 	GL_VENDOR_INTEL,
     25 	GL_VENDOR_NVIDIA,
     26 };
     27 
     28 typedef struct {
     29 	v2   mouse;
     30 	v2   last_mouse;
     31 	b32  executable_reloaded;
     32 	f32  dt;
     33 } BeamformerInput;
     34 
     35 #define CUDA_INIT_FN(name) void name(u32 *input_dims, u32 *decoded_dims)
     36 typedef CUDA_INIT_FN(cuda_init_fn);
     37 CUDA_INIT_FN(cuda_init_stub) {}
     38 
     39 #define CUDA_REGISTER_BUFFERS_FN(name) void name(u32 *rf_data_ssbos, u32 rf_buffer_count, u32 raw_data_ssbo)
     40 typedef CUDA_REGISTER_BUFFERS_FN(cuda_register_buffers_fn);
     41 CUDA_REGISTER_BUFFERS_FN(cuda_register_buffers_stub) {}
     42 
     43 #define CUDA_DECODE_FN(name) void name(size_t input_offset, u32 output_buffer_idx, u32 rf_channel_offset)
     44 typedef CUDA_DECODE_FN(cuda_decode_fn);
     45 CUDA_DECODE_FN(cuda_decode_stub) {}
     46 
     47 #define CUDA_HILBERT_FN(name) void name(u32 input_buffer_idx, u32 output_buffer_idx)
     48 typedef CUDA_HILBERT_FN(cuda_hilbert_fn);
     49 CUDA_HILBERT_FN(cuda_hilbert_stub) {}
     50 
     51 #define CUDA_SET_CHANNEL_MAPPING_FN(name) void name(i16 *channel_mapping)
     52 typedef CUDA_SET_CHANNEL_MAPPING_FN(cuda_set_channel_mapping_fn);
     53 CUDA_SET_CHANNEL_MAPPING_FN(cuda_set_channel_mapping_stub) {}
     54 
     55 #define CUDALibraryProcedureList \
     56 	X(decode,              "cuda_decode")              \
     57 	X(hilbert,             "cuda_hilbert")             \
     58 	X(init,                "init_cuda_configuration")  \
     59 	X(register_buffers,    "register_cuda_buffers")    \
     60 	X(set_channel_mapping, "cuda_set_channel_mapping")
     61 
     62 #define X(name, ...) DEBUG_IMPORT cuda_## name ##_fn *cuda_## name;
     63 CUDALibraryProcedureList
     64 #undef X
     65 
     66 /* TODO(rnp): this should be a UBO */
     67 #define FRAME_VIEW_MODEL_MATRIX_LOC   0
     68 #define FRAME_VIEW_VIEW_MATRIX_LOC    1
     69 #define FRAME_VIEW_PROJ_MATRIX_LOC    2
     70 #define FRAME_VIEW_DYNAMIC_RANGE_LOC  3
     71 #define FRAME_VIEW_THRESHOLD_LOC      4
     72 #define FRAME_VIEW_GAMMA_LOC          5
     73 #define FRAME_VIEW_LOG_SCALE_LOC      6
     74 #define FRAME_VIEW_BB_COLOUR_LOC      7
     75 #define FRAME_VIEW_BB_FRACTION_LOC    8
     76 #define FRAME_VIEW_SOLID_BB_LOC      10
     77 
     78 #define FRAME_VIEW_BB_COLOUR   0.92, 0.88, 0.78, 1.0
     79 #define FRAME_VIEW_BB_FRACTION 0.007f
     80 
     81 #define FRAME_VIEW_RENDER_TARGET_SIZE 1024, 1024
     82 
     83 typedef struct {
     84 	u32 shader;
     85 	u32 framebuffers[2];  /* [0] -> multisample target, [1] -> normal target for resolving */
     86 	u32 renderbuffers[2]; /* only used for 3D views, size is fixed */
     87 	b32 updated;
     88 } FrameViewRenderContext;
     89 
     90 #include "beamformer_parameters.h"
     91 #include "beamformer_shared_memory.c"
     92 
     93 typedef struct {
     94 	iptr elements_offset;
     95 	i32  elements;
     96 	u32  buffer;
     97 	u32  vao;
     98 } BeamformerRenderModel;
     99 
    100 typedef struct {
    101 	BeamformerFilterKind       kind;
    102 	BeamformerFilterParameters parameters;
    103 	f32 time_delay;
    104 	i32 length;
    105 	u32 texture;
    106 } BeamformerFilter;
    107 
    108 #define DAS_SHADER_FLAGS_LIST \
    109 	X(RxColumns,          (1 << 0)) \
    110 	X(TxColumns,          (1 << 1)) \
    111 	X(Interpolate,        (1 << 2)) \
    112 	X(CoherencyWeighting, (1 << 3))
    113 
    114 #define X(k, v, ...) DASShaderFlags_## k = v,
    115 typedef enum {DAS_SHADER_FLAGS_LIST} DASShaderFlags;
    116 #undef X
    117 
    118 static_assert(BeamformerSamplingMode_Count < 4, "filter sample mode mask borked");
    119 #define FILTER_SHADER_FLAGS_LIST \
    120 	X(SamplingModeMask, ((1 << 0) | (1 << 1))) \
    121 	X(MapChannels,      (1 << 2))
    122 #define X(k, v, ...) FilterShaderFlags_## k = v,
    123 typedef enum {FILTER_SHADER_FLAGS_LIST} FilterShaderFlags;
    124 #undef X
    125 
    126 /* X(name, type, gltype) */
    127 #define BEAMFORMER_FILTER_UBO_PARAM_LIST \
    128 	X(input_channel_stride,   u32, uint)  \
    129 	X(input_sample_stride,    u32, uint)  \
    130 	X(input_transmit_stride,  u32, uint)  \
    131 	X(output_channel_stride,  u32, uint)  \
    132 	X(output_sample_stride,   u32, uint)  \
    133 	X(output_transmit_stride, u32, uint)  \
    134 	X(decimation_rate,        u32, uint)  \
    135 	X(shader_flags,           u32, int)   \
    136 	X(demodulation_frequency, f32, float) \
    137 	X(sampling_frequency,     f32, float)
    138 
    139 /* X(name, type, gltype) */
    140 #define BEAMFORMER_DECODE_UBO_PARAM_LIST \
    141 	X(input_channel_stride,   u32, uint) \
    142 	X(input_sample_stride,    u32, uint) \
    143 	X(input_transmit_stride,  u32, uint) \
    144 	X(output_channel_stride,  u32, uint) \
    145 	X(output_sample_stride,   u32, uint) \
    146 	X(output_transmit_stride, u32, uint) \
    147 	X(transmit_count,         u32, uint) \
    148 	X(decode_mode,            u32, uint)
    149 
    150 /* X(name, type, gltype) */
    151 #define BEAMFORMER_DAS_UBO_PARAM_LIST \
    152 	X(voxel_transform,        m4,  mat4)  \
    153 	X(xdc_transform,          m4,  mat4)  \
    154 	X(xdc_element_pitch,      v2,  vec2)  \
    155 	X(sampling_frequency,     f32, float) \
    156 	X(demodulation_frequency, f32, float) \
    157 	X(speed_of_sound,         f32, float) \
    158 	X(time_offset,            f32, float) \
    159 	X(f_number,               f32, float) \
    160 	X(shader_flags,           u32, int)   \
    161 	X(shader_kind,            u32, uint)  \
    162 	X(sample_count,           u32, uint)  \
    163 	X(channel_count,          u32, uint)  \
    164 	X(acquisition_count,      u32, uint)
    165 
    166 typedef alignas(16) struct {
    167 	#define X(name, type, ...) type name;
    168 	BEAMFORMER_DECODE_UBO_PARAM_LIST
    169 	#undef X
    170 } BeamformerDecodeUBO;
    171 static_assert((sizeof(BeamformerDecodeUBO) & 15) == 0, "UBO size must be a multiple of 16");
    172 
    173 typedef alignas(16) struct {
    174 	#define X(name, type, ...) type name;
    175 	BEAMFORMER_FILTER_UBO_PARAM_LIST
    176 	#undef X
    177 	float _pad[2];
    178 } BeamformerFilterUBO;
    179 static_assert((sizeof(BeamformerFilterUBO) & 15) == 0, "UBO size must be a multiple of 16");
    180 
    181 typedef alignas(16) struct {
    182 	#define X(name, type, ...) type name;
    183 	BEAMFORMER_DAS_UBO_PARAM_LIST
    184 	#undef X
    185 } BeamformerDASUBO;
    186 static_assert((sizeof(BeamformerDASUBO) & 15) == 0, "UBO size must be a multiple of 16");
    187 
    188 /* TODO(rnp): das should remove redundant info and add voxel transform */
    189 /* TODO(rnp): need 1 UBO per filter slot */
    190 #define BEAMFORMER_COMPUTE_UBO_LIST \
    191 	X(DAS,        BeamformerDASUBO,    das)    \
    192 	X(Decode,     BeamformerDecodeUBO, decode) \
    193 	X(Filter,     BeamformerFilterUBO, filter) \
    194 	X(Demodulate, BeamformerFilterUBO, demod)
    195 
    196 #define X(k, ...) BeamformerComputeUBOKind_##k,
    197 typedef enum {BEAMFORMER_COMPUTE_UBO_LIST BeamformerComputeUBOKind_Count} BeamformerComputeUBOKind;
    198 #undef X
    199 
    200 #define BEAMFORMER_COMPUTE_TEXTURE_LIST \
    201 	X(ChannelMapping, GL_R16I)  \
    202 	X(FocalVectors,   GL_RG32F) \
    203 	X(SparseElements, GL_R16I)  \
    204 	X(Hadamard,       GL_R8I)
    205 
    206 typedef enum {
    207 	#define X(k, ...) BeamformerComputeTextureKind_##k,
    208 	BEAMFORMER_COMPUTE_TEXTURE_LIST
    209 	#undef X
    210 	BeamformerComputeTextureKind_Count
    211 } BeamformerComputeTextureKind;
    212 static_assert((BeamformerComputeTextureKind_Count - 1) == BeamformerComputeTextureKind_Hadamard,
    213               "BeamformerComputeTextureKind_Hadamard must be end of TextureKinds");
    214 
    215 typedef struct BeamformerComputePlan BeamformerComputePlan;
    216 struct BeamformerComputePlan {
    217 	BeamformerComputePipeline pipeline;
    218 
    219 	uv3 decode_dispatch;
    220 	uv3 demod_dispatch;
    221 
    222 	u32 rf_size;
    223 	i32 hadamard_order;
    224 
    225 	v3  min_coordinate;
    226 	v3  max_coordinate;
    227 	iv3 output_points;
    228 	i32 average_frames;
    229 
    230 	u32 textures[BeamformerComputeTextureKind_Count];
    231 	u32 ubos[BeamformerComputeUBOKind_Count];
    232 
    233 	BeamformerFilter filters[BeamformerFilterSlots];
    234 
    235 	#define X(k, type, name) type name ##_ubo_data;
    236 	BEAMFORMER_COMPUTE_UBO_LIST
    237 	#undef X
    238 
    239 	BeamformerComputePlan *next;
    240 };
    241 
    242 typedef struct {
    243 	GLsync upload_syncs[BeamformerMaxRawDataFramesInFlight];
    244 	GLsync compute_syncs[BeamformerMaxRawDataFramesInFlight];
    245 
    246 	u32 ssbo;
    247 	u32 size;
    248 
    249 	u32 data_timestamp_query;
    250 
    251 	u32 insertion_index;
    252 	u32 compute_index;
    253 } BeamformerRFBuffer;
    254 
    255 typedef struct {
    256 	u32                programs[BeamformerShaderKind_ComputeCount];
    257 	BeamformerRFBuffer rf_buffer;
    258 
    259 	BeamformerComputePlan *compute_plans[BeamformerMaxParameterBlockSlots];
    260 	BeamformerComputePlan *compute_plan_freelist;
    261 
    262 	/* NOTE(rnp): two interstage ssbos are allocated so that they may be used to
    263 	 * ping pong data between compute stages */
    264 	u32 ping_pong_ssbos[2];
    265 	u32 last_output_ssbo_index;
    266 
    267 	u32 ping_pong_ssbo_size;
    268 
    269 	f32 processing_progress;
    270 	b32 processing_compute;
    271 
    272 	u32 shader_timer_ids[BeamformerMaxComputeShaderStages];
    273 
    274 	BeamformerRenderModel unit_cube_model;
    275 } BeamformerComputeContext;
    276 
    277 typedef enum {
    278 	#define X(type, id, ...) DASShaderKind_##type = id,
    279 	DAS_SHADER_KIND_LIST
    280 	#undef X
    281 	DASShaderKind_Count
    282 } DASShaderKind;
    283 
    284 typedef struct {
    285 	BeamformerComputeStatsTable table;
    286 	f32 average_times[BeamformerShaderKind_Count];
    287 
    288 	u64 last_rf_timer_count;
    289 	f32 rf_time_delta_average;
    290 
    291 	u32 latest_frame_index;
    292 	u32 latest_rf_index;
    293 } ComputeShaderStats;
    294 
    295 /* TODO(rnp): maybe this also gets used for CPU timing info as well */
    296 typedef enum {
    297 	ComputeTimingInfoKind_ComputeFrameBegin,
    298 	ComputeTimingInfoKind_ComputeFrameEnd,
    299 	ComputeTimingInfoKind_Shader,
    300 	ComputeTimingInfoKind_RF_Data,
    301 } ComputeTimingInfoKind;
    302 
    303 typedef struct {
    304 	u64 timer_count;
    305 	ComputeTimingInfoKind kind;
    306 	union {
    307 		BeamformerShaderKind shader;
    308 	};
    309 } ComputeTimingInfo;
    310 
    311 typedef struct {
    312 	u32 write_index;
    313 	u32 read_index;
    314 	b32 compute_frame_active;
    315 	ComputeTimingInfo buffer[4096];
    316 } ComputeTimingTable;
    317 
    318 typedef struct {
    319 	BeamformerRFBuffer *rf_buffer;
    320 	SharedMemoryRegion *shared_memory;
    321 	ComputeTimingTable *compute_timing_table;
    322 	i32                *compute_worker_sync;
    323 } BeamformerUploadThreadContext;
    324 
    325 struct BeamformerFrame {
    326 	u32 texture;
    327 	b32 ready_to_present;
    328 
    329 	iv3 dim;
    330 	i32 mips;
    331 
    332 	/* NOTE: for use when displaying either prebeamformed frames or on the current frame
    333 	 * when we intend to recompute on the next frame */
    334 	v3  min_coordinate;
    335 	v3  max_coordinate;
    336 
    337 	// metadata
    338 	u32                    id;
    339 	u32                    compound_count;
    340 	DASShaderKind          das_shader_kind;
    341 	BeamformerViewPlaneTag view_plane_tag;
    342 
    343 	BeamformerFrame *next;
    344 };
    345 
    346 #define GL_PARAMETERS \
    347 	X(MAJOR_VERSION,                   version_major,                   "")      \
    348 	X(MINOR_VERSION,                   version_minor,                   "")      \
    349 	X(MIN_MAP_BUFFER_ALIGNMENT,        min_map_buffer_alignment,        "")      \
    350 	X(TEXTURE_BUFFER_OFFSET_ALIGNMENT, texture_buffer_offset_alignment, "")      \
    351 	X(MAX_TEXTURE_BUFFER_SIZE,         max_texture_buffer_size,         "")      \
    352 	X(MAX_TEXTURE_SIZE,                max_2d_texture_dim,              "")      \
    353 	X(MAX_3D_TEXTURE_SIZE,             max_3d_texture_dim,              "")      \
    354 	X(MAX_SHADER_STORAGE_BLOCK_SIZE,   max_ssbo_size,                   "")      \
    355 	X(MAX_COMPUTE_SHARED_MEMORY_SIZE,  max_shared_memory_size,          "")      \
    356 	X(MAX_UNIFORM_BLOCK_SIZE,          max_ubo_size,                    "")      \
    357 	X(MAX_SERVER_WAIT_TIMEOUT,         max_server_wait_time,            " [ns]")
    358 
    359 typedef struct {
    360 	enum gl_vendor_ids vendor_id;
    361 	#define X(glname, name, suffix) i32 name;
    362 	GL_PARAMETERS
    363 	#undef X
    364 } GLParams;
    365 
    366 typedef struct {
    367 	GLParams gl;
    368 
    369 	iv2 window_size;
    370 	b32 should_exit;
    371 
    372 	Arena  ui_backing_store;
    373 	void  *ui;
    374 	u32    ui_dirty_parameter_blocks;
    375 
    376 	BeamformerComputeContext compute_context;
    377 
    378 	/* TODO(rnp): ideally this would go in the UI but its hard to manage with the UI
    379 	 * destroying itself on hot-reload */
    380 	FrameViewRenderContext frame_view_render_context;
    381 
    382 	OS     os;
    383 	Stream error_stream;
    384 
    385 	BeamformWorkQueue *beamform_work_queue;
    386 
    387 	ComputeShaderStats *compute_shader_stats;
    388 	ComputeTimingTable *compute_timing_table;
    389 
    390 	SharedMemoryRegion shared_memory;
    391 
    392 	BeamformerFrame beamform_frames[BeamformerMaxSavedFrames];
    393 	BeamformerFrame *latest_frame;
    394 	u32 next_render_frame_index;
    395 	u32 display_frame_index;
    396 
    397 	/* NOTE: this will only be used when we are averaging */
    398 	u32             averaged_frame_index;
    399 	BeamformerFrame averaged_frames[2];
    400 } BeamformerCtx;
    401 
    402 struct ShaderReloadContext {
    403 	BeamformerCtx *beamformer_context;
    404 	s8   path;
    405 	s8   name;
    406 	s8   header;
    407 	u32 *shader;
    408 	ShaderReloadContext *link;
    409 	GLenum     gl_type;
    410 	BeamformerShaderKind kind;
    411 };
    412 
    413 #define BEAMFORMER_FRAME_STEP_FN(name) void name(BeamformerCtx *ctx, BeamformerInput *input)
    414 typedef BEAMFORMER_FRAME_STEP_FN(beamformer_frame_step_fn);
    415 
    416 #define BEAMFORMER_COMPLETE_COMPUTE_FN(name) void name(iptr user_context, Arena *arena, iptr gl_context)
    417 typedef BEAMFORMER_COMPLETE_COMPUTE_FN(beamformer_complete_compute_fn);
    418 
    419 #define BEAMFORMER_RF_UPLOAD_FN(name) void name(BeamformerUploadThreadContext *ctx, Arena arena)
    420 typedef BEAMFORMER_RF_UPLOAD_FN(beamformer_rf_upload_fn);
    421 
    422 #define BEAMFORMER_RELOAD_SHADER_FN(name) b32 name(OS *os, BeamformerCtx *ctx, \
    423                                                    ShaderReloadContext *src, Arena arena, s8 shader_name)
    424 typedef BEAMFORMER_RELOAD_SHADER_FN(beamformer_reload_shader_fn);
    425 
    426 #define BEAMFORMER_DEBUG_UI_DEINIT_FN(name) void name(BeamformerCtx *ctx)
    427 typedef BEAMFORMER_DEBUG_UI_DEINIT_FN(beamformer_debug_ui_deinit_fn);
    428 
    429 #endif /*_BEAMFORMER_H_ */