vtgl

terminal emulator implemented in OpenGL
git clone anongit@rnpnr.xyz:vtgl.git
Log | Files | Refs | Feed | LICENSE

Commit: 5ffa479a7573f04097b7b4ba7112da1e6dfda25b
Parent: ce1b97be1ecc16d0737955fd79918ce58f8351d4
Author: Randy Palamar
Date:   Mon,  4 Nov 2024 08:44:13 -0700

hierarchical debug viewing

still some jank but it will be fixed soon

Diffstat:
Mdebug.c | 74+++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
Mdebug.h | 54++++++++++++++++++++++++++++++------------------------
Mvtgl.c | 9++++-----
3 files changed, 83 insertions(+), 54 deletions(-)

diff --git a/debug.c b/debug.c @@ -81,6 +81,8 @@ restart_collation(DebugState *ds, u32 invalid_record_index) end_temp_arena(ds->temp_memory); ds->temp_memory = begin_temp_arena(&ds->memory); ds->first_free_block = 0; + /* TODO: no clear parameter */ + ds->records = alloc(&ds->memory, typeof(*ds->records), 2*MAX_DEBUG_RECORD_COUNT); ds->record_count = 0; ds->record_bar_scale = 0; ds->record_working_index = invalid_record_index + 1; @@ -88,18 +90,19 @@ restart_collation(DebugState *ds, u32 invalid_record_index) } static void -coalesce_debug_events(DebugState *ds, u32 invalid_snapshot_index, DebugMetadata *metadata) +coalesce_debug_events(DebugState *ds, u32 invalid_snapshot_index) { BEGIN_TIMED_BLOCK(); for (;; ds->record_working_index++) { - if (ds->record_working_index == DEBUG_SNAPSHOT_COUNT) + if (ds->record_working_index == MAX_DEBUG_RECORD_COUNT) ds->record_working_index = 0; if (ds->record_working_index == invalid_snapshot_index) break; u32 record_index = ds->record_working_index; for (u32 j = 0; j < g_debug_table.events_count[record_index]; j++) { - DebugEvent *de = g_debug_table.events[record_index] + j; + DebugEvent *de = g_debug_table.events[record_index] + j; + DebugMetadata *source_metadata = g_debug_table.metadata + de->metadata_index; if (de->type == DE_FRAME_MARK) { if (ds->open_record) { @@ -113,27 +116,26 @@ coalesce_debug_events(DebugState *ds, u32 invalid_snapshot_index, DebugMetadata ds->record_bar_scale = record_bar_scale; } ds->record_count++; - if (ds->record_count >= DEBUG_SNAPSHOT_COUNT) - /* TODO: is this just an error ? */ - goto end; } ds->open_record = ds->records + ds->record_count; ds->open_record->start_clock = de->clock; ds->open_record->end_clock = 0; ds->open_record->region_count = 0; ds->open_record->wall_time = 0; - ds->open_record->first_block = get_open_debug_block(ds, 0); + ds->open_record->first_block = 0; ds->open_record->regions = alloc(&ds->memory, DebugRegion, MAX_DEBUG_REGION_COUNT); } else if (ds->open_record) { + u32 frame_index = (ds->record_count - 1) % MAX_DEBUG_RECORD_COUNT; DebugRecord *or = ds->open_record; //ASSERT(or == ds->records + record_index); //u64 relative_clock = de->clock - record->start_clock; switch (de->type) { case DE_BEGIN: { OpenDebugBlock *odb = get_open_debug_block(ds, de); - odb->starting_record_index = record_index; + odb->starting_record_index = frame_index; odb->parent = or->first_block; + odb->source = source_metadata; or->first_block = odb; } break; case DE_END: { @@ -142,14 +144,15 @@ coalesce_debug_events(DebugState *ds, u32 invalid_snapshot_index, DebugMetadata OpenDebugBlock *odb = or->first_block; DebugEvent *oe = odb->opening_event; - if (oe->debug_metadata_index != de->debug_metadata_index) { + if (oe->metadata_index != de->metadata_index) { /* TODO: the first block was never closed */ INVALID_CODE_PATH; break; } - if (odb->starting_record_index == record_index) { - if (odb->parent->opening_event == 0) { + if (odb->starting_record_index == frame_index) { + DebugMetadata *source = odb->parent ? odb->parent->source : 0; + if (source == ds->selected_metadata) { f32 min_t = (oe->clock - or->start_clock); f32 max_t = (de->clock - or->start_clock); if ((de->clock - oe->clock) > 1) { @@ -157,7 +160,8 @@ coalesce_debug_events(DebugState *ds, u32 invalid_snapshot_index, DebugMetadata ASSERT(or->region_count <= MAX_DEBUG_REGION_COUNT); dr->min_t = min_t; dr->max_t = max_t; - dr->debug_metadata_index = de->debug_metadata_index; + dr->meta = source_metadata; + dr->colour_index = de->metadata_index; } } } else { @@ -175,11 +179,17 @@ coalesce_debug_events(DebugState *ds, u32 invalid_snapshot_index, DebugMetadata } } -end: END_TIMED_BLOCK(); } static void +refresh_collation(DebugState *ds) +{ + restart_collation(ds, g_debug_table.snapshot_index); + coalesce_debug_events(ds, g_debug_table.snapshot_index); +} + +static void draw_debug_bar_chart(Term *t, DebugState *ds, RenderCtx *rc, v2 bar_chart_top_left, f32 bar_chart_magnitude) { BEGIN_TIMED_BLOCK(); @@ -211,12 +221,16 @@ draw_debug_bar_chart(Term *t, DebugState *ds, RenderCtx *rc, v2 bar_chart_top_le pos.y -= bar_thick + bar_pad; - DebugMetadata *txt_meta = 0; - f32 txt_secs = 0; + DebugRegion *hot_region = 0; + f32 hot_region_secs; + + u32 displayed_records = ds->record_count; + if (displayed_records > 12) + displayed_records = 12; Stream txt = stream_alloc(ds->temp_memory.arena, 1024); - for (u32 i = 0; i < ds->record_count; i++) { - DebugRecord *record = ds->records + i; + for (u32 i = 0; i < displayed_records; i++) { + DebugRecord *record = ds->records + (ds->record_count - (i + 1)) % MAX_DEBUG_RECORD_COUNT; f32 cycs_to_secs = record->wall_time / (f32)(record->end_clock - record->start_clock); f32 scale = cycs_to_secs * secs_scale; @@ -227,10 +241,10 @@ draw_debug_bar_chart(Term *t, DebugState *ds, RenderCtx *rc, v2 bar_chart_top_le f32 time = cycs * scale; Rect r = {.pos = pos, .size = {.h = bar_thick, .w = time}}; if (r.size.w > 1.0f) { - push_rect(rc, r, colours[dr->debug_metadata_index % ARRAY_COUNT(colours)]); + push_rect(rc, r, colours[dr->colour_index % ARRAY_COUNT(colours)]); if (point_in_rect(mouse, r)) { - txt_meta = debug_metadata + dr->debug_metadata_index; - txt_secs = cycs * cycs_to_secs; + hot_region = dr; + hot_region_secs = cycs * cycs_to_secs; } pos.x += r.size.w; } @@ -250,21 +264,22 @@ draw_debug_bar_chart(Term *t, DebugState *ds, RenderCtx *rc, v2 bar_chart_top_le Rect target_marker = {.pos = pos}; target_marker.pos.x += bar_chart_magnitude; target_marker.size.w = 4; - target_marker.size.h = ds->record_count * (bar_thick + bar_pad) - bar_pad; - push_rect(rc, target_marker, colours[0]); + target_marker.size.h = displayed_records * (bar_thick + bar_pad) - bar_pad; + push_rect(rc, target_marker, (v4){.g = .38, .b = .78, .a = 1}); stream_push_s8(&txt, s8("Target Time: ")); stream_push_f64(&txt, target_time * 1e3, 100); pos.x += bar_chart_magnitude + 8; - pos.y = bar_chart_top_left.y - 0.5 * DEBUG_SNAPSHOT_COUNT * (bar_thick + bar_pad); + pos.y = bar_chart_top_left.y - 0.75 * displayed_records * (bar_thick + bar_pad); stream_push_s8(&txt, s8(" [ms]")); push_s8(rc, pos, fg, g_ui_debug_font_id, stream_to_s8(&txt)); - if (txt_meta) { + if (hot_region) { + DebugMetadata *txt_meta = hot_region->meta; txt.widx = 0; stream_push_s8(&txt, c_str_to_s8(txt_meta->function_name)); stream_push_s8(&txt, s8(": ")); - stream_push_f64(&txt, txt_secs * 1e3, 100); + stream_push_f64(&txt, hot_region_secs * 1e3, 100); stream_push_s8(&txt, s8(" [ms] ")); stream_push_s8(&txt, c_str_to_s8(txt_meta->file_name)); stream_push_byte(&txt, ':'); @@ -272,6 +287,15 @@ draw_debug_bar_chart(Term *t, DebugState *ds, RenderCtx *rc, v2 bar_chart_top_le push_s8(rc, mouse, fg, g_ui_debug_font_id, stream_to_s8(&txt)); } + /* TODO: this should be stored so that we can properly mask */ + b32 pressed = glfwGetMouseButton(t->gl.window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS; + if (pressed && pressed != ds->mouse_pressed_last_frame) { + if (hot_region) ds->selected_metadata = hot_region->meta; + else ds->selected_metadata = 0; + refresh_collation(ds); + } + ds->mouse_pressed_last_frame = pressed; + END_TIMED_BLOCK(); } diff --git a/debug.h b/debug.h @@ -3,17 +3,12 @@ #define MAX_DEBUG_EVENT_COUNT (16 * 65536) /* TODO: this is way too high and it only seems to be necessary when resizing */ #define MAX_DEBUG_REGION_COUNT 80 * 1024 -#define DEBUG_SNAPSHOT_COUNT 16 - -typedef struct { - f32 min_t; - f32 max_t; - u16 debug_metadata_index; -} DebugRegion; +#define MAX_DEBUG_META_COUNT 4096 +#define MAX_DEBUG_RECORD_COUNT 16 typedef __attribute__((aligned(16))) struct { u64 clock; - u16 debug_metadata_index; + u16 metadata_index; u16 type; union { /* TODO: store core + thread id if we make this multithreaded */ @@ -22,8 +17,23 @@ typedef __attribute__((aligned(16))) struct { }; } DebugEvent; +typedef struct { + char *file_name; + char *function_name; + + u32 line_number; +} DebugMetadata; + +typedef struct { + f32 min_t; + f32 max_t; + DebugMetadata *meta; + u16 colour_index; +} DebugRegion; + typedef struct OpenDebugBlock { DebugEvent *opening_event; + DebugMetadata *source; struct OpenDebugBlock *parent; struct OpenDebugBlock *next_free; u32 starting_record_index; @@ -51,9 +61,12 @@ typedef struct { f32 gpu_target_time; u32 frame_draw_count; + DebugMetadata *selected_metadata; + b32 mouse_pressed_last_frame; + u32 record_count; u32 record_working_index; - DebugRecord records[DEBUG_SNAPSHOT_COUNT]; + DebugRecord *records; DebugRecord *open_record; OpenDebugBlock *first_free_block; @@ -93,29 +106,22 @@ enum debug_event_types { }; typedef struct { - char *file_name; - char *function_name; - - u32 line_number; -} DebugMetadata; - -typedef struct { - DebugEvent events[DEBUG_SNAPSHOT_COUNT][MAX_DEBUG_EVENT_COUNT]; - u32 events_count[DEBUG_SNAPSHOT_COUNT]; + DebugEvent events[MAX_DEBUG_RECORD_COUNT][MAX_DEBUG_EVENT_COUNT]; + u32 events_count[MAX_DEBUG_RECORD_COUNT]; u64 event_array_event_index; + DebugMetadata metadata[MAX_DEBUG_META_COUNT]; + u32 metadata_count; u32 snapshot_index; } DebugTable; static DebugTable g_debug_table; -DebugMetadata debug_metadata[]; - #define RECORD_DEBUG_EVENT_COMMON(counter, event_type) \ u64 event_index = __atomic_fetch_add(&g_debug_table.event_array_event_index, 1, __ATOMIC_RELAXED); \ ASSERT((event_index & 0xFFFFFFFF) < MAX_DEBUG_EVENT_COUNT); \ DebugEvent *event = g_debug_table.events[event_index >> 32] + (event_index & 0xFFFFFFFF); \ - event->clock = __rdtsc(); \ - event->debug_metadata_index = counter; \ - event->type = event_type + event->clock = __rdtsc(); \ + event->metadata_index = counter; \ + event->type = event_type #define RECORD_DEBUG_EVENT(counter, event_type) \ { \ @@ -131,7 +137,7 @@ DebugMetadata debug_metadata[]; #define BEGIN_TIMED_BLOCK(...) \ u16 __counter = __COUNTER__; \ { \ - DebugMetadata *meta = debug_metadata + __counter; \ + DebugMetadata *meta = g_debug_table.metadata + __counter; \ meta->file_name = __FILE__; \ meta->function_name = (char *)__FUNCTION__; \ meta->line_number = __LINE__; \ diff --git a/vtgl.c b/vtgl.c @@ -925,12 +925,10 @@ end: #ifdef _DEBUG #include "debug.c" -DebugMetadata debug_metadata[__COUNTER__]; - DEBUG_EXPORT DEBUG_END_FRAME_FN(debug_end_frame) { g_debug_table.snapshot_index++; - if (g_debug_table.snapshot_index == DEBUG_SNAPSHOT_COUNT) + if (g_debug_table.snapshot_index == MAX_DEBUG_RECORD_COUNT) g_debug_table.snapshot_index = 0; u64 event_array_event_index = __atomic_exchange_n(&g_debug_table.event_array_event_index, (u64)g_debug_table.snapshot_index << 32, @@ -940,6 +938,7 @@ DEBUG_EXPORT DEBUG_END_FRAME_FN(debug_end_frame) u32 event_count = event_array_event_index & 0xFFFFFFFF; g_debug_table.events_count[array_index] = event_count; + g_debug_table.metadata_count = __COUNTER__; if (!debug_state->initialized) { debug_state->temp_memory = begin_temp_arena(&debug_state->memory); @@ -950,9 +949,9 @@ DEBUG_EXPORT DEBUG_END_FRAME_FN(debug_end_frame) } if (!debug_state->paused) { - if (debug_state->record_count >= DEBUG_SNAPSHOT_COUNT) + if (debug_state->record_count >= 2*MAX_DEBUG_RECORD_COUNT) restart_collation(debug_state, g_debug_table.snapshot_index); - coalesce_debug_events(debug_state, g_debug_table.snapshot_index, debug_metadata); + coalesce_debug_events(debug_state, g_debug_table.snapshot_index); } }