diff --git a/build.bat b/build.bat index d8a2ca72..d088335e 100644 --- a/build.bat +++ b/build.bat @@ -24,6 +24,7 @@ cd /D "%~dp0" :: :: - `asan`: enable address sanitizer :: - `telemetry`: enable RAD telemetry profiling support +:: - `spall`: enable spall profiling support :: --- Unpack Arguments ------------------------------------------------------- for %%a in (%*) do set "%%a=1" @@ -39,6 +40,7 @@ if "%~1"=="release" if "%~2"=="" echo [default mode, assuming `raddbg` build] && :: --- Unpack Command Line Build Arguments ------------------------------------ set auto_compile_flags= if "%telemetry%"=="1" set auto_compile_flags=%auto_compile_flags% -DPROFILE_TELEMETRY=1 && echo [telemetry profiling enabled] +if "%spall%"=="1" set auto_compile_flags=%auto_compile_flags% -DPROFILE_SPALL=1 && echo [spall profiling enabled] if "%asan%"=="1" set auto_compile_flags=%auto_compile_flags% -fsanitize=address && echo [asan enabled] if "%opengl%"=="1" set auto_compile_flags=%auto_compile_flags% -DR_BACKEND=R_BACKEND_OPENGL && echo [opengl render backend] diff --git a/project.4coder b/project.4coder index 32a1e737..16c108c1 100644 --- a/project.4coder +++ b/project.4coder @@ -46,7 +46,7 @@ load_paths = commands = { //- rjf: [raddbg] - .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, + .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg spall", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, //- rjf: [textperf] // .f1 = { .win = "raddbg_stable --ipc kill_all && build no_meta telemetry textperf && raddbg_stable --ipc bring_to_front && raddbg_stable --ipc run", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, diff --git a/src/base/base_entry_point.c b/src/base/base_entry_point.c index 6d489e66..b79c10c9 100644 --- a/src/base/base_entry_point.c +++ b/src/base/base_entry_point.c @@ -17,6 +17,11 @@ main_thread_base_entry_point(int arguments_count, char **arguments) tmInitialize(sizeof(tm_data), tm_data); #endif + //- rjf: set up spall +#if PROFILE_SPALL + spall_profile = spall_init_file("spall_capture", 1); +#endif + //- rjf: parse command line String8List command_line_argument_strings = os_string_list_from_argcv(scratch.arena, arguments_count, arguments); CmdLine cmdline = cmd_line_from_string_list(scratch.arena, command_line_argument_strings); diff --git a/src/base/base_profile.c b/src/base/base_profile.c index 8ac6bce5..03a8d523 100644 --- a/src/base/base_profile.c +++ b/src/base/base_profile.c @@ -1,2 +1,16 @@ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) + +#if PROFILE_SPALL +internal inline void +spall_begin(char *fmt, ...) +{ + Temp scratch = scratch_begin(0, 0); + va_list args; + va_start(args, fmt); + String8 string = push_str8fv(scratch.arena, fmt, args); + spall_buffer_begin(&spall_profile, &spall_buffer, string.str, string.size, os_now_microseconds()); + va_end(args); + scratch_end(scratch); +} +#endif diff --git a/src/base/base_profile.h b/src/base/base_profile.h index b39a2fc5..3981e365 100644 --- a/src/base/base_profile.h +++ b/src/base/base_profile.h @@ -10,6 +10,9 @@ #if !defined(PROFILE_TELEMETRY) # define PROFILE_TELEMETRY 0 #endif +#if !defined(PROFILE_SPALL) +# define PROFILE_SPALL 0 +#endif //////////////////////////////// //~ rjf: Third Party Includes @@ -19,6 +22,8 @@ # if OS_WINDOWS # pragma comment(lib, "rad_tm_win64.lib") # endif +#elif PROFILE_SPALL +# include "spall.h" #endif //////////////////////////////// @@ -61,6 +66,32 @@ scratch_end(scratch); \ } #endif +//////////////////////////////// +//~ rjf: Spall Profile Defines + +#if PROFILE_SPALL +global U64 spall_capturing = 1; +global SpallProfile spall_profile = {0}; +thread_static SpallBuffer spall_buffer = {0}; +internal inline void spall_begin(char *fmt, ...); +# define ProfBegin(...) (spall_capturing ? (spall_begin(__VA_ARGS__), 0) : 0) +# define ProfBeginDynamic(...) (spall_capturing ? (spall_begin(__VA_ARGS__), 0) : 0) +# define ProfEnd(...) (spall_capturing ? (spall_buffer_end(&spall_profile, &spall_buffer, os_now_microseconds())), 0 : 0) +# define ProfTick(...) +# define ProfIsCapturing(...) (!!spall_capturing) +# define ProfBeginCapture(...) (spall_capturing = 1) +# define ProfEndCapture(...) (spall_capturing = 0) +# define ProfThreadName(...) +# define ProfMsg(...) +# define ProfBeginLockWait(...) +# define ProfEndLockWait(...) +# define ProfLockTake(...) +# define ProfLockDrop(...) +# define ProfColor(color) +# define ProfBeginV(...) +# define ProfNoteV(...) +#endif + //////////////////////////////// //~ rjf: Zeroify Undefined Defines diff --git a/src/base/base_thread_context.c b/src/base/base_thread_context.c index 1a3f84ed..897b8f2f 100644 --- a/src/base/base_thread_context.c +++ b/src/base/base_thread_context.c @@ -10,12 +10,19 @@ C_LINKAGE thread_static TCTX* tctx_thread_local = 0; #endif internal void -tctx_init_and_equip(TCTX *tctx){ +tctx_init_and_equip(TCTX *tctx) +{ MemoryZeroStruct(tctx); Arena **arena_ptr = tctx->arenas; - for (U64 i = 0; i < ArrayCount(tctx->arenas); i += 1, arena_ptr += 1){ + for(U64 i = 0; i < ArrayCount(tctx->arenas); i += 1, arena_ptr += 1) + { *arena_ptr = arena_alloc(); } +#if PROFILE_SPALL + spall_buffer.length = MB(1); + spall_buffer.data = push_array_no_zero(tctx->arenas[0], U8, spall_buffer.length); + spall_buffer_init(&spall_profile, &spall_buffer); +#endif tctx_thread_local = tctx; } @@ -28,37 +35,42 @@ tctx_release(void) } } -internal TCTX* -tctx_get_equipped(void){ - return(tctx_thread_local); +internal TCTX * +tctx_get_equipped(void) +{ + return tctx_thread_local; } -internal Arena* -tctx_get_scratch(Arena **conflicts, U64 count){ +internal Arena * +tctx_get_scratch(Arena **conflicts, U64 count) +{ TCTX *tctx = tctx_get_equipped(); - Arena *result = 0; Arena **arena_ptr = tctx->arenas; - for (U64 i = 0; i < ArrayCount(tctx->arenas); i += 1, arena_ptr += 1){ + for(U64 i = 0; i < ArrayCount(tctx->arenas); i += 1, arena_ptr += 1) + { Arena **conflict_ptr = conflicts; B32 has_conflict = 0; - for (U64 j = 0; j < count; j += 1, conflict_ptr += 1){ - if (*arena_ptr == *conflict_ptr){ + for(U64 j = 0; j < count; j += 1, conflict_ptr += 1) + { + if(*arena_ptr == *conflict_ptr) + { has_conflict = 1; break; } } - if (!has_conflict){ + if(!has_conflict) + { result = *arena_ptr; break; } } - - return(result); + return result; } internal void -tctx_set_thread_name(String8 string){ +tctx_set_thread_name(String8 string) +{ TCTX *tctx = tctx_get_equipped(); U64 size = ClampTop(string.size, sizeof(tctx->thread_name)); MemoryCopy(tctx->thread_name, string.str, size); @@ -66,21 +78,24 @@ tctx_set_thread_name(String8 string){ } internal String8 -tctx_get_thread_name(void){ +tctx_get_thread_name(void) +{ TCTX *tctx = tctx_get_equipped(); String8 result = str8(tctx->thread_name, tctx->thread_name_size); - return(result); + return result; } internal void -tctx_write_srcloc(char *file_name, U64 line_number){ +tctx_write_srcloc(char *file_name, U64 line_number) +{ TCTX *tctx = tctx_get_equipped(); tctx->file_name = file_name; tctx->line_number = line_number; } internal void -tctx_read_srcloc(char **file_name, U64 *line_number){ +tctx_read_srcloc(char **file_name, U64 *line_number) +{ TCTX *tctx = tctx_get_equipped(); *file_name = tctx->file_name; *line_number = tctx->line_number; diff --git a/src/raddbg/raddbg_views.c b/src/raddbg/raddbg_views.c index 80fd780b..54e16e5f 100644 --- a/src/raddbg/raddbg_views.c +++ b/src/raddbg/raddbg_views.c @@ -2591,7 +2591,7 @@ RD_VIEW_UI_FUNCTION_DEF(memory) Rng1S64 scroll_idx_rng = r1s64(0, (view_range_last - view_range.min) / num_columns); ////////////////////////////// - //- rjf: determine visible range of rows + //- rjf: determine visible range of rows (including occluded) // Rng1S64 viz_range_rows = {0}; S64 num_possible_visible_rows = 0; @@ -2613,6 +2613,19 @@ RD_VIEW_UI_FUNCTION_DEF(memory) Rng2F32 footer_rect = r2f32p(0, panel_dim.y-footer_dim, panel_dim.x-scroll_bar_dim, panel_dim.y); Rng2F32 content_rect = r2f32p(0, row_height_px, panel_dim.x-scroll_bar_dim, panel_dim.y); + ////////////////////////////// + //- rjf: determine visible range of rows (only non-occluded) + // + Rng1S64 viz_range_nonoccluded_rows = {0}; + S64 num_possible_nonoccluded_visible_rows = 0; + { + num_possible_nonoccluded_visible_rows = (dim_2f32(content_rect).y - dim_2f32(footer_rect).y) / row_height_px; + viz_range_nonoccluded_rows.min = viz_range_rows.min + (S64)(content_rect.y0 / row_height_px); + viz_range_nonoccluded_rows.max = viz_range_nonoccluded_rows.min + num_possible_nonoccluded_visible_rows; + viz_range_nonoccluded_rows.min = clamp_1s64(scroll_idx_rng, viz_range_nonoccluded_rows.min); + viz_range_nonoccluded_rows.max = clamp_1s64(scroll_idx_rng, viz_range_nonoccluded_rows.max); + } + ////////////////////////////// //- rjf: bump backwards if we are past the first if(viz_range_rows.min > 0) @@ -2766,7 +2779,7 @@ RD_VIEW_UI_FUNCTION_DEF(memory) { mv->center_cursor = 0; S64 cursor_row_idx = (cursor_base_vaddr - view_range.min) / num_columns; - S64 new_idx = (cursor_row_idx-num_possible_visible_rows/2+1); + S64 new_idx = (cursor_row_idx-num_possible_nonoccluded_visible_rows/2+1); new_idx = clamp_1s64(scroll_idx_rng, new_idx); ui_scroll_pt_target_idx(&scroll_pos.y, new_idx); } @@ -2779,8 +2792,8 @@ RD_VIEW_UI_FUNCTION_DEF(memory) mv->contain_cursor = 0; S64 cursor_row_idx = (cursor_base_vaddr - view_range.min) / num_columns; Rng1S64 cursor_viz_range = r1s64(clamp_1s64(scroll_idx_rng, cursor_row_idx-2), clamp_1s64(scroll_idx_rng, cursor_row_idx+3)); - S64 min_delta = Min(0, cursor_viz_range.min-viz_range_rows.min); - S64 max_delta = Max(0, cursor_viz_range.max-viz_range_rows.max); + S64 min_delta = Min(0, cursor_viz_range.min-viz_range_nonoccluded_rows.min); + S64 max_delta = Max(0, cursor_viz_range.max-viz_range_nonoccluded_rows.max); S64 new_idx = scroll_pos.y.idx+min_delta+max_delta; new_idx = clamp_1s64(scroll_idx_rng, new_idx); ui_scroll_pt_target_idx(&scroll_pos.y, new_idx);