more block tree / eval visualization integration work with watch views

This commit is contained in:
Ryan Fleury
2024-09-26 13:13:30 -07:00
parent 715bd36965
commit 338fabd9d0
2 changed files with 601 additions and 564 deletions
@@ -809,6 +809,10 @@ internal EV_Key
ev2_key_from_num(EV2_BlockRangeList *block_ranges, U64 num) ev2_key_from_num(EV2_BlockRangeList *block_ranges, U64 num)
{ {
EV_Key key = {0}; EV_Key key = {0};
if(block_ranges->first)
{
key = ev_key_make(ev_hash_from_key(ev_key_root()), 1);
}
U64 base_num = 1; U64 base_num = 1;
for(EV2_BlockRangeNode *n = block_ranges->first; n != 0; n = n->next) for(EV2_BlockRangeNode *n = block_ranges->first; n != 0; n = n->next)
{ {
@@ -830,7 +834,7 @@ ev2_key_from_num(EV2_BlockRangeList *block_ranges, U64 num)
internal U64 internal U64
ev2_num_from_key(EV2_BlockRangeList *block_ranges, EV_Key key) ev2_num_from_key(EV2_BlockRangeList *block_ranges, EV_Key key)
{ {
U64 result = 0; U64 result = 1;
U64 base_num = 1; U64 base_num = 1;
for(EV2_BlockRangeNode *n = block_ranges->first; n != 0; n = n->next) for(EV2_BlockRangeNode *n = block_ranges->first; n != 0; n = n->next)
{ {
+167 -134
View File
@@ -797,8 +797,8 @@ rd_watch_view_point_from_tbl(EV2_BlockRangeList *block_ranges, Vec2S64 tbl)
{ {
RD_WatchViewPoint pt = zero_struct; RD_WatchViewPoint pt = zero_struct;
pt.x = tbl.x; pt.x = tbl.x;
pt.key = ev2_key_from_num(block_ranges, tbl.y); pt.key = ev2_key_from_num(block_ranges, (U64)tbl.y + 1);
pt.parent_key = ev2_block_range_from_num(block_ranges, tbl.y).block->key; pt.parent_key = ev2_block_range_from_num(block_ranges, (U64)tbl.y + 1).block->key;
return pt; return pt;
} }
@@ -807,7 +807,7 @@ rd_tbl_from_watch_view_point(EV2_BlockRangeList *block_ranges, RD_WatchViewPoint
{ {
Vec2S64 tbl = {0}; Vec2S64 tbl = {0};
tbl.x = pt.x; tbl.x = pt.x;
tbl.y = ev2_num_from_key(block_ranges, pt.key); tbl.y = (S64)ev2_num_from_key(block_ranges, pt.key) - 1;
return tbl; return tbl;
} }
@@ -1237,8 +1237,8 @@ rd_watch_view_build(RD_WatchViewState *ewv, RD_WatchViewFlags flags, String8 roo
ewv->text_edit_state_slots_count = u64_up_to_pow2(selection_dim.y+1); ewv->text_edit_state_slots_count = u64_up_to_pow2(selection_dim.y+1);
ewv->text_edit_state_slots_count = Max(ewv->text_edit_state_slots_count, 64); ewv->text_edit_state_slots_count = Max(ewv->text_edit_state_slots_count, 64);
ewv->text_edit_state_slots = push_array(ewv->text_edit_arena, RD_WatchViewTextEditState*, ewv->text_edit_state_slots_count); ewv->text_edit_state_slots = push_array(ewv->text_edit_arena, RD_WatchViewTextEditState*, ewv->text_edit_state_slots_count);
EV2_WindowedRowList rows = ev2_windowed_row_list_from_block_range_list(scratch.arena, eval_view, filter, &block_ranges, r1u64(ui_scroll_list_row_from_item(&row_blocks, selection_tbl.min.y-1), EV2_WindowedRowList rows = ev2_windowed_row_list_from_block_range_list(scratch.arena, eval_view, filter, &block_ranges, r1u64(ui_scroll_list_row_from_item(&row_blocks, selection_tbl.min.y),
ui_scroll_list_row_from_item(&row_blocks, selection_tbl.max.y-1)+1)); ui_scroll_list_row_from_item(&row_blocks, selection_tbl.max.y)+1));
EV2_Row *row = rows.first; EV2_Row *row = rows.first;
for(S64 y = selection_tbl.min.y; y <= selection_tbl.max.y; y += 1, row = row->next) for(S64 y = selection_tbl.min.y; y <= selection_tbl.max.y; y += 1, row = row->next)
{ {
@@ -1268,8 +1268,8 @@ rd_watch_view_build(RD_WatchViewState *ewv, RD_WatchViewFlags flags, String8 roo
// //
if(!ewv->text_editing && evt->slot == UI_EventActionSlot_Accept) if(!ewv->text_editing && evt->slot == UI_EventActionSlot_Accept)
{ {
EV2_WindowedRowList rows = ev2_windowed_row_list_from_block_range_list(scratch.arena, eval_view, filter, &block_ranges, r1u64(ui_scroll_list_row_from_item(&row_blocks, selection_tbl.min.y-1), EV2_WindowedRowList rows = ev2_windowed_row_list_from_block_range_list(scratch.arena, eval_view, filter, &block_ranges, r1u64(ui_scroll_list_row_from_item(&row_blocks, selection_tbl.min.y),
ui_scroll_list_row_from_item(&row_blocks, selection_tbl.max.y-1)+1)); ui_scroll_list_row_from_item(&row_blocks, selection_tbl.max.y)+1));
EV2_Row *row = rows.first; EV2_Row *row = rows.first;
for(S64 y = selection_tbl.min.y; y <= selection_tbl.max.y && row != 0; y += 1, row = row->next) for(S64 y = selection_tbl.min.y; y <= selection_tbl.max.y && row != 0; y += 1, row = row->next)
{ {
@@ -1448,8 +1448,8 @@ rd_watch_view_build(RD_WatchViewState *ewv, RD_WatchViewFlags flags, String8 roo
case RD_WatchViewColumnKind_Value: case RD_WatchViewColumnKind_Value:
if(editing_complete && evt->slot != UI_EventActionSlot_Cancel) if(editing_complete && evt->slot != UI_EventActionSlot_Cancel)
{ {
EV2_WindowedRowList rows = ev2_windowed_row_list_from_block_range_list(scratch.arena, eval_view, filter, &block_ranges, r1u64(ui_scroll_list_row_from_item(&row_blocks, y-1), EV2_WindowedRowList rows = ev2_windowed_row_list_from_block_range_list(scratch.arena, eval_view, filter, &block_ranges, r1u64(ui_scroll_list_row_from_item(&row_blocks, y),
ui_scroll_list_row_from_item(&row_blocks, y-1)+1)); ui_scroll_list_row_from_item(&row_blocks, y)+1));
B32 success = 0; B32 success = 0;
if(rows.first != 0) if(rows.first != 0)
{ {
@@ -1506,8 +1506,8 @@ rd_watch_view_build(RD_WatchViewState *ewv, RD_WatchViewFlags flags, String8 roo
{ {
taken = 1; taken = 1;
String8List strs = {0}; String8List strs = {0};
EV2_WindowedRowList rows = ev2_windowed_row_list_from_block_range_list(scratch.arena, eval_view, filter, &block_ranges, r1u64(ui_scroll_list_row_from_item(&row_blocks, selection_tbl.min.y-1), EV2_WindowedRowList rows = ev2_windowed_row_list_from_block_range_list(scratch.arena, eval_view, filter, &block_ranges, r1u64(ui_scroll_list_row_from_item(&row_blocks, selection_tbl.min.y),
ui_scroll_list_row_from_item(&row_blocks, selection_tbl.max.y-1)+1)); ui_scroll_list_row_from_item(&row_blocks, selection_tbl.max.y)+1));
EV2_Row *row = rows.first; EV2_Row *row = rows.first;
for(S64 y = selection_tbl.min.y; y <= selection_tbl.max.y && row != 0; y += 1, row = row->next) for(S64 y = selection_tbl.min.y; y <= selection_tbl.max.y && row != 0; y += 1, row = row->next)
{ {
@@ -1602,7 +1602,7 @@ rd_watch_view_build(RD_WatchViewState *ewv, RD_WatchViewFlags flags, String8 roo
if(!ewv->text_editing && !(evt->flags & UI_EventFlag_Delete) && !(evt->flags & UI_EventFlag_Reorder)) if(!ewv->text_editing && !(evt->flags & UI_EventFlag_Delete) && !(evt->flags & UI_EventFlag_Reorder))
{ {
B32 cursor_tbl_min_is_empty_selection[Axis2_COUNT] = {0, 1}; B32 cursor_tbl_min_is_empty_selection[Axis2_COUNT] = {0, 1};
Rng2S64 cursor_tbl_range = r2s64(v2s64(0, 0), v2s64(ewv->column_count-1, block_tree.total_row_count)); Rng2S64 cursor_tbl_range = r2s64(v2s64(0, 0), v2s64(ewv->column_count-1, block_tree.total_row_count-1));
Vec2S32 delta = evt->delta_2s32; Vec2S32 delta = evt->delta_2s32;
if(evt->flags & UI_EventFlag_PickSelectSide && !MemoryMatchStruct(&selection_tbl.min, &selection_tbl.max)) if(evt->flags & UI_EventFlag_PickSelectSide && !MemoryMatchStruct(&selection_tbl.min, &selection_tbl.max))
{ {
@@ -1764,7 +1764,7 @@ rd_watch_view_build(RD_WatchViewState *ewv, RD_WatchViewFlags flags, String8 roo
scroll_list_params.dim_px = dim_2f32(rect); scroll_list_params.dim_px = dim_2f32(rect);
scroll_list_params.cursor_range = r2s64(v2s64(0, 0), v2s64(3, block_tree.total_item_count)); scroll_list_params.cursor_range = r2s64(v2s64(0, 0), v2s64(3, block_tree.total_item_count));
scroll_list_params.item_range = r1s64(0, block_tree.total_row_count); scroll_list_params.item_range = r1s64(0, block_tree.total_row_count);
scroll_list_params.cursor_min_is_empty_selection[Axis2_Y] = 1; scroll_list_params.cursor_min_is_empty_selection[Axis2_Y] = 0;
scroll_list_params.row_blocks = row_blocks; scroll_list_params.row_blocks = row_blocks;
} }
UI_BoxFlags disabled_flags = ui_top_flags(); UI_BoxFlags disabled_flags = ui_top_flags();
@@ -1785,9 +1785,146 @@ rd_watch_view_build(RD_WatchViewState *ewv, RD_WatchViewFlags flags, String8 roo
Vec2F32 scroll_list_view_off_px = ui_top_parent()->parent->view_off; Vec2F32 scroll_list_view_off_px = ui_top_parent()->parent->view_off;
//////////////////////////// ////////////////////////////
//- rjf: build table header //- rjf: viz blocks -> rows
// //
if(0) UI_TableVector UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) EV2_WindowedRowList rows = {0};
{
rows = ev2_windowed_row_list_from_block_range_list(scratch.arena, eval_view, filter, &block_ranges, r1u64(visible_row_rng.min, visible_row_rng.max+1));
}
////////////////////////////
//- rjf: build table
//
ProfScope("build table")
{
U64 global_row_idx = rows.count_before_semantic;
U64 global_row_num = global_row_idx+1;
for(EV2_Row *row = rows.first; row != 0; row = row->next, global_row_idx += 1, global_row_num += 1)
{
////////////////////////
//- rjf: unpack row info
//
U64 row_hash = ev_hash_from_key(row->key);
U64 row_depth = ev2_depth_from_block(row->block);
if(row_depth > 0)
{
row_depth -= 1;
}
B32 row_selected = (selection_tbl.min.y <= global_row_idx && global_row_idx <= selection_tbl.max.y);
B32 row_expanded = ev_expansion_from_key(eval_view, row->key);
E_Eval row_eval = e_eval_from_expr(scratch.arena, row->expr);
E_Type *row_type = e_type_from_key(scratch.arena, row_eval.type_key);
B32 row_is_expandable = ev2_row_is_expandable(row);
B32 row_is_editable = ev2_row_is_editable(row);
B32 next_row_expanded = row_expanded;
RD_ViewRuleInfo *ui_view_rule_info = rd_view_rule_info_from_string(row->block->expand_view_rule_info->string);
MD_Node *ui_view_rule_params_root = row->block->expand_view_rule_params;
if(ui_view_rule_info->ui == 0)
{
ui_view_rule_info = &rd_nil_view_rule_info;
ui_view_rule_params_root = &md_nil_node;
}
////////////////////////
//- rjf: choose kind of row
//
typedef enum RowKind
{
RowKind_Normal,
RowKind_Header,
RowKind_Canvas,
}
RowKind;
RowKind row_kind = RowKind_Normal;
if(ev_key_match(row->block->key, ev_key_root()))
{
row_kind = RowKind_Header;
}
else if(ui_view_rule_info != &rd_nil_view_rule_info && ui_view_rule_info->ui != 0)
{
row_kind = RowKind_Canvas;
}
////////////////////////
//- rjf: determine if row's data is fresh and/or bad
//
B32 row_is_fresh = 0;
B32 row_is_bad = 0;
switch(row_eval.mode)
{
default:{}break;
case E_Mode_Offset:
{
CTRL_Entity *space_entity = rd_ctrl_entity_from_eval_space(row_eval.space);
if(space_entity->kind == CTRL_EntityKind_Process)
{
U64 size = e_type_byte_size_from_key(row_eval.type_key);
size = Min(size, 64);
Rng1U64 vaddr_rng = r1u64(row_eval.value.u64, row_eval.value.u64+size);
CTRL_ProcessMemorySlice slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, space_entity->handle, vaddr_rng, 0);
for(U64 idx = 0; idx < (slice.data.size+63)/64; idx += 1)
{
if(slice.byte_changed_flags[idx] != 0)
{
row_is_fresh = 1;
}
if(slice.byte_bad_flags[idx] != 0)
{
row_is_bad = 1;
}
}
}
}break;
}
////////////////////////
//- rjf: determine row's flags & color palette
//
UI_BoxFlags row_flags = 0;
UI_Palette *palette = ui_top_palette();
{
if(row_is_fresh)
{
palette = ui_build_palette(ui_top_palette(), .background = rd_rgba_from_theme_color(RD_ThemeColor_HighlightOverlay));
row_flags |= UI_BoxFlag_DrawBackground;
}
else if(global_row_idx & 1)
{
palette = ui_build_palette(ui_top_palette(), .background = rd_rgba_from_theme_color(RD_ThemeColor_BaseBackgroundAlt));
row_flags |= UI_BoxFlag_DrawBackground;
}
switch(row_kind)
{
default:{}break;
case RowKind_Normal:{row_flags |= UI_BoxFlag_DisableFocusOverlay;}break;
case RowKind_Header:{row_flags |= UI_BoxFlag_DrawSideBottom|UI_BoxFlag_DisableFocusOverlay;}break;
case RowKind_Canvas:{row_flags |= UI_BoxFlag_Clip;}break;
}
}
////////////////////////
//- rjf: build row box
//
ui_set_next_palette(palette);
ui_set_next_flags(disabled_flags);
ui_set_next_pref_width(ui_pct(1, 0));
ui_set_next_pref_height(ui_px(scroll_list_params.row_height_px*row->visual_size, 1.f));
ui_set_next_focus_hot(row_selected ? UI_FocusKind_On : UI_FocusKind_Off);
UI_Box *row_box = ui_build_box_from_stringf(row_flags|(!row->next)*UI_BoxFlag_DrawSideBottom|UI_BoxFlag_Clickable, "row_%I64x", row_hash);
ui_ts_vector_idx += 1;
ui_ts_cell_idx = 0;
//////////////////////
//- rjf: build row contents
//
UI_Parent(row_box) switch(row_kind)
{
////////////////////
//- rjf: header row
//
case RowKind_Header:
{
UI_FlagsAdd(UI_BoxFlag_DrawTextWeak)
{ {
for(RD_WatchViewColumn *col = ewv->first_column; col != 0; col = col->next) for(RD_WatchViewColumn *col = ewv->first_column; col != 0; col = col->next)
UI_TableCell UI_TableCell
@@ -1853,122 +1990,14 @@ rd_watch_view_build(RD_WatchViewState *ewv, RD_WatchViewFlags flags, String8 roo
} }
} }
} }
////////////////////////////
//- rjf: viz blocks -> rows
//
EV2_WindowedRowList rows = {0};
{
rows = ev2_windowed_row_list_from_block_range_list(scratch.arena, eval_view, filter, &block_ranges, r1u64(visible_row_rng.min, visible_row_rng.max+1));
}
////////////////////////////
//- rjf: build table
//
ProfScope("build table")
{
U64 semantic_num = rows.count_before_semantic + 1;
for(EV2_Row *row = rows.first; row != 0; row = row->next, semantic_num += 1)
{
////////////////////////
//- rjf: unpack row info
//
U64 row_hash = ev_hash_from_key(row->key);
U64 row_depth = ev2_depth_from_block(row->block);
B32 row_selected = (selection_tbl.min.y <= semantic_num && semantic_num <= selection_tbl.max.y);
B32 row_expanded = ev_expansion_from_key(eval_view, row->key);
E_Eval row_eval = e_eval_from_expr(scratch.arena, row->expr);
E_Type *row_type = e_type_from_key(scratch.arena, row_eval.type_key);
B32 row_is_expandable = ev2_row_is_expandable(row);
B32 row_is_editable = ev2_row_is_editable(row);
B32 next_row_expanded = row_expanded;
RD_ViewRuleInfo *ui_view_rule_info = rd_view_rule_info_from_string(row->block->expand_view_rule_info->string);
MD_Node *ui_view_rule_params_root = row->block->expand_view_rule_params;
if(ui_view_rule_info->ui == 0)
{
ui_view_rule_info = &rd_nil_view_rule_info;
ui_view_rule_params_root = &md_nil_node;
}
////////////////////////
//- rjf: determine if row's data is fresh and/or bad
//
B32 row_is_fresh = 0;
B32 row_is_bad = 0;
switch(row_eval.mode)
{
default:{}break;
case E_Mode_Offset:
{
CTRL_Entity *space_entity = rd_ctrl_entity_from_eval_space(row_eval.space);
if(space_entity->kind == CTRL_EntityKind_Process)
{
U64 size = e_type_byte_size_from_key(row_eval.type_key);
size = Min(size, 64);
Rng1U64 vaddr_rng = r1u64(row_eval.value.u64, row_eval.value.u64+size);
CTRL_ProcessMemorySlice slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, space_entity->handle, vaddr_rng, 0);
for(U64 idx = 0; idx < (slice.data.size+63)/64; idx += 1)
{
if(slice.byte_changed_flags[idx] != 0)
{
row_is_fresh = 1;
}
if(slice.byte_bad_flags[idx] != 0)
{
row_is_bad = 1;
}
}
}
}break; }break;
}
//////////////////////// ////////////////////
//- rjf: determine row's color palette //- rjf: canvas row
// //
UI_BoxFlags row_flags = 0; case RowKind_Canvas:
UI_Palette *palette = ui_top_palette(); UI_FocusHot(row_selected ? UI_FocusKind_On : UI_FocusKind_Off)
{ {
if(row_is_fresh)
{
palette = ui_build_palette(ui_top_palette(), .background = rd_rgba_from_theme_color(RD_ThemeColor_HighlightOverlay));
row_flags |= UI_BoxFlag_DrawBackground;
}
else if(semantic_num & 1)
{
palette = ui_build_palette(ui_top_palette(), .background = rd_rgba_from_theme_color(RD_ThemeColor_BaseBackgroundAlt));
row_flags |= UI_BoxFlag_DrawBackground;
}
}
////////////////////////
//- rjf: build row box
//
ui_set_next_palette(palette);
ui_set_next_flags(disabled_flags);
ui_set_next_pref_width(ui_pct(1, 0));
ui_set_next_pref_height(ui_px(scroll_list_params.row_height_px*row->visual_size, 1.f));
ui_set_next_focus_hot(row_selected ? UI_FocusKind_On : UI_FocusKind_Off);
UI_Box *row_box = ui_build_box_from_stringf(row_flags|
(!row->next) * UI_BoxFlag_DrawSideBottom|
UI_BoxFlag_Clickable|
((ui_view_rule_info == &rd_nil_view_rule_info) * UI_BoxFlag_DisableFocusOverlay)|
((ui_view_rule_info != &rd_nil_view_rule_info) * UI_BoxFlag_Clip),
"row_%I64x", row_hash);
ui_ts_vector_idx += 1;
ui_ts_cell_idx = 0;
////////////////////////
//- rjf: canvas block row -> build singular row for "escape hatch" ui
//
B32 did_row_build = 0;
if(!did_row_build && ui_view_rule_info != &rd_nil_view_rule_info)
UI_Parent(row_box) UI_FocusHot(row_selected ? UI_FocusKind_On : UI_FocusKind_Off)
{
//- rjf: build ui hook row contents
if(ui_view_rule_info != &rd_nil_view_rule_info && ui_view_rule_info->ui != 0)
{
did_row_build = 1;
//- rjf: unpack //- rjf: unpack
RD_WatchViewPoint pt = {0, row->block->key, row->key}; RD_WatchViewPoint pt = {0, row->block->key, row->key};
RD_View *view = rd_view_from_handle(rd_regs()->view); RD_View *view = rd_view_from_handle(rd_regs()->view);
@@ -2060,16 +2089,15 @@ rd_watch_view_build(RD_WatchViewState *ewv, RD_WatchViewFlags flags, String8 roo
//- rjf: pop interaction registers //- rjf: pop interaction registers
rd_pop_regs(); rd_pop_regs();
} }
} }break;
}
//////////////////////// ////////////////////
//- rjf: build regular row contents in all other cases //- rjf: normal row
// //
if(!did_row_build) UI_Parent(row_box) UI_HeightFill default:
case RowKind_Normal:
UI_HeightFill
{ {
did_row_build = 1;
////////////////////// //////////////////////
//- rjf: draw start of cache lines in expansions //- rjf: draw start of cache lines in expansions
// //
@@ -2223,12 +2251,14 @@ rd_watch_view_build(RD_WatchViewState *ewv, RD_WatchViewFlags flags, String8 roo
}break; }break;
case RD_WatchViewColumnKind_FrameSelection: case RD_WatchViewColumnKind_FrameSelection:
{ {
#if 0 // TODO(rjf): @blocks
if(semantic_num - 1 == rd_regs()->unwind_count - rd_regs()->inline_depth) if(semantic_num - 1 == rd_regs()->unwind_count - rd_regs()->inline_depth)
{ {
cell_icon = RD_IconKind_RightArrow; cell_icon = RD_IconKind_RightArrow;
CTRL_Entity *thread = ctrl_entity_from_handle(d_state->ctrl_entity_store, rd_regs()->thread); CTRL_Entity *thread = ctrl_entity_from_handle(d_state->ctrl_entity_store, rd_regs()->thread);
cell_base_color = rd_rgba_from_ctrl_entity(thread); cell_base_color = rd_rgba_from_ctrl_entity(thread);
} }
#endif
}break; }break;
} }
@@ -2428,6 +2458,8 @@ rd_watch_view_build(RD_WatchViewState *ewv, RD_WatchViewFlags flags, String8 roo
ui_labelf("Block Key: {0x%I64x, %I64u}", row->block->key.parent_hash, row->block->key.child_num); ui_labelf("Block Key: {0x%I64x, %I64u}", row->block->key.parent_hash, row->block->key.child_num);
ui_labelf("Row Key: {0x%I64x, %I64u}", row->key.parent_hash, row->key.child_num); ui_labelf("Row Key: {0x%I64x, %I64u}", row->key.parent_hash, row->key.child_num);
ui_labelf("Cursor Key: {0x%I64x, %I64u}", ewv->cursor.key.parent_hash, ewv->cursor.key.child_num); ui_labelf("Cursor Key: {0x%I64x, %I64u}", ewv->cursor.key.parent_hash, ewv->cursor.key.child_num);
ui_spacer(ui_em(1.f, 1.f));
ui_labelf("Cursor Table Coordinates: {%I64u, %I64u}", selection_tbl.min.x, selection_tbl.min.y);
} }
//- rjf: [DEV] hovering -> eval system tooltips //- rjf: [DEV] hovering -> eval system tooltips
@@ -2576,6 +2608,7 @@ rd_watch_view_build(RD_WatchViewState *ewv, RD_WatchViewFlags flags, String8 roo
} }
} }
} }
}break;
} }
////////////////////// //////////////////////