diff --git a/.gitignore b/.gitignore index d9cb9499..59e2f67e 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ *.cap *.tracy *.pdb +*.exe .vs/* unused/ diff --git a/build.c b/build.c index 9d9015ec..5c216a1b 100644 --- a/build.c +++ b/build.c @@ -22,6 +22,7 @@ Bool arg_crtlib = false; Bool arg_debinfo = false; Bool arg_developer = false; Bool arg_profiling = false; +Bool arg_profiler_sampling = false; Bool arg_unoptimized = false; /* ========================== * @@ -349,6 +350,7 @@ void OnBuild(StringList cli_args) if (StringEqual(arg, Lit("-debinfo"))) arg_debinfo = true; if (StringEqual(arg, Lit("-developer"))) arg_developer = true; if (StringEqual(arg, Lit("-profiling"))) arg_profiling = true; + if (StringEqual(arg, Lit("-sampling"))) arg_profiler_sampling = true; if (StringEqual(arg, Lit("-unoptimized"))) arg_unoptimized = true; } break; } @@ -393,6 +395,7 @@ void OnBuild(StringList cli_args) SH_PrintF(Lit("[%F]\n"), FmtStr(compiler)); if (arg_asan) SH_Print(Lit("[Asan Enabled]\n")); if (arg_profiling) SH_Print(Lit("[Profiling]\n")); + if (arg_profiler_sampling) SH_Print(Lit("[Profiler sampling]\n")); if (arg_developer) SH_Print(Lit("[Developer build]\n")); SH_Print(Lit("------------------------------\n\n")); } @@ -570,7 +573,7 @@ void OnBuild(StringList cli_args) /* Profiling */ if (arg_profiling) { if (!arg_crtlib) { - Error(Lit("CRTLIB (C runtime library) Must be enabled when compiling with profiling enabled")); + Error(Lit("CRTLIB (C runtime library) must be enabled when compiling with profiling enabled")); OS_Exit(1); } if (arg_msvc) { @@ -580,8 +583,9 @@ void OnBuild(StringList cli_args) StringListAppend(&perm, &compile_args, Lit("-DPROFILING=1")); /* Tracy flags */ StringListAppend(&perm, &compile_args, Lit("-DTRACY_ENABLE=1")); - StringListAppend(&perm, &compile_args, Lit("-DTRACY_CALLSTACK=5")); - StringListAppend(&perm, &compile_args, Lit("-DTRACY_NO_SAMPLING -DTRACY_NO_SYSTEM_TRACING -DTRACY_NO_CALLSTACK")); + if (!arg_profiler_sampling) { + StringListAppend(&perm, &compile_args, Lit("-DTRACY_NO_SAMPLING -DTRACY_NO_SYSTEM_TRACING -DTRACY_NO_CALLSTACK")); + } /* Disable compile_warnings when compiling tracy client */ compile_warnings = (StringList) { 0 }; link_warnings = (StringList) { 0 }; @@ -589,6 +593,14 @@ void OnBuild(StringList cli_args) StringListAppend(&perm, &link_warnings, Lit("-Wno-everything")); } + /* Profiler sampling */ + if (arg_profiler_sampling) { + if (!arg_profiling) { + Error(Lit("Profiling must be enabled to use profiler sampling")); + OS_Exit(1); + } + } + if (!arg_msvc) { String incbin_dir = StringReplace(&perm, out_inc_dir_path, Lit("\\"), Lit("/")); StringListAppend(&perm, &compile_args, StringF(&perm, Lit("-DINCBIN_DIR_RAW=\"%F\""), FmtStr(incbin_dir))); diff --git a/profile.bat b/profile.bat index 3241f074..873aebd2 100644 --- a/profile.bat +++ b/profile.bat @@ -1,4 +1,43 @@ @echo off +setlocal enabledelayedexpansion + +:: Unpack arguments +for %%a in (%*) do set "%%a=1" + +set app_path=%1 + +if NOT "%escalate%" == "1" goto skipEscalate +:: This enables tracy sampling by running the executable in administrator mode. +:: BatchGotAdmin +:: https://stackoverflow.com/a/10052222 +:------------------------------------- +:: --> Check for permissions +if "%PROCESSOR_ARCHITECTURE%" EQU "amd64" ( + >nul 2>&1 "%SYSTEMROOT%\SysWOW64\cacls.exe" "%SYSTEMROOT%\SysWOW64\config\system" +) else ( + >nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system" +) + +:: --> If error flag set, we do not have admin. +if '%errorlevel%' NEQ '0' ( + echo Requesting administrative privileges... + goto UACPrompt +) else ( goto gotAdmin ) + +:UACPrompt + echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs" + set params= %* + echo UAC.ShellExecute "cmd.exe", "/c ""%~s0"" %params:"=""%", "", "runas", 1 >> "%temp%\getadmin.vbs" + + "%temp%\getadmin.vbs" + del "%temp%\getadmin.vbs" + exit /B + +:gotAdmin + pushd "%CD%" + CD /D "%~dp0" +:-------------------------------------- +:skipEscalate :: `ping` is being used in place of `TIMEOUT` :: https://www.ibm.com/support/pages/timeout-command-run-batch-job-exits-immediately-and-returns-error-input-redirection-not-supported-exiting-process-immediately @@ -7,8 +46,8 @@ taskkill /im tracy-profiler.exe /f 2> nul start tracy-capture.exe -o .tracy -f -echo Launching app... -build\clang-user-profiling\bin\powerplay.exe +echo Launching app "%app_path%"... +%app_path% if NOT %errorlevel% == 0 ( echo. diff --git a/src/app.c b/src/app.c index 3121f34a..e8f1b210 100644 --- a/src/app.c +++ b/src/app.c @@ -258,7 +258,7 @@ void app_entry_point(struct string args_str) /* Start callback threads */ for (struct exit_callback *callback = G.exit_callbacks_head; callback; callback = callback->next) { - callback->thread = sys_thread_alloc(&exit_callback_thread_entry_point, callback, LIT("[P4] Exit callback thread")); + callback->thread = sys_thread_alloc(&exit_callback_thread_entry_point, callback, LIT("[P1] Exit callback thread")); } /* Wait on callback threads */ @@ -288,6 +288,8 @@ void app_entry_point(struct string args_str) arena_temp_end(temp); } + sys_window_release(&window); + logf_info("Program exited normally"); scratch_end(scratch); } diff --git a/src/bitbuff.c b/src/bitbuff.c index 887d2b2e..1729def6 100644 --- a/src/bitbuff.c +++ b/src/bitbuff.c @@ -252,7 +252,7 @@ void bw_write_bit(struct bitbuff_writer *bw, u8 value) } /* Writes a variable length unsigned integer. - * Value is written in chunks w/ 8th bit signaling continuation bit. */ + * Value is written in chunks of 7 bits w/ 8th bit signaling continuation. */ void bw_write_uv(struct bitbuff_writer *bw, u64 value) { _dbg_write_magic(bw, DBG_MAGIC_UV, 0); @@ -265,7 +265,7 @@ void bw_write_uv(struct bitbuff_writer *bw, u64 value) } /* Writes a variable length signed integer. - * Similar to bw_write_uv, except the first byte's 7th bit is a sign bit + * Similar to bw_write_uv, except the 7th bit of the first byte is a sign bit * indicating that the value is stored in twos compliment. */ void bw_write_iv(struct bitbuff_writer *bw, i64 value) { @@ -530,7 +530,7 @@ i64 br_read_iv(struct bitbuff_reader *br) if (sign_bit) { /* Sign bit is 1, indicating result is stored in twos compliment */ res = sint_from_twos_compliment(tc, num_bits); - } else { + } else { res = (i64)tc; } diff --git a/src/draw.c b/src/draw.c index 676f9d8b..775a6f71 100644 --- a/src/draw.c +++ b/src/draw.c @@ -365,7 +365,7 @@ void draw_text_ex(struct renderer_cmd_buffer *cmdbuff, struct font *font, struct }; struct quad quad = quad_from_rect(RECT(x, y, width, height)); - draw_quad_texture_ex(cmdbuff, font->texture, sprite_tag_nil(), clip, 0xFFFFFFFF, 0xFFFFFFFF, quad); + draw_quad_texture_ex(cmdbuff, font->texture, sprite_tag_nil(), clip, COLOR_WHITE, COLOR_WHITE, quad); draw_pos.x += glyph->advance * scale; } diff --git a/src/host.c b/src/host.c index ad809ee6..f0c80bb2 100644 --- a/src/host.c +++ b/src/host.c @@ -194,7 +194,7 @@ struct host *host_alloc(u16 listen_port) host->sock = sock_alloc(listen_port, MEGABYTE(2), MEGABYTE(2)); host->rcv_buffer_write_mutex = sys_mutex_alloc(); - host->receiver_thread = sys_thread_alloc(&host_receiver_thread_entry_point, host, LIT("[P6] Host receiver")); + host->receiver_thread = sys_thread_alloc(&host_receiver_thread_entry_point, host, LIT("[P5] Host receiver")); return host; } diff --git a/src/playback_wasapi.c b/src/playback_wasapi.c index e748150f..25be6a32 100644 --- a/src/playback_wasapi.c +++ b/src/playback_wasapi.c @@ -60,7 +60,7 @@ struct playback_startup_receipt playback_startup(struct mixer_startup_receipt *m (UNUSED)mixer_sr; wasapi_initialize(); - G.playback_thread = sys_thread_alloc(&playback_thread_entry_point, NULL, LIT("[P3] Audio thread")); + G.playback_thread = sys_thread_alloc(&playback_thread_entry_point, NULL, LIT("[P7] Audio thread")); app_register_exit_callback(&playback_shutdown); return (struct playback_startup_receipt) { 0 }; diff --git a/src/sprite.c b/src/sprite.c index 2fa5e8cb..970a8bed 100644 --- a/src/sprite.c +++ b/src/sprite.c @@ -259,7 +259,7 @@ struct sprite_startup_receipt sprite_startup(struct renderer_startup_receipt *re G.evictor_mutex = sys_mutex_alloc(); G.evictor_cv = sys_condition_variable_alloc(); - G.evictor_thread = sys_thread_alloc(sprite_evictor_thread_entry_point, NULL, LIT("[P7] Sprite evictor")); + G.evictor_thread = sys_thread_alloc(sprite_evictor_thread_entry_point, NULL, LIT("[P2] Sprite evictor")); app_register_exit_callback(&sprite_shutdown); @@ -347,6 +347,7 @@ INTERNAL void cache_node_load_texture(struct cache_node *n, struct sprite_tag ta ASSERT(string_ends_with(path, LIT(".ase"))); ASSERT(n->kind == CACHE_NODE_KIND_TEXTURE); + /* TODO: Replace arena allocs w/ buddy allocator */ /* TODO: Arena probably overkill. Just using it to store texture struct. */ n->arena = arena_alloc(TEXTURE_ARENA_RESERVE); u64 memory_size = 0; @@ -653,6 +654,7 @@ INTERNAL void cache_node_load_sheet(struct cache_node *n, struct sprite_tag tag) //ASSERT(string_ends_with(path, LIT(".ase"))); ASSERT(n->kind == CACHE_NODE_KIND_SHEET); + /* TODO: Replace arena allocs w/ buddy allocator */ n->arena = arena_alloc(SHEET_ARENA_RESERVE); { /* Decode */ diff --git a/src/sys_win32.c b/src/sys_win32.c index 59928bd3..f822f853 100644 --- a/src/sys_win32.c +++ b/src/sys_win32.c @@ -817,7 +817,7 @@ INTERNAL struct win32_window *win32_window_alloc(void) window->event_callbacks_mutex = sys_mutex_alloc(); /* Start window thread for processing events */ - window->event_thread = sys_thread_alloc(&window_thread_entry_point, window, LIT("[P8] Window thread")); + window->event_thread = sys_thread_alloc(&window_thread_entry_point, window, LIT("[P4] Window thread")); /* Wait for event thread to create actual window */ sync_flag_wait(&window->ready_sf); @@ -2144,7 +2144,7 @@ int CALLBACK wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance, /* Call app thread and wait for return */ { /* Start app thread */ - struct sys_thread app_thread = sys_thread_alloc(&win32_app_thread_entry_point, NULL, LIT("[P9] App thread")); + struct sys_thread app_thread = sys_thread_alloc(&win32_app_thread_entry_point, NULL, LIT("[P0] App thread")); /* Get app thread handle */ HANDLE app_thread_handle = 0; diff --git a/src/user.c b/src/user.c index e2b35000..b44e29f7 100644 --- a/src/user.c +++ b/src/user.c @@ -204,17 +204,19 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr, G.window = window; sys_window_register_event_callback(G.window, &window_event_callback); + /* TODO: Remove this */ + connect_address_str = STRING(0, 0); if (connect_address_str.len == 0) { G.local_sim_ctx = sim_ctx_alloc(sprite_sr, phys_sr, host_sr, sim_snapshot_sr, 12345); G.connect_address_str = LIT("127.0.0.1:12345"); - G.local_sim_thread = sys_thread_alloc(&user_local_sim_thread_entry_point, G.local_sim_ctx, LIT("[P2] Local sim thread")); + G.local_sim_thread = sys_thread_alloc(&user_local_sim_thread_entry_point, G.local_sim_ctx, LIT("[P8] Local sim thread")); } else { G.connect_address_str = string_copy(&G.arena, connect_address_str); } G.debug_draw = true; - G.user_thread = sys_thread_alloc(&user_thread_entry_point, NULL, LIT("[P1] User thread")); + G.user_thread = sys_thread_alloc(&user_thread_entry_point, NULL, LIT("[P9] User thread")); app_register_exit_callback(&user_shutdown); return (struct user_startup_receipt) { 0 }; @@ -443,6 +445,7 @@ INTERNAL void user_update(void) case SIM_EVENT_KIND_SNAPSHOT: { + /* TODO: Only read newest tick event */ if (event_tick > G.world->tick) { u64 ss0_tick = event->snapshot_tick_start; u64 ss1_tick = event->snapshot_tick_end; diff --git a/src/work.c b/src/work.c index f91b9b08..6f7f7219 100644 --- a/src/work.c +++ b/src/work.c @@ -122,7 +122,7 @@ struct work_startup_receipt work_startup(u32 num_worker_threads) struct worker *prev = NULL; for (u32 i = 0; i < num_worker_threads; ++i) { struct string thread_name = string_format(scratch.arena, - LIT("[P0] Worker %F"), + LIT("[P6] Worker %F"), FMT_UINT(i)); struct worker *worker = arena_push_zero(&G.arena, struct worker);