starfield

starfield.git
git clone git://git.lenczewski.org/starfield.git
Log | Files | Refs | Submodules | README | LICENSE

win_starfield.c (6127B)


      1 #include "win_starfield.h"
      2 
      3 internal struct win_starfield_state state;
      4 
      5 int WINAPI
      6 WinMain(HINSTANCE instance, HINSTANCE prev_instance, LPSTR cmdline, int cmdshow)
      7 {
      8 	/* TODO: parse out commandline arguments for debug behaviour? */
      9 	(void) instance;
     10 	(void) prev_instance;
     11 	(void) cmdline;
     12 	(void) cmdshow;
     13 
     14 	/* NOTE: the windows dll loader checks the parent directory of our
     15 	 * instance when loading libraries, so no need to do anything fancy
     16 	 */
     17 	char starfield_library_path[] = "starfield.dll";
     18 
     19 	if (!load_starfield_api(starfield_library_path, &state.starfield_api)) {
     20 		fprintf(stderr, "Failed to load starfield library: %s\n", starfield_library_path);
     21 		_exit(1);
     22 	}
     23 
     24 	state.platform_api = load_platform_api();
     25 
     26 	struct starfield_thread thread = {
     27 		.id = 0,
     28 	};
     29 
     30 	if (!init_memory(&state.platform_arena, 32 * MiB,
     31 			 &state.renderer_arena, 32 * MiB,
     32 			 &state.starfield_arena, 64 * MiB)) {
     33 		fprintf(stderr, "Failed to initialise memory\n");
     34 		_exit(1);
     35 	}
     36 
     37 	f32 target_render_rate = 60.0, target_physics_rate = 60.0;
     38 
     39 	u32 target_us_per_frame = USECS / target_render_rate;
     40 	u32 target_us_per_tick = USECS / target_physics_rate;
     41 
     42 	(void) target_us_per_tick;
     43 
     44 	u32 period_us = target_us_per_frame, buffered_periods = 2;
     45 	if (!init_audio(&state.platform_arena, &state.audio, period_us, buffered_periods)) {
     46 		fprintf(stderr, "Failed to initialise platform audio\n");
     47 	}
     48 
     49 	if (!init_video(&state.platform_arena, &state.video, instance)) {
     50 		fprintf(stderr, "Failed to initialise platform video\n");
     51 		_exit(1);
     52 	}
     53 
     54 	if (!init_vulkan(&state.renderer_arena, &state.vulkan)) {
     55 		fprintf(stderr, "Failed to initialise platform renderer\n");
     56 		_exit(1);
     57 	}
     58 
     59 	struct starfield_memory starfield_memory = {
     60 		.ptr = state.starfield_arena.ptr,
     61 		.cap = state.starfield_arena.cap,
     62 		.len = state.starfield_arena.len,
     63 	};
     64 
     65 	state.starfield_api.init(&thread, &starfield_memory, &state.platform_api);
     66 
     67 	state.running = 1;
     68 
     69 	f32 dt = 0;
     70 	while (state.running) {
     71 		struct starfield_input input = {
     72 			0,
     73 		};
     74 
     75 		state.starfield_api.update(&thread, &starfield_memory,
     76 					    &state.platform_api, &input, dt);
     77 
     78 		if (state.audio.enabled) {
     79 			state.starfield_api.sample(&thread, &starfield_memory,
     80 						   &state.platform_api, &state.audio.buffer, dt);
     81 
     82 			play_audio(&state.audio);
     83 		}
     84 
     85 		state.starfield_api.render(&thread, &starfield_memory,
     86 					   &state.platform_api, &state.renderer_api,
     87 					   state.video.width, state.video.height, dt);
     88 
     89 		draw_frame(&state.video);
     90 
     91 		Sleep(1000);
     92 	}
     93 
     94 	state.starfield_api.free(&thread, &state.starfield_memory, &state.platform_api);
     95 
     96 	free_vulkan(&state.vulkan);
     97 
     98 	_exit(0);
     99 }
    100 
    101 #define LOAD_SYMBOL(loc, T, sym) \
    102 	((loc) = (T *) GetProcAddress(library, sym))
    103 
    104 internal b32
    105 load_starfield_api(char const *filename, struct starfield_api *api)
    106 {
    107 	HMODULE library = LoadLibraryA(filename);
    108 	if (!library) return false;
    109 
    110 	LOAD_SYMBOL(api->init, starfield_api_init_t, "starfield_init");
    111 	LOAD_SYMBOL(api->update, starfield_api_update_t, "starfield_update");
    112 	LOAD_SYMBOL(api->render, starfield_api_render_t, "starfield_render");
    113 	LOAD_SYMBOL(api->sample, starfield_api_sample_t, "starfield_sample");
    114 	LOAD_SYMBOL(api->free, starfield_api_free_t, "starfield_free");
    115 
    116 	return true;
    117 }
    118 
    119 internal b32
    120 init_memory(struct arena *platform_arena, u64 platform_capacity,
    121 	    struct arena *renderer_arena, u64 renderer_capacity,
    122 	    struct arena *starfield_arena, u64 starfield_capacity)
    123 {
    124 #ifdef STARFIELD_DEBUG
    125 	void *base_addr = (void *) (2 * TiB);
    126 #else
    127 	void *base_addr = NULL;
    128 #endif
    129 
    130 	u64 huge_page_alignment = GetLargePageMinimum();
    131 	u64 len = ALIGN_NEXT(platform_capacity + renderer_capacity + starfield_capacity,
    132 			     huge_page_alignment);
    133 
    134 	/* TODO: add hugetlb support?
    135 	 * https://learn.microsoft.com/en-us/windows/win32/memory/large-page-support
    136 	 */
    137 	DWORD alloc_type = MEM_RESERVE | MEM_COMMIT;
    138 	void *ptr = VirtualAlloc(base_addr, len,
    139 				 alloc_type | MEM_LARGE_PAGES,
    140 				 PAGE_READWRITE);
    141 
    142 	if (!ptr)
    143 		ptr = VirtualAlloc(base_addr, len, alloc_type, PAGE_READWRITE);
    144 
    145 	if (!ptr)
    146 		return false;
    147 
    148 	/* NOTE: windows guarantees that the memory returned by VirtualAlloc
    149 	 * is zero-ed, so no need to memset it here
    150 	 */
    151 
    152 	platform_arena->ptr = ptr;
    153 	platform_arena->cap = platform_capacity;
    154 	platform_arena->len = 0;
    155 
    156 	renderer_arena->ptr = (u8 *) ptr + platform_capacity;
    157 	renderer_arena->cap = renderer_capacity;
    158 	renderer_arena->len = 0;
    159 
    160 	starfield_arena->ptr = (u8 *) ptr + platform_capacity + renderer_capacity;
    161 	starfield_arena->cap = starfield_capacity;
    162 	starfield_arena->len = 0;
    163 
    164 	return true;
    165 }
    166 
    167 internal b32
    168 init_audio(struct arena *arena, struct win_audio *audio, u64 period_us, u32 buffered_periods)
    169 {
    170 	(void) arena;
    171 	(void) audio;
    172 	(void) period_us;
    173 	(void) buffered_periods;
    174 
    175 	return false;
    176 }
    177 
    178 internal void
    179 play_audio(struct win_audio *audio)
    180 {
    181 	(void) audio;
    182 }
    183 
    184 internal b32
    185 init_video(struct arena *arena, struct win_video *video, HINSTANCE instance)
    186 {
    187 	(void) arena;
    188 	(void) video;
    189 	(void) instance;
    190 
    191 	return false;
    192 }
    193 
    194 internal void
    195 draw_frame(struct win_video *video)
    196 {
    197 	(void) video;
    198 }
    199 
    200 internal b32
    201 init_vulkan(struct arena *arena, struct win_vulkan *vulkan)
    202 {
    203 	(void) arena;
    204 	(void) vulkan;
    205 
    206 	return false;
    207 }
    208 
    209 internal void
    210 free_vulkan(struct win_vulkan *vulkan)
    211 {
    212 	(void) vulkan;
    213 }
    214 
    215 /* platform implementation
    216  * ===========================================================================
    217  */
    218 
    219 #ifdef STARFIELD_DEBUG
    220 
    221 DEBUG_PLATFORM_READ_FILE(DEBUG_platform_read_file)
    222 {
    223 	(void) filename;
    224 
    225 	return (struct DEBUG_platform_read_file_result) {0};
    226 }
    227 
    228 DEBUG_PLATFORM_WRITE_FILE(DEBUG_platform_write_file)
    229 {
    230 	(void) filename;
    231 	(void) buf;
    232 	(void) len;
    233 
    234 	return false;
    235 }
    236 
    237 DEBUG_PLATFORM_FREE_FILE_MEMORY(DEBUG_platform_free_file_memory)
    238 {
    239 	(void) ptr;
    240 }
    241 
    242 #endif
    243 
    244 internal struct platform_api
    245 load_platform_api(void)
    246 {
    247 	return (struct platform_api) {
    248 #ifdef STARFIELD_DEBUG
    249 		.DEBUG_read_file = DEBUG_platform_read_file,
    250 		.DEBUG_write_file = DEBUG_platform_write_file,
    251 		.DEBUG_free_file_memory = DEBUG_platform_free_file_memory,
    252 #endif
    253 	};
    254 }
    255 
    256 /* utils
    257  * ===========================================================================
    258  */
    259 
    260 // TODO: implement renderer