ogl_beamforming

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

beamformer_internal.h (10394B)


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