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_ */