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 (19905B)


      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.c"
     11 #include "generated/beamformer_core.c"
     12 #include "generated/beamformer_shader_data.c"
     13 
     14 #include "external/raylib/src/raylib.h"
     15 #include "external/raylib/src/rlgl.h"
     16 
     17 #define beamformer_info(s) str8("[info] " s "\n")
     18 
     19 #define os_path_separator() (str8){.data = &os_system_info()->path_separator_byte, .length = 1}
     20 
     21 typedef struct { u64 value; } GPUHandle;
     22 typedef struct { u64 value; } GPUCommandList;
     23 typedef struct { u64 value; } GPUSplitBarrier;
     24 
     25 typedef struct { u64 value[1]; } VulkanHandle;
     26 
     27 typedef enum {
     28 	GPUTimeline_Graphics,
     29 	GPUTimeline_Compute,
     30 	GPUTimeline_Transfer,
     31 	GPUTimeline_Count,
     32 } GPUTimeline;
     33 
     34 typedef enum {
     35 	VulkanShaderKind_Vertex,
     36 	VulkanShaderKind_Mesh,
     37 	VulkanShaderKind_Fragment,
     38 	VulkanShaderKind_Compute,
     39 	VulkanShaderKind_Count,
     40 } VulkanShaderKind;
     41 
     42 typedef enum {
     43 	VulkanImageUsage_None,
     44 	VulkanImageUsage_Colour,
     45 	VulkanImageUsage_DepthStencil,
     46 	VulkanImageUsage_Count,
     47 } VulkanImageUsage;
     48 
     49 typedef enum {
     50 	VulkanUsageFlag_ImageSampling       = 1 << 0,
     51 	VulkanUsageFlag_HostReadWrite       = 1 << 1, // NOTE: not valid on images
     52 	/* NOTE: uses:
     53 	 * - image-image copy operations
     54 	 * - buffer-buffer copy operations
     55 	 */
     56 	VulkanUsageFlag_TransferSource      = 1 << 2,
     57 	VulkanUsageFlag_TransferDestination = 1 << 3,
     58 } VulkanUsageFlags;
     59 
     60 typedef struct {
     61 	VulkanShaderKind kind;
     62 	i32              specialization_struct_id;
     63 	void            *specialization_data;
     64 	str8             text;
     65 	str8             name;
     66 } VulkanPipelineCreateInfo;
     67 
     68 typedef struct {
     69 	GPUHandle handle;
     70 	u64       gpu_pointer;
     71 	i64       size;
     72 
     73 	// NOTE: only used for render models
     74 	u64       index_count;
     75 } GPUBuffer;
     76 
     77 typedef struct {
     78 	VulkanHandle image;
     79 	u32          width;
     80 	u32          height;
     81 	u32          samples;
     82 	u32          mip_map_levels;
     83 	// TODO(rnp): this is only here for importing from OpenGL, move it back into handle later
     84 	u64          memory_size;
     85 } GPUImage;
     86 
     87 typedef enum {
     88 	GPUVendor_AMD      = 0x1002,
     89 	GPUVendor_NVIDIA   = 0x10DE,
     90 	GPUVendor_Qualcomm = 0x5143,
     91 	GPUVendor_Intel    = 0x8086,
     92 } GPUVendor;
     93 
     94 typedef struct {
     95 	str8      name;
     96 	GPUVendor vendor;
     97 
     98 	f32 timestamp_period_ns;
     99 
    100 	u32 max_compute_shared_memory_size;
    101 	u16 max_msaa_samples;
    102 	u16 subgroup_size;
    103 
    104 	b32 cooperative_matrix;
    105 
    106 	u32 max_image_dimension_2D;
    107 	// NOTE(rnp): vulkan compute will output to a buffer so this won't be relevant
    108 	u32 max_image_dimension_3D;
    109 
    110 	u64 gpu_heap_size;
    111 	u64 gpu_heap_used;
    112 } GPUInfo;
    113 
    114 typedef struct {
    115 	i64               size;
    116 	VulkanUsageFlags  flags;
    117 
    118 	// NOTE(rnp): only required if buffer will be used on multiple timelines
    119 	u32               timeline_count;
    120 	GPUTimeline      *timelines_used;
    121 
    122 	OSHandle         *export;
    123 
    124 	str8              label;
    125 } GPUBufferAllocateInfo;
    126 
    127 typedef struct {
    128 	GPUBuffer model;
    129 	u32       vertex_count;
    130 	u32       normals_offset;
    131 } RenderModel;
    132 
    133 #include "threads.c"
    134 #include "util_os_ui.c"
    135 
    136 ///////////////////////////
    137 // NOTE: vulkan layer API
    138 DEBUG_IMPORT void vk_load(OSLibrary vulkan, Stream *error);
    139 
    140 DEBUG_IMPORT GPUInfo *gpu_info(void);
    141 
    142 DEBUG_IMPORT void gpu_buffer_allocate(GPUBuffer *, GPUBufferAllocateInfo info);
    143 DEBUG_IMPORT void gpu_buffer_release(GPUBuffer *);
    144 DEBUG_IMPORT void gpu_buffer_range_upload(GPUBuffer *, void *data, u64 offset, u64 size, b32 non_temporal);
    145 DEBUG_IMPORT void gpu_buffer_range_download(void *output, GPUBuffer *, u64 source_offset, u64 size, b32 non_temporal);
    146 DEBUG_IMPORT u64  gpu_round_up_to_sync_size(u64, u64 min);
    147 
    148 // NOTE: images are 2D only, any other use case should just use a buffer and index in the shader
    149 DEBUG_IMPORT void vk_image_allocate(GPUImage *, u32 width, u32 height, u32 mips, u32 samples, VulkanImageUsage usage, VulkanUsageFlags flags, OSHandle *export, str8 label);
    150 DEBUG_IMPORT void vk_image_release(GPUImage *);
    151 
    152 DEBUG_IMPORT void vk_render_model_allocate(GPUBuffer *, void *indices, u64 index_count, u64 model_size, str8 label);
    153 DEBUG_IMPORT void vk_render_model_range_upload(GPUBuffer *, void *data, u64 offset, u64 size, b32 non_temporal);
    154 DEBUG_IMPORT void vk_render_model_release(GPUBuffer *);
    155 
    156 /* NOTE: Pipelines do not have bindings. Data should be passed using push constants.
    157  * In particular the push constants should contain pointers to gpu memory using the
    158  * BufferDeviceAddress extension. */
    159 // TODO(rnp): change this to accept SPIR-V directly and accept BakeParameters as specialization data
    160 DEBUG_IMPORT VulkanHandle vk_pipeline(VulkanPipelineCreateInfo *infos, u32 count, u32 push_constants_size);
    161 DEBUG_IMPORT b32          vk_pipeline_valid(VulkanHandle);
    162 DEBUG_IMPORT void         vk_pipeline_release(VulkanHandle);
    163 
    164 DEBUG_IMPORT b32 vk_buffer_needs_sync(GPUBuffer *);
    165 
    166 DEBUG_IMPORT VulkanHandle vk_create_semaphore(OSHandle *export);
    167 
    168 DEBUG_IMPORT b32             gpu_host_wait_timeline(GPUTimeline timeline, u64 value, u64 timeout_ns);
    169 DEBUG_IMPORT u64             gpu_host_signal_timeline(GPUTimeline timeline);
    170 
    171 DEBUG_IMPORT GPUCommandList  gpu_command_list_begin(GPUTimeline timeline);
    172 // NOTE: extra semaphores only exist for synchronization with OpenGL and will be removed in the future
    173 DEBUG_IMPORT u64             gpu_command_list_end(GPUCommandList command, VulkanHandle wait_semaphore, VulkanHandle finished_semaphore);
    174 
    175 DEBUG_IMPORT void            gpu_command_bind_pipeline(GPUCommandList command, VulkanHandle pipeline);
    176 DEBUG_IMPORT void            gpu_command_pipeline_barrier(GPUCommandList command);
    177 DEBUG_IMPORT void            gpu_command_clear_buffer(GPUCommandList command, GPUBuffer *buffer, u64 offset, u64 size, u32 clear_word);
    178 DEBUG_IMPORT void            gpu_command_dispatch_compute(GPUCommandList command, uv3 dispatch);
    179 DEBUG_IMPORT void            gpu_command_push_constants(GPUCommandList command, u32 offset, u32 size, void *values);
    180 DEBUG_IMPORT void            gpu_command_timestamp(GPUCommandList command);
    181 DEBUG_IMPORT void            gpu_command_wait_timeline(GPUCommandList command, GPUTimeline timeline, u64 value);
    182 
    183 DEBUG_IMPORT void            gpu_command_begin_rendering(GPUCommandList command, GPUImage *restrict colour, GPUImage *restrict depth, GPUImage *restrict resolve);
    184 DEBUG_IMPORT void            gpu_command_draw(GPUCommandList command, GPUBuffer *model);
    185 DEBUG_IMPORT void            gpu_command_scissor(GPUCommandList command, u32 width, u32 height, u32 x_offset, u32 y_offset);
    186 DEBUG_IMPORT void            gpu_command_viewport(GPUCommandList command, f32 width, f32 height, f32 x_offset, f32 y_offset, f32 min_depth, f32 max_depth);
    187 DEBUG_IMPORT void            gpu_command_end_rendering(GPUCommandList command);
    188 
    189 DEBUG_IMPORT void            gpu_command_copy_buffer(GPUCommandList command, GPUBuffer *restrict destination, GPUBuffer *restrict source, u64 source_offset, i64 size);
    190 
    191 // NOTE: returns array of valid timestamps. Calling thread may stall until results available.
    192 DEBUG_IMPORT u64 *           gpu_read_timestamps(GPUTimeline timeline, u64 *count, Arena *arena);
    193 
    194 #if BEAMFORMER_RENDERDOC_HOOKS
    195 DEBUG_IMPORT void *       vk_renderdoc_instance_handle(void);
    196 
    197 #define RENDERDOC_GET_API_FN(name) b32 name(u32 version, void **out_api)
    198 typedef RENDERDOC_GET_API_FN(renderdoc_get_api_fn);
    199 
    200 #define RENDERDOC_START_FRAME_CAPTURE_FN(name) void name(void *instance_handle, i64 window_handle)
    201 typedef RENDERDOC_START_FRAME_CAPTURE_FN(renderdoc_start_frame_capture_fn);
    202 
    203 #define RENDERDOC_END_FRAME_CAPTURE_FN(name) b32 name(void *instance_handle, i64 window_handle)
    204 typedef RENDERDOC_END_FRAME_CAPTURE_FN(renderdoc_end_frame_capture_fn);
    205 
    206 typedef alignas(16) u8 RenderDocAPI[216];
    207 #define RENDERDOC_API_FN_ADDR(a, offset) (*(i64 *)((*a) + offset))
    208 #define RENDERDOC_START_FRAME_CAPTURE(a) (renderdoc_start_frame_capture_fn *)RENDERDOC_API_FN_ADDR(a, 152)
    209 #define RENDERDOC_END_FRAME_CAPTURE(a)   (renderdoc_end_frame_capture_fn *)  RENDERDOC_API_FN_ADDR(a, 168)
    210 
    211 DEBUG_IMPORT renderdoc_start_frame_capture_fn *start_frame_capture;
    212 DEBUG_IMPORT renderdoc_end_frame_capture_fn   *end_frame_capture;
    213 #define start_renderdoc_capture() if (start_frame_capture) start_frame_capture(vk_renderdoc_instance_handle(), 0)
    214 #define end_renderdoc_capture()   if (end_frame_capture)   end_frame_capture(vk_renderdoc_instance_handle(), 0)
    215 #define renderdoc_attached(...)   (start_frame_capture != 0)
    216 
    217 #else
    218 #define start_renderdoc_capture(...)
    219 #define end_renderdoc_capture(...)
    220 #define renderdoc_attached(...) (0)
    221 #endif
    222 
    223 #include "util_os.c"
    224 
    225 ///////////////////////////////
    226 // NOTE: CUDA Library Bindings
    227 
    228 #define cuda_supported() (cuda_init != cuda_init_stub)
    229 #define CUDA_INIT_FN(name) void name(u32 *input_dims, u32 *decoded_dims)
    230 typedef CUDA_INIT_FN(cuda_init_fn);
    231 CUDA_INIT_FN(cuda_init_stub) {}
    232 
    233 #define CUDA_REGISTER_BUFFERS_FN(name) void name(u32 *rf_data_ssbos, u32 rf_buffer_count, u32 raw_data_ssbo)
    234 typedef CUDA_REGISTER_BUFFERS_FN(cuda_register_buffers_fn);
    235 CUDA_REGISTER_BUFFERS_FN(cuda_register_buffers_stub) {}
    236 
    237 #define CUDA_HILBERT_FN(name) void name(u32 input_buffer_idx, u32 output_buffer_idx)
    238 typedef CUDA_HILBERT_FN(cuda_hilbert_fn);
    239 CUDA_HILBERT_FN(cuda_hilbert_stub) {}
    240 
    241 #define CUDA_SET_CHANNEL_MAPPING_FN(name) void name(i16 *channel_mapping)
    242 typedef CUDA_SET_CHANNEL_MAPPING_FN(cuda_set_channel_mapping_fn);
    243 CUDA_SET_CHANNEL_MAPPING_FN(cuda_set_channel_mapping_stub) {}
    244 
    245 #define CUDALibraryProcedureList \
    246 	X(hilbert,             "cuda_hilbert")             \
    247 	X(init,                "init_cuda_configuration")  \
    248 	X(register_buffers,    "register_cuda_buffers")    \
    249 	X(set_channel_mapping, "cuda_set_channel_mapping")
    250 
    251 #define X(name, ...) DEBUG_IMPORT cuda_## name ##_fn *cuda_## name;
    252 CUDALibraryProcedureList
    253 #undef X
    254 
    255 /////////////////////////////////////
    256 // NOTE: Core Beamformer Definitions
    257 
    258 #include "beamformer_compute_stats.c"
    259 #include "beamformer_shared_memory.c"
    260 
    261 typedef struct {
    262 	BeamformerFilterParameters parameters;
    263 	f32                        time_delay;
    264 	i32                        length;
    265 	void                      *data;
    266 } BeamformerFilter;
    267 
    268 typedef struct {
    269 	uv3 layout;
    270 	uv3 dispatch;
    271 	u32 compile_flags;
    272 	BeamformerDataKind input_data_kind;
    273 	BeamformerDataKind output_data_kind;
    274 	BeamformerShaderBakeParameters bake;
    275 } BeamformerShaderDescriptor;
    276 
    277 typedef struct BeamformerComputePlan BeamformerComputePlan;
    278 struct BeamformerComputePlan {
    279 	BeamformerComputePipeline pipeline;
    280 
    281 	VulkanHandle vulkan_pipelines[BeamformerMaxComputeShaderStages];
    282 
    283 	u32 first_image_shader_index;
    284 	u32 channel_count;
    285 	u32 raw_channel_byte_stride;
    286 
    287 	u32 dirty_programs;
    288 
    289 	BeamformerAcquisitionKind acquisition_kind;
    290 	u32                       acquisition_count;
    291 	BeamformerContrastMode    contrast_mode;
    292 
    293 	u32 rf_size;
    294 	b32 iq_pipeline;
    295 
    296 	m4  ui_voxel_transform;
    297 	// NOTE(rnp): final voxel transform determining frame dimensions
    298 	m4  voxel_transform;
    299 	// NOTE(rnp): final voxel transform used for beamforming
    300 	m4  das_voxel_transform;
    301 
    302 	iv3 output_points;
    303 	i32 average_frames;
    304 
    305 	// TODO(rnp): specialization constants
    306 	v2  xdc_element_pitch;
    307 	m4  xdc_transform;
    308 
    309 	u32  readi_group;
    310 
    311 	GPUBuffer gpu_temp_arena;
    312 
    313 	BeamformerFilterParameters filter_parameters[BeamformerFilterSlots];
    314 
    315 	u128 shader_hashes[BeamformerMaxComputeShaderStages];
    316 	BeamformerShaderDescriptor shader_descriptors[BeamformerMaxComputeShaderStages];
    317 
    318 	BeamformerComputePlan *next;
    319 };
    320 
    321 typedef struct {
    322 	u64 upload_complete_values[BeamformerMaxRawDataFramesInFlight];
    323 	u64 compute_complete_values[BeamformerMaxRawDataFramesInFlight];
    324 
    325 	GPUBuffer buffer;
    326 
    327 	u32 active_rf_size;
    328 
    329 	u64 timestamp;
    330 
    331 	u64 insertion_index;
    332 	u64 compute_index;
    333 } BeamformerRFBuffer;
    334 
    335 typedef struct {
    336 	BeamformerComputeStatsTable table;
    337 	f32 average_times[BeamformerShaderKind_Count];
    338 
    339 	u64 last_rf_timer_count;
    340 	f32 rf_time_delta_average;
    341 
    342 	u32 latest_frame_index;
    343 	u32 latest_rf_index;
    344 } ComputeShaderStats;
    345 
    346 /* TODO(rnp): maybe this also gets used for CPU timing info as well */
    347 typedef enum {
    348 	ComputeTimingInfoKind_ComputeFrameBegin,
    349 	ComputeTimingInfoKind_ComputeFrameEnd,
    350 	ComputeTimingInfoKind_Shader,
    351 	ComputeTimingInfoKind_RF_Data,
    352 } ComputeTimingInfoKind;
    353 
    354 typedef struct {
    355 	u64 timer_count;
    356 	ComputeTimingInfoKind kind;
    357 	union {
    358 		struct {
    359 			static_assert(BeamformerShaderKind_Count <= U16_MAX, "");
    360 			u16 shader;
    361 			u16 shader_slot;
    362 		};
    363 	};
    364 } ComputeTimingInfo;
    365 
    366 typedef struct {
    367 	u32 write_index;
    368 	u32 read_index;
    369 	b32 compute_frame_active;
    370 
    371 	u32                  in_flight_shader_count;
    372 	BeamformerShaderKind in_flight_shader_ids[BeamformerMaxComputeShaderStages];
    373 
    374 	ComputeTimingInfo buffer[4096];
    375 } ComputeTimingTable;
    376 
    377 typedef struct {
    378 	BeamformerRFBuffer      *rf_buffer;
    379 	BeamformerSharedMemory  *shared_memory;
    380 	i64                      shared_memory_size;
    381 	ComputeTimingTable      *compute_timing_table;
    382 	i32                     *compute_worker_sync;
    383 } BeamformerUploadThreadContext;
    384 
    385 typedef struct {
    386 	u64 gpu_pointer;
    387 	u64 timeline_valid_value;
    388 
    389 	/* NOTE: for use when displaying either prebeamformed frames or on the current frame
    390 	 * when we intend to recompute on the next frame */
    391 	m4  voxel_transform;
    392 
    393 	iv3 points;
    394 
    395 	u32                       id;
    396 	u32                       compound_count;
    397 	u32                       parameter_block;
    398 	BeamformerDataKind        data_kind;
    399 	BeamformerAcquisitionKind acquisition_kind;
    400 	BeamformerContrastMode    contrast_mode;
    401 	BeamformerViewPlaneTag    view_plane_tag;
    402 } BeamformerFrame;
    403 
    404 /* NOTE(rnp): backing storage for beamformed frames. The amount of backlog frames
    405 * is dependant on the currently requested output size. */
    406 typedef struct {
    407 	GPUBuffer   buffer[1];
    408 
    409 	u64         next_offset;
    410 	u64         counter;
    411 
    412 	BeamformerFrame frames[BeamformerMaxBacklogFrames];
    413 } BeamformerFrameBacklog;
    414 
    415 typedef struct {
    416 	BeamformerRFBuffer rf_buffer;
    417 
    418 	BeamformerComputePlan *compute_plans[BeamformerMaxParameterBlocks];
    419 	BeamformerComputePlan *compute_plan_freelist;
    420 
    421 	/* NOTE(rnp): used to ping pong data between compute stages.
    422 	 *
    423 	 * Allocate one extra slot for DAS output to allow overlap with the next
    424 	 * channel chunk batch. To obtain optimal overlap we need 2 extra slots
    425 	 * and we need to ping pong submissions between queues. This is not
    426 	 * implemented so we only do 1 extra slot for now.
    427 	 */
    428 	#define PING_PONG_BUFFER_SLOTS (2 + 1)
    429 	GPUBuffer ping_pong_buffer;
    430 	OSHandle  ping_pong_export_handle;
    431 	u32       ping_pong_input_index;
    432 
    433 	f32 processing_progress;
    434 	b32 processing_compute;
    435 
    436 	BeamformerFrameBacklog backlog;
    437 } BeamformerComputeContext;
    438 
    439 typedef struct {
    440 	Arena    *arena;
    441 	iptr      user_context;
    442 	i32       sync_variable;
    443 	b32       awake;
    444 	OSThread  handle;
    445 } GLWorkerThreadContext;
    446 
    447 typedef struct {
    448 	str8                 name;
    449 	BeamformerRegisters *registers;
    450 } BeamformerCommand;
    451 
    452 typedef struct BeamformerRegistersNode BeamformerRegistersNode;
    453 struct BeamformerRegistersNode {
    454 	BeamformerRegistersNode *next;
    455 	BeamformerRegisters      v;
    456 };
    457 
    458 typedef struct BeamformerCommandNode BeamformerCommandNode;
    459 struct BeamformerCommandNode {
    460 	BeamformerCommandNode *next;
    461 	BeamformerCommandNode *prev;
    462 	BeamformerCommand      command;
    463 };
    464 
    465 typedef struct {
    466 	BeamformerCommandNode *first;
    467 	BeamformerCommandNode *last;
    468 	u64                    count;
    469 } BeamformerCommandList;
    470 
    471 typedef enum {
    472 	BeamformerState_Uninitialized = 0,
    473 	BeamformerState_Running,
    474 	BeamformerState_ShouldClose,
    475 	BeamformerState_Terminated,
    476 } BeamformerState;
    477 
    478 typedef enum {
    479 	RulerState_None,
    480 	RulerState_Start,
    481 	RulerState_Hold,
    482 	RulerState_Count,
    483 } RulerState;
    484 
    485 typedef struct {
    486 	v3 start;
    487 	v3 end;
    488 	RulerState state;
    489 } Ruler;
    490 
    491 typedef struct {
    492 	f32 t;
    493 	f32 scale;
    494 } BeamformerUIBlinker;
    495 
    496 #define BEAMFORMER_FRAME_VIEW_KIND_LIST \
    497 	X(Latest,   "Latest")     \
    498 	X(3DXPlane, "3D X-Plane") \
    499 	X(Copy,     "Copy")       \
    500 
    501 typedef enum {
    502 	#define X(kind, ...) BeamformerFrameViewKind_##kind,
    503 	BEAMFORMER_FRAME_VIEW_KIND_LIST
    504 	#undef X
    505 	BeamformerFrameViewKind_Count,
    506 } BeamformerFrameViewKind;
    507 
    508 typedef struct BeamformerFrameView BeamformerFrameView;
    509 struct BeamformerFrameView {
    510 	BeamformerFrameViewKind kind;
    511 	b32 dirty;
    512 
    513 	// NOTE(rnp): for FrameViewKindCopy
    514 	GPUBuffer copy_buffer;
    515 
    516 	GPUImage colour_image;
    517 	// NOTE(rnp): temporary, on w32 we must hold onto this when importing vulkan data to OpenGL
    518 	OSHandle export_handle;
    519 	u32      memory_object;
    520 	u32      texture;
    521 
    522 	b32 log_scale;
    523 	f32 threshold;
    524 	f32 dynamic_range;
    525 	f32 gamma;
    526 
    527 	union {
    528 		/* BeamformerFrameViewKind_Latest/BeamformerFrameViewKind_Copy */
    529 		struct {
    530 			b32   scale_bar_active[2];
    531 			Ruler ruler;
    532 			BeamformerViewPlaneTag view_plane;
    533 			BeamformerFrame frame;
    534 		};
    535 
    536 		/* BeamformerFrameViewKind_3DXPlane */
    537 		struct {
    538 			f32 hot_t[BeamformerViewPlaneTag_Count];
    539 			//b32 plane_active[BeamformerViewPlaneTag_Count];
    540 			b32 plane_active[BeamformerViewPlaneTag_Count - 2];
    541 			i32 plane_drag_index;
    542 			f32 rotation;
    543 			b32 demo;
    544 			v3  hit_start_point;
    545 			v3  hit_test_point;
    546 		};
    547 	};
    548 
    549 	BeamformerFrameView *prev, *next;
    550 };
    551 
    552 typedef struct BeamformerUIPanel BeamformerUIPanel;
    553 struct BeamformerUIPanel {
    554 	BeamformerUIPanel *parent;
    555 	BeamformerUIPanel *last_child;
    556 	BeamformerUIPanel *first_child;
    557 	BeamformerUIPanel *previous_sibling;
    558 	BeamformerUIPanel *next_sibling;
    559 
    560 	u64 child_count;
    561 
    562 	BeamformerPanelKind kind;
    563 	union {
    564 		BeamformerFrameView *frame_view;
    565 
    566 		BeamformerUIPanel *tab_focus;
    567 
    568 		BeamformerUIBlinker compute_stats_broken_shader_blinker;
    569 		BeamformerUIBlinker live_imaging_save_button_blinker;
    570 
    571 		struct {
    572 			u32 parameter_block;
    573 			b16 expand_coordinate[2];
    574 		} parameter_listing;
    575 
    576 		struct {
    577 			Axis2 axis;
    578 			f32   fraction;
    579 		} split;
    580 	} u;
    581 };
    582 
    583 typedef struct {
    584 	BeamformerState state;
    585 
    586 	iv2 window_size;
    587 
    588 	Arena *arena;
    589 	Arena *ui_arena;
    590 	void  *ui;
    591 	u32    ui_dirty_parameter_blocks;
    592 
    593 	u64    frame_timestamp;
    594 	u64    frame_index;
    595 	Arena *frame_arenas[2];
    596 
    597 	BeamformerUIPanel *auto_live_control_panel;
    598 	u64                live_imaging_active_frame;
    599 	b32                live_imaging_active;
    600 
    601 	BeamformerRegistersNode  base_registers;
    602 	BeamformerRegistersNode *registers;
    603 
    604 	BeamformerCommandList command_queues[2];
    605 
    606 	Stream error_stream;
    607 
    608 	BeamformerSharedMemory *shared_memory;
    609 	i64                     shared_memory_size;
    610 
    611 	BeamformerFrame *latest_frame;
    612 
    613 	// TODO(rnp): track elsewhere
    614 	b32 render_shader_updated;
    615 
    616 	/* NOTE: this will only be used when we are averaging */
    617 	u32             averaged_frame_index;
    618 	BeamformerFrame averaged_frames[2];
    619 
    620 	GLWorkerThreadContext  upload_worker;
    621 	GLWorkerThreadContext  compute_worker;
    622 
    623 	BeamformerComputeContext compute_context;
    624 
    625 	ComputeShaderStats compute_shader_stats[1];
    626 	ComputeTimingTable compute_timing_table[1];
    627 
    628 	BeamformWorkQueue  beamform_work_queue[1];
    629 
    630 	// TODO(rnp): this should go to the UI eventually
    631 	OSWindow main_window;
    632 } BeamformerCtx;
    633 
    634 typedef enum {
    635 	BeamformerFileReloadKind_ComputeInternalShader,
    636 	BeamformerFileReloadKind_ComputeShader,
    637 	BeamformerFileReloadKind_RenderShader,
    638 } BeamformerFileReloadKind;
    639 
    640 typedef struct {
    641 	BeamformerShaderKind shader;
    642 	VulkanHandle *       pipeline;
    643 } BeamformerShaderReloadData;
    644 
    645 typedef struct {
    646 	BeamformerShaderKind  shader;
    647 	VulkanShaderKind      shader_kind;
    648 
    649 	// NOTE(rnp): based on BakeShaders compile time value
    650 	str8                  filename_or_data;
    651 
    652 	BeamformerShaderDescriptor *shader_descriptor;
    653 
    654 	uv3 layout;
    655 } BeamformerShaderReloadInfo;
    656 
    657 typedef struct {
    658 	BeamformerFileReloadKind kind;
    659 	union {
    660 		BeamformerShaderReloadData shader_reload;
    661 	};
    662 } BeamformerFileReloadContext;
    663 
    664 #define BEAMFORMER_COMPLETE_COMPUTE_FN(name) void name(BeamformerCtx *ctx, Arena *arena)
    665 typedef BEAMFORMER_COMPLETE_COMPUTE_FN(beamformer_complete_compute_fn);
    666 
    667 #define BEAMFORMER_RF_UPLOAD_FN(name) void name(BeamformerUploadThreadContext *ctx)
    668 typedef BEAMFORMER_RF_UPLOAD_FN(beamformer_rf_upload_fn);
    669 
    670 #define BEAMFORMER_DEBUG_UI_DEINIT_FN(name) void name(BeamformerCtx *ctx)
    671 typedef BEAMFORMER_DEBUG_UI_DEINIT_FN(beamformer_debug_ui_deinit_fn);
    672 
    673 #endif /* BEAMFORMER_INTERNAL_H */