box-targeted UI debug break cmd

This commit is contained in:
jacob 2026-04-03 11:42:25 -05:00
parent 48eb87aec8
commit d7ecdfb950
8 changed files with 2857 additions and 2636 deletions

View File

@ -14,7 +14,7 @@
//~ Tweakable definitions //~ Tweakable definitions
#define G_D12_TearingIsAllowed 1 #define G_D12_TearingIsAllowed 1
#define G_D12_FrameLatency 1 #define G_D12_FrameLatency 2
#define G_D12_SwapchainBufferCount 2 #define G_D12_SwapchainBufferCount 2
#define G_D12_SwapchainFlags ( \ #define G_D12_SwapchainFlags ( \
((G_D12_TearingIsAllowed != 0) * DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING) | \ ((G_D12_TearingIsAllowed != 0) * DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING) | \

View File

@ -2163,6 +2163,9 @@ P_Frame *P_PushFrame(P_World *world, P_Frame *src_frame, i64 tick)
void P_StepFrame(P_Frame *frame) void P_StepFrame(P_Frame *frame)
{ {
TempArena scratch = BeginScratchNoConflict(); TempArena scratch = BeginScratchNoConflict();
ProfZoneDF("Simulate world")
{
P_World *world = frame->world; P_World *world = frame->world;
P_Frame *prev_frame = frame->prev; P_Frame *prev_frame = frame->prev;
@ -3725,6 +3728,6 @@ void P_StepFrame(P_Frame *frame)
//- End frame //- End frame
frame->time_ns += sim_dt_ns; frame->time_ns += sim_dt_ns;
}
EndScratch(scratch); EndScratch(scratch);
} }

View File

