beamformer.h (7663B)
1 /* See LICENSE for license details. */ 2 #ifndef _BEAMFORMER_H_ 3 #define _BEAMFORMER_H_ 4 5 #include <glad.h> 6 7 #define GRAPHICS_API_OPENGL_43 8 #include <raylib.h> 9 #include <rlgl.h> 10 11 #include "util.h" 12 13 #define BG_COLOUR (v4){.r = 0.15, .g = 0.12, .b = 0.13, .a = 1.0} 14 #define FG_COLOUR (v4){.r = 0.92, .g = 0.88, .b = 0.78, .a = 1.0} 15 #define FOCUSED_COLOUR (v4){.r = 0.86, .g = 0.28, .b = 0.21, .a = 1.0} 16 #define HOVERED_COLOUR (v4){.r = 0.11, .g = 0.50, .b = 0.59, .a = 1.0} 17 #define RULER_COLOUR (v4){.r = 1.00, .g = 0.70, .b = 0.00, .a = 1.0} 18 19 #define INFO_COLUMN_WIDTH 560 20 /* NOTE: extra space used for allowing mouse clicks after end of text */ 21 #define TEXT_BOX_EXTRA_X 10.0f 22 23 #define TEXT_HOVER_SPEED 5.0f 24 25 #define RECT_BTN_COLOUR (Color){.r = 0x43, .g = 0x36, .b = 0x3a, .a = 0xff} 26 #define RECT_BTN_BORDER_COLOUR (Color){.r = 0x00, .g = 0x00, .b = 0x00, .a = 0xCC} 27 #define RECT_BTN_ROUNDNESS 0.3f 28 #define RECT_BTN_BORDER_WIDTH 6.0f 29 30 enum program_flags { 31 SHOULD_EXIT = 1 << 0, 32 RELOAD_SHADERS = 1 << 1, 33 GEN_MIPMAPS = 1 << 30, 34 }; 35 36 enum gl_vendor_ids { 37 GL_VENDOR_AMD, 38 GL_VENDOR_ARM, 39 GL_VENDOR_INTEL, 40 GL_VENDOR_NVIDIA, 41 }; 42 43 typedef struct { 44 u8 buf[64]; 45 i32 buf_len; 46 i32 cursor; 47 f32 cursor_blink_t; 48 f32 cursor_blink_scale; 49 } InputState; 50 51 enum variable_flags { 52 V_CAUSES_COMPUTE = 1 << 29, 53 V_GEN_MIPMAPS = 1 << 30, 54 }; 55 56 enum interaction_states { 57 IS_NONE, 58 IS_NOP, 59 IS_SET, 60 IS_DRAG, 61 IS_SCROLL, 62 IS_TEXT, 63 64 IS_DISPLAY, 65 IS_SCALE_BAR, 66 }; 67 68 typedef struct { 69 Variable hot; 70 Variable next_hot; 71 Variable active; 72 u32 hot_state; 73 u32 state; 74 v2 last_mouse_click_p; 75 } InteractionState; 76 77 typedef struct { 78 TempArena frame_temporary_arena; 79 Arena arena_for_frame; 80 81 Font font; 82 Font small_font; 83 84 InteractionState interaction; 85 InputState text_input_state; 86 } BeamformerUI; 87 88 #define MAX_FRAMES_IN_FLIGHT 3 89 90 #define INIT_CUDA_CONFIGURATION_FN(name) void name(u32 *input_dims, u32 *decoded_dims, u16 *channel_mapping) 91 typedef INIT_CUDA_CONFIGURATION_FN(init_cuda_configuration_fn); 92 INIT_CUDA_CONFIGURATION_FN(init_cuda_configuration_stub) {} 93 94 #define REGISTER_CUDA_BUFFERS_FN(name) void name(u32 *rf_data_ssbos, u32 rf_buffer_count, u32 raw_data_ssbo) 95 typedef REGISTER_CUDA_BUFFERS_FN(register_cuda_buffers_fn); 96 REGISTER_CUDA_BUFFERS_FN(register_cuda_buffers_stub) {} 97 98 #define CUDA_DECODE_FN(name) void name(size_t input_offset, u32 output_buffer_idx, u32 rf_channel_offset) 99 typedef CUDA_DECODE_FN(cuda_decode_fn); 100 CUDA_DECODE_FN(cuda_decode_stub) {} 101 102 #define CUDA_HILBERT_FN(name) void name(u32 input_buffer_idx, u32 output_buffer_idx) 103 typedef CUDA_HILBERT_FN(cuda_hilbert_fn); 104 CUDA_HILBERT_FN(cuda_hilbert_stub) {} 105 106 #define CUDA_LIB_FNS \ 107 X(cuda_decode) \ 108 X(cuda_hilbert) \ 109 X(init_cuda_configuration) \ 110 X(register_cuda_buffers) 111 112 typedef struct { 113 void *lib; 114 u64 timestamp; 115 #define X(name) name ## _fn *name; 116 CUDA_LIB_FNS 117 #undef X 118 } CudaLib; 119 120 #include "beamformer_parameters.h" 121 typedef struct { 122 BeamformerParameters raw; 123 enum compute_shaders compute_stages[16]; 124 u32 compute_stages_count; 125 b32 upload; 126 b32 export_next_frame; 127 c8 export_pipe_name[1024]; 128 } BeamformerParametersFull; 129 130 #define CS_UNIFORMS \ 131 X(CS_DAS, volume_export_dim_offset) \ 132 X(CS_DAS, volume_export_pass) \ 133 X(CS_DAS, xdc_index) \ 134 X(CS_DAS, xdc_transform) \ 135 X(CS_DAS, cycle_t) \ 136 X(CS_MIN_MAX, mips_level) \ 137 X(CS_SUM, sum_prescale) 138 139 typedef struct { 140 u32 programs[CS_LAST]; 141 142 u32 timer_index; 143 u32 timer_ids[MAX_FRAMES_IN_FLIGHT][CS_LAST]; 144 b32 timer_active[MAX_FRAMES_IN_FLIGHT][CS_LAST]; 145 GLsync timer_fences[MAX_FRAMES_IN_FLIGHT]; 146 f32 last_frame_time[CS_LAST]; 147 148 /* NOTE: the raw_data_ssbo is allocated at 3x the required size to allow for tiled 149 * transfers when the GPU is running behind the CPU. It is not mapped on NVIDIA because 150 * their drivers _will_ store the buffer in the system memory. This doesn't happen 151 * for Intel or AMD and mapping the buffer is preferred. In either case incoming data can 152 * be written to the arena at the appropriate offset for the current raw_data_index. An 153 * additional BufferSubData is needed on NVIDIA to upload the data. */ 154 GLsync raw_data_fences[MAX_FRAMES_IN_FLIGHT]; 155 Arena raw_data_arena; 156 u32 raw_data_ssbo; 157 u32 raw_data_index; 158 159 /* NOTE: Decoded data is only relevant in the context of a single frame. We use two 160 * buffers so that they can be swapped when chaining multiple compute stages */ 161 u32 rf_data_ssbos[2]; 162 u32 last_output_ssbo_index; 163 u32 hadamard_ssbo; 164 uv2 hadamard_dim; 165 166 u32 shared_ubo; 167 168 uv4 dec_data_dim; 169 uv2 rf_raw_dim; 170 171 #define X(idx, name) i32 name ## _id; 172 CS_UNIFORMS 173 #undef X 174 } ComputeShaderCtx; 175 176 typedef struct { 177 Shader shader; 178 RenderTexture2D output; 179 /* TODO: cleanup: X macro? */ 180 i32 db_cutoff_id; 181 i32 threshold_id; 182 f32 db; 183 f32 threshold; 184 } FragmentShaderCtx; 185 186 typedef struct { 187 /* NOTE: we always have one extra texture to sum into; thus the final output data 188 * is always found in textures[dim.w - 1] */ 189 u32 textures[MAX_MULTI_XDC_COUNT + 1]; 190 uv4 dim; 191 u32 mips; 192 } BeamformFrame; 193 194 typedef struct { 195 BeamformFrame frame; 196 u32 timer_ids[2]; 197 f32 runtime; 198 u32 rf_data_ssbo; 199 u32 shader; 200 u32 dispatch_index; 201 b32 timer_active; 202 } PartialComputeCtx; 203 204 typedef struct { 205 enum gl_vendor_ids vendor_id; 206 i32 version_major; 207 i32 version_minor; 208 i32 max_2d_texture_dim; 209 i32 max_3d_texture_dim; 210 i32 max_ssbo_size; 211 i32 max_ubo_size; 212 } GLParams; 213 214 enum beamform_work { 215 BW_FULL_COMPUTE, 216 BW_RECOMPUTE, 217 BW_PARTIAL_COMPUTE, 218 BW_SAVE_FRAME, 219 BW_SEND_FRAME, 220 BW_SSBO_COPY, 221 }; 222 223 typedef struct { 224 u32 source_ssbo; 225 u32 dest_ssbo; 226 } BeamformSSBOCopy; 227 228 typedef struct { 229 BeamformFrame *frame; 230 iptr export_handle; 231 u32 raw_data_ssbo_index; 232 b32 first_pass; 233 } BeamformCompute; 234 235 typedef struct { 236 BeamformFrame *frame; 237 iptr output_handle; 238 } BeamformOutputFrame; 239 240 /* NOTE: discriminated union based on type */ 241 typedef struct BeamformWork { 242 struct BeamformWork *next; 243 union { 244 BeamformSSBOCopy ssbo_copy_ctx; 245 BeamformCompute compute_ctx; 246 BeamformOutputFrame output_frame_ctx; 247 }; 248 u32 type; 249 } BeamformWork; 250 251 typedef struct { 252 BeamformWork *first; 253 BeamformWork *last; 254 BeamformWork *next_free; 255 i32 compute_in_flight; 256 b32 did_compute_this_frame; 257 } BeamformWorkQueue; 258 259 typedef struct { 260 BeamformFrame *frames; 261 u32 capacity; 262 u32 offset; 263 u32 cursor; 264 u32 needed_frames; 265 } BeamformFrameIterator; 266 267 typedef struct BeamformerCtx { 268 GLParams gl; 269 270 uv2 window_size; 271 u32 flags; 272 273 Arena ui_backing_store; 274 BeamformerUI *ui; 275 276 BeamformFrame beamform_frames[MAX_BEAMFORMED_SAVED_FRAMES]; 277 u32 displayed_frame_index; 278 279 /* NOTE: this will only be used when we are averaging */ 280 BeamformFrame averaged_frame; 281 ComputeShaderCtx csctx; 282 FragmentShaderCtx fsctx; 283 PartialComputeCtx partial_compute_ctx; 284 285 Arena export_buffer; 286 287 CudaLib cuda_lib; 288 Platform platform; 289 Stream error_stream; 290 291 BeamformWorkQueue beamform_work_queue; 292 293 BeamformerParametersFull *params; 294 } BeamformerCtx; 295 296 #define LABEL_GL_OBJECT(type, id, s) {s8 _s = (s); glObjectLabel(type, id, _s.len, (c8 *)_s.data);} 297 298 #define BEAMFORMER_FRAME_STEP_FN(name) void name(BeamformerCtx *ctx, Arena *arena, \ 299 BeamformerInput *input) 300 typedef BEAMFORMER_FRAME_STEP_FN(beamformer_frame_step_fn); 301 302 #endif /*_BEAMFORMER_H_ */