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


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