@ -109,6 +109,7 @@ void S_TickForever(WaveLaneCtx *lane)
////////////////////////////// //////////////////////////////
//- Swap //- Swap
ProfZoneDF("Swap sim state")
{ {
b32 swapin = IsSwappedIn(); b32 swapin = IsSwappedIn();
b32 swapout = shutdown && IsSwappingOut(); b32 swapout = shutdown && IsSwappingOut();
@ -166,6 +167,7 @@ void S_TickForever(WaveLaneCtx *lane)
NET_Listen(net_pipe, port); NET_Listen(net_pipe, port);
P_MsgList in_msgs = Zi; P_MsgList in_msgs = Zi;
ProfZoneDF("Pop net messages")
{ {
NET_MsgList net_msgs = NET_Swap(frame_arena, net_pipe); NET_MsgList net_msgs = NET_Swap(frame_arena, net_pipe);
for (NET_Msg *net_msg = net_msgs.first; net_msg; net_msg = net_msg->next) for (NET_Msg *net_msg = net_msgs.first; net_msg; net_msg = net_msg->next)

View File

@ -3712,7 +3712,7 @@ void V_TickForever(WaveLaneCtx *lane)
b32 show_panels = frame->is_editing && !hide_editor_ui; b32 show_panels = (frame->is_editing && !hide_editor_ui) || TweakBool("Show panels when not editing", 1);
@ -3734,32 +3734,134 @@ void V_TickForever(WaveLaneCtx *lane)
if (show_panels && V.root_panel) if (show_panels && V.root_panel)
{ {
Struct(DfsPanel) { DfsPanel *next; V_Panel *panel; }; Struct(BfsPanel) { BfsPanel *next; V_Panel *panel; };
DfsPanel *top_dfs_panel = PushStruct(frame->arena, DfsPanel); BfsPanel *first_bfs_panel = PushStruct(frame->arena, BfsPanel);
top_dfs_panel->panel = V.root_panel; BfsPanel *last_bfs_panel = first_bfs_panel;
first_bfs_panel->panel = V.root_panel;
for (DfsPanel *dfs_panel = top_dfs_panel; dfs_panel; dfs_panel = top_dfs_panel) for (BfsPanel *parent_panel_bfs = first_bfs_panel; parent_panel_bfs; parent_panel_bfs = first_bfs_panel)
{ {
SllStackPop(top_dfs_panel); SllQueuePop(first_bfs_panel, last_bfs_panel);
V_Panel *panel = dfs_panel->panel; V_Panel *parent_panel = parent_panel_bfs->panel;
for (V_Panel *child = panel->first; child; child = child->next) for (V_Panel *panel = parent_panel->first; panel; panel = panel->next)
{ {
DfsPanel *child_dfs = PushStruct(frame->arena, DfsPanel); BfsPanel *panel_bfs = PushStruct(frame->arena, BfsPanel);
child_dfs->panel = child; panel_bfs->panel = panel;
SllStackPush(top_dfs_panel, child_dfs); SllQueuePush(first_bfs_panel, last_bfs_panel, panel_bfs);
UI_PushDF(Tag, panel->contents_box.v)
UI_PushDF(Parent, panel->contents_box)
{
//////////////////////////////
//- Build console panel
if (panel->flags & V_PanelFlag_Console)
ProfZoneDF("Build console panel")
{
//- Gather visible logs
Struct(VisLog)
{
VisLog *next;
LogEvent log_ev;
};
u64 display_logs_count = 0;
VisLog *first_vis_log = 0;
VisLog *last_vis_log = 0;
i32 max_log_level = LogLevel_Trace;
u32 max_display_logs = 30;
i64 max_time_ns = NsFromSeconds(1000);
LogEventsArray log_events = GetLogEvents();
{
b32 done = 0;
for (u64 log_event_idx = log_events.count; log_event_idx-- > 0 && display_logs_count < max_display_logs && !done;)
{
LogEvent ev = log_events.events[log_event_idx];
if (ev.time_ns > (frame->time_ns - max_time_ns))
{
if (ev.level <= max_log_level)
{
VisLog *vis_log = PushStruct(frame->arena, VisLog);
vis_log->log_ev = ev;
SllQueuePush(first_vis_log, last_vis_log, vis_log);
++display_logs_count;
}
}
else
{
done = 1;
}
}
}
//- Build log entries UI
UI_PushDF(ChildAlignment, UI_Region_BottomLeft)
// UI_PushDF(Anchor, UI_Region_BottomLeft)
// UI_SetNext(Height, UI_Shrink(0, 1));
UI_PushDF(Parent, UI_BuildColumn())
{
// UI_SetNext(BackgroundColor, VEC4(0.1, 0.5, 0.5, 0.8));
// UI_SetNext(Height, UI_Grow(1, 0));
// UI_BuildBox();
// UI_SetNext(Flags, UI_BoxFlag_Floating)
UI_SetNext(Height, UI_Shrink(0, 1));
UI_PushDF(Parent, UI_BuildColumn())
{
for (VisLog *vis_log = first_vis_log; vis_log; vis_log = vis_log->next)
{
LogEvent ev = vis_log->log_ev;
String log_msg = ev.msg;
String display_text = StringF(frame->arena, "%F", FmtString(log_msg));
// UI_BuildLabelF("%F", FmtString(text));
UI_SetNext(Height, UI_Shrink(0, 1));
UI_SetNext(Text, display_text);
// UI_SetNext(ChildAlignment, UI_Region_BottomLeft);
UI_SetNext(ChildAlignment, UI_Region_TopLeft);
UI_SetNext(Flags, UI_BoxFlag_DrawText);
UI_BuildBox();
}
}
}
} }
////////////////////////////// //////////////////////////////
//- Build profiler //- Build profiler panel
if (!TweakBool("Hide profiler", 0))
if (panel->flags & V_PanelFlag_Profiler) if (panel->flags & V_PanelFlag_Profiler)
ProfZoneDF("Build profiler panel")
{ {
// FIXME: Finalize // FIXME: Finalize
@ -3812,7 +3914,6 @@ void V_TickForever(WaveLaneCtx *lane)
//- Build profiler //- Build profiler
UI_Key profiler_box = UI_KeyF("profiler"); UI_Key profiler_box = UI_KeyF("profiler");
ProfZoneDF("Build profiler")
UI_PushDF(Tag, profiler_box.v) UI_PushDF(Tag, profiler_box.v)
UI_PushDF(Parent, profiler_box) UI_PushDF(Parent, profiler_box)
{ {
@ -3828,7 +3929,9 @@ void V_TickForever(WaveLaneCtx *lane)
UI_Size graph_height = UI_Fnt(2, 1); UI_Size graph_height = UI_Fnt(2, 1);
UI_Size main_height = UI_Grow(1, 0); UI_Size main_height = UI_Grow(1, 0);
UI_Size zone_height = UI_Fnt(1.25, 0); UI_Size zone_height = UI_Fnt(1.25, 0);
UI_Size track_height = UI_Fnt(10, 0); // UI_Size track_height = UI_Fnt(10, 0);
UI_Size track_height = UI_Grow(1, 0);
// UI_Size track_height = UI_Shrink(0, 0);
f32 zone_text_padding_px = UI_Top(FontSize) * 0.2; f32 zone_text_padding_px = UI_Top(FontSize) * 0.2;
// Vec2 old_main_dims = DimsFromRng2(UI_Rect(main_box)); // Vec2 old_main_dims = DimsFromRng2(UI_Rect(main_box));
@ -4137,14 +4240,10 @@ void V_TickForever(WaveLaneCtx *lane)
visual_zone_start_px = MaxF64(visual_zone_start_px, parent_vis->start_px); visual_zone_start_px = MaxF64(visual_zone_start_px, parent_vis->start_px);
if (left_vis) if (left_vis)
{ {
// visual_zone_start_px = MaxF64(visual_zone_start_px, CeilF64(left_vis->end_px));
visual_zone_start_px = MaxF64(visual_zone_start_px, left_vis->end_px); visual_zone_start_px = MaxF64(visual_zone_start_px, left_vis->end_px);
} }
// visual_zone_start_px = MinF64(visual_zone_start_px, visual_zone_end_px - min_zone_width_px); visual_zone_start_px = RoundF32(visual_zone_start_px);
// visual_zone_start_px = MaxF64(visual_zone_start_px, parent_vis->start_px); visual_zone_end_px = RoundF32(visual_zone_end_px);
// visual_zone_end_px = MaxF64(visual_zone_end_px, visual_zone_start_px + min_zone_width_px);
// visual_zone_end_px = MinF64(visual_zone_end_px, parent_vis->end_px);
} }
// Push vis zone // Push vis zone
@ -4215,6 +4314,7 @@ void V_TickForever(WaveLaneCtx *lane)
} }
} }
// Vec4 profiler_color = theme.col.window_bg;
Vec4 profiler_color = theme.col.window_bg; Vec4 profiler_color = theme.col.window_bg;
f32 profiler_opacity = TweakFloat("Profiler opacity", 1, 0, 1); f32 profiler_opacity = TweakFloat("Profiler opacity", 1, 0, 1);
@ -4332,6 +4432,9 @@ void V_TickForever(WaveLaneCtx *lane)
UI_PushDF(Tag, HashF("vis track %F", FmtUint(vis_track->id))) UI_PushDF(Tag, HashF("vis track %F", FmtUint(vis_track->id)))
UI_PushDF(Parent, UI_BuildColumn()) UI_PushDF(Parent, UI_BuildColumn())
{ {
// UI_BuildSpacer(UI_Px(10, 0), Axis_Y);
// UI_BuildSpacer(UI_Grow(1, 0), Axis_Y);
//- Zone rows //- Zone rows
UI_Key *zone_row_boxes = PushStructs(frame->arena, UI_Key, vis_track->rows_count); UI_Key *zone_row_boxes = PushStructs(frame->arena, UI_Key, vis_track->rows_count);
for (u64 zone_row_box_idx = 0; zone_row_box_idx < vis_track->rows_count; ++zone_row_box_idx) for (u64 zone_row_box_idx = 0; zone_row_box_idx < vis_track->rows_count; ++zone_row_box_idx)
@ -4357,11 +4460,6 @@ void V_TickForever(WaveLaneCtx *lane)
{ {
hovered_zone_box = zone_box; hovered_zone_box = zone_box;
hovered_zone = zone; hovered_zone = zone;
// FIXME: Remove this
b32 raah = UI_HotAbsolute(main_box);
} }
f32 zone_hovered = can_hover * UI_Hovered(zone_box) * UI_Hot(main_box); f32 zone_hovered = can_hover * UI_Hovered(zone_box) * UI_Hot(main_box);
@ -4536,13 +4634,15 @@ void V_TickForever(WaveLaneCtx *lane)
// Right collapsed lines // Right collapsed lines
if (is_collapsed) if (is_collapsed)
{
// Right zag
{ {
UI_SetNext(Width, UI_Grow(1, 0)); UI_SetNext(Width, UI_Grow(1, 0));
UI_SetNext(ZagColor, zone_line_color); UI_SetNext(ZagColor, zone_line_color);
UI_BuildBox(); UI_BuildBox();
} }
else
{
UI_SetNext(Width, UI_Px(3, 1));
UI_BuildBox();
} }
} }
} }
@ -4760,6 +4860,8 @@ void V_TickForever(WaveLaneCtx *lane)
} }
} }
} }
}
}
@ -4795,7 +4897,6 @@ void V_TickForever(WaveLaneCtx *lane)
UI_PushDF(Tag, HashF("vis panels")) UI_PushDF(Tag, HashF("vis panels"))
{ {
// FIXME: Remove this // FIXME: Remove this
////////////////////////////// //////////////////////////////
@ -4836,18 +4937,18 @@ void V_TickForever(WaveLaneCtx *lane)
} }
} }
//- Test panel //- Test console panel
{ {
V_Panel *parent = subroot_row_panel; V_Panel *parent = subroot_row_panel;
V_Panel *panel = PushStruct(perm, V_Panel); V_Panel *panel = PushStruct(perm, V_Panel);
panel->parent = parent; panel->parent = parent;
panel->axis = Axis_X; panel->axis = Axis_X;
DllQueuePush(parent->first, parent->last, panel); DllQueuePush(parent->first, parent->last, panel);
panel->box = UI_KeyF("test raah panel"); panel->box = UI_KeyF("test raah console panel");
panel->contents_box = UI_KeyF("panel contents box %F", FmtUint(panel->box.v)); panel->contents_box = UI_KeyF("panel contents box %F", FmtUint(panel->box.v));
panel->resizer_box = UI_KeyF("panel resizer box %F", FmtUint(panel->box.v)); panel->resizer_box = UI_KeyF("panel resizer box %F", FmtUint(panel->box.v));
panel->flags |= V_PanelFlag_Profiler; panel->flags |= V_PanelFlag_Console;
panel->pct = 0.25; panel->pct = 0.5;
} }
//- Vis screen panel //- Vis screen panel
@ -4862,6 +4963,21 @@ void V_TickForever(WaveLaneCtx *lane)
panel->resizer_box = UI_KeyF("panel resizer box %F", FmtUint(panel->box.v)); panel->resizer_box = UI_KeyF("panel resizer box %F", FmtUint(panel->box.v));
panel->pct = 1; panel->pct = 1;
} }
//- Test profiler panel
{
V_Panel *parent = subroot_row_panel;
V_Panel *panel = PushStruct(perm, V_Panel);
panel->parent = parent;
panel->axis = Axis_X;
DllQueuePush(parent->first, parent->last, panel);
panel->box = UI_KeyF("test raah profiler panel");
panel->contents_box = UI_KeyF("panel contents box %F", FmtUint(panel->box.v));
panel->resizer_box = UI_KeyF("panel r esizer box %F", FmtUint(panel->box.v)); if (!TweakBool("Hide profiler", 0))
panel->flags |= V_PanelFlag_Profiler;
panel->pct = 0.5;
}
} }
@ -4913,14 +5029,14 @@ void V_TickForever(WaveLaneCtx *lane)
{ {
SllQueuePop(first_panel_bfs, last_panel_bfs); SllQueuePop(first_panel_bfs, last_panel_bfs);
V_Panel *parent_panel = bfs_parent->panel; V_Panel *parent_panel = bfs_parent->panel;
UI_Key parent_contents_box = parent_panel->contents_box;
Axis parent_axis = parent_panel->axis; Axis parent_axis = parent_panel->axis;
Rng2 parent_rect = UI_Rect(parent_contents_box); Rng2 parent_rect = UI_Rect(parent_panel->contents_box);
Vec2 parent_dims = DimsFromRng2(parent_rect); Vec2 parent_dims = DimsFromRng2(parent_rect);
f32 parent_contents_size_px = MaxF32(DimsFromRng2(UI_Rect(parent_contents_box)).v[parent_axis], 1); f32 parent_contents_size_px = MaxF32(DimsFromRng2(UI_Rect(parent_panel->contents_box)).v[parent_axis], 1);
UI_PushDF(Parent, parent_contents_box) UI_PushDF(Tag, parent_panel->contents_box.v)
UI_PushDF(Parent, parent_panel->contents_box)
{ {
f32 minimum_panel_pct = 0.05; f32 minimum_panel_pct = 0.05;
@ -5006,6 +5122,7 @@ void V_TickForever(WaveLaneCtx *lane)
// UI_SetNext(AxisSize, UI_Grow(panel_pct, 1), .axis = parent_axis); // UI_SetNext(AxisSize, UI_Grow(panel_pct, 1), .axis = parent_axis);
UI_SetNext(AxisSize, UI_Grow(panel_pct, 0), .axis = parent_axis); UI_SetNext(AxisSize, UI_Grow(panel_pct, 0), .axis = parent_axis);
// UI_SetNext(AxisSize, UI_Px(panel_pct * parent_contents_size_px, 0), .axis = parent_axis);
UI_SetNext(AxisSize, UI_Grow(1, 0), .axis = !parent_axis); UI_SetNext(AxisSize, UI_Grow(1, 0), .axis = !parent_axis);
UI_SetNext(ChildLayoutAxis, parent_axis); UI_SetNext(ChildLayoutAxis, parent_axis);
UI_PushDF(Tag, panel_box.v) UI_PushDF(Tag, panel_box.v)
@ -8131,7 +8248,14 @@ void V_TickForever(WaveLaneCtx *lane)
UI_Pop(FontSize); UI_Pop(FontSize);
} }
UI_BuildLabelF(" Arenas: %F", FmtSint(GetGstat(NumArenas))); UI_BuildLabelF(" Arenas: %F", FmtSint(GetGstat(NumArenas)));
if (PROFILING_ENABLED)
{
UI_BuildLabelF(" Arena memory committed: %F MiB (Collecting profiler samples, so perpetual growth is expected)", FmtFloat((f64)GetGstat(ArenaMemoryCommitted) / 1024 / 1024, .p = 3));
}
else
{
UI_BuildLabelF(" Arena memory committed: %F MiB", FmtFloat((f64)GetGstat(ArenaMemoryCommitted) / 1024 / 1024, .p = 3)); UI_BuildLabelF(" Arena memory committed: %F MiB", FmtFloat((f64)GetGstat(ArenaMemoryCommitted) / 1024 / 1024, .p = 3));
}
UI_BuildLabelF(" Arena memory reserved: %F TiB", FmtFloat((f64)GetGstat(ArenaMemoryReserved) / 1024 / 1024 / 1024 / 1024, .p = 3)); UI_BuildLabelF(" Arena memory reserved: %F TiB", FmtFloat((f64)GetGstat(ArenaMemoryReserved) / 1024 / 1024 / 1024 / 1024, .p = 3));
} }
UI_BuildSpacer(UI_Px(padding, 1), Axis_Y); UI_BuildSpacer(UI_Px(padding, 1), Axis_Y);

