move opengl library loading to a thread that starts as soon as possible and is awaited as late as we can allow
This commit is contained in:
		| @@ -28,6 +28,7 @@ typedef struct EngineContext { | |||||||
|     char **argv; |     char **argv; | ||||||
|     /* where the app was run from, used as the root for packs */ |     /* where the app was run from, used as the root for packs */ | ||||||
|     char *base_dir; |     char *base_dir; | ||||||
|  |     char *title; | ||||||
|  |  | ||||||
|     Vec2 window_dims; |     Vec2 window_dims; | ||||||
|     Rect viewport_rect; |     Rect viewport_rect; | ||||||
|   | |||||||
							
								
								
									
										156
									
								
								src/twn_loop.c
									
									
									
									
									
								
							
							
						
						
									
										156
									
								
								src/twn_loop.c
									
									
									
									
									
								
							| @@ -4,7 +4,6 @@ | |||||||
| #include "twn_util.h" | #include "twn_util.h" | ||||||
| #include "twn_util_c.h" | #include "twn_util_c.h" | ||||||
| #include "twn_game_object_c.h" | #include "twn_game_object_c.h" | ||||||
| #include "twn_audio_c.h" |  | ||||||
| #include "twn_textures_c.h" | #include "twn_textures_c.h" | ||||||
|  |  | ||||||
| #include <SDL2/SDL.h> | #include <SDL2/SDL.h> | ||||||
| @@ -20,6 +19,9 @@ | |||||||
| #define PACKAGE_EXTENSION "btw" | #define PACKAGE_EXTENSION "btw" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | static SDL_Thread *opengl_load_thread; | ||||||
|  |  | ||||||
|  |  | ||||||
| static int event_callback(void *userdata, SDL_Event *event) { | static int event_callback(void *userdata, SDL_Event *event) { | ||||||
|     (void)userdata; |     (void)userdata; | ||||||
|  |  | ||||||
| @@ -342,14 +344,16 @@ ERR_PACK_MANIFEST_PATH_ALLOC_FAIL: | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| static bool initialize(void) { | static int opengl_load_thread_fn(void *data) { | ||||||
|     profile_start("SDL initialization"); |     (void)data; | ||||||
|     if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_EVENTS) == -1) { |  | ||||||
|         CRY_SDL("SDL initialization failed."); |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|     profile_end("SDL initialization"); |  | ||||||
|  |  | ||||||
|  |     SDL_GL_LoadLibrary(NULL); | ||||||
|  |  | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | static bool initialize(void) { | ||||||
|     /* first things first, most things here will be loaded from the config file */ |     /* first things first, most things here will be loaded from the config file */ | ||||||
|     /* it's expected to be present in the data directory, no matter what */ |     /* it's expected to be present in the data directory, no matter what */ | ||||||
|     /* that is why PhysicsFS is initialized before anything else */ |     /* that is why PhysicsFS is initialized before anything else */ | ||||||
| @@ -446,11 +450,11 @@ static bool initialize(void) { | |||||||
|     SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); |     SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); | ||||||
|     SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); |     SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); | ||||||
|  |  | ||||||
|     /* init got far enough to create a window */ |  | ||||||
|     { |  | ||||||
|     toml_datum_t datum_title = toml_string_in(about, "title"); |     toml_datum_t datum_title = toml_string_in(about, "title"); | ||||||
|     if (!datum_title.ok) |     if (!datum_title.ok) | ||||||
|             datum_title.u.s = "townengine project"; |         datum_title.u.s = SDL_strdup("townengine project"); | ||||||
|  |  | ||||||
|  |     ctx.title = datum_title.u.s; | ||||||
|  |  | ||||||
|     /* not yet used |     /* not yet used | ||||||
|     toml_datum_t datum_developer = toml_string_in(about, "developer"); |     toml_datum_t datum_developer = toml_string_in(about, "developer"); | ||||||
| @@ -485,52 +489,7 @@ static bool initialize(void) { | |||||||
|     ctx.game.resolution.x = (float)ctx.base_render_width; |     ctx.game.resolution.x = (float)ctx.base_render_width; | ||||||
|     ctx.game.resolution.y = (float)ctx.base_render_height; |     ctx.game.resolution.y = (float)ctx.base_render_height; | ||||||
|  |  | ||||||
|         /* TODO: investigate viability of detached thread driver and window creation, as it's the worst load time offender */ |  | ||||||
|         profile_start("window creation"); |  | ||||||
|         ctx.window = SDL_CreateWindow(datum_title.u.s, |  | ||||||
|                                       SDL_WINDOWPOS_CENTERED, |  | ||||||
|                                       SDL_WINDOWPOS_CENTERED, |  | ||||||
|                                       (int)ctx.base_render_width, |  | ||||||
|                                       (int)ctx.base_render_height, |  | ||||||
|                                       //SDL_WINDOW_ALLOW_HIGHDPI | |  | ||||||
|                                           SDL_WINDOW_RESIZABLE | |  | ||||||
|                                           SDL_WINDOW_OPENGL); |  | ||||||
|         profile_end("window creation"); |  | ||||||
|  |  | ||||||
|         if (datum_title.ok) |  | ||||||
|             SDL_free(datum_title.u.s); |  | ||||||
|  |  | ||||||
|     //SDL_free(datum_developer.u.s); |     //SDL_free(datum_developer.u.s); | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (ctx.window == NULL) { |  | ||||||
|         CRY_SDL("Window creation failed."); |  | ||||||
|         goto fail; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     profile_start("opengl context creation"); |  | ||||||
|     ctx.gl_context = SDL_GL_CreateContext(ctx.window); |  | ||||||
|     if (!ctx.gl_context) { |  | ||||||
|         CRY_SDL("GL context creation failed."); |  | ||||||
|         goto fail; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (SDL_GL_MakeCurrent(ctx.window, ctx.gl_context)) { |  | ||||||
|         CRY_SDL("GL context binding failed."); |  | ||||||
|         goto fail; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /* TODO: figure out what we ultimately prefer */ |  | ||||||
|     SDL_GL_SetSwapInterval(0); |  | ||||||
|  |  | ||||||
|     if (!render_init()) |  | ||||||
|         goto fail; |  | ||||||
|  |  | ||||||
|     setup_viewport(0, 0, (int)ctx.base_render_width, (int)ctx.base_render_height); |  | ||||||
|     profile_end("opengl context creation"); |  | ||||||
|  |  | ||||||
|     /* might need this to have multiple windows */ |  | ||||||
|     ctx.window_id = SDL_GetWindowID(ctx.window); |  | ||||||
|  |  | ||||||
|     /* TODO: */ |     /* TODO: */ | ||||||
|     // SDL_GetRendererOutputSize(ctx.renderer, &ctx.window_w, &ctx.window_h); |     // SDL_GetRendererOutputSize(ctx.renderer, &ctx.window_w, &ctx.window_h); | ||||||
| @@ -628,11 +587,6 @@ static bool initialize(void) { | |||||||
|     ctx.render_queue_2d = NULL; |     ctx.render_queue_2d = NULL; | ||||||
|     ctx.uncolored_mesh_batches = NULL; |     ctx.uncolored_mesh_batches = NULL; | ||||||
|  |  | ||||||
|     profile_start("texture and text cache initialization"); |  | ||||||
|     textures_cache_init(&ctx.texture_cache, ctx.window); |  | ||||||
|     text_cache_init(&ctx.text_cache); |  | ||||||
|     profile_end("texture and text cache initialization"); |  | ||||||
|  |  | ||||||
|     /* input */ |     /* input */ | ||||||
|     toml_datum_t datum_keybind_slots = toml_int_in(engine, "keybind_slots"); |     toml_datum_t datum_keybind_slots = toml_int_in(engine, "keybind_slots"); | ||||||
|     if (!datum_keybind_slots.ok) { |     if (!datum_keybind_slots.ok) { | ||||||
| @@ -652,6 +606,63 @@ static bool initialize(void) { | |||||||
|     ctx.game.fog_color = (Color){ 255, 255, 255, 255 }; /* TODO: pick some grey? */ |     ctx.game.fog_color = (Color){ 255, 255, 255, 255 }; /* TODO: pick some grey? */ | ||||||
|     ctx.game.fog_end = 1.0f; |     ctx.game.fog_end = 1.0f; | ||||||
|  |  | ||||||
|  |     update_viewport(); | ||||||
|  |  | ||||||
|  |     profile_start("game object load"); | ||||||
|  |     /* now we can actually start doing stuff */ | ||||||
|  |     game_object_load(); | ||||||
|  |     profile_end("game object load"); | ||||||
|  |  | ||||||
|  |     /* delayed as further as possible so that more work is done before we have to wait */ | ||||||
|  |     SDL_WaitThread(opengl_load_thread, NULL); | ||||||
|  |     profile_end("opengl loading"); | ||||||
|  |  | ||||||
|  |     /* TODO: investigate viability of detached thread driver and window creation, as it's the worst load time offender */ | ||||||
|  |     profile_start("window creation"); | ||||||
|  |     ctx.window = SDL_CreateWindow(ctx.title, | ||||||
|  |                                   SDL_WINDOWPOS_CENTERED, | ||||||
|  |                                   SDL_WINDOWPOS_CENTERED, | ||||||
|  |                                   (int)ctx.base_render_width, | ||||||
|  |                                   (int)ctx.base_render_height, | ||||||
|  |                                   //SDL_WINDOW_ALLOW_HIGHDPI | | ||||||
|  |                                       SDL_WINDOW_RESIZABLE | | ||||||
|  |                                       SDL_WINDOW_OPENGL); | ||||||
|  |     profile_end("window creation"); | ||||||
|  |  | ||||||
|  |     if (ctx.window == NULL) { | ||||||
|  |         CRY_SDL("Window creation failed."); | ||||||
|  |         goto fail; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     profile_start("opengl context creation"); | ||||||
|  |     ctx.gl_context = SDL_GL_CreateContext(ctx.window); | ||||||
|  |     if (!ctx.gl_context) { | ||||||
|  |         CRY_SDL("GL context creation failed."); | ||||||
|  |         goto fail; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (SDL_GL_MakeCurrent(ctx.window, ctx.gl_context)) { | ||||||
|  |         CRY_SDL("GL context binding failed."); | ||||||
|  |         goto fail; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* TODO: figure out what we ultimately prefer */ | ||||||
|  |     SDL_GL_SetSwapInterval(0); | ||||||
|  |  | ||||||
|  |     if (!render_init()) | ||||||
|  |         goto fail; | ||||||
|  |  | ||||||
|  |     setup_viewport(0, 0, (int)ctx.base_render_width, (int)ctx.base_render_height); | ||||||
|  |     profile_end("opengl context creation"); | ||||||
|  |  | ||||||
|  |     /* might need this to have multiple windows */ | ||||||
|  |     ctx.window_id = SDL_GetWindowID(ctx.window); | ||||||
|  |  | ||||||
|  |     profile_start("texture and text cache initialization"); | ||||||
|  |     textures_cache_init(&ctx.texture_cache, ctx.window); | ||||||
|  |     text_cache_init(&ctx.text_cache); | ||||||
|  |     profile_end("texture and text cache initialization"); | ||||||
|  |  | ||||||
|     return true; |     return true; | ||||||
|  |  | ||||||
| fail: | fail: | ||||||
| @@ -674,7 +685,9 @@ static void clean_up(void) { | |||||||
|     PHYSFS_deinit(); |     PHYSFS_deinit(); | ||||||
|  |  | ||||||
|     SDL_free(ctx.base_dir); |     SDL_free(ctx.base_dir); | ||||||
|  |     SDL_free(ctx.title); | ||||||
|     SDL_GL_DeleteContext(ctx.gl_context); |     SDL_GL_DeleteContext(ctx.gl_context); | ||||||
|  |     SDL_GL_UnloadLibrary(); | ||||||
|     SDL_Quit(); |     SDL_Quit(); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -688,6 +701,20 @@ static void reset_state(void) { | |||||||
| int enter_loop(int argc, char **argv) { | int enter_loop(int argc, char **argv) { | ||||||
|     profile_start("startup"); |     profile_start("startup"); | ||||||
|  |  | ||||||
|  |     profile_start("SDL initialization"); | ||||||
|  |     if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_EVENTS) == -1) { | ||||||
|  |         CRY_SDL("SDL initialization failed."); | ||||||
|  |         return EXIT_FAILURE; | ||||||
|  |     } | ||||||
|  |     profile_end("SDL initialization"); | ||||||
|  |  | ||||||
|  |     profile_start("opengl loading"); | ||||||
|  |     opengl_load_thread = SDL_CreateThread(opengl_load_thread_fn, "opengl loader", NULL); | ||||||
|  |     if (!opengl_load_thread) { | ||||||
|  |         CRY_SDL("Cannot create opengl loading thread: "); | ||||||
|  |         return EXIT_FAILURE; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     ctx.argc = argc; |     ctx.argc = argc; | ||||||
|     ctx.argv = argv; |     ctx.argv = argv; | ||||||
|     ctx.base_dir = SDL_GetBasePath(); |     ctx.base_dir = SDL_GetBasePath(); | ||||||
| @@ -763,13 +790,6 @@ int enter_loop(int argc, char **argv) { | |||||||
|         ctx.game.debug = false; |         ctx.game.debug = false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     update_viewport(); |  | ||||||
|  |  | ||||||
|     profile_start("game object load"); |  | ||||||
|     /* now we can actually start doing stuff */ |  | ||||||
|     game_object_load(); |  | ||||||
|     profile_end("game object load"); |  | ||||||
|  |  | ||||||
|     ctx.was_successful = true; |     ctx.was_successful = true; | ||||||
|     ctx.game.initialization_needed = true; |     ctx.game.initialization_needed = true; | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user