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