View File

@ -317,6 +317,7 @@ Enum(V_PanelFlag)
V_PanelFlag_None = 0, V_PanelFlag_None = 0,
V_PanelFlag_Spawn = (1 << 0), V_PanelFlag_Spawn = (1 << 0),
V_PanelFlag_Profiler = (1 << 1), V_PanelFlag_Profiler = (1 << 1),
V_PanelFlag_Console = (1 << 2),
}; };
Struct(V_Panel) Struct(V_Panel)

View File

@ -762,7 +762,8 @@ ComputeShader(V_CompositeCS)
Vec4 backdrop_color = 0; Vec4 backdrop_color = 0;
{ {
if (!frame.is_editing || !is_in_world) // if (!frame.is_editing || !is_in_world)
if (1)
{ {
backdrop_color = backdrop.SampleLevel(bilinear_sampler, screen_uv, 0); backdrop_color = backdrop.SampleLevel(bilinear_sampler, screen_uv, 0);
} }

View File

@ -514,6 +514,19 @@ void UI_SetRawTexture(UI_Key key, G_TextureRef tex, Rng2 uv)
SllQueuePush(frame->first_cmd_node, frame->last_cmd_node, n); SllQueuePush(frame->first_cmd_node, frame->last_cmd_node, n);
} }
void UI_DebugBreak(UI_Key key, UI_DebugBreakFlag debug_break_flags)
{
UI_Frame *frame = UI_CurrentFrame();
UI_CmdNode *n = PushStruct(frame->arena, UI_CmdNode);
n->cmd.kind = UI_CmdKind_DebugBreak;
{
n->cmd.debug_break.key = key;
n->cmd.debug_break.flags = debug_break_flags;
}
++frame->cmds_count;
SllQueuePush(frame->first_cmd_node, frame->last_cmd_node, n);
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Begin frame //~ Begin frame
@ -562,7 +575,7 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags)
} }
frame->window_frame = WND_BeginFrame(G_Format_R16G16B16A16_Float, WND_BackbufferSizeMode_MatchMonitor); frame->window_frame = WND_BeginFrame(G_Format_R16G16B16A16_Float, WND_BackbufferSizeMode_MatchMonitor);
ProfZoneDF("Begin UI") ProfZoneDF("Prepare UI")
{ {
UI.cl = G_PrepareCommandList(G_QueueKind_Direct); UI.cl = G_PrepareCommandList(G_QueueKind_Direct);
ResetArena(frame->arena); ResetArena(frame->arena);
@ -617,7 +630,7 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags)
for (u64 pre_index = UI.boxes_count; pre_index-- > 0;) for (u64 pre_index = UI.boxes_count; pre_index-- > 0;)
{ {
UI_Box *box = prev_frame->boxes_pre[pre_index]; UI_Box *box = prev_frame->boxes_pre[pre_index];
UI_DebugBreak(box, UI_DebugBreakFlag_CheckCursorHover); UI_ExecuteDebugBreak(box, UI_DebugBreakFlag_CheckCursorHover);
//- Reset state //- Reset state
{ {
box->child_mouse_hovered = 0; box->child_mouse_hovered = 0;
@ -810,7 +823,7 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags)
UI_Box *box = prev_frame->boxes_pre[pre_index]; UI_Box *box = prev_frame->boxes_pre[pre_index];
UI_Box *parent = box->parent; UI_Box *parent = box->parent;
UI_Feedback *feedback = &box->feedback; UI_Feedback *feedback = &box->feedback;
UI_DebugBreak(box, UI_DebugBreakFlag_BuildFeedback); UI_ExecuteDebugBreak(box, UI_DebugBreakFlag_BuildFeedback);
// Propagate capture state upwards // Propagate capture state upwards
box->child_mouse_hovered = box->mouse_hovered || box->child_mouse_hovered; box->child_mouse_hovered = box->mouse_hovered || box->child_mouse_hovered;
@ -1159,7 +1172,7 @@ GC_Run UI_ScaleRun(Arena *arena, GC_Run unscaled_run, Vec2 scale)
void UI_EndFrame(UI_Frame *frame, i32 vsync) void UI_EndFrame(UI_Frame *frame, i32 vsync)
{ {
TempArena scratch = BeginScratchNoConflict(); TempArena scratch = BeginScratchNoConflict();
ProfZoneDF("End UI") ProfZoneDF("Commit UI")
{ {
UI_BoxIter box_iter = Zi; UI_BoxIter box_iter = Zi;
@ -1174,6 +1187,7 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
////////////////////////////// //////////////////////////////
//- Create boxes from build cmds //- Create boxes from build cmds
ProfZoneDF("Create boxes")
for (UI_CmdNode *cmd_node = frame->first_cmd_node; cmd_node; cmd_node = cmd_node->next) for (UI_CmdNode *cmd_node = frame->first_cmd_node; cmd_node; cmd_node = cmd_node->next)
{ {
UI_Cmd cmd = cmd_node->cmd; UI_Cmd cmd = cmd_node->cmd;
@ -1217,8 +1231,9 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
} }
////////////////////////////// //////////////////////////////
//- Update boxes from cmds //- Apply build cmds
ProfZoneDF("Apply build cmds")
for (UI_CmdNode *cmd_node = frame->first_cmd_node; cmd_node; cmd_node = cmd_node->next) for (UI_CmdNode *cmd_node = frame->first_cmd_node; cmd_node; cmd_node = cmd_node->next)
{ {
UI_Cmd cmd = cmd_node->cmd; UI_Cmd cmd = cmd_node->cmd;
@ -1294,9 +1309,31 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
} }
} }
//////////////////////////////
//- Apply debug break cmds
if (UI_IsDebugBreakEnabled)
{
ProfZoneDF("Apply debug break cmds")
for (UI_CmdNode *cmd_node = frame->first_cmd_node; cmd_node; cmd_node = cmd_node->next)
{
UI_Cmd cmd = cmd_node->cmd;
if (cmd.kind == UI_CmdKind_DebugBreak)
{
UI_Key key = cmd.debug_break.key;
UI_Box *box = UI_BoxFromKey(key);
if (box)
{
box->desc.debug_break_flags |= cmd.debug_break.flags;
}
}
}
}
////////////////////////////// //////////////////////////////
//- Prune cached boxes //- Prune cached boxes
ProfZoneDF("Prune boxes")
{ {
u64 prunes_count = 0; u64 prunes_count = 0;
UI_Box **prunes = PushStructsNoZero(scratch.arena, UI_Box *, UI.boxes_count); UI_Box **prunes = PushStructsNoZero(scratch.arena, UI_Box *, UI.boxes_count);
@ -1355,12 +1392,15 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
////////////////////////////// //////////////////////////////
//- Layout //- Layout
// Prepare layout data
u64 boxes_count = UI.boxes_count; u64 boxes_count = UI.boxes_count;
UI_Box **boxes_pre = PushStructsNoZero(frame->arena, UI_Box *, boxes_count); UI_Box **boxes_pre = PushStructsNoZero(frame->arena, UI_Box *, boxes_count);
UI_Box **boxes_post = PushStructsNoZero(frame->arena, UI_Box *, boxes_count); UI_Box **boxes_post = PushStructsNoZero(frame->arena, UI_Box *, boxes_count);
frame->boxes_pre = boxes_pre; frame->boxes_pre = boxes_pre;
frame->boxes_post = boxes_post; frame->boxes_post = boxes_post;
ProfZoneDF("Layout UI")
{
//- Prepare layout data
ProfZoneDF("Layout prepass")
{ {
u64 pre_index = 0; u64 pre_index = 0;
u64 post_index = 0; u64 post_index = 0;
@ -1369,7 +1409,7 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
UI_Box *box = ir.box; UI_Box *box = ir.box;
if (ir.pre) if (ir.pre)
{ {
UI_DebugBreak(box, UI_DebugBreakFlag_PrepLayout); UI_ExecuteDebugBreak(box, UI_DebugBreakFlag_PrepLayout);
box->pre_index = pre_index; box->pre_index = pre_index;
boxes_pre[pre_index] = box; boxes_pre[pre_index] = box;
@ -1403,18 +1443,26 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
Assert(post_index == boxes_count); Assert(post_index == boxes_count);
} }
// Solve independent sizes //- Solve independent sizes
ProfZoneDF("Solve independent sizes")
for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index) for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index)
{ {
UI_Box *box = boxes_pre[pre_index]; UI_Box *box = boxes_pre[pre_index];
UI_DebugBreak(box, UI_DebugBreakFlag_IndependentSolve); UI_ExecuteDebugBreak(box, UI_DebugBreakFlag_IndependentSolve);
for (Axis axis = 0; axis < Axis_COUNTXY; ++axis) for (Axis axis = 0; axis < Axis_COUNTXY; ++axis)
{ {
UI_Size size = box->desc.pref_semantic_dims[axis]; UI_Size size = box->desc.pref_semantic_dims[axis];
if (size.kind == UI_SizeKind_Pixel) if (size.kind == UI_SizeKind_Pixel)
{
if (TweakBool("RAAAAAAAAAAAAAH", 1))
{ {
box->solved_dims.v[axis] = size.v; box->solved_dims.v[axis] = size.v;
} }
else
{
box->solved_dims.v[axis] = CeilF32(size.v);
}
}
else if (size.kind == UI_SizeKind_Shrink) else if (size.kind == UI_SizeKind_Shrink)
{ {
if (AnyBit(box->desc.flags, UI_BoxFlag_DrawText)) if (AnyBit(box->desc.flags, UI_BoxFlag_DrawText))
@ -1428,21 +1476,36 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
{ {
text_size = box->glyph_run.font_ascent + box->glyph_run.font_descent; text_size = box->glyph_run.font_ascent + box->glyph_run.font_descent;
} }
if (TweakBool("RAAAAAAAAAAAAAH", 1))
{
box->solved_dims.v[axis] = text_size + (size.v * 2); box->solved_dims.v[axis] = text_size + (size.v * 2);
} }
else
{
box->solved_dims.v[axis] = CeilF32(text_size + (size.v * 2));
}
}
else if (!SPR_IsSheetKeyNil(box->desc.sprite_sheet)) else if (!SPR_IsSheetKeyNil(box->desc.sprite_sheet))
{
if (TweakBool("RAAAAAAAAAAAAAH", 1))
{ {
box->solved_dims.v[axis] = box->sprite.tex_rect.p1.v[axis] - box->sprite.tex_rect.p0.v[axis] + (size.v * 2); box->solved_dims.v[axis] = box->sprite.tex_rect.p1.v[axis] - box->sprite.tex_rect.p0.v[axis] + (size.v * 2);
} }
else
{
box->solved_dims.v[axis] = CeilF32(box->sprite.tex_rect.p1.v[axis] - box->sprite.tex_rect.p0.v[axis] + (size.v * 2));
}
}
} }
} }
} }
// Solve upwards-dependent sizes along layout axis //- Solve upwards-dependent sizes along layout axis
ProfZoneDF("Solve upwards-dependent sizes (along layout-axis)")
for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index) for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index)
{ {
UI_Box *box = boxes_pre[pre_index]; UI_Box *box = boxes_pre[pre_index];
UI_DebugBreak(box, UI_DebugBreakFlag_UpwardsDependentSolveLayoutAxis); UI_ExecuteDebugBreak(box, UI_DebugBreakFlag_UpwardsDependentSolveLayoutAxis);
if (box->parent) if (box->parent)
{ {
Axis axis = box->parent->desc.child_layout_axis; Axis axis = box->parent->desc.child_layout_axis;
@ -1455,8 +1518,10 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
{ {
UI_Size ancestor_size = ancestor->desc.pref_semantic_dims[axis]; UI_Size ancestor_size = ancestor->desc.pref_semantic_dims[axis];
if ( if (
ancestor_size.kind == UI_SizeKind_Pixel || ( ancestor_size.kind == UI_SizeKind_Pixel ||
ancestor_size.kind == UI_SizeKind_Shrink && ( (
ancestor_size.kind == UI_SizeKind_Shrink &&
(
AnyBit(box->desc.flags, UI_BoxFlag_DrawText) || AnyBit(box->desc.flags, UI_BoxFlag_DrawText) ||
!SPR_IsSheetKeyNil(box->desc.sprite_sheet) !SPR_IsSheetKeyNil(box->desc.sprite_sheet)
) )
@ -1473,11 +1538,12 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
} }
} }
// Solve downwards-dependent sizes //- Solve downwards-dependent sizes
ProfZoneDF("Solve downwards-dependent sizes")
for (u64 post_index = 0; post_index < boxes_count; ++post_index) for (u64 post_index = 0; post_index < boxes_count; ++post_index)
{ {
UI_Box *box = boxes_post[post_index]; UI_Box *box = boxes_post[post_index];
UI_DebugBreak(box, UI_DebugBreakFlag_DownwardsDependentSolve); UI_ExecuteDebugBreak(box, UI_DebugBreakFlag_DownwardsDependentSolve);
for (Axis axis = 0; axis < Axis_COUNTXY; ++axis) for (Axis axis = 0; axis < Axis_COUNTXY; ++axis)
{ {
UI_Size size = box->desc.pref_semantic_dims[axis]; UI_Size size = box->desc.pref_semantic_dims[axis];
@ -1499,16 +1565,18 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
} }
} }
} }
box->solved_dims.v[axis] = CeilF32(accum + (size.v * 2)); // box->solved_dims.v[axis] = CeilF32(accum + (size.v * 2));
box->solved_dims.v[axis] = accum + (size.v * 2);
} }
} }
} }
// Solve upwards-dependent sizes along non-layout axis //- Solve upwards-dependent sizes along non-layout axis
ProfZoneDF("Solve upwards-dependent sizes (along non-layout-axis)")
for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index) for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index)
{ {
UI_Box *box = boxes_pre[pre_index]; UI_Box *box = boxes_pre[pre_index];
UI_DebugBreak(box, UI_DebugBreakFlag_UpwardsDependentSolveNonLayoutAxis); UI_ExecuteDebugBreak(box, UI_DebugBreakFlag_UpwardsDependentSolveNonLayoutAxis);
if (box->parent) if (box->parent)
{ {
Axis axis = !box->parent->desc.child_layout_axis; Axis axis = !box->parent->desc.child_layout_axis;
@ -1520,11 +1588,12 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
} }
} }
// Solve violations //- Solve violations
ProfZoneDF("Solve violations")
for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index) for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index)
{ {
UI_Box *box = boxes_pre[pre_index]; UI_Box *box = boxes_pre[pre_index];
UI_DebugBreak(box, UI_DebugBreakFlag_SolveViolations); UI_ExecuteDebugBreak(box, UI_DebugBreakFlag_SolveViolations);
for (Axis axis = 0; axis < Axis_COUNTXY; ++axis) for (Axis axis = 0; axis < Axis_COUNTXY; ++axis)
{ {
f32 box_size = box->solved_dims.v[axis]; f32 box_size = box->solved_dims.v[axis];
@ -1539,7 +1608,7 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
b32 is_floating = AnyBit(child->desc.flags, UI_BoxFlag_Floating); b32 is_floating = AnyBit(child->desc.flags, UI_BoxFlag_Floating);
if (!is_floating) if (!is_floating)
{ {
f32 size = child->solved_dims.v[axis]; f32 size = RoundF32(child->solved_dims.v[axis]);
f32 strictness = child->desc.pref_semantic_dims[axis].strictness; f32 strictness = child->desc.pref_semantic_dims[axis].strictness;
f32 flex = size * (1.0 - strictness); f32 flex = size * (1.0 - strictness);
if (axis == box->desc.child_layout_axis) if (axis == box->desc.child_layout_axis)
@ -1562,7 +1631,7 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
for (UI_Box *child = box->first; child; child = child->next) for (UI_Box *child = box->first; child; child = child->next)
{ {
b32 is_floating = AnyBit(child->desc.flags, UI_BoxFlag_Floating); b32 is_floating = AnyBit(child->desc.flags, UI_BoxFlag_Floating);
f32 unconstrained_size = child->solved_dims.v[axis]; f32 unconstrained_size = RoundF32(child->solved_dims.v[axis]);
f32 strictness = child->desc.pref_semantic_dims[axis].strictness; f32 strictness = child->desc.pref_semantic_dims[axis].strictness;
f32 flex = unconstrained_size * (1.0 - strictness); f32 flex = unconstrained_size * (1.0 - strictness);
f32 new_size = unconstrained_size; f32 new_size = unconstrained_size;
@ -1593,7 +1662,7 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
} }
if (!is_floating) if (!is_floating)
{ {
size_accum += new_size; size_accum += RoundF32(new_size);
} }
child->solved_dims.v[axis] = new_size; child->solved_dims.v[axis] = new_size;
} }
@ -1603,11 +1672,12 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
} }
} }
// Solve final positions //- Solve final positions
ProfZoneDF("Solve final screen positions")
for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index) for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index)
{ {
UI_Box *box = boxes_pre[pre_index]; UI_Box *box = boxes_pre[pre_index];
UI_DebugBreak(box, UI_DebugBreakFlag_FinalSolve); UI_ExecuteDebugBreak(box, UI_DebugBreakFlag_FinalSolve);
UI_Box *parent = box->parent; UI_Box *parent = box->parent;
@ -1620,14 +1690,14 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
b32 is_floating = AnyBit(box->desc.flags, UI_BoxFlag_Floating); b32 is_floating = AnyBit(box->desc.flags, UI_BoxFlag_Floating);
// Apply scale //- Apply scale
for (Axis axis = 0; axis < Axis_COUNTXY; ++axis) for (Axis axis = 0; axis < Axis_COUNTXY; ++axis)
{ {
f32 unscaled_size = box->solved_dims.v[axis]; f32 unscaled_size = box->solved_dims.v[axis];
f32 scaled_size = 0; f32 scaled_size = 0;
if (box->solved_scale.v[axis] == 1) if (box->solved_scale.v[axis] == 1)
{ {
scaled_size = RoundF32(unscaled_size); scaled_size = RoundF32(unscaled_size); // Can cause layout issues
// scaled_size = unscaled_size; // scaled_size = unscaled_size;
} }
else else
@ -1637,7 +1707,7 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
box->solved_dims.v[axis] = scaled_size; box->solved_dims.v[axis] = scaled_size;
} }
// Compute anchor offset //- Compute anchor offset
Vec2 anchor_offset = Zi; Vec2 anchor_offset = Zi;
{ {
UI_RegionPair anchor_region = UI_PairFromRegion(box->desc.anchor); UI_RegionPair anchor_region = UI_PairFromRegion(box->desc.anchor);
@ -1680,7 +1750,7 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
// box->cursor = FloorF32(box->cursor); // box->cursor = FloorF32(box->cursor);
} }
// Solve screen rect //- Solve screen rect
{ {
// Compute offset // Compute offset
Vec2 offset = Zi; Vec2 offset = Zi;
@ -1718,17 +1788,9 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
} }
} }
} }
if (box->solved_scale.x == 1)
{
offset.x = RoundF32(offset.x);
}
if (box->solved_scale.y == 1)
{
offset.y = RoundF32(offset.y);
}
} }
// Compute rect //- Compute rect
Vec2 screen_pos = parent ? AddVec2(parent->screen_rect.p0, offset) : VEC2(0, 0); Vec2 screen_pos = parent ? AddVec2(parent->screen_rect.p0, offset) : VEC2(0, 0);
if (is_floating) if (is_floating)
{ {
@ -1744,8 +1806,21 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
screen_pos.y = MaxF32(parent->screen_rect.p0.y, screen_pos.y - overshoot.y); screen_pos.y = MaxF32(parent->screen_rect.p0.y, screen_pos.y - overshoot.y);
} }
} }
box->screen_rect.p0 = screen_pos; box->screen_rect.p0 = screen_pos;
box->screen_rect.p1 = AddVec2(box->screen_rect.p0, box->solved_dims); box->screen_rect.p1 = AddVec2(box->screen_rect.p0, box->solved_dims);
if (box->solved_scale.x == 1)
{
box->screen_rect.p0.x = RoundF32(box->screen_rect.p0.x);
box->screen_rect.p1.x = RoundF32(box->screen_rect.p1.x);
}
if (box->solved_scale.y == 1)
{
box->screen_rect.p0.y = RoundF32(box->screen_rect.p0.y);
box->screen_rect.p1.y = RoundF32(box->screen_rect.p1.y);
}
box->screen_anchor = AddVec2(box->screen_rect.p0, anchor_offset); box->screen_anchor = AddVec2(box->screen_rect.p0, anchor_offset);
// Update parent cursor // Update parent cursor
@ -1755,7 +1830,7 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
} }
} }
// Solve scissor //- Solve scissor
{ {
box->solved_scissor = Rng2Inf; box->solved_scissor = Rng2Inf;
if (box->desc.flags & UI_BoxFlag_Scissor || !parent) if (box->desc.flags & UI_BoxFlag_Scissor || !parent)
@ -1768,7 +1843,7 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
} }
} }
// Solve screen rounding //- Solve screen rounding
{ {
UI_Round rounding = box->desc.rounding; UI_Round rounding = box->desc.rounding;
Vec2 half_dims = MulVec2(SubVec2(box->screen_rect.p1, box->screen_rect.p0), 0.5); Vec2 half_dims = MulVec2(SubVec2(box->screen_rect.p1, box->screen_rect.p0), 0.5);
@ -1819,6 +1894,8 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
box->gen = box->old_gen; box->gen = box->old_gen;
} }
}
////////////////////////////// //////////////////////////////
//- Render //- Render
@ -1830,11 +1907,11 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
//- Build render data //- Build render data
// Build GPU rect data // Build GPU rect data
ProfZoneDF("Build UI GPU rects") ProfZoneDF("Build GPU rects")
for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index) for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index)
{ {
UI_Box *box = boxes_pre[pre_index]; UI_Box *box = boxes_pre[pre_index];
UI_DebugBreak(box, UI_DebugBreakFlag_BuildGpuData); UI_ExecuteDebugBreak(box, UI_DebugBreakFlag_BuildGpuData);
GC_Run raw_run_unscaled = box->glyph_run; GC_Run raw_run_unscaled = box->glyph_run;
GC_Run raw_run = UI_ScaleRun(frame->arena, raw_run_unscaled, box->solved_scale); GC_Run raw_run = UI_ScaleRun(frame->arena, raw_run_unscaled, box->solved_scale);
@ -1879,6 +1956,7 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
UI_AxisRegion y_alignment = child_alignment.v[Axis_Y]; UI_AxisRegion y_alignment = child_alignment.v[Axis_Y];
// Box rect // Box rect
ProfZoneDF("GPU box rect")
{ {
UI_GpuRect *rect = PushStruct(frame->rects_arena, UI_GpuRect); UI_GpuRect *rect = PushStruct(frame->rects_arena, UI_GpuRect);
rect->bounds = box->screen_rect; rect->bounds = box->screen_rect;
@ -1909,7 +1987,9 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
} }
} }
// Text rects
if (should_upload_text || AnyBit(frame->frame_flags, UI_FrameFlag_Debug)) if (should_upload_text || AnyBit(frame->frame_flags, UI_FrameFlag_Debug))
ProfZoneDF("GPU text rects")
{ {
f32 max_baseline_length = CeilF32(DimsFromRng2(box->screen_rect).x); f32 max_baseline_length = CeilF32(DimsFromRng2(box->screen_rect).x);
b32 should_truncate = FloorF32(raw_run.baseline_length) > max_baseline_length && !AnyBit(box->desc.flags, UI_BoxFlag_DontTruncateText); b32 should_truncate = FloorF32(raw_run.baseline_length) > max_baseline_length && !AnyBit(box->desc.flags, UI_BoxFlag_DontTruncateText);
@ -2037,7 +2117,7 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
////////////////////////////// //////////////////////////////
//- Upload data to GPU //- Upload data to GPU
ProfZoneDF("UI GPU upload") ProfZoneDF("Upload boxes to GPU")
G_ProfZoneDF(UI.cl, "UI GPU upload") G_ProfZoneDF(UI.cl, "UI GPU upload")
{ {
// Target // Target

View File

@ -262,6 +262,7 @@ Enum(UI_CmdKind)
{ {
UI_CmdKind_None, UI_CmdKind_None,
UI_CmdKind_BuildBox, UI_CmdKind_BuildBox,
UI_CmdKind_DebugBreak,
UI_CmdKind_SetRawTexture, UI_CmdKind_SetRawTexture,
}; };
@ -312,6 +313,11 @@ Struct(UI_Cmd)
{ {
UI_BoxDesc box; UI_BoxDesc box;
struct struct
{
UI_Key key;
UI_DebugBreakFlag flags;
} debug_break;
struct
{ {
UI_Key key; UI_Key key;
G_TextureRef tex; G_TextureRef tex;
@ -568,12 +574,16 @@ UI_Checkpoint UI_TopCp(void);
UI_Key UI_BuildBoxEx(UI_Key semantic_key); UI_Key UI_BuildBoxEx(UI_Key semantic_key);
#define UI_BuildBox() UI_BuildBoxEx(UI_NilKey) #define UI_BuildBox() UI_BuildBoxEx(UI_NilKey)
void UI_DebugBreak(UI_Key key, UI_DebugBreakFlag debug_break_flags);
void UI_SetRawTexture(UI_Key key, G_TextureRef tex, Rng2 uv); void UI_SetRawTexture(UI_Key key, G_TextureRef tex, Rng2 uv);
#if IsRtcEnabled #define UI_IsDebugBreakEnabled IsRtcEnabled
#define UI_DebugBreak(box, target_flags) do { if (box->desc.debug_break_flags & target_flags) { DEBUGBREAK; } } while (0)
#if UI_IsDebugBreakEnabled
#define UI_ExecuteDebugBreak(box, target_flags) do { if ((box)->desc.debug_break_flags & (target_flags)) { DEBUGBREAK; } } while (0)
#else #else
#define UI_DebugBreak(...) #define UI_ExecuteDebugBreak(...)
#endif #endif
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////