ogl_beamforming

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

beamformer.h (10304B)


      1 /* See LICENSE for license details. */
      2 #ifndef _BEAMFORMER_H_
      3 #define _BEAMFORMER_H_
      4 
      5 #include "util.h"
      6 #include "opengl.h"
      7 
      8 #include "generated/beamformer.meta.c"
      9 #include "generated/beamformer_shaders.c"
     10 
     11 #include <raylib_extended.h>
     12 #include <rlgl.h>
     13 
     14 ///////////////////
     15 // REQUIRED OS API
     16 function void os_barrier_wait(Barrier);
     17 function iptr os_error_handle(void);
     18 function s8   os_path_separator(void);
     19 function OS_READ_WHOLE_FILE_FN(os_read_whole_file);
     20 function OS_SHARED_MEMORY_LOCK_REGION_FN(os_shared_memory_region_lock);
     21 function OS_SHARED_MEMORY_UNLOCK_REGION_FN(os_shared_memory_region_unlock);
     22 function OS_WAKE_WAITERS_FN(os_wake_waiters);
     23 function OS_WRITE_FILE_FN(os_write_file);
     24 
     25 #include "threads.c"
     26 #include "util_gl.c"
     27 
     28 typedef struct {
     29 	Arena memory;
     30 	f64   dt;
     31 	v2    mouse;
     32 	v2    last_mouse;
     33 	b32   executable_reloaded;
     34 } BeamformerInput;
     35 
     36 #define CUDA_INIT_FN(name) void name(u32 *input_dims, u32 *decoded_dims)
     37 typedef CUDA_INIT_FN(cuda_init_fn);
     38 CUDA_INIT_FN(cuda_init_stub) {}
     39 
     40 #define CUDA_REGISTER_BUFFERS_FN(name) void name(u32 *rf_data_ssbos, u32 rf_buffer_count, u32 raw_data_ssbo)
     41 typedef CUDA_REGISTER_BUFFERS_FN(cuda_register_buffers_fn);
     42 CUDA_REGISTER_BUFFERS_FN(cuda_register_buffers_stub) {}
     43 
     44 #define CUDA_DECODE_FN(name) void name(size_t input_offset, u32 output_buffer_idx, u32 rf_channel_offset)
     45 typedef CUDA_DECODE_FN(cuda_decode_fn);
     46 CUDA_DECODE_FN(cuda_decode_stub) {}
     47 
     48 #define CUDA_HILBERT_FN(name) void name(u32 input_buffer_idx, u32 output_buffer_idx)
     49 typedef CUDA_HILBERT_FN(cuda_hilbert_fn);
     50 CUDA_HILBERT_FN(cuda_hilbert_stub) {}
     51 
     52 #define CUDA_SET_CHANNEL_MAPPING_FN(name) void name(i16 *channel_mapping)
     53 typedef CUDA_SET_CHANNEL_MAPPING_FN(cuda_set_channel_mapping_fn);
     54 CUDA_SET_CHANNEL_MAPPING_FN(cuda_set_channel_mapping_stub) {}
     55 
     56 #define CUDALibraryProcedureList \
     57 	X(decode,              "cuda_decode")              \
     58 	X(hilbert,             "cuda_hilbert")             \
     59 	X(init,                "init_cuda_configuration")  \
     60 	X(register_buffers,    "register_cuda_buffers")    \
     61 	X(set_channel_mapping, "cuda_set_channel_mapping")
     62 
     63 #define X(name, ...) DEBUG_IMPORT cuda_## name ##_fn *cuda_## name;
     64 CUDALibraryProcedureList
     65 #undef X
     66 
     67 /* TODO(rnp): this should be a UBO */
     68 #define FRAME_VIEW_MODEL_MATRIX_LOC   0
     69 #define FRAME_VIEW_VIEW_MATRIX_LOC    1
     70 #define FRAME_VIEW_PROJ_MATRIX_LOC    2
     71 #define FRAME_VIEW_DYNAMIC_RANGE_LOC  3
     72 #define FRAME_VIEW_THRESHOLD_LOC      4
     73 #define FRAME_VIEW_GAMMA_LOC          5
     74 #define FRAME_VIEW_LOG_SCALE_LOC      6
     75 #define FRAME_VIEW_BB_COLOUR_LOC      7
     76 #define FRAME_VIEW_BB_FRACTION_LOC    8
     77 #define FRAME_VIEW_SOLID_BB_LOC      10
     78 
     79 #define FRAME_VIEW_BB_COLOUR   0.92, 0.88, 0.78, 1.0
     80 #define FRAME_VIEW_BB_FRACTION 0.007f
     81 
     82 #define FRAME_VIEW_RENDER_TARGET_SIZE 1024, 1024
     83 
     84 typedef struct {
     85 	u32 shader;
     86 	u32 framebuffers[2];  /* [0] -> multisample target, [1] -> normal target for resolving */
     87 	u32 renderbuffers[2]; /* only used for 3D views, size is fixed */
     88 	b32 updated;
     89 } FrameViewRenderContext;
     90 
     91 #include "beamformer_parameters.h"
     92 #include "beamformer_shared_memory.c"
     93 
     94 typedef struct {
     95 	iptr elements_offset;
     96 	i32  elements;
     97 	u32  buffer;
     98 	u32  vao;
     99 } BeamformerRenderModel;
    100 
    101 typedef struct {
    102 	BeamformerFilterParameters parameters;
    103 	f32 time_delay;
    104 	i32 length;
    105 	u32 ssbo;
    106 } BeamformerFilter;
    107 
    108 /* X(name, type, gltype) */
    109 #define BEAMFORMER_DAS_UBO_PARAM_LIST \
    110 	X(voxel_transform,        m4,  mat4) \
    111 	X(xdc_transform,          m4,  mat4) \
    112 	X(xdc_element_pitch,      v2,  vec2)
    113 
    114 typedef alignas(16) struct {
    115 	#define X(name, type, ...) type name;
    116 	BEAMFORMER_DAS_UBO_PARAM_LIST
    117 	#undef X
    118 	float _pad[2];
    119 } BeamformerDASUBO;
    120 static_assert((sizeof(BeamformerDASUBO) & 15) == 0, "UBO size must be a multiple of 16");
    121 
    122 /* TODO(rnp): need 1 UBO per filter slot */
    123 #define BEAMFORMER_COMPUTE_UBO_LIST \
    124 	X(DAS,        BeamformerDASUBO,    das)
    125 
    126 #define X(k, ...) BeamformerComputeUBOKind_##k,
    127 typedef enum {BEAMFORMER_COMPUTE_UBO_LIST BeamformerComputeUBOKind_Count} BeamformerComputeUBOKind;
    128 #undef X
    129 
    130 // X(kind, gl_kind, texture_format, pixel_type)
    131 #define BEAMFORMER_COMPUTE_TEXTURE_LIST \
    132 	X(FocalVectors,                GL_RG32F, GL_RG,          GL_FLOAT) \
    133 	X(SparseElements,              GL_R16I,  GL_RED_INTEGER, GL_SHORT) \
    134 	X(TransmitReceiveOrientations, GL_R8I,   GL_RED_INTEGER, GL_BYTE)
    135 
    136 #define BEAMFORMER_COMPUTE_TEXTURE_LIST_FULL \
    137 	BEAMFORMER_COMPUTE_TEXTURE_LIST \
    138 	X(Hadamard,       GL_R32F)
    139 
    140 typedef enum {
    141 	#define X(k, ...) BeamformerComputeTextureKind_##k,
    142 	BEAMFORMER_COMPUTE_TEXTURE_LIST_FULL
    143 	#undef X
    144 	BeamformerComputeTextureKind_Count
    145 } BeamformerComputeTextureKind;
    146 static_assert((BeamformerComputeTextureKind_Count - 1) == BeamformerComputeTextureKind_Hadamard,
    147               "BeamformerComputeTextureKind_Hadamard must be end of TextureKinds");
    148 
    149 typedef struct {
    150 	uv3 layout;
    151 	uv3 dispatch;
    152 	BeamformerShaderBakeParameters bake;
    153 } BeamformerShaderDescriptor;
    154 
    155 typedef struct BeamformerComputePlan BeamformerComputePlan;
    156 struct BeamformerComputePlan {
    157 	BeamformerComputePipeline pipeline;
    158 
    159 	u32 programs[BeamformerMaxComputeShaderStages];
    160 
    161 	u32 dirty_programs;
    162 
    163 	BeamformerAcquisitionKind acquisition_kind;
    164 	u32                       acquisition_count;
    165 
    166 	u32 rf_size;
    167 	i32 hadamard_order;
    168 	b32 iq_pipeline;
    169 
    170 	v3  min_coordinate;
    171 	v3  max_coordinate;
    172 	iv3 output_points;
    173 	i32 average_frames;
    174 
    175 	u32 textures[BeamformerComputeTextureKind_Count];
    176 	u32 ubos[BeamformerComputeUBOKind_Count];
    177 
    178 	BeamformerFilter filters[BeamformerFilterSlots];
    179 
    180 	#define X(k, type, name) type name ##_ubo_data;
    181 	BEAMFORMER_COMPUTE_UBO_LIST
    182 	#undef X
    183 
    184 	u128 shader_hashes[BeamformerMaxComputeShaderStages];
    185 	BeamformerShaderDescriptor shader_descriptors[BeamformerMaxComputeShaderStages];
    186 
    187 	BeamformerComputePlan *next;
    188 };
    189 
    190 typedef struct {
    191 	GLsync upload_syncs[BeamformerMaxRawDataFramesInFlight];
    192 	GLsync compute_syncs[BeamformerMaxRawDataFramesInFlight];
    193 
    194 	u8 *buffer;
    195 
    196 	u32 ssbo;
    197 
    198 	u32 size;
    199 	u32 active_rf_size;
    200 
    201 	u32 data_timestamp_query;
    202 
    203 	u32 insertion_index;
    204 	u32 compute_index;
    205 } BeamformerRFBuffer;
    206 
    207 typedef struct {
    208 	BeamformerRFBuffer rf_buffer;
    209 
    210 	BeamformerComputePlan *compute_plans[BeamformerMaxParameterBlockSlots];
    211 	BeamformerComputePlan *compute_plan_freelist;
    212 
    213 	/* NOTE(rnp): two interstage ssbos are allocated so that they may be used to
    214 	 * ping pong data between compute stages */
    215 	u32 ping_pong_ssbos[2];
    216 	u32 last_output_ssbo_index;
    217 
    218 	u32 ping_pong_ssbo_size;
    219 
    220 	f32 processing_progress;
    221 	b32 processing_compute;
    222 
    223 	u32 shader_timer_ids[BeamformerMaxComputeShaderStages];
    224 
    225 	BeamformerRenderModel unit_cube_model;
    226 } BeamformerComputeContext;
    227 
    228 typedef struct {
    229 	BeamformerComputeStatsTable table;
    230 	f32 average_times[BeamformerShaderKind_Count];
    231 
    232 	u64 last_rf_timer_count;
    233 	f32 rf_time_delta_average;
    234 
    235 	u32 latest_frame_index;
    236 	u32 latest_rf_index;
    237 } ComputeShaderStats;
    238 
    239 /* TODO(rnp): maybe this also gets used for CPU timing info as well */
    240 typedef enum {
    241 	ComputeTimingInfoKind_ComputeFrameBegin,
    242 	ComputeTimingInfoKind_ComputeFrameEnd,
    243 	ComputeTimingInfoKind_Shader,
    244 	ComputeTimingInfoKind_RF_Data,
    245 } ComputeTimingInfoKind;
    246 
    247 typedef struct {
    248 	u64 timer_count;
    249 	ComputeTimingInfoKind kind;
    250 	union {
    251 		BeamformerShaderKind shader;
    252 	};
    253 } ComputeTimingInfo;
    254 
    255 typedef struct {
    256 	u32 write_index;
    257 	u32 read_index;
    258 	b32 compute_frame_active;
    259 	ComputeTimingInfo buffer[4096];
    260 } ComputeTimingTable;
    261 
    262 typedef struct {
    263 	BeamformerRFBuffer *rf_buffer;
    264 	SharedMemoryRegion *shared_memory;
    265 	ComputeTimingTable *compute_timing_table;
    266 	i32                *compute_worker_sync;
    267 } BeamformerUploadThreadContext;
    268 
    269 struct BeamformerFrame {
    270 	u32 texture;
    271 	b32 ready_to_present;
    272 
    273 	iv3 dim;
    274 	i32 mips;
    275 
    276 	/* NOTE: for use when displaying either prebeamformed frames or on the current frame
    277 	 * when we intend to recompute on the next frame */
    278 	v3  min_coordinate;
    279 	v3  max_coordinate;
    280 
    281 	// metadata
    282 	GLenum                    gl_kind;
    283 	u32                       id;
    284 	u32                       compound_count;
    285 	u32                       parameter_block;
    286 	BeamformerAcquisitionKind acquisition_kind;
    287 	BeamformerViewPlaneTag    view_plane_tag;
    288 
    289 	BeamformerFrame *next;
    290 };
    291 
    292 typedef struct {
    293 	iv2 window_size;
    294 
    295 	Arena  arena;
    296 	Arena  ui_backing_store;
    297 	void  *ui;
    298 	u32    ui_dirty_parameter_blocks;
    299 
    300 	BeamformerComputeContext compute_context;
    301 
    302 	/* TODO(rnp): ideally this would go in the UI but its hard to manage with the UI
    303 	 * destroying itself on hot-reload */
    304 	FrameViewRenderContext frame_view_render_context;
    305 
    306 	Stream error_stream;
    307 
    308 	BeamformWorkQueue *beamform_work_queue;
    309 
    310 	ComputeShaderStats *compute_shader_stats;
    311 	ComputeTimingTable *compute_timing_table;
    312 
    313 	SharedMemoryRegion shared_memory;
    314 
    315 	BeamformerFrame beamform_frames[BeamformerMaxSavedFrames];
    316 	BeamformerFrame *latest_frame;
    317 	u32 next_render_frame_index;
    318 	u32 display_frame_index;
    319 
    320 	/* NOTE: this will only be used when we are averaging */
    321 	u32             averaged_frame_index;
    322 	BeamformerFrame averaged_frames[2];
    323 
    324 	GLWorkerThreadContext  upload_worker;
    325 	GLWorkerThreadContext  compute_worker;
    326 
    327 	DEBUG_DECL(renderdoc_start_frame_capture_fn *start_frame_capture;)
    328 	DEBUG_DECL(renderdoc_end_frame_capture_fn   *end_frame_capture;)
    329 } BeamformerCtx;
    330 #define BeamformerContextMemory(a) (BeamformerCtx *)arena_aligned_start(a, alignof(BeamformerCtx))
    331 
    332 typedef struct ShaderReloadContext ShaderReloadContext;
    333 struct ShaderReloadContext {
    334 	BeamformerCtx       *beamformer_context;
    335 	ShaderReloadContext *link;
    336 	s8     header;
    337 	GLenum gl_type;
    338 	i32    reloadable_info_index;
    339 };
    340 
    341 #define BEAMFORMER_FRAME_STEP_FN(name) void name(BeamformerInput *input)
    342 typedef BEAMFORMER_FRAME_STEP_FN(beamformer_frame_step_fn);
    343 
    344 #define BEAMFORMER_COMPLETE_COMPUTE_FN(name) void name(iptr user_context, Arena *arena, iptr gl_context)
    345 typedef BEAMFORMER_COMPLETE_COMPUTE_FN(beamformer_complete_compute_fn);
    346 
    347 #define BEAMFORMER_RF_UPLOAD_FN(name) void name(BeamformerUploadThreadContext *ctx)
    348 typedef BEAMFORMER_RF_UPLOAD_FN(beamformer_rf_upload_fn);
    349 
    350 #define BEAMFORMER_RELOAD_SHADER_FN(name) b32 name(s8 path, ShaderReloadContext *src, \
    351                                                    Arena arena, s8 shader_name)
    352 typedef BEAMFORMER_RELOAD_SHADER_FN(beamformer_reload_shader_fn);
    353 
    354 #define BEAMFORMER_DEBUG_UI_DEINIT_FN(name) void name(Arena memory)
    355 typedef BEAMFORMER_DEBUG_UI_DEINIT_FN(beamformer_debug_ui_deinit_fn);
    356 
    357 #endif /*_BEAMFORMER_H_ */