adjust top-level rd_frame structure to allow N cycles (rather than 1) of [rd cmds], [d tick] per frame; fix a few ctrl thread driving issues in dbg engine

This commit is contained in:
Ryan Fleury
2024-09-15 12:46:03 -07:00
parent 114ebfa27b
commit 3c262fccf3
2 changed files with 4128 additions and 4109 deletions
+4
View File
@@ -1939,8 +1939,12 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
for(CTRL_EntityNode *n = threads.first; n != 0; n = n->next)
{
CTRL_Entity *thread = n->v;
if(thread->is_frozen)
{
str8_list_push(scratch.arena, &strings, str8_struct(&thread->id));
str8_list_push(scratch.arena, &strings, str8_struct(&thread->is_frozen));
}
}
for(U64 idx = 0; idx < breakpoints->count; idx += 1)
{
D_Breakpoint *bp = &breakpoints->v[idx];
+77 -62
View File
@@ -9928,6 +9928,11 @@ rd_frame(void)
}
//////////////////////////////
//- rjf: loop - consume events in core, tick engine, and repeat
//
for(U64 cmd_process_loop_idx = 0; cmd_process_loop_idx < 3; cmd_process_loop_idx += 1)
{
////////////////////////////
//- rjf: unpack eval-dependent info
//
CTRL_Entity *process = ctrl_entity_from_handle(d_state->ctrl_entity_store, rd_regs()->process);
@@ -9982,7 +9987,7 @@ rd_frame(void)
}
}
//////////////////////////////
////////////////////////////
//- rjf: build eval type context
//
E_TypeCtx *type_ctx = push_array(scratch.arena, E_TypeCtx, 1);
@@ -9996,7 +10001,7 @@ rd_frame(void)
}
e_select_type_ctx(type_ctx);
//////////////////////////////
////////////////////////////
//- rjf: build eval parse context
//
E_ParseCtx *parse_ctx = push_array(scratch.arena, E_ParseCtx, 1);
@@ -10016,7 +10021,7 @@ rd_frame(void)
}
e_select_parse_ctx(parse_ctx);
//////////////////////////////
////////////////////////////
//- rjf: build eval IR context
//
E_IRCtx *ir_ctx = push_array(scratch.arena, E_IRCtx, 1);
@@ -10101,7 +10106,7 @@ rd_frame(void)
}
e_select_ir_ctx(ir_ctx);
//////////////////////////////
////////////////////////////
//- rjf: build eval interpretation context
//
E_InterpretCtx *interpret_ctx = push_array(scratch.arena, E_InterpretCtx, 1);
@@ -10120,7 +10125,7 @@ rd_frame(void)
}
e_select_interpret_ctx(interpret_ctx);
//////////////////////////////
////////////////////////////
//- rjf: build eval visualization view rule table
//
EV_ViewRuleInfoTable *view_rule_info_table = push_array(scratch.arena, EV_ViewRuleInfoTable, 1);
@@ -10129,7 +10134,7 @@ rd_frame(void)
}
ev_select_view_rule_info_table(view_rule_info_table);
//////////////////////////////
////////////////////////////
//- rjf: autosave if needed
//
{
@@ -10142,7 +10147,7 @@ rd_frame(void)
}
}
//////////////////////////////
////////////////////////////
//- rjf: process top-level graphical commands
//
B32 panel_reset_done = 0;
@@ -14068,55 +14073,7 @@ rd_frame(void)
}
}
//////////////////////////////
//- rjf: rotate command slots, bump command gen counter
//
// in this step, we rotate the ring buffer of command batches (command
// arenas & lists). when the cmds_gen (the position of the ring buffer)
// is even, the command queue is in a "read/write" mode, and this is uniquely
// usable by the core - this is done so that commands in the core can push
// other commands, and have those other commands processed on the same frame.
//
// in view code, however, they can only use the current command queue in a
// "read only" mode, because new commands pushed by those views must be
// processed first by the core. so, before calling into view code, the
// cmds_gen is incremented to be *odd*. this way, the views will *write*
// commands into the 0 slot, but *read* from the 1 slot (which will contain
// this frame's commands).
//
// after view code runs, the generation number is incremented back to even.
// the commands pushed by the view will be in the queue, and the core can
// treat that queue as r/w again.
//
if(depth == 0)
{
// rjf: rotate
{
Arena *first_arena = rd_state->cmds_arenas[0];
RD_CmdList first_cmds = rd_state->cmds[0];
MemoryCopy(rd_state->cmds_arenas,
rd_state->cmds_arenas+1,
sizeof(rd_state->cmds_arenas[0])*(ArrayCount(rd_state->cmds_arenas)-1));
MemoryCopy(rd_state->cmds,
rd_state->cmds+1,
sizeof(rd_state->cmds[0])*(ArrayCount(rd_state->cmds)-1));
rd_state->cmds_arenas[ArrayCount(rd_state->cmds_arenas)-1] = first_arena;
rd_state->cmds[ArrayCount(rd_state->cmds_arenas)-1] = first_cmds;
}
// rjf: clear next batch
{
arena_clear(rd_state->cmds_arenas[0]);
MemoryZeroStruct(&rd_state->cmds[0]);
}
// rjf: bump
{
rd_state->cmds_gen += 1;
}
}
//////////////////////////////
////////////////////////////
//- rjf: gather targets
//
D_TargetArray targets = {0};
@@ -14140,7 +14097,7 @@ rd_frame(void)
}
}
//////////////////////////////
////////////////////////////
//- rjf: gather breakpoints
//
D_BreakpointArray breakpoints = {0};
@@ -14169,7 +14126,7 @@ rd_frame(void)
}
}
//////////////////////////////
////////////////////////////
//- rjf: gather path maps
//
D_PathMapArray path_maps = {0};
@@ -14177,7 +14134,7 @@ rd_frame(void)
// TODO(rjf): @msgs
}
//////////////////////////////
////////////////////////////
//- rjf: gather exception code filters
//
U64 exception_code_filters[(CTRL_ExceptionCodeKind_COUNT+63)/64] = {0};
@@ -14185,12 +14142,13 @@ rd_frame(void)
// TODO(rjf): @msgs
}
//////////////////////////////
////////////////////////////
//- rjf: tick debug engine
//
U64 cmd_count_pre_tick = rd_state->cmds[0].count;
D_EventList engine_events = d_tick(scratch.arena, &targets, &breakpoints, &path_maps, exception_code_filters);
//////////////////////////////
////////////////////////////
//- rjf: no selected thread? -> try to snap to any existing thread
//
if(ctrl_entity_from_handle(d_state->ctrl_entity_store, rd_base_regs()->thread) == &ctrl_entity_nil)
@@ -14211,7 +14169,7 @@ rd_frame(void)
}
}
//////////////////////////////
////////////////////////////
//- rjf: process debug engine events
//
for(D_EventNode *n = engine_events.first; n != 0; n = n->next)
@@ -14281,6 +14239,15 @@ rd_frame(void)
}
}
////////////////////////////
//- rjf: early-out if no new commands
//
if(rd_state->cmds[0].count == cmd_count_pre_tick)
{
break;
}
}
//////////////////////////////
//- rjf: animate confirmation
//
@@ -14365,6 +14332,54 @@ rd_frame(void)
rd_queue_drag_drop();
}
////////////////////////////
//- rjf: rotate command slots, bump command gen counter
//
// in this step, we rotate the ring buffer of command batches (command
// arenas & lists). when the cmds_gen (the position of the ring buffer)
// is even, the command queue is in a "read/write" mode, and this is uniquely
// usable by the core - this is done so that commands in the core can push
// other commands, and have those other commands processed on the same frame.
//
// in view code, however, they can only use the current command queue in a
// "read only" mode, because new commands pushed by those views must be
// processed first by the core. so, before calling into view code, the
// cmds_gen is incremented to be *odd*. this way, the views will *write*
// commands into the 0 slot, but *read* from the 1 slot (which will contain
// this frame's commands).
//
// after view code runs, the generation number is incremented back to even.
// the commands pushed by the view will be in the queue, and the core can
// treat that queue as r/w again.
//
if(depth == 0)
{
// rjf: rotate
{
Arena *first_arena = rd_state->cmds_arenas[0];
RD_CmdList first_cmds = rd_state->cmds[0];
MemoryCopy(rd_state->cmds_arenas,
rd_state->cmds_arenas+1,
sizeof(rd_state->cmds_arenas[0])*(ArrayCount(rd_state->cmds_arenas)-1));
MemoryCopy(rd_state->cmds,
rd_state->cmds+1,
sizeof(rd_state->cmds[0])*(ArrayCount(rd_state->cmds)-1));
rd_state->cmds_arenas[ArrayCount(rd_state->cmds_arenas)-1] = first_arena;
rd_state->cmds[ArrayCount(rd_state->cmds_arenas)-1] = first_cmds;
}
// rjf: clear next batch
{
arena_clear(rd_state->cmds_arenas[0]);
MemoryZeroStruct(&rd_state->cmds[0]);
}
// rjf: bump
{
rd_state->cmds_gen += 1;
}
}
//////////////////////////////
//- rjf: update/render all windows
//