ogl_beamforming

Ultrasound Beamforming Implemented with OpenGL
git clone anongit@rnpnr.xyz:ogl_beamforming.git
Log | Files | Refs | Feed | Submodules | LICENSE

main_w32.c (4976B)


      1 /* See LICENSE for license details. */
      2 #ifndef _WIN32
      3 #error This file is only meant to be compiled for Win32
      4 #endif
      5 
      6 #include "beamformer.h"
      7 
      8 typedef struct {
      9 	iptr io_completion_handle;
     10 } w32_context;
     11 
     12 enum w32_io_events {
     13 	W32_IO_FILE_WATCH,
     14 	W32_IO_PIPE,
     15 };
     16 
     17 typedef struct {
     18 	u64  tag;
     19 	iptr context;
     20 } w32_io_completion_event;
     21 
     22 #include "os_win32.c"
     23 
     24 #define OS_DEBUG_LIB_NAME      ".\\beamformer.dll"
     25 #define OS_DEBUG_LIB_TEMP_NAME ".\\beamformer_temp.dll"
     26 
     27 #define OS_CUDA_LIB_NAME       "external\\cuda_toolkit.dll"
     28 #define OS_CUDA_LIB_TEMP_NAME  "external\\cuda_toolkit_temp.dll"
     29 
     30 #define OS_RENDERDOC_SONAME    "renderdoc.dll"
     31 
     32 #define OS_PIPE_NAME           "\\\\.\\pipe\\beamformer_data_fifo"
     33 #define OS_SMEM_NAME           "Local\\ogl_beamformer_parameters"
     34 
     35 #define OS_PATH_SEPERATOR      "\\"
     36 
     37 #include "static.c"
     38 
     39 static void
     40 dispatch_file_watch(OS *os, FileWatchDirectory *fw_dir, u8 *buf, Arena arena)
     41 {
     42 	i64 offset = 0;
     43 	TempArena save_point = {0};
     44 	w32_file_notify_info *fni = (w32_file_notify_info *)buf;
     45 	do {
     46 		end_temp_arena(save_point);
     47 		save_point = begin_temp_arena(&arena);
     48 
     49 		Stream path = {.data = arena_commit(&arena, KB(1)), .cap = KB(1)};
     50 
     51 		if (fni->action != FILE_ACTION_MODIFIED) {
     52 			stream_append_s8(&path, s8("unknown file watch event: "));
     53 			stream_append_u64(&path, fni->action);
     54 			stream_append_byte(&path, '\n');
     55 			os->write_file(os->stderr, stream_to_s8(&path));
     56 			stream_reset(&path, 0);
     57 		}
     58 
     59 		stream_append_s8(&path, fw_dir->name);
     60 		stream_append_byte(&path, '\\');
     61 
     62 		s8 file_name = s16_to_s8(&arena, (s16){.data = fni->filename,
     63 		                                       .len  = fni->filename_size / 2});
     64 		stream_append_s8(&path, file_name);
     65 		stream_append_byte(&path, 0);
     66 		stream_commit(&path, -1);
     67 
     68 		u64 hash = s8_hash(file_name);
     69 		for (u32 i = 0; i < fw_dir->file_watch_count; i++) {
     70 			FileWatch *fw = fw_dir->file_watches + i;
     71 			if (fw->hash == hash) {
     72 				fw->callback(os, stream_to_s8(&path), fw->user_data, arena);
     73 				break;
     74 			}
     75 		}
     76 
     77 		offset = fni->next_entry_offset;
     78 		fni    = (w32_file_notify_info *)((u8 *)fni + offset);
     79 	} while (offset);
     80 }
     81 
     82 static void
     83 clear_io_queue(OS *os, BeamformerInput *input, Arena arena)
     84 {
     85 	w32_context *ctx = (w32_context *)os->context;
     86 
     87 	iptr handle = ctx->io_completion_handle;
     88 	w32_overlapped *overlapped;
     89 	u32  bytes_read;
     90 	uptr user_data;
     91 	while (GetQueuedCompletionStatus(handle, &bytes_read, &user_data, &overlapped, 0)) {
     92 		w32_io_completion_event *event = (w32_io_completion_event *)user_data;
     93 		switch (event->tag) {
     94 		case W32_IO_FILE_WATCH: {
     95 			FileWatchDirectory *dir = (FileWatchDirectory *)event->context;
     96 			dispatch_file_watch(os, dir, dir->buffer.beg, arena);
     97 			zero_struct(overlapped);
     98 			ReadDirectoryChangesW(dir->handle, dir->buffer.beg, 4096, 0,
     99 			                      FILE_NOTIFY_CHANGE_LAST_WRITE, 0, overlapped, 0);
    100 		} break;
    101 		case W32_IO_PIPE: break;
    102 		}
    103 	}
    104 }
    105 
    106 static b32
    107 poll_pipe(Pipe *p, Stream *e, OS *os)
    108 {
    109 	u8  data;
    110 	i32 total_read = 0;
    111 	b32 result = ReadFile(p->file, &data, 0, &total_read, 0);
    112 	if (!result) {
    113 		i32 error = GetLastError();
    114 		/* NOTE: These errors mean nothing's been sent yet, otherwise pipe is busted
    115 		 * and needs to be recreated. */
    116 		if (error != ERROR_NO_DATA &&
    117 		    error != ERROR_PIPE_LISTENING &&
    118 		    error != ERROR_PIPE_NOT_CONNECTED)
    119 		{
    120 			DisconnectNamedPipe(p->file);
    121 			CloseHandle(p->file);
    122 			*p = os_open_named_pipe(p->name);
    123 
    124 			if (p->file == INVALID_FILE) {
    125 				stream_append_s8(e, s8("poll_pipe: failed to reopen pipe: error: "));
    126 				stream_append_i64(e, GetLastError());
    127 				stream_append_byte(e, '\n');
    128 				os->write_file(os->stderr, stream_to_s8(e));
    129 				stream_reset(e, 0);
    130 			}
    131 		}
    132 	}
    133 	return result;
    134 }
    135 
    136 int
    137 main(void)
    138 {
    139 	BeamformerCtx   ctx   = {0};
    140 	BeamformerInput input = {.executable_reloaded = 1};
    141 	Arena temp_memory = os_alloc_arena((Arena){0}, MB(16));
    142 	ctx.error_stream  = stream_alloc(&temp_memory, MB(1));
    143 
    144 	ctx.ui_backing_store        = sub_arena(&temp_memory, MB(2), KB(4));
    145 	ctx.os.compute_worker.arena = sub_arena(&temp_memory, MB(2), KB(4));
    146 
    147 	Pipe data_pipe    = os_open_named_pipe(OS_PIPE_NAME);
    148 	input.pipe_handle = data_pipe.file;
    149 	ASSERT(data_pipe.file != INVALID_FILE);
    150 
    151 	#define X(name) ctx.os.name = os_ ## name;
    152 	OS_FNS
    153 	#undef X
    154 
    155 	w32_context w32_ctx = {0};
    156 	w32_ctx.io_completion_handle = CreateIoCompletionPort(INVALID_FILE, 0, 0, 0);
    157 
    158 	ctx.os.context               = (iptr)&w32_ctx;
    159 	ctx.os.compute_worker.asleep = 1;
    160 	ctx.os.stderr                = GetStdHandle(STD_ERROR_HANDLE);
    161 
    162 	debug_init(&ctx.os, (iptr)&input, &temp_memory);
    163 	setup_beamformer(&ctx, &temp_memory);
    164 	os_wake_thread(ctx.os.compute_worker.sync_handle);
    165 
    166 	while (!ctx.should_exit) {
    167 		clear_io_queue(&ctx.os, &input, temp_memory);
    168 
    169 		input.last_mouse = input.mouse;
    170 		input.mouse.rl   = GetMousePosition();
    171 
    172 		input.pipe_data_available = poll_pipe(&data_pipe, &ctx.error_stream, &ctx.os);
    173 
    174 		beamformer_frame_step(&ctx, &temp_memory, &input);
    175 
    176 		input.executable_reloaded = 0;
    177 	}
    178 }