diff --git a/src/config.h b/src/config.h index 247aad23..176a202d 100644 --- a/src/config.h +++ b/src/config.h @@ -24,7 +24,7 @@ //~ Settings -#define PROFILING_ENABLED 0 +#define PROFILING_ENABLED 1 diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index 65df1866..8e3435dd 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -928,7 +928,6 @@ void V_TickForever(WaveLaneCtx *lane) CopyBytes(frame->real_held_buttons, prev_frame->real_held_buttons, sizeof(frame->real_held_buttons)); CopyBytes(frame->held_buttons, prev_frame->held_buttons, sizeof(frame->held_buttons)); frame->palette = prev_frame->palette; - frame->profiler = prev_frame->profiler; frame->is_editing = prev_frame->is_editing; frame->ui_debug = prev_frame->ui_debug; frame->show_console = prev_frame->show_console; @@ -3565,6 +3564,1221 @@ void V_TickForever(WaveLaneCtx *lane) + ////////////////////////////// + //- Collect profiler samples + + if (PROFILING_ENABLED) ProfZoneDF("Collect profiler samples") + { + RegisteredProfTracksArray prof_tracks = FetchRegisteredProfTracks(frame->arena); + for (u64 track_idx = 0; track_idx < prof_tracks.count; ++track_idx) + { + ProfTrack *prof_track = prof_tracks.tracks[track_idx]; + + //- Fetch collection track + V_ZoneTrack *zone_track = 0; + { + for (zone_track = V.first_zone_track; zone_track; zone_track = zone_track->next) + { + if (zone_track->prof_track->id == prof_track->id) + { + break; + } + } + if (!zone_track) + { + zone_track = PushStruct(perm, V_ZoneTrack); + zone_track->prof_track = prof_track; + zone_track->id = V.zone_tracks_count++; + SllQueuePush(V.first_zone_track, V.last_zone_track, zone_track); + + // Push root zone + zone_track->root_zone = PushStruct(perm, V_Zone); + zone_track->root_zone->start_ns = I64Min; + zone_track->root_zone->end_ns = I64Max; + zone_track->open_zone = zone_track->root_zone; + } + } + + //- Process new samples + { + // TODO: Clamp collection size + u64 sample_start_seq = zone_track->next_collection_sample_seq; + u64 sample_end_seq = Atomic64Fetch(&prof_track->top_sample_seq); + u64 samples_count = sample_end_seq - sample_start_seq; + + f64 ns_per_tsc = GetNsPerTsc(); + i64 startup_tsc = GetStartupTsc(); + + for (u64 sample_seq = sample_start_seq; sample_seq < sample_end_seq; ++sample_seq) + { + u64 sample_idx = sample_seq % ProfSamplesRingCap; + ProfSample *sample = &prof_track->samples_ring[sample_idx]; + + i64 sample_time_ns = (sample->tsc - startup_tsc) * ns_per_tsc; + + b32 is_begin_zone = !(sample->flags & ProfSampleFlag_EndZone); + b32 is_end_zone = !is_begin_zone; + if (is_begin_zone) + { + //- Begin zone + V_Zone *parent = zone_track->open_zone; + u64 zone_id = V.total_zones_count++; + + //- Fetch chunk + V_ZoneChunk *chunk = parent->last_chunk; + { + u64 new_chunk_capacity = 1; + if (chunk && chunk->count >= chunk->capacity) + { + new_chunk_capacity = chunk->capacity * 2; + chunk = 0; + } + if (!chunk) + { + chunk = PushStruct(perm, V_ZoneChunk); + chunk->capacity = new_chunk_capacity; + chunk->zones = PushStructsNoZero(perm, V_Zone, chunk->capacity); + SllQueuePush(parent->first_chunk, parent->last_chunk, chunk); + } + } + + V_Zone *zone = &chunk->zones[chunk->count++]; + { + zone->id = zone_id; + zone->start_ns = sample_time_ns; + zone->end_ns = I64Max; + zone->parent = parent; + zone->depth = parent->depth + 1; + + // TODO: More efficient name processing + char *name_cstr = sample->name_cstr_lit; + zone->name = StringFromCstrNoLimit(name_cstr); + + u64 color_seed = HashString(zone->name); + f32 h = (Norm16(color_seed >> 0) * 1) * 360; + f32 s = TweakFloat("Profiler zone saturation", 0.50, 0, 1); + f32 v = TweakFloat("Profiler zone brightness", 1.00, 0, 1); + zone->color = SrgbFromHsv(h, s, v); + } + zone_track->open_zone = zone; + + // Update ancestor counts + for (V_Zone *ancestor = parent; ancestor; ancestor = ancestor->parent) + { + ancestor->total_descendents_count += 1; + } + } + else if (is_end_zone) + { + //- End zone + V_Zone *zone = zone_track->open_zone; + { + zone->end_ns = sample_time_ns; + } + zone_track->open_zone = zone->parent; + } + } + + zone_track->next_collection_sample_seq = sample_end_seq; + } + } + } + + + + + + + + + + + + + + + + + + + ////////////////////////////// + //- Build panel contents + + + + + + + + + + b32 show_panels = frame->is_editing && !hide_editor_ui; + + + + + + + // FIXME: Limit dims based on sample buffer capacity + // b32 should_draw_profiler_graph = frame->profiler.is_showing && frame->profiler.graph_dims.x > 0 && frame->profiler.graph_dims.y > 0; + // frame->profiler_graph_dims = frame->profiler.graph_dims; + // frame->profiler_frame_seq = V.profiler_frame_seq; + + + UI_Key profiler_graph_box = UI_KeyF("graph"); + b32 should_draw_profiler_graph = 0; + V.profiler_graph_dims = DimsFromRng2(UI_Rect(profiler_graph_box)); + // frame->profiler_graph_dims = frame->profiler.graph_dims; + // frame->profiler_frame_seq = V.profiler_frame_seq; + + + + + + if (show_panels && V.root_panel) + { + Struct(DfsPanel) { DfsPanel *next; V_Panel *panel; }; + DfsPanel *top_dfs_panel = PushStruct(frame->arena, DfsPanel); + top_dfs_panel->panel = V.root_panel; + + for (DfsPanel *dfs_panel = top_dfs_panel; dfs_panel; dfs_panel = top_dfs_panel) + { + SllStackPop(top_dfs_panel); + V_Panel *panel = dfs_panel->panel; + + for (V_Panel *child = panel->first; child; child = child->next) + { + DfsPanel *child_dfs = PushStruct(frame->arena, DfsPanel); + child_dfs->panel = child; + SllStackPush(top_dfs_panel, child_dfs); + } + + + + ////////////////////////////// + //- Build profiler + + + if (panel->flags & V_PanelFlag_Profiler) + { + // FIXME: Finalize + + + + // // FIXME: Remove this + // if (frame->tick == 1) + // { + // frame->profiler.is_showing = 1; + // } + + + + + + + + + + + V_Profiler *profiler = &panel->profiler; + + f64 min_profiler_ns_per_px = 1; + // f64 max_profiler_ns_per_px = NsFromSeconds(100); + f64 max_profiler_ns_per_px = frame->time_ns / 10; + profiler->target_ns_per_px = ClampF64(profiler->target_ns_per_px, min_profiler_ns_per_px, max_profiler_ns_per_px); + profiler->ns_per_px = ClampF64(profiler->ns_per_px, min_profiler_ns_per_px, max_profiler_ns_per_px); + + UI_PushDF(OmitFlags, UI_BoxFlag_CaptureMouse * !!(frame->is_looking)) + // if (profiler->is_showing) + { + // FIXME: Remove this + + // if (frame->tick == 1) + // { + // // profiler->ns_per_px = NsFromSeconds(0.0001); + // profiler->target_ns_per_px = NsFromSeconds(0.01); + // } + + + // FIXME: Remove this + { + V_ProfilerFrame *pf = &V.profiler_frames[V.profiler_frame_seq % V_ProfilerFramesCap]; + V.profiler_frame_seq += 1; + } + + + + + + //- Build profiler + UI_Key profiler_box = UI_KeyF("profiler"); + ProfZoneDF("Build profiler") + UI_PushDF(Tag, profiler_box.v) + UI_PushDF(Parent, profiler_box) + { + UI_Key main_box = UI_KeyF("main"); + + // UI_Size profiler_height = UI_Fnt(70, 1); + UI_Size profiler_height = UI_Grow(1, 0); + UI_Size header_height = UI_Fnt(2, 1); + UI_Size footer_height = UI_Fnt(2, 1); + UI_Size window_padding = UI_Fnt(0.60, 1); + UI_Size minor_padding = UI_Fnt(0.15, 1); + // UI_Size graph_height = UI_Grow(0.25, 0); + UI_Size graph_height = UI_Fnt(2, 1); + UI_Size main_height = UI_Grow(1, 0); + UI_Size zone_height = UI_Fnt(1.25, 0); + UI_Size track_height = UI_Fnt(10, 0); + f32 zone_text_padding_px = UI_Top(FontSize) * 0.2; + + // Vec2 old_main_dims = DimsFromRng2(UI_Rect(main_box)); + // old_main_dims.x = MaxF32(old_main_dims.x, 1); + // old_main_dims.y = MaxF32(old_main_dims.y, 1); + + + + // if (profiler->view_start_ns == 0 && profiler->view_end_ns == 0) + // { + // profiler->view_start_ns = NsFromSeconds(0); + // profiler->view_end_ns = NsFromSeconds(10); + // } + + + // f32 old_cursor_offset_px = frame->screen_cursor.x - UI_Rect(main_box).p0.x; + // i64 old_cursor_offset_ns = (old_cursor_offset_px / old_main_dims.x) * (profiler->view_end_ns - profiler->view_start_ns); + // i64 old_cursor_ns = profiler->view_start_ns + old_cursor_offset_ns; + + f32 cursor_px = frame->screen_cursor.x - UI_Rect(main_box).p0.x; + + b32 is_main_hot = UI_HotAbsolute(main_box); + // if (is_main_hot) + { + profiler->cursor_ns = (cursor_px * profiler->ns_per_px) + profiler->view_ns; + } + + // Snap view + if (!profiler->unsnap) + { + f64 snap_width_ns = NsFromSeconds(1.0 / 10.0); + profiler->target_view_ns = frame->time_ns - snap_width_ns; + profiler->target_ns_per_px = snap_width_ns / MaxF32(DimsFromRng2(UI_Rect(main_box)).x, 100); + } + + f32 prof_zoom_rate = 1.65; + f64 prof_lerp_rate = SaturateF64(frame->dt * 25); + + { + f64 zooms = UI_Presses(main_box, Button_WheelDown) - UI_Presses(main_box, Button_WheelUp); + if (zooms != 0) + { + profiler->unsnap = 1; + } + f64 zoom_factor = PowF64(prof_zoom_rate, zooms); + profiler->target_ns_per_px *= zoom_factor; + profiler->target_view_ns = profiler->cursor_ns - (profiler->cursor_ns - profiler->target_view_ns) * zoom_factor; + if (zooms != 0) + { + profiler->last_zoom_delta = profiler->target_ns_per_px - profiler->ns_per_px; + profiler->last_view_delta = profiler->target_view_ns - profiler->view_ns; + } + f64 overshoot_factor = 0.01; + profiler->ns_per_px = LerpF64(profiler->ns_per_px, profiler->target_ns_per_px + profiler->last_zoom_delta * overshoot_factor, prof_lerp_rate); + profiler->view_ns = LerpF64(profiler->view_ns, profiler->target_view_ns + profiler->last_view_delta * overshoot_factor, prof_lerp_rate); + + if (profiler->last_zoom_delta < 0) + { + profiler->ns_per_px = MaxF64(profiler->ns_per_px, profiler->target_ns_per_px); + } + else if (profiler->last_zoom_delta > 0) + { + profiler->ns_per_px = MinF64(profiler->ns_per_px, profiler->target_ns_per_px); + } + + if (profiler->last_view_delta < 0) + { + profiler->view_ns = MaxF64(profiler->view_ns, profiler->target_view_ns); + } + else if (profiler->last_view_delta > 0) + { + profiler->view_ns = MinF64(profiler->view_ns, profiler->target_view_ns); + } + } + + + + + + + + + + + + + + + + + + + // if (profiler->is_dragging && !prev_frame->profiler.is_dragging) + // { + // profiler->drag_view_ns = profiler->view_ns; + // profiler->drag_cursor_px = cursor_px; + // } + + // if (profiler->is_dragging) + // { + // profiler->view_ns = profiler->drag_view_ns - ((cursor_px - profiler->drag_cursor_px) * profiler->ns_per_px); + // } + + + + + // FIXME: Recalc cursor after zoom + + + + + // if (is_main_hot) + { + profiler->cursor_ns = (cursor_px * profiler->ns_per_px) + profiler->view_ns; + } + + + + + + + // TODO: Drag in px units for sharper resolution + if (UI_Downs(main_box, Button_M2) || UI_Downs(main_box, Button_M3)) + { + profiler->drag_view_ns = profiler->view_ns; + profiler->drag_cursor_px = cursor_px; + } + + // Drag ruler + // TODO: When measuring stopped, lerp ruler closed + b32 is_measuring = 0; + if (UI_Downs(main_box, Button_M1)) + { + profiler->unsnap = 1; + profiler->ruler_start_ns = profiler->cursor_ns; + } + if (UI_Held(main_box, Button_M1)) + { + profiler->unsnap = 1; + is_measuring = 1; + profiler->target_ruler_opacity = 1; + } + else + { + profiler->target_ruler_opacity = 0; + } + profiler->ruler_opacity = LerpF32(profiler->ruler_opacity, profiler->target_ruler_opacity, prof_lerp_rate); + + // Drag view + if (UI_Held(main_box, Button_M2) || UI_Held(main_box, Button_M3)) + { + profiler->unsnap = 1; + profiler->view_ns = profiler->drag_view_ns - ((cursor_px - profiler->drag_cursor_px) * profiler->ns_per_px); + profiler->target_view_ns = profiler->view_ns; + } + + + + + + + + + // FIXME: Remove this + b32 do_break = frame->real_held_buttons[Button_B] && !prev_frame->real_held_buttons[Button_B]; + + + + + + + + // FIXME: Remove this + f64 view_range_len_px = DimsFromRng2(UI_Rect(main_box)).x; + f64 view_range_len_ns = view_range_len_px * profiler->ns_per_px; + + f64 view_start_ns = profiler->view_ns; + f64 view_end_ns = view_start_ns + view_range_len_ns; + + f64 view_start_px = view_start_ns / profiler->ns_per_px; + f64 view_end_px = view_end_ns / profiler->ns_per_px; + + + + + + + + + + + + + + + + + //- Generate visible zones + + Struct(VisZone) + { + VisZone *parent; + VisZone *next; + VisZone *next_bfs; + V_Zone *zone; + + u32 depth; + u64 id; + String name; + Vec4 color; + + f64 start_px; + f64 end_px; + + i64 start_ns; + i64 end_ns; + + u64 collapsed_count; + }; + + Struct(VisTrack) + { + VisTrack *next; + u64 id; + + u32 rows_count; + VisZone *first_zone; + VisZone *last_zone; + }; + + VisTrack *first_vis_track = 0; + VisTrack *last_vis_track = 0; + f32 zone_collapse_threshold_px = 10; + f32 zone_name_hide_threshold_px = UI_Top(FontSize) * 3; + f32 min_zone_width_px = 6; + ProfZoneDF("Generate visible zones") + { + for (V_ZoneTrack *zone_track = V.first_zone_track; zone_track; zone_track = zone_track->next) + { + // TODO: Ignore non-visible tracks + // TODO: Ignore non-visible depths + + VisTrack *vis_track = PushStruct(frame->arena, VisTrack); + SllQueuePush(first_vis_track, last_vis_track, vis_track); + vis_track->id = zone_track->id; + + VisZone *first_bfs_vis_zone = 0; + VisZone *last_bfs_vis_zone = 0; + + // Push root vis zone node to bfs + { + VisZone *root_bfs = PushStruct(frame->arena, VisZone); + root_bfs->zone = zone_track->root_zone; + root_bfs->start_px = -Inf; + root_bfs->end_px = Inf; + root_bfs->start_ns = I64Min; + root_bfs->end_ns = I64Max; + root_bfs->id = zone_track->root_zone->id; + SllQueuePushN(first_bfs_vis_zone, last_bfs_vis_zone, root_bfs, next_bfs); + } + + for (VisZone *parent_vis = first_bfs_vis_zone; parent_vis; parent_vis = first_bfs_vis_zone) + { + SllQueuePopN(first_bfs_vis_zone, last_bfs_vis_zone, next_bfs); + V_Zone *parent = parent_vis->zone; + + // Process child zones + { + b32 reached_end_of_view = 0; + VisZone *left_vis = 0; + for (V_ZoneChunk *chunk = parent->first_chunk; chunk && !reached_end_of_view; chunk = chunk->next) + { + i64 chunk_start_ns = chunk->zones[0].start_ns; + i64 chunk_end_ns = MinI64(chunk->zones[chunk->count - 1].end_ns, frame->time_ns); + + // i64 should_collapse_chunk = (chunk->end_ns - chunk->start_ns) / + + if (chunk_start_ns <= view_end_ns && chunk_end_ns >= view_start_ns) + { + // TODO: Binary search to find start within chunk + for (u64 chunk_zone_idx = 0; chunk_zone_idx < chunk->count && !reached_end_of_view; ++chunk_zone_idx) + { + V_Zone *zone = &chunk->zones[chunk_zone_idx]; + if (zone->start_ns > view_end_ns) + { + reached_end_of_view = 1; + } + else + { + i64 zone_start_ns = zone->start_ns; + i64 zone_end_ns = MinI64(zone->end_ns, frame->time_ns); + i64 zone_elapsed_ns = zone_end_ns - zone_start_ns; + i64 visual_zone_start_ns = MaxI64(zone_start_ns, profiler->view_ns); + i64 visual_zone_end_ns = MinI64(zone_end_ns, profiler->view_ns + view_range_len_ns); + + f64 visual_zone_start_px = visual_zone_start_ns / profiler->ns_per_px; + f64 visual_zone_end_px = visual_zone_end_ns / profiler->ns_per_px; + + { + visual_zone_end_px = MaxF64(visual_zone_end_px, visual_zone_start_px + min_zone_width_px); + { + f32 overshoot = MaxF32(visual_zone_end_px - parent_vis->end_px, 0); + visual_zone_start_px -= overshoot; + visual_zone_end_px -= overshoot; + } + visual_zone_start_px = MaxF64(visual_zone_start_px, parent_vis->start_px); + 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 = MinF64(visual_zone_start_px, visual_zone_end_px - min_zone_width_px); + // visual_zone_start_px = MaxF64(visual_zone_start_px, parent_vis->start_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 + if (visual_zone_end_px <= (frame->time_ns / profiler->ns_per_px)) + { + b32 should_collapse_zone = (visual_zone_end_px - visual_zone_start_px) <= zone_collapse_threshold_px; + String zone_name = zone->name; + u64 zone_id = zone->id; + Vec4 zone_color = zone->color; + + // b32 should_collapse_zone = visual_zone_len_px <= zone_collapse_threshold_px; + // b32 should_collapse_zone = 0; + + // if (visual_zone_start_ns > view_end_ns) + // { + // reached_end_of_view = 1; + // } + + if (visual_zone_end_ns >= view_start_ns && visual_zone_start_ns <= view_end_ns) + { + VisZone *vis_zone = 0; + if ( + should_collapse_zone && + left_vis && + left_vis->collapsed_count > 0 && + ((zone_start_ns - left_vis->end_ns) / profiler->ns_per_px) < zone_collapse_threshold_px + ) + { + vis_zone = left_vis; + } + else + { + vis_zone = PushStruct(frame->arena, VisZone); + vis_zone->zone = zone; + vis_zone->parent = parent_vis; + vis_zone->start_ns = zone_start_ns; + vis_zone->start_px = visual_zone_start_px; + vis_zone->name = zone_name; + vis_zone->id = zone_id; + } + + SllQueuePush(vis_track->first_zone, vis_track->last_zone, vis_zone); + vis_zone->end_px = visual_zone_end_px; + vis_zone->end_ns = zone_end_ns; + vis_zone->color = zone_color; + vis_zone->depth = zone->depth; + vis_track->rows_count = MaxU32(vis_track->rows_count, vis_zone->depth); + + if (should_collapse_zone) + { + vis_zone->collapsed_count += zone->total_descendents_count + 1; + } + + left_vis = vis_zone; + + if (!should_collapse_zone) + { + SllQueuePushN(first_bfs_vis_zone, last_bfs_vis_zone, vis_zone, next_bfs); + } + } + } + } + } + } + } + } + } + } + } + + Vec4 profiler_color = theme.col.window_bg; + f32 profiler_opacity = TweakFloat("Profiler opacity", 1, 0, 1); + + Vec4 timeline_cursor_color = theme.col.window_bd; + timeline_cursor_color.a = UI_Hot(main_box) * 0.75; + UI_Size timeline_cursor_width = UI_Fnt(0.15, 1); + + UI_Key hovered_zone_box = Zi; + VisZone *hovered_zone = 0; + f64 ruler_len_ns = 0; + + Vec4 main_color_sampled = profiler_color; + main_color_sampled.r *= 0.75; + main_color_sampled.g *= 0.75; + main_color_sampled.b *= 0.75; + + Vec4 main_color_unsampled = main_color_sampled; + main_color_unsampled.r *= 0.85; + main_color_unsampled.g *= 0.85; + main_color_unsampled.b *= 0.85; + + Vec4 collapsed_line_color = SrgbFromHsv(64, 1, 0.5); + Vec4 collapsed_text_color = SrgbFromHsv(64, 1, 0.75); + + // main_color_sampled.g += 0.05; + + UI_SetNext(Parent, vis_screen_box); + UI_SetNext(BorderColor, theme.col.window_bd); + UI_SetNext(BorderSize, 2); + UI_SetNext(BackgroundColor, profiler_color); + UI_SetNext(Rounding, UI_Rpx(10 * theme.rounding)); + UI_SetNext(Height, profiler_height); + UI_SetNext(Flags, UI_BoxFlag_CaptureMouse); + UI_SetNext(Opacity, profiler_opacity); + UI_SetNext(Parent, panel->contents_box); + UI_PushDF(Width, UI_Grow(1, 0)) + UI_PushDF(Parent, UI_BuildColumnEx(profiler_box)) + UI_PushDF(Parent, UI_BuildRow()) + { + UI_BuildSpacer(window_padding, Axis_X); + UI_PushDF(Parent, UI_BuildColumn()) + { + //- Header + // UI_PushDF(BackgroundColor, Color_Red) + // UI_SetNext(BorderColor, Color_Red); + // UI_SetNext(BorderSize, 1); + // UI_SetNext(ChildAlignment, UI_Region_Center); + // UI_PushDF(Height, header_height) + // UI_PushDF(Parent, UI_BuildBoxEx(UI_KeyF("profiler header"))) + // { + // UI_PushDF(TextColor, theme.col.hint) + // UI_BuildLabelF("Profiler"); + // } + + UI_BuildSpacer(window_padding, Axis_Y); + + UI_BuildDivider(UI_Px(1, 1), theme.col.divider, Axis_Y); + + //- Graph + // UI_SetNext(BackgroundColor, Color_Cyan); + UI_SetNext(Height, graph_height); + UI_PushDF(Parent, UI_BuildBoxEx(profiler_graph_box)) + { + } + // UI_BuildDivider(UI_Px(1, 1), theme.col.divider, Axis_Y); + + UI_BuildDivider(UI_Px(1, 1), theme.col.divider, Axis_Y); + + UI_BuildSpacer(window_padding, Axis_Y); + + //- Main area + UI_SetNext(BackgroundColor, main_color_unsampled); + UI_SetNext(Height, main_height); + UI_SetNext(Rounding, UI_Rpx(5 * theme.rounding)); + // UI_SetNext(Flags, UI_BoxFlag_CaptureMouse | UI_BoxFlag_CaptureThroughChildren | UI_BoxFlag_Scissor); + UI_SetNext(Flags, UI_BoxFlag_CaptureMouse | UI_BoxFlag_CaptureThroughChildren); + // UI_SetNext(Flags, UI_BoxFlag_CaptureMouse); + UI_PushDF(Parent, UI_BuildColumnEx(main_box)) + { + //- Active area background + UI_PushDF(Opacity, 0.75) + { + f64 aabg_left_ns = MaxF64(0, profiler->view_ns); + f64 aabg_right_ns = MinF64(frame->time_ns, view_end_ns); + + f64 aabg_len_ns = aabg_right_ns - aabg_left_ns; + f64 aabg_len_px = aabg_len_ns / profiler->ns_per_px; + + f64 aabg_cursor_offset_px = (aabg_left_ns - profiler->view_ns) / profiler->ns_per_px; + f32 aabg_offset_px = (aabg_left_ns - profiler->view_ns) / profiler->ns_per_px; + Vec2 aabg_cursor_pos = VEC2(aabg_cursor_offset_px, 0); + Vec2 aabg_pos = VEC2(aabg_offset_px, 0); + UI_Size aabg_width = UI_Px(aabg_len_px, 1); + + Vec4 aabg_color = main_color_sampled; + + // Ruler rect + { + // UI_SetNext(BorderSize, 1); + // UI_SetNext(BorderColor, Color_White); + UI_SetNext(Width, aabg_width); + UI_SetNext(FloatingPos, aabg_pos); + UI_SetNext(BackgroundColor, aabg_color); + UI_SetNext(Flags, UI_BoxFlag_Floating); + UI_BuildBoxEx(UI_KeyF("active area background")); + } + } + + //- Zone tracks + ProfZoneDF("Build zones") + { + for (VisTrack *vis_track = first_vis_track; vis_track; vis_track = vis_track->next) + { + UI_SetNext(Height, track_height); + UI_PushDF(Tag, HashF("vis track %F", FmtUint(vis_track->id))) + UI_PushDF(Parent, UI_BuildColumn()) + { + //- Zone rows + 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) + { + UI_Key zone_row_box = UI_KeyF("zone row %F", FmtUint(zone_row_box_idx)); + zone_row_boxes[zone_row_box_idx] = zone_row_box; + // UI_SetNext(Height, zone_height); + UI_SetNext(Height, zone_height); + UI_PushDF(Parent, UI_BuildRowEx(zone_row_box)) + { + } + } + + //- Zones + for (VisZone *zone = vis_track->first_zone; zone; zone = zone->next) + { + UI_Key zone_row_box = zone_row_boxes[zone->depth - 1]; + b32 can_hover = profiler->unsnap; + + UI_Key zone_box = UI_KeyF("Zone %F", FmtUint(zone->id)); + b32 is_hovered = can_hover && UI_HoveredAbsolute(zone_box) && UI_HotAbsolute(main_box); + if (is_hovered) + { + hovered_zone_box = zone_box; + 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); + + f64 zone_offset_px = zone->start_px - view_start_px; + f64 zone_len_px = zone->end_px - zone->start_px; + + Vec2 zone_pos = VEC2(zone_offset_px, 0); + UI_Size zone_width = UI_Px(zone_len_px, 1); + + Vec4 zone_color = zone->color; + Vec4 zone_color_bd = zone_color; + + zone_color_bd = MulVec4(zone_color_bd, 0.65); + zone_color_bd.a = 1; + + Vec4 zone_text_color = UI_Top(TextColor); + zone_text_color.a *= 0.75; + + Vec4 zone_line_color = Zi; + + // b32 is_collapsed = zone->is_collapsed; + b32 is_collapsed = zone->collapsed_count > 0; + // b32 is_collapsed = zone->collapsed_count > 0 || zone_len_px <= min_zone_width_px; + + // UI_Size collapsed_line_size = UI_Px(2, 1); + UI_Size collapsed_line_size = UI_Px(1.5, 1); + // Vec4 collapsed_text_color = theme.col.positive; + // Vec4 collapsed_line_color = theme.col.negative; + // Vec4 collapsed_line_color = SrgbFromHsv(TweakFloat("RAAAAAAAAAH H", 100, 0, 360), TweakFloat("RAAAAAAAAAH S", 0.50, 0, 1), TweakFloat("RAAAAAAAAAH V", 1.00, 0, 1)); + // Vec4 collapsed_line_color = Color_Black; + // Vec4 collapsed_line_color = theme.col.hint; + // Vec4 collapsed_text_color = theme.col.positive; + // Vec4 collapsed_text_color = SrgbFromHsv(TweakFloat("RAAAAAAAAAH H", 100, 0, 360), TweakFloat("RAAAAAAAAAH S", 0.50, 0, 1), TweakFloat("RAAAAAAAAAH V", 1.00, 0, 1)); + + // Vec4 collapsed_line_color = SrgbFromHsv(32, 1, 0.5); + // Vec4 collapsed_text_color = SrgbFromHsv(32, 1, 1); + + // Vec4 collapsed_line_color = SrgbFromHsv(64, 1, 0.5); + // Vec4 collapsed_text_color = SrgbFromHsv(64, 1, 0.75); + + // collapsed_text_color = LerpSrgb(collapsed_text_color, Color_White, zone_hovered); + // collapsed_line_color = LerpSrgb(collapsed_line_color, Color_White, zone_hovered); + + + + + + String zone_text = zone->name; + if (is_collapsed) + { + zone_text = StringF(frame->arena, "%F", FmtUint(zone->collapsed_count)); + zone_text_color = collapsed_text_color; + zone_line_color = collapsed_line_color; + + // zone_color = VEC4(0, 0, 0, 0); + // zone_color = VEC4(1, 0, 1, 1); + // zone_color = VEC4(0.15, 0.15, 0.15, 0.5); + // zone_color = VEC4(0.20, 0.20, 0.20, 0.5); + + + zone_color = VEC4(0.25, 0.25, 0.25, 0.5); + + + // if (zone->collapsed_count > 1) + // { + // zone_color = VEC4(0.25, 0.25, 0.25, 0.5); + // } + // else + // { + // zone_color = Color_White; + // } + + + + // zone_color = VEC4(0.4, 0.4, 0.4, 0.5); + zone_color_bd = VEC4(0, 0, 0, 0); + + // zone_color = LerpSrgb(zone_color, Color_Transparent, zone_hovered); + + } + + if (zone_len_px < zone_name_hide_threshold_px) + { + zone_text.len = 0; + } + + zone_color_bd = LerpSrgb(zone_color_bd, Color_White, zone_hovered * !is_collapsed); + zone_text_color = LerpSrgb(zone_text_color, Color_White, zone_hovered); + zone_line_color = LerpSrgb(zone_line_color, Color_White, zone_hovered); + + + f32 collapsed_zones_per_px = zone->collapsed_count / zone_len_px; + // f32 zag_intensity = 50 / collapsed_zones_per_px; + // zag_intensity = MaxF32(zag_intensity, 5); + + // f32 top_zag_information_density = 10; + f32 top_zag_information_density = zone_collapse_threshold_px; + // f32 zag_intensity = SmoothstepF32(0, top_zag_information_density, collapsed_zones_per_px); + // f32 zag_intensity = 1; + f32 zag_intensity = 0.3; + // f32 zag_intensity = TweakFloat("RAAAAAAAAAAAAAH", 1, 0, 1); + + f32 period_max = 20; + f32 period_min = 5; + f32 zag_period = LerpF32(period_max, period_min, zag_intensity); + + f32 amplitude_max = UI_Top(FontSize) * 0.15; + f32 amplitude_min = UI_Top(FontSize) * 0.05; + f32 zag_amplitude = LerpF32(amplitude_max, amplitude_min, zag_intensity); + + UI_SetNext(Width, zone_width); + UI_SetNext(Height, UI_Grow(1, 0)); + UI_SetNext(BackgroundColor, zone_color); + UI_SetNext(BorderColor, zone_color_bd); + UI_SetNext(BorderSize, 1); + UI_SetNext(FloatingPos, zone_pos); + UI_SetNext(ChildAlignment, UI_Region_Center); + UI_SetNext( + Flags, + UI_BoxFlag_Floating | + UI_BoxFlag_DontClampFloatingX | + UI_BoxFlag_DontClampFloatingY | + UI_BoxFlag_CaptureMouse | + UI_BoxFlag_Scissor + ); + UI_SetNext(Parent, zone_row_box); + // UI_PushDF(OrFlags, UI_Top(OrFlags) | (UI_BoxFlag_DontTruncateText * !!(is_collapsed))) + // UI_PushDF(OmitFlags, UI_Top(OmitFlags) | (UI_BoxFlag_Scissor * !!(is_collapsed))) + // UI_PushDF(ZagPeriod, UI_Top(FontSize) * 1) + // UI_PushDF(ZagPeriod, (collapsed_zones_per_px * UI_Top(FontSize)) * 0.1) + // UI_PushDF(ZagPeriod, collapsed_zones_per_px / (UI_Top(FontSize) * 1)) + UI_PushDF(ZagPeriod, zag_period) + UI_PushDF(ZagThickness, 1.5) + UI_PushDF(ZagRoundness, 1) + UI_PushDF(ZagAmplitude, zag_amplitude) + UI_PushDF(Parent, UI_BuildRowEx(zone_box)) + { + if (is_collapsed) + { + // Left zag + UI_SetNext(Width, UI_Grow(1, 0)); + UI_SetNext(ZagColor, zone_line_color); + UI_BuildBox(); + } + else + { + UI_SetNext(Width, UI_Px(3, 1)); + UI_BuildBox(); + } + + if (zone_text.len > 0) + { + // Zone name + // if (zone_len_px > zone_collapse_threshold_px * 3) + { + if (is_collapsed) + { + UI_SetNext(Width, UI_Shrink(0, 1)); + UI_SetNext(ChildAlignment, UI_Region_Center); + } + else + { + UI_SetNext(ChildAlignment, UI_Region_Left); + UI_SetNext(Width, UI_Grow(1, 0)); + } + UI_SetNext(FontSize, UI_Top(FontSize) * theme.h5); + UI_SetNext(TextColor, zone_text_color); + UI_SetNext(Text, zone_text); + UI_SetNext(Flags, UI_BoxFlag_DrawText | UI_BoxFlag_DontTruncateText); + UI_BuildRow(); + } + + // Right collapsed lines + if (is_collapsed) + { + // Right zag + { + UI_SetNext(Width, UI_Grow(1, 0)); + UI_SetNext(ZagColor, zone_line_color); + UI_BuildBox(); + } + } + } + } + } + } + } + } + + + + + + //- Ruler + UI_PushDF(Opacity, profiler->ruler_opacity) + { + { + f64 ruler_left_ns = MinF64(profiler->ruler_start_ns, profiler->cursor_ns); + f64 ruler_right_ns = MaxF64(profiler->ruler_start_ns, profiler->cursor_ns); + ruler_left_ns = ClampF64(ruler_left_ns, view_start_ns, view_end_ns); + ruler_right_ns = ClampF64(ruler_right_ns, view_start_ns, view_end_ns); + + ruler_len_ns = ruler_right_ns - ruler_left_ns; + f64 ruler_len_px = ruler_len_ns / profiler->ns_per_px; + + f64 ruler_cursor_offset_px = (profiler->ruler_start_ns - profiler->view_ns) / profiler->ns_per_px; + f32 ruler_offset_px = (ruler_left_ns - profiler->view_ns) / profiler->ns_per_px; + Vec2 ruler_cursor_pos = VEC2(ruler_cursor_offset_px, 0); + Vec2 ruler_pos = VEC2(ruler_offset_px, 0); + UI_Size ruler_width = UI_Px(ruler_len_px, 1); + + // Vec4 ruler_color = VEC4(0.25, 0.25, 0.25, 0.25); + Vec4 ruler_color = VEC4(0.20, 0.20, 0.20, 0.25); + + // Ruler rect + { + // UI_SetNext(BorderSize, 1); + // UI_SetNext(BorderColor, Color_White); + // UI_PushDF(Opacity, profiler->ruler_opacity) + UI_SetNext(Width, ruler_width); + UI_SetNext(FloatingPos, ruler_pos); + UI_SetNext(BackgroundColor, ruler_color); + UI_SetNext(Flags, UI_BoxFlag_Floating); + UI_BuildBoxEx(UI_KeyF("ruler")); + } + + // Ruler cursor + { + // UI_SetNext(BorderSize, 1); + // UI_SetNext(BorderColor, Color_White); + UI_SetNext(BackgroundColor, timeline_cursor_color); + UI_SetNext(Width, timeline_cursor_width); + UI_SetNext(FloatingPos, ruler_cursor_pos); + UI_SetNext(Anchor, UI_Region_Top); + UI_SetNext(Flags, UI_BoxFlag_Floating); + UI_BuildBoxEx(UI_KeyF("ruler cursor")); + } + } + } + + //- Timeline cursor + { + // Vec2 timeline_cursor_pos = VEC2(old_cursor_offset_px, 0); + Vec2 timeline_cursor_pos = VEC2((profiler->cursor_ns - profiler->view_ns) / profiler->ns_per_px, 0); + + UI_SetNext(Width, timeline_cursor_width); + UI_SetNext(Height, UI_Grow(1, 0)); + UI_SetNext(BackgroundColor, timeline_cursor_color); + UI_SetNext(FloatingPos, timeline_cursor_pos); + UI_SetNext(Flags, UI_BoxFlag_Floating); + UI_BuildBox(); + } + + //- Timeline tooltop + { + b32 show_ruler_time = is_measuring && ruler_len_ns != 0; + b32 show_hovered_zone = hovered_zone != 0; + if (show_ruler_time || show_hovered_zone) + { + UI_Key tooltip_box = UI_KeyF("tooltip"); + Vec2 tooltip_pos = SubVec2(frame->screen_cursor, UI_Anchor(main_box)); + tooltip_pos = AddVec2(tooltip_pos, theme.tooltip_offset_px); + f32 tooltip_opacity = 0.95; + + UI_SetNext(Opacity, tooltip_opacity); + UI_SetNext(BackgroundColor, theme.col.window_bg); + UI_SetNext(BorderColor, theme.col.window_bd); + UI_SetNext(Rounding, UI_Rpx(theme.rounding * 5)); + UI_SetNext(BorderSize, 1); + UI_SetNext(Anchor, UI_Region_TopLeft); + UI_SetNext(FloatingPos, tooltip_pos); + UI_SetNext(Flags, UI_BoxFlag_Floating); + UI_PushDF(Width, UI_Shrink(0, 1)) + UI_PushDF(Height, UI_Shrink(0, 1)) + UI_PushDF(Parent, UI_BuildRowEx(tooltip_box)) + { + UI_BuildSpacer(window_padding, Axis_X); + + UI_SetNext(Width, UI_Shrink(0, 1)); + UI_SetNext(Height, UI_Shrink(0, 1)); + UI_PushDF(Parent, UI_BuildColumn()) + { + UI_BuildSpacer(window_padding, Axis_Y); + + if (show_ruler_time) + { + // UI_SetNext(TextColor, theme.col.positive); + // UI_SetNext(TextColor, theme.col.button_active); + + UI_SetNext(TextColor, theme.col.button_selected); + UI_BuildLabelF("%F", FmtTimeNs(ruler_len_ns, .p = 2)); + + // UI_SetNext(TextColor, theme.col.button_selected); + // UI_BuildLabelF("Ruler"); + + if (show_hovered_zone) + { + UI_BuildSpacer(minor_padding, Axis_Y); + UI_BuildSpacer(minor_padding, Axis_Y); + UI_BuildDivider(UI_Px(1, 0), theme.col.divider, Axis_Y); + UI_BuildSpacer(minor_padding, Axis_Y); + } + } + + if (show_hovered_zone) + { + VisZone *zone = hovered_zone; + UI_PushDF(Parent, UI_BuildRow()) + { + i64 elapsed_ns = zone->end_ns - zone->start_ns; + UI_PushDF(Parent, UI_BuildColumn()) + { + UI_BuildLabelF("%F ", FmtTimeNs(elapsed_ns, .p = 2)); + + if (zone->collapsed_count > 0) + { + UI_PushDF(Parent, UI_BuildRow()) + { + if (zone->collapsed_count == 1) + { + // // UI_BuildLabelF(" (%F)", FmtUint(zone->collapsed_count)); + // UI_SetNext(TextColor, theme.col.hint); + // UI_BuildLabelF("%F", FmtString(zone->name)); + + // UI_SetNext(TextColor, collapsed_text_color); + // UI_BuildLabelF(" (Too small to display)"); + + UI_SetNext(TextColor, collapsed_text_color); + UI_BuildLabelF("1 zone too small to display: "); + UI_SetNext(TextColor, theme.col.hint); + UI_BuildLabelF("%F", FmtString(zone->name)); + } + else + { + // UI_SetNext(TextColor, theme.col.hint); + // UI_BuildLabelF("Zones too small to display"); + + // UI_SetNext(TextColor, collapsed_text_color); + // UI_BuildLabelF(" (%F)", FmtUint(zone->collapsed_count)); + + + // UI_SetNext(TextColor, theme.col.hint); + UI_SetNext(TextColor, collapsed_text_color); + UI_BuildLabelF("%F zones too small to display", FmtUint(zone->collapsed_count)); + } + } + } + else + { + UI_SetNext(TextColor, theme.col.hint); + UI_BuildLabelF("%F", FmtString(zone->name)); + } + } + } + } + + UI_BuildSpacer(window_padding, Axis_Y); + } + UI_BuildSpacer(window_padding, Axis_X); + } + } + } + } + + // UI_BuildSpacer(window_padding, Axis_Y); + + //- Footer + UI_PushDF(Height, footer_height) + UI_PushDF(ChildAlignment, UI_Region_Center) + UI_PushDF(Parent, UI_BuildRow()) + { + if (IsUnoptimized) + { + UI_PushDF(Width, UI_Shrink(0, 1)) + UI_PushDF(Height, UI_Shrink(0, 1)) + UI_PushDF(ChildAlignment, UI_Region_Left) + UI_PushDF(TextColor, theme.col.warn) + UI_PushDF(Parent, UI_BuildRow()) + { + UI_BuildIcon(theme.icon_font, UI_Icon_Warning); + // UI_BuildIcon(theme.icon_font, UI_Icon_Info); + UI_BuildLabelF(" Profiling an unoptimized build"); + } + } + + // Right side text + UI_BuildSpacer(UI_Grow(1, 0), Axis_X); + UI_SetNext(Opacity, UI_Hot(main_box)); + UI_BuildLabelF("%Fs", FmtFloat(SecondsFromNs(profiler->cursor_ns), .p = 3)); + } + } + UI_BuildSpacer(window_padding, Axis_X); + } + } + } + } + } + } + + + + + + + + + + + + + + + + + + + @@ -3575,36 +4789,14 @@ void V_TickForever(WaveLaneCtx *lane) - // FIXME: Remove this + + UI_PushDF(Tag, HashF("vis panels")) { - Struct(V_Panel) - { - V_Panel *parent; - V_Panel *next; - V_Panel *prev; - V_Panel *first; - V_Panel *last; - Axis axis; - - UI_Key box; - UI_Key contents_box; - UI_Key resizer_box; - - f32 pct; - - f32 drag_resize_pct; - f32 drag_resize_pct_per_px; - - b32 is_organizational; - }; - - - - PERSIST V_Panel *root_panel = 0; + // FIXME: Remove this ////////////////////////////// //- Init test panels @@ -3612,11 +4804,11 @@ void V_TickForever(WaveLaneCtx *lane) // FIXME: Remove this - if (!root_panel) + if (!V.root_panel) { V_Panel *subroot_row_panel = 0; - //- Root panel column + //- Root panel { { V_Panel *panel = PushStruct(perm, V_Panel); @@ -3625,15 +4817,15 @@ void V_TickForever(WaveLaneCtx *lane) panel->resizer_box = UI_KeyF("panel resizer box %F", FmtUint(panel->box.v)); panel->pct = 1; panel->axis = Axis_Y; - root_panel = panel; + V.root_panel = panel; } - //- Sub-root panel row + //- Sub-root panel { - V_Panel *parent = root_panel; + V_Panel *parent = V.root_panel; V_Panel *panel = PushStruct(perm, V_Panel); panel->parent = parent; - panel->axis = Axis_X; + panel->axis = Axis_Y; DllQueuePush(parent->first, parent->last, panel); panel->box = UI_KeyF("test raah subroot row panel"); panel->contents_box = UI_KeyF("panel contents box %F", FmtUint(panel->box.v)); @@ -3654,6 +4846,7 @@ void V_TickForever(WaveLaneCtx *lane) panel->box = UI_KeyF("test raah panel"); 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->flags |= V_PanelFlag_Profiler; panel->pct = 0.25; } @@ -3685,7 +4878,6 @@ void V_TickForever(WaveLaneCtx *lane) // UI_PushDF(Parent, vis_root_box) - b32 show_panels = frame->is_editing && !hide_editor_ui; if (!show_panels) { UI_SetNext(Flags, UI_BoxFlag_Floating); @@ -3713,14 +4905,9 @@ void V_TickForever(WaveLaneCtx *lane) UI_BuildBoxEx(vis_panels_box); Struct(PanelBfs) { PanelBfs *next; V_Panel *panel; }; - PanelBfs *first_panel_bfs = 0; - PanelBfs *last_panel_bfs = 0; - - { - PanelBfs *root_bfs = PushStruct(frame->arena, PanelBfs); - root_bfs->panel = root_panel; - SllQueuePush(first_panel_bfs, last_panel_bfs, root_bfs); - } + PanelBfs *first_panel_bfs = PushStruct(frame->arena, PanelBfs); + PanelBfs *last_panel_bfs = first_panel_bfs; + first_panel_bfs->panel = V.root_panel; for (PanelBfs *bfs_parent = first_panel_bfs; bfs_parent; bfs_parent = first_panel_bfs) { @@ -3926,6 +5113,15 @@ void V_TickForever(WaveLaneCtx *lane) + + + + + + + + + @@ -6698,1113 +7894,7 @@ void V_TickForever(WaveLaneCtx *lane) - ////////////////////////////// - //- Collect profiler samples - if (PROFILING_ENABLED) ProfZoneDF("Collect profiler samples") - { - RegisteredProfTracksArray prof_tracks = FetchRegisteredProfTracks(frame->arena); - for (u64 track_idx = 0; track_idx < prof_tracks.count; ++track_idx) - { - ProfTrack *prof_track = prof_tracks.tracks[track_idx]; - - //- Fetch collection track - V_ZoneTrack *zone_track = 0; - { - for (zone_track = V.first_zone_track; zone_track; zone_track = zone_track->next) - { - if (zone_track->prof_track->id == prof_track->id) - { - break; - } - } - if (!zone_track) - { - zone_track = PushStruct(perm, V_ZoneTrack); - zone_track->prof_track = prof_track; - zone_track->id = V.zone_tracks_count++; - SllQueuePush(V.first_zone_track, V.last_zone_track, zone_track); - - // Push root zone - zone_track->root_zone = PushStruct(perm, V_Zone); - zone_track->root_zone->start_ns = I64Min; - zone_track->root_zone->end_ns = I64Max; - zone_track->open_zone = zone_track->root_zone; - } - } - - //- Process new samples - { - // TODO: Clamp collection size - u64 sample_start_seq = zone_track->next_collection_sample_seq; - u64 sample_end_seq = Atomic64Fetch(&prof_track->top_sample_seq); - u64 samples_count = sample_end_seq - sample_start_seq; - - f64 ns_per_tsc = GetNsPerTsc(); - i64 startup_tsc = GetStartupTsc(); - - for (u64 sample_seq = sample_start_seq; sample_seq < sample_end_seq; ++sample_seq) - { - u64 sample_idx = sample_seq % ProfSamplesRingCap; - ProfSample *sample = &prof_track->samples_ring[sample_idx]; - - i64 sample_time_ns = (sample->tsc - startup_tsc) * ns_per_tsc; - - b32 is_begin_zone = !(sample->flags & ProfSampleFlag_EndZone); - b32 is_end_zone = !is_begin_zone; - if (is_begin_zone) - { - //- Begin zone - V_Zone *parent = zone_track->open_zone; - u64 zone_id = V.total_zones_count++; - - //- Fetch chunk - V_ZoneChunk *chunk = parent->last_chunk; - { - u64 new_chunk_capacity = 1; - if (chunk && chunk->count >= chunk->capacity) - { - new_chunk_capacity = chunk->capacity * 2; - chunk = 0; - } - if (!chunk) - { - chunk = PushStruct(perm, V_ZoneChunk); - chunk->capacity = new_chunk_capacity; - chunk->zones = PushStructsNoZero(perm, V_Zone, chunk->capacity); - SllQueuePush(parent->first_chunk, parent->last_chunk, chunk); - } - } - - V_Zone *zone = &chunk->zones[chunk->count++]; - { - zone->id = zone_id; - zone->start_ns = sample_time_ns; - zone->end_ns = I64Max; - zone->parent = parent; - zone->depth = parent->depth + 1; - - // TODO: More efficient name processing - char *name_cstr = sample->name_cstr_lit; - zone->name = StringFromCstrNoLimit(name_cstr); - - u64 color_seed = HashString(zone->name); - f32 h = (Norm16(color_seed >> 0) * 1) * 360; - f32 s = TweakFloat("Profiler zone saturation", 0.50, 0, 1); - f32 v = TweakFloat("Profiler zone brightness", 1.00, 0, 1); - zone->color = SrgbFromHsv(h, s, v); - } - zone_track->open_zone = zone; - - // Update ancestor counts - for (V_Zone *ancestor = parent; ancestor; ancestor = ancestor->parent) - { - ancestor->total_descendents_count += 1; - } - } - else if (is_end_zone) - { - //- End zone - V_Zone *zone = zone_track->open_zone; - { - zone->end_ns = sample_time_ns; - } - zone_track->open_zone = zone->parent; - } - } - - zone_track->next_collection_sample_seq = sample_end_seq; - } - } - } - - - - - - ////////////////////////////// - //- Build profiler - - - // FIXME: Finalize - - - V_Profiler *profiler = &frame->profiler; - - f64 min_profiler_ns_per_px = 1; - // f64 max_profiler_ns_per_px = NsFromSeconds(100); - f64 max_profiler_ns_per_px = frame->time_ns / 10; - profiler->target_ns_per_px = ClampF64(profiler->target_ns_per_px, min_profiler_ns_per_px, max_profiler_ns_per_px); - profiler->ns_per_px = ClampF64(profiler->ns_per_px, min_profiler_ns_per_px, max_profiler_ns_per_px); - - UI_Key profiler_graph_box = UI_KeyF("graph"); - UI_PushDF(OmitFlags, UI_BoxFlag_CaptureMouse * !!(frame->is_looking)) - if (profiler->is_showing) - { - - - - // FIXME: Remove this - - // if (frame->tick == 1) - // { - // // profiler->ns_per_px = NsFromSeconds(0.0001); - // profiler->target_ns_per_px = NsFromSeconds(0.01); - // } - - profiler->graph_dims = DimsFromRng2(UI_Rect(profiler_graph_box)); - - - // FIXME: Remove this - { - V_ProfilerFrame *pf = &V.profiler_frames[V.profiler_frame_seq % V_ProfilerFramesCap]; - V.profiler_frame_seq += 1; - } - - - - - - //- Build profiler - UI_Key profiler_box = UI_KeyF("profiler"); - ProfZoneDF("Build profiler") - UI_PushDF(Tag, profiler_box.v) - UI_PushDF(Parent, profiler_box) - { - UI_Key main_box = UI_KeyF("main"); - - UI_Size profiler_height = UI_Fnt(70, 1); - UI_Size header_height = UI_Fnt(2, 1); - UI_Size footer_height = UI_Fnt(2, 1); - UI_Size window_padding = UI_Fnt(0.60, 1); - UI_Size minor_padding = UI_Fnt(0.15, 1); - // UI_Size graph_height = UI_Grow(0.25, 0); - UI_Size graph_height = UI_Fnt(2, 1); - UI_Size main_height = UI_Grow(1, 0); - UI_Size zone_height = UI_Fnt(1.25, 0); - UI_Size track_height = UI_Fnt(10, 0); - f32 zone_text_padding_px = UI_Top(FontSize) * 0.2; - - // Vec2 old_main_dims = DimsFromRng2(UI_Rect(main_box)); - // old_main_dims.x = MaxF32(old_main_dims.x, 1); - // old_main_dims.y = MaxF32(old_main_dims.y, 1); - - - - // if (profiler->view_start_ns == 0 && profiler->view_end_ns == 0) - // { - // profiler->view_start_ns = NsFromSeconds(0); - // profiler->view_end_ns = NsFromSeconds(10); - // } - - - // f32 old_cursor_offset_px = frame->screen_cursor.x - UI_Rect(main_box).p0.x; - // i64 old_cursor_offset_ns = (old_cursor_offset_px / old_main_dims.x) * (profiler->view_end_ns - profiler->view_start_ns); - // i64 old_cursor_ns = profiler->view_start_ns + old_cursor_offset_ns; - - f32 cursor_px = frame->screen_cursor.x - UI_Rect(main_box).p0.x; - - b32 is_main_hot = UI_HotAbsolute(main_box); - if (is_main_hot) - { - profiler->cursor_ns = (cursor_px * profiler->ns_per_px) + profiler->view_ns; - } - - // Snap view - if (profiler->snap) - { - f64 snap_width_ns = NsFromSeconds(1.0 / 10.0); - profiler->target_view_ns = frame->time_ns - snap_width_ns; - profiler->target_ns_per_px = snap_width_ns / MaxF32(DimsFromRng2(UI_Rect(main_box)).x, 100); - } - - f32 prof_zoom_rate = 1.65; - f64 prof_lerp_rate = SaturateF64(frame->dt * 25); - - { - f64 zooms = UI_Presses(main_box, Button_WheelDown) - UI_Presses(main_box, Button_WheelUp); - if (zooms != 0) - { - profiler->snap = 0; - } - f64 zoom_factor = PowF64(prof_zoom_rate, zooms); - profiler->target_ns_per_px *= zoom_factor; - profiler->target_view_ns = profiler->cursor_ns - (profiler->cursor_ns - profiler->target_view_ns) * zoom_factor; - if (zooms != 0) - { - profiler->last_zoom_delta = profiler->target_ns_per_px - profiler->ns_per_px; - profiler->last_view_delta = profiler->target_view_ns - profiler->view_ns; - } - f64 overshoot_factor = 0.01; - profiler->ns_per_px = LerpF64(profiler->ns_per_px, profiler->target_ns_per_px + profiler->last_zoom_delta * overshoot_factor, prof_lerp_rate); - profiler->view_ns = LerpF64(profiler->view_ns, profiler->target_view_ns + profiler->last_view_delta * overshoot_factor, prof_lerp_rate); - - if (profiler->last_zoom_delta < 0) - { - profiler->ns_per_px = MaxF64(profiler->ns_per_px, profiler->target_ns_per_px); - } - else if (profiler->last_zoom_delta > 0) - { - profiler->ns_per_px = MinF64(profiler->ns_per_px, profiler->target_ns_per_px); - } - - if (profiler->last_view_delta < 0) - { - profiler->view_ns = MaxF64(profiler->view_ns, profiler->target_view_ns); - } - else if (profiler->last_view_delta > 0) - { - profiler->view_ns = MinF64(profiler->view_ns, profiler->target_view_ns); - } - } - - - - - - - - - - - - - - - - - - - // if (profiler->is_dragging && !prev_frame->profiler.is_dragging) - // { - // profiler->drag_view_ns = profiler->view_ns; - // profiler->drag_cursor_px = cursor_px; - // } - - // if (profiler->is_dragging) - // { - // profiler->view_ns = profiler->drag_view_ns - ((cursor_px - profiler->drag_cursor_px) * profiler->ns_per_px); - // } - - - - - // FIXME: Recalc cursor after zoom - - - - - if (is_main_hot) - { - profiler->cursor_ns = (cursor_px * profiler->ns_per_px) + profiler->view_ns; - } - - - - - - - // TODO: Drag in px units for sharper resolution - if (UI_Downs(main_box, Button_M2) || UI_Downs(main_box, Button_M3)) - { - profiler->drag_view_ns = profiler->view_ns; - profiler->drag_cursor_px = cursor_px; - } - - // Drag ruler - // TODO: When measuring stopped, lerp ruler closed - b32 is_measuring = 0; - if (UI_Downs(main_box, Button_M1)) - { - profiler->snap = 0; - profiler->ruler_start_ns = profiler->cursor_ns; - } - if (UI_Held(main_box, Button_M1)) - { - profiler->snap = 0; - is_measuring = 1; - profiler->target_ruler_opacity = 1; - } - else - { - profiler->target_ruler_opacity = 0; - } - profiler->ruler_opacity = LerpF32(profiler->ruler_opacity, profiler->target_ruler_opacity, prof_lerp_rate); - - // Drag view - if (UI_Held(main_box, Button_M2) || UI_Held(main_box, Button_M3)) - { - profiler->snap = 0; - profiler->view_ns = profiler->drag_view_ns - ((cursor_px - profiler->drag_cursor_px) * profiler->ns_per_px); - profiler->target_view_ns = profiler->view_ns; - } - - - - - - - - - // FIXME: Remove this - b32 do_break = frame->real_held_buttons[Button_B] && !prev_frame->real_held_buttons[Button_B]; - - - - - - - - // FIXME: Remove this - f64 view_range_len_px = DimsFromRng2(UI_Rect(main_box)).x; - f64 view_range_len_ns = view_range_len_px * profiler->ns_per_px; - - f64 view_start_ns = profiler->view_ns; - f64 view_end_ns = view_start_ns + view_range_len_ns; - - f64 view_start_px = view_start_ns / profiler->ns_per_px; - f64 view_end_px = view_end_ns / profiler->ns_per_px; - - - - - - - - - - - - - - - - - //- Generate visible zones - - Struct(VisZone) - { - VisZone *parent; - VisZone *next; - VisZone *next_bfs; - V_Zone *zone; - - u32 depth; - u64 id; - String name; - Vec4 color; - - f64 start_px; - f64 end_px; - - i64 start_ns; - i64 end_ns; - - u64 collapsed_count; - }; - - Struct(VisTrack) - { - VisTrack *next; - u64 id; - - u32 rows_count; - VisZone *first_zone; - VisZone *last_zone; - }; - - VisTrack *first_vis_track = 0; - VisTrack *last_vis_track = 0; - f32 zone_collapse_threshold_px = 10; - f32 zone_name_hide_threshold_px = UI_Top(FontSize) * 3; - f32 min_zone_width_px = 6; - ProfZoneDF("Generate visible zones") - { - for (V_ZoneTrack *zone_track = V.first_zone_track; zone_track; zone_track = zone_track->next) - { - // TODO: Ignore non-visible tracks - // TODO: Ignore non-visible depths - - VisTrack *vis_track = PushStruct(frame->arena, VisTrack); - SllQueuePush(first_vis_track, last_vis_track, vis_track); - vis_track->id = zone_track->id; - - VisZone *first_bfs_vis_zone = 0; - VisZone *last_bfs_vis_zone = 0; - - // Push root vis zone node to bfs - { - VisZone *root_bfs = PushStruct(frame->arena, VisZone); - root_bfs->zone = zone_track->root_zone; - root_bfs->start_px = -Inf; - root_bfs->end_px = Inf; - root_bfs->start_ns = I64Min; - root_bfs->end_ns = I64Max; - root_bfs->id = zone_track->root_zone->id; - SllQueuePushN(first_bfs_vis_zone, last_bfs_vis_zone, root_bfs, next_bfs); - } - - for (VisZone *parent_vis = first_bfs_vis_zone; parent_vis; parent_vis = first_bfs_vis_zone) - { - SllQueuePopN(first_bfs_vis_zone, last_bfs_vis_zone, next_bfs); - V_Zone *parent = parent_vis->zone; - - // Process child zones - { - b32 reached_end_of_view = 0; - VisZone *left_vis = 0; - for (V_ZoneChunk *chunk = parent->first_chunk; chunk && !reached_end_of_view; chunk = chunk->next) - { - i64 chunk_start_ns = chunk->zones[0].start_ns; - i64 chunk_end_ns = MinI64(chunk->zones[chunk->count - 1].end_ns, frame->time_ns); - - // i64 should_collapse_chunk = (chunk->end_ns - chunk->start_ns) / - - if (chunk_start_ns <= view_end_ns && chunk_end_ns >= view_start_ns) - { - // TODO: Binary search to find start within chunk - for (u64 chunk_zone_idx = 0; chunk_zone_idx < chunk->count && !reached_end_of_view; ++chunk_zone_idx) - { - V_Zone *zone = &chunk->zones[chunk_zone_idx]; - if (zone->start_ns > view_end_ns) - { - reached_end_of_view = 1; - } - else - { - i64 zone_start_ns = zone->start_ns; - i64 zone_end_ns = MinI64(zone->end_ns, frame->time_ns); - i64 zone_elapsed_ns = zone_end_ns - zone_start_ns; - i64 visual_zone_start_ns = MaxI64(zone_start_ns, profiler->view_ns); - i64 visual_zone_end_ns = MinI64(zone_end_ns, profiler->view_ns + view_range_len_ns); - - f64 visual_zone_start_px = visual_zone_start_ns / profiler->ns_per_px; - f64 visual_zone_end_px = visual_zone_end_ns / profiler->ns_per_px; - - { - visual_zone_end_px = MaxF64(visual_zone_end_px, visual_zone_start_px + min_zone_width_px); - { - f32 overshoot = MaxF32(visual_zone_end_px - parent_vis->end_px, 0); - visual_zone_start_px -= overshoot; - visual_zone_end_px -= overshoot; - } - visual_zone_start_px = MaxF64(visual_zone_start_px, parent_vis->start_px); - 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 = MinF64(visual_zone_start_px, visual_zone_end_px - min_zone_width_px); - // visual_zone_start_px = MaxF64(visual_zone_start_px, parent_vis->start_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 - if (visual_zone_end_px <= (frame->time_ns / profiler->ns_per_px)) - { - b32 should_collapse_zone = (visual_zone_end_px - visual_zone_start_px) <= zone_collapse_threshold_px; - String zone_name = zone->name; - u64 zone_id = zone->id; - Vec4 zone_color = zone->color; - - // b32 should_collapse_zone = visual_zone_len_px <= zone_collapse_threshold_px; - // b32 should_collapse_zone = 0; - - // if (visual_zone_start_ns > view_end_ns) - // { - // reached_end_of_view = 1; - // } - - if (visual_zone_end_ns >= view_start_ns && visual_zone_start_ns <= view_end_ns) - { - VisZone *vis_zone = 0; - if ( - should_collapse_zone && - left_vis && - left_vis->collapsed_count > 0 && - ((zone_start_ns - left_vis->end_ns) / profiler->ns_per_px) < zone_collapse_threshold_px - ) - { - vis_zone = left_vis; - } - else - { - vis_zone = PushStruct(frame->arena, VisZone); - vis_zone->zone = zone; - vis_zone->parent = parent_vis; - vis_zone->start_ns = zone_start_ns; - vis_zone->start_px = visual_zone_start_px; - vis_zone->name = zone_name; - vis_zone->id = zone_id; - } - - SllQueuePush(vis_track->first_zone, vis_track->last_zone, vis_zone); - vis_zone->end_px = visual_zone_end_px; - vis_zone->end_ns = zone_end_ns; - vis_zone->color = zone_color; - vis_zone->depth = zone->depth; - vis_track->rows_count = MaxU32(vis_track->rows_count, vis_zone->depth); - - if (should_collapse_zone) - { - vis_zone->collapsed_count += zone->total_descendents_count + 1; - } - - left_vis = vis_zone; - - if (!should_collapse_zone) - { - SllQueuePushN(first_bfs_vis_zone, last_bfs_vis_zone, vis_zone, next_bfs); - } - } - } - } - } - } - } - } - } - } - } - - Vec4 profiler_color = theme.col.window_bg; - f32 profiler_opacity = TweakFloat("Profiler opacity", 1, 0, 1); - - Vec4 timeline_cursor_color = theme.col.window_bd; - timeline_cursor_color.a = UI_Hot(main_box) * 0.75; - UI_Size timeline_cursor_width = UI_Fnt(0.15, 1); - - UI_Key hovered_zone_box = Zi; - VisZone *hovered_zone = 0; - f64 ruler_len_ns = 0; - - Vec4 main_color_sampled = profiler_color; - main_color_sampled.r *= 0.75; - main_color_sampled.g *= 0.75; - main_color_sampled.b *= 0.75; - - Vec4 main_color_unsampled = main_color_sampled; - main_color_unsampled.r *= 0.85; - main_color_unsampled.g *= 0.85; - main_color_unsampled.b *= 0.85; - - Vec4 collapsed_line_color = SrgbFromHsv(64, 1, 0.5); - Vec4 collapsed_text_color = SrgbFromHsv(64, 1, 0.75); - - // main_color_sampled.g += 0.05; - - UI_SetNext(Parent, vis_screen_box); - UI_SetNext(BorderColor, theme.col.window_bd); - UI_SetNext(BorderSize, 2); - UI_SetNext(BackgroundColor, profiler_color); - UI_SetNext(Rounding, UI_Rpx(10 * theme.rounding)); - UI_SetNext(Height, profiler_height); - UI_SetNext(Flags, UI_BoxFlag_CaptureMouse); - UI_SetNext(Opacity, profiler_opacity); - UI_PushDF(Width, UI_Grow(1, 0)) - UI_PushDF(Parent, UI_BuildColumnEx(profiler_box)) - UI_PushDF(Parent, UI_BuildRow()) - { - UI_BuildSpacer(window_padding, Axis_X); - UI_PushDF(Parent, UI_BuildColumn()) - { - //- Header - // UI_PushDF(BackgroundColor, Color_Red) - // UI_SetNext(BorderColor, Color_Red); - // UI_SetNext(BorderSize, 1); - UI_SetNext(ChildAlignment, UI_Region_Center); - UI_PushDF(Height, header_height) - UI_PushDF(Parent, UI_BuildBoxEx(UI_KeyF("profiler header"))) - { - UI_PushDF(TextColor, theme.col.hint) - UI_BuildLabelF("Profiler"); - } - - UI_BuildSpacer(window_padding, Axis_Y); - - UI_BuildDivider(UI_Px(1, 1), theme.col.divider, Axis_Y); - - //- Graph - // UI_SetNext(BackgroundColor, Color_Cyan); - UI_SetNext(Height, graph_height); - UI_PushDF(Parent, UI_BuildBoxEx(profiler_graph_box)) - { - } - // UI_BuildDivider(UI_Px(1, 1), theme.col.divider, Axis_Y); - - UI_BuildDivider(UI_Px(1, 1), theme.col.divider, Axis_Y); - - UI_BuildSpacer(window_padding, Axis_Y); - - //- Main area - UI_SetNext(BackgroundColor, main_color_unsampled); - UI_SetNext(Height, main_height); - UI_SetNext(Rounding, UI_Rpx(5 * theme.rounding)); - // UI_SetNext(Flags, UI_BoxFlag_CaptureMouse | UI_BoxFlag_CaptureThroughChildren | UI_BoxFlag_Scissor); - UI_SetNext(Flags, UI_BoxFlag_CaptureMouse | UI_BoxFlag_CaptureThroughChildren); - // UI_SetNext(Flags, UI_BoxFlag_CaptureMouse); - UI_PushDF(Parent, UI_BuildColumnEx(main_box)) - { - //- Active area background - UI_PushDF(Opacity, 0.75) - { - f64 aabg_left_ns = MaxF64(0, profiler->view_ns); - f64 aabg_right_ns = MinF64(frame->time_ns, view_end_ns); - - f64 aabg_len_ns = aabg_right_ns - aabg_left_ns; - f64 aabg_len_px = aabg_len_ns / profiler->ns_per_px; - - f64 aabg_cursor_offset_px = (aabg_left_ns - profiler->view_ns) / profiler->ns_per_px; - f32 aabg_offset_px = (aabg_left_ns - profiler->view_ns) / profiler->ns_per_px; - Vec2 aabg_cursor_pos = VEC2(aabg_cursor_offset_px, 0); - Vec2 aabg_pos = VEC2(aabg_offset_px, 0); - UI_Size aabg_width = UI_Px(aabg_len_px, 1); - - Vec4 aabg_color = main_color_sampled; - - // Ruler rect - { - // UI_SetNext(BorderSize, 1); - // UI_SetNext(BorderColor, Color_White); - UI_SetNext(Width, aabg_width); - UI_SetNext(FloatingPos, aabg_pos); - UI_SetNext(BackgroundColor, aabg_color); - UI_SetNext(Flags, UI_BoxFlag_Floating); - UI_BuildBoxEx(UI_KeyF("active area background")); - } - } - - //- Zone tracks - ProfZoneDF("Build zones") - { - for (VisTrack *vis_track = first_vis_track; vis_track; vis_track = vis_track->next) - { - UI_SetNext(Height, track_height); - UI_PushDF(Tag, HashF("vis track %F", FmtUint(vis_track->id))) - UI_PushDF(Parent, UI_BuildColumn()) - { - //- Zone rows - 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) - { - UI_Key zone_row_box = UI_KeyF("zone row %F", FmtUint(zone_row_box_idx)); - zone_row_boxes[zone_row_box_idx] = zone_row_box; - // UI_SetNext(Height, zone_height); - UI_SetNext(Height, zone_height); - UI_PushDF(Parent, UI_BuildRowEx(zone_row_box)) - { - } - } - - //- Zones - for (VisZone *zone = vis_track->first_zone; zone; zone = zone->next) - { - UI_Key zone_row_box = zone_row_boxes[zone->depth - 1]; - b32 can_hover = !profiler->snap; - - UI_Key zone_box = UI_KeyF("Zone %F", FmtUint(zone->id)); - b32 is_hovered = can_hover && UI_HoveredAbsolute(zone_box) && UI_HotAbsolute(main_box); - if (is_hovered) - { - hovered_zone_box = zone_box; - hovered_zone = zone; - } - f32 zone_hovered = can_hover * UI_Hovered(zone_box) * UI_Hot(main_box); - - f64 zone_offset_px = zone->start_px - view_start_px; - f64 zone_len_px = zone->end_px - zone->start_px; - - Vec2 zone_pos = VEC2(zone_offset_px, 0); - UI_Size zone_width = UI_Px(zone_len_px, 1); - - Vec4 zone_color = zone->color; - Vec4 zone_color_bd = zone_color; - - zone_color_bd = MulVec4(zone_color_bd, 0.65); - zone_color_bd.a = 1; - - Vec4 zone_text_color = UI_Top(TextColor); - zone_text_color.a *= 0.75; - - Vec4 zone_line_color = Zi; - - // b32 is_collapsed = zone->is_collapsed; - b32 is_collapsed = zone->collapsed_count > 0; - // b32 is_collapsed = zone->collapsed_count > 0 || zone_len_px <= min_zone_width_px; - - // UI_Size collapsed_line_size = UI_Px(2, 1); - UI_Size collapsed_line_size = UI_Px(1.5, 1); - // Vec4 collapsed_text_color = theme.col.positive; - // Vec4 collapsed_line_color = theme.col.negative; - // Vec4 collapsed_line_color = SrgbFromHsv(TweakFloat("RAAAAAAAAAH H", 100, 0, 360), TweakFloat("RAAAAAAAAAH S", 0.50, 0, 1), TweakFloat("RAAAAAAAAAH V", 1.00, 0, 1)); - // Vec4 collapsed_line_color = Color_Black; - // Vec4 collapsed_line_color = theme.col.hint; - // Vec4 collapsed_text_color = theme.col.positive; - // Vec4 collapsed_text_color = SrgbFromHsv(TweakFloat("RAAAAAAAAAH H", 100, 0, 360), TweakFloat("RAAAAAAAAAH S", 0.50, 0, 1), TweakFloat("RAAAAAAAAAH V", 1.00, 0, 1)); - - // Vec4 collapsed_line_color = SrgbFromHsv(32, 1, 0.5); - // Vec4 collapsed_text_color = SrgbFromHsv(32, 1, 1); - - // Vec4 collapsed_line_color = SrgbFromHsv(64, 1, 0.5); - // Vec4 collapsed_text_color = SrgbFromHsv(64, 1, 0.75); - - // collapsed_text_color = LerpSrgb(collapsed_text_color, Color_White, zone_hovered); - // collapsed_line_color = LerpSrgb(collapsed_line_color, Color_White, zone_hovered); - - - - - - String zone_text = zone->name; - if (is_collapsed) - { - zone_text = StringF(frame->arena, "%F", FmtUint(zone->collapsed_count)); - zone_text_color = collapsed_text_color; - zone_line_color = collapsed_line_color; - - // zone_color = VEC4(0, 0, 0, 0); - // zone_color = VEC4(1, 0, 1, 1); - // zone_color = VEC4(0.15, 0.15, 0.15, 0.5); - // zone_color = VEC4(0.20, 0.20, 0.20, 0.5); - - - zone_color = VEC4(0.25, 0.25, 0.25, 0.5); - - - // if (zone->collapsed_count > 1) - // { - // zone_color = VEC4(0.25, 0.25, 0.25, 0.5); - // } - // else - // { - // zone_color = Color_White; - // } - - - - // zone_color = VEC4(0.4, 0.4, 0.4, 0.5); - zone_color_bd = VEC4(0, 0, 0, 0); - - // zone_color = LerpSrgb(zone_color, Color_Transparent, zone_hovered); - - } - - if (zone_len_px < zone_name_hide_threshold_px) - { - zone_text.len = 0; - } - - zone_color_bd = LerpSrgb(zone_color_bd, Color_White, zone_hovered * !is_collapsed); - zone_text_color = LerpSrgb(zone_text_color, Color_White, zone_hovered); - zone_line_color = LerpSrgb(zone_line_color, Color_White, zone_hovered); - - - f32 collapsed_zones_per_px = zone->collapsed_count / zone_len_px; - // f32 zag_intensity = 50 / collapsed_zones_per_px; - // zag_intensity = MaxF32(zag_intensity, 5); - - // f32 top_zag_information_density = 10; - f32 top_zag_information_density = zone_collapse_threshold_px; - // f32 zag_intensity = SmoothstepF32(0, top_zag_information_density, collapsed_zones_per_px); - // f32 zag_intensity = 1; - f32 zag_intensity = 0.3; - // f32 zag_intensity = TweakFloat("RAAAAAAAAAAAAAH", 1, 0, 1); - - f32 period_max = 20; - f32 period_min = 5; - f32 zag_period = LerpF32(period_max, period_min, zag_intensity); - - f32 amplitude_max = UI_Top(FontSize) * 0.15; - f32 amplitude_min = UI_Top(FontSize) * 0.05; - f32 zag_amplitude = LerpF32(amplitude_max, amplitude_min, zag_intensity); - - UI_SetNext(Width, zone_width); - UI_SetNext(Height, UI_Grow(1, 0)); - UI_SetNext(BackgroundColor, zone_color); - UI_SetNext(BorderColor, zone_color_bd); - UI_SetNext(BorderSize, 1); - UI_SetNext(FloatingPos, zone_pos); - UI_SetNext(ChildAlignment, UI_Region_Center); - UI_SetNext( - Flags, - UI_BoxFlag_Floating | - UI_BoxFlag_DontClampFloatingX | - UI_BoxFlag_DontClampFloatingY | - UI_BoxFlag_CaptureMouse | - UI_BoxFlag_Scissor - ); - UI_SetNext(Parent, zone_row_box); - // UI_PushDF(OrFlags, UI_Top(OrFlags) | (UI_BoxFlag_DontTruncateText * !!(is_collapsed))) - // UI_PushDF(OmitFlags, UI_Top(OmitFlags) | (UI_BoxFlag_Scissor * !!(is_collapsed))) - // UI_PushDF(ZagPeriod, UI_Top(FontSize) * 1) - // UI_PushDF(ZagPeriod, (collapsed_zones_per_px * UI_Top(FontSize)) * 0.1) - // UI_PushDF(ZagPeriod, collapsed_zones_per_px / (UI_Top(FontSize) * 1)) - UI_PushDF(ZagPeriod, zag_period) - UI_PushDF(ZagThickness, 1.5) - UI_PushDF(ZagRoundness, 1) - UI_PushDF(ZagAmplitude, zag_amplitude) - UI_PushDF(Parent, UI_BuildRowEx(zone_box)) - { - if (is_collapsed) - { - // Left zag - UI_SetNext(Width, UI_Grow(1, 0)); - UI_SetNext(ZagColor, zone_line_color); - UI_BuildBox(); - } - else - { - UI_SetNext(Width, UI_Px(3, 1)); - UI_BuildBox(); - } - - if (zone_text.len > 0) - { - // Zone name - // if (zone_len_px > zone_collapse_threshold_px * 3) - { - if (is_collapsed) - { - UI_SetNext(Width, UI_Shrink(0, 1)); - UI_SetNext(ChildAlignment, UI_Region_Center); - } - else - { - UI_SetNext(ChildAlignment, UI_Region_Left); - UI_SetNext(Width, UI_Grow(1, 0)); - } - UI_SetNext(FontSize, UI_Top(FontSize) * theme.h5); - UI_SetNext(TextColor, zone_text_color); - UI_SetNext(Text, zone_text); - UI_SetNext(Flags, UI_BoxFlag_DrawText | UI_BoxFlag_DontTruncateText); - UI_BuildRow(); - } - - // Right collapsed lines - if (is_collapsed) - { - // Right zag - { - UI_SetNext(Width, UI_Grow(1, 0)); - UI_SetNext(ZagColor, zone_line_color); - UI_BuildBox(); - } - } - } - } - } - } - } - } - - - - - - //- Ruler - UI_PushDF(Opacity, profiler->ruler_opacity) - { - { - f64 ruler_left_ns = MinF64(profiler->ruler_start_ns, profiler->cursor_ns); - f64 ruler_right_ns = MaxF64(profiler->ruler_start_ns, profiler->cursor_ns); - ruler_left_ns = ClampF64(ruler_left_ns, view_start_ns, view_end_ns); - ruler_right_ns = ClampF64(ruler_right_ns, view_start_ns, view_end_ns); - - ruler_len_ns = ruler_right_ns - ruler_left_ns; - f64 ruler_len_px = ruler_len_ns / profiler->ns_per_px; - - f64 ruler_cursor_offset_px = (profiler->ruler_start_ns - profiler->view_ns) / profiler->ns_per_px; - f32 ruler_offset_px = (ruler_left_ns - profiler->view_ns) / profiler->ns_per_px; - Vec2 ruler_cursor_pos = VEC2(ruler_cursor_offset_px, 0); - Vec2 ruler_pos = VEC2(ruler_offset_px, 0); - UI_Size ruler_width = UI_Px(ruler_len_px, 1); - - // Vec4 ruler_color = VEC4(0.25, 0.25, 0.25, 0.25); - Vec4 ruler_color = VEC4(0.20, 0.20, 0.20, 0.25); - - // Ruler rect - { - // UI_SetNext(BorderSize, 1); - // UI_SetNext(BorderColor, Color_White); - // UI_PushDF(Opacity, profiler->ruler_opacity) - UI_SetNext(Width, ruler_width); - UI_SetNext(FloatingPos, ruler_pos); - UI_SetNext(BackgroundColor, ruler_color); - UI_SetNext(Flags, UI_BoxFlag_Floating); - UI_BuildBoxEx(UI_KeyF("ruler")); - } - - // Ruler cursor - { - // UI_SetNext(BorderSize, 1); - // UI_SetNext(BorderColor, Color_White); - UI_SetNext(BackgroundColor, timeline_cursor_color); - UI_SetNext(Width, timeline_cursor_width); - UI_SetNext(FloatingPos, ruler_cursor_pos); - UI_SetNext(Anchor, UI_Region_Top); - UI_SetNext(Flags, UI_BoxFlag_Floating); - UI_BuildBoxEx(UI_KeyF("ruler cursor")); - } - } - } - - //- Timeline cursor - { - // Vec2 timeline_cursor_pos = VEC2(old_cursor_offset_px, 0); - Vec2 timeline_cursor_pos = VEC2((profiler->cursor_ns - profiler->view_ns) / profiler->ns_per_px, 0); - - UI_SetNext(Width, timeline_cursor_width); - UI_SetNext(Height, UI_Grow(1, 0)); - UI_SetNext(BackgroundColor, timeline_cursor_color); - UI_SetNext(FloatingPos, timeline_cursor_pos); - UI_SetNext(Flags, UI_BoxFlag_Floating); - UI_BuildBox(); - } - - //- Timeline tooltop - { - b32 show_ruler_time = is_measuring && ruler_len_ns != 0; - b32 show_hovered_zone = hovered_zone != 0; - if (show_ruler_time || show_hovered_zone) - { - UI_Key tooltip_box = UI_KeyF("tooltip"); - Vec2 tooltip_pos = SubVec2(frame->screen_cursor, UI_Anchor(main_box)); - tooltip_pos = AddVec2(tooltip_pos, theme.tooltip_offset_px); - f32 tooltip_opacity = 0.95; - - UI_SetNext(Opacity, tooltip_opacity); - UI_SetNext(BackgroundColor, theme.col.window_bg); - UI_SetNext(BorderColor, theme.col.window_bd); - UI_SetNext(Rounding, UI_Rpx(theme.rounding * 5)); - UI_SetNext(BorderSize, 1); - UI_SetNext(Anchor, UI_Region_TopLeft); - UI_SetNext(FloatingPos, tooltip_pos); - UI_SetNext(Flags, UI_BoxFlag_Floating); - UI_PushDF(Width, UI_Shrink(0, 1)) - UI_PushDF(Height, UI_Shrink(0, 1)) - UI_PushDF(Parent, UI_BuildRowEx(tooltip_box)) - { - UI_BuildSpacer(window_padding, Axis_X); - - UI_SetNext(Width, UI_Shrink(0, 1)); - UI_SetNext(Height, UI_Shrink(0, 1)); - UI_PushDF(Parent, UI_BuildColumn()) - { - UI_BuildSpacer(window_padding, Axis_Y); - - if (show_ruler_time) - { - // UI_SetNext(TextColor, theme.col.positive); - // UI_SetNext(TextColor, theme.col.button_active); - - UI_SetNext(TextColor, theme.col.button_selected); - UI_BuildLabelF("%F", FmtTimeNs(ruler_len_ns, .p = 2)); - - // UI_SetNext(TextColor, theme.col.button_selected); - // UI_BuildLabelF("Ruler"); - - if (show_hovered_zone) - { - UI_BuildSpacer(minor_padding, Axis_Y); - UI_BuildSpacer(minor_padding, Axis_Y); - UI_BuildDivider(UI_Px(1, 0), theme.col.divider, Axis_Y); - UI_BuildSpacer(minor_padding, Axis_Y); - } - } - - if (show_hovered_zone) - { - VisZone *zone = hovered_zone; - UI_PushDF(Parent, UI_BuildRow()) - { - i64 elapsed_ns = zone->end_ns - zone->start_ns; - UI_PushDF(Parent, UI_BuildColumn()) - { - UI_BuildLabelF("%F ", FmtTimeNs(elapsed_ns, .p = 2)); - - if (zone->collapsed_count > 0) - { - UI_PushDF(Parent, UI_BuildRow()) - { - if (zone->collapsed_count == 1) - { - // // UI_BuildLabelF(" (%F)", FmtUint(zone->collapsed_count)); - // UI_SetNext(TextColor, theme.col.hint); - // UI_BuildLabelF("%F", FmtString(zone->name)); - - // UI_SetNext(TextColor, collapsed_text_color); - // UI_BuildLabelF(" (Too small to display)"); - - UI_SetNext(TextColor, collapsed_text_color); - UI_BuildLabelF("1 zone too small to display: "); - UI_SetNext(TextColor, theme.col.hint); - UI_BuildLabelF("%F", FmtString(zone->name)); - } - else - { - // UI_SetNext(TextColor, theme.col.hint); - // UI_BuildLabelF("Zones too small to display"); - - // UI_SetNext(TextColor, collapsed_text_color); - // UI_BuildLabelF(" (%F)", FmtUint(zone->collapsed_count)); - - - // UI_SetNext(TextColor, theme.col.hint); - UI_SetNext(TextColor, collapsed_text_color); - UI_BuildLabelF("%F zones too small to display", FmtUint(zone->collapsed_count)); - } - } - } - else - { - UI_SetNext(TextColor, theme.col.hint); - UI_BuildLabelF("%F", FmtString(zone->name)); - } - } - } - } - - UI_BuildSpacer(window_padding, Axis_Y); - } - UI_BuildSpacer(window_padding, Axis_X); - } - } - } - } - - // UI_BuildSpacer(window_padding, Axis_Y); - - //- Footer - UI_PushDF(Height, footer_height) - UI_PushDF(ChildAlignment, UI_Region_Center) - UI_PushDF(Parent, UI_BuildRow()) - { - if (IsUnoptimized) - { - UI_PushDF(Width, UI_Shrink(0, 1)) - UI_PushDF(Height, UI_Shrink(0, 1)) - UI_PushDF(ChildAlignment, UI_Region_Left) - UI_PushDF(TextColor, theme.col.warn) - UI_PushDF(Parent, UI_BuildRow()) - { - UI_BuildIcon(theme.icon_font, UI_Icon_Warning); - // UI_BuildIcon(theme.icon_font, UI_Icon_Info); - UI_BuildLabelF(" Profiling an unoptimized build"); - } - } - - // Right side text - UI_BuildSpacer(UI_Grow(1, 0), Axis_X); - UI_SetNext(Opacity, UI_Hot(main_box)); - UI_BuildLabelF("%Fs", FmtFloat(SecondsFromNs(profiler->cursor_ns), .p = 3)); - } - } - UI_BuildSpacer(window_padding, Axis_X); - } - } - } @@ -8701,11 +8791,11 @@ void V_TickForever(WaveLaneCtx *lane) case V_CmdKind_toggle_profiler: { - frame->profiler.is_showing = !frame->profiler.is_showing; - if (frame->profiler.is_showing) - { - frame->profiler.snap = 1; - } + // frame->profiler.is_showing = !frame->profiler.is_showing; + // if (frame->profiler.is_showing) + // { + // frame->profiler.snap = 1; + // } } break; case V_CmdKind_toggle_timeline: @@ -8844,7 +8934,7 @@ void V_TickForever(WaveLaneCtx *lane) Rng3 screen_viewport = RNG3(VEC3(0, 0, 0), VEC3(frame->screen_dims.x, frame->screen_dims.y, 1)); Rng2 screen_scissor = RNG2(VEC2(screen_viewport.p0.x, screen_viewport.p0.y), VEC2(screen_viewport.p1.x, screen_viewport.p1.y)); - b32 should_draw_profiler_graph = profiler->is_showing && profiler->graph_dims.x > 0 && profiler->graph_dims.y > 0; + ProfZoneDF("Build GPU cmds") { ////////////////////////////// @@ -8904,25 +8994,20 @@ void V_TickForever(WaveLaneCtx *lane) ); // Profiler graph - // FIXME: Limit dims based on sample buffer capacity - frame->profiler_graph_dims = profiler->graph_dims; - frame->profiler_frame_seq = V.profiler_frame_seq; - - if (should_draw_profiler_graph) - { - frame->profiler_graph = G_PushTexture2D( - cl, gpu_frame_arena, - G_TextureLayout_Family, - G_Format_R16G16B16A16_Float, - profiler->graph_dims, - .flags = G_MemoryFlag_AllowTextureRW, - .name = StringF(frame->arena, "Profiler graph [%F]", FmtSint(frame->tick)) - ); - { - Rng2 uv = RNG2(VEC2(0, 0), VEC2(1, 1)); - UI_SetRawTexture(profiler_graph_box, frame->profiler_graph, uv); - } - } + // if (should_draw_profiler_graph) + // { + // frame->profiler_graph = G_PushTexture2D( + // cl, gpu_frame_arena, + // G_TextureLayout_Family, + // G_Format_R16G16B16A16_Float, + // .flags = G_MemoryFlag_AllowTextureRW, + // .name = StringF(frame->arena, "Profiler graph [%F]", FmtSint(frame->tick)) + // ); + // { + // Rng2 uv = RNG2(VEC2(0, 0), VEC2(1, 1)); + // UI_SetRawTexture(profiler_graph_box, frame->profiler_graph, uv); + // } + // } // Albedo texture frame->albedo = G_PushTexture2D( diff --git a/src/pp/pp_vis/pp_vis_core.h b/src/pp/pp_vis/pp_vis_core.h index 06bf6fc6..eee405ea 100644 --- a/src/pp/pp_vis/pp_vis_core.h +++ b/src/pp/pp_vis/pp_vis_core.h @@ -288,9 +288,8 @@ Struct(V_ZoneTrack) Struct(V_Profiler) { - Vec2 graph_dims; b32 is_showing; - b32 snap; + b32 unsnap; f64 target_view_ns; f64 view_ns; @@ -310,92 +309,44 @@ Struct(V_Profiler) f64 drag_cursor_px; }; +//////////////////////////////////////////////////////////// +//~ Panel types +Enum(V_PanelFlag) +{ + V_PanelFlag_None = 0, + V_PanelFlag_Spawn = (1 << 0), + V_PanelFlag_Profiler = (1 << 1), +}; +Struct(V_Panel) +{ + V_Panel *parent; + V_Panel *next; + V_Panel *prev; + V_Panel *first; + V_Panel *last; + //- Panel layout + Axis axis; + UI_Key box; + UI_Key contents_box; + UI_Key resizer_box; + f32 pct; + f32 drag_resize_pct; + f32 drag_resize_pct_per_px; + b32 is_organizational; + //- Panel contents - - - - - - - - -// //////////////////////////////////////////////////////////// -// //~ Window types - - - - - - - -// // TODO: Remove this - - - - -// // TODO: Move boolean fields into bitwise property flags - -// Struct(V_Panel) -// { -// V_Panel *parent; -// V_Panel *next; -// V_Panel *prev; -// V_Panel *first; -// V_Panel *last; -// i64 count; - -// UI_Key key; -// UI_Key divider_key; - -// f32 pref_ratio; -// b32 resizing; - -// Axis axis; - -// b32 is_organizing_panel; -// b32 is_vis_ui_panel; -// b32 is_editor_panel; - -// i64 active_window_idx; -// i64 windows_count; -// struct V_Window *first_window; -// struct V_Window *last_window; -// }; - -// Struct(V_Window) -// { -// V_Panel *panel; -// V_Window *next_in_panel; -// V_Window *prev_in_panel; - -// UI_Key key; - -// b32 is_tile_window; -// b32 is_prefab_window; -// }; - - - - - - - - - - - - - - + V_PanelFlag flags; + V_Profiler profiler; +}; //////////////////////////////////////////////////////////// //~ Draw types @@ -466,7 +417,6 @@ Struct(V_Frame) Button held_buttons[Button_COUNT]; // User input state captured for gameplay Button real_held_buttons[Button_COUNT]; // Actual state of user input regardless of keyboard / mouse focus V_Palette palette; - V_Profiler profiler; UI_Key text_input_focus; @@ -505,10 +455,7 @@ Struct(V_Ctx) - // i64 panels_count; - // i64 windows_count; - // V_Panel *root_panel; - // V_Window *dragging_window; + V_Panel *root_panel; @@ -532,6 +479,7 @@ Struct(V_Ctx) Atomic32 shutdown; Fence shutdown_complete; + Vec2 profiler_graph_dims; u64 profiler_frame_seq; V_ProfilerFrame *profiler_frames; diff --git a/src/ui/ui_core.c b/src/ui/ui_core.c index fb818c55..21aa496c 100644 --- a/src/ui/ui_core.c +++ b/src/ui/ui_core.c @@ -822,8 +822,8 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags) } if (box->desc.flags & UI_BoxFlag_CaptureThroughChildren) { - box->mouse_hovered = box->child_mouse_hovered || box->mouse_captured; - box->mouse_captured = box->child_mouse_captured || box->mouse_hovered; + box->mouse_hovered = box->child_mouse_hovered || box->mouse_hovered; + box->mouse_captured = box->child_mouse_captured || box->mouse_captured; } feedback->active_absolute = box->mouse_captured; diff --git a/src/ui/ui_core.h b/src/ui/ui_core.h index 5356cffb..f9691c7e 100644 --- a/src/ui/ui_core.h +++ b/src/ui/ui_core.h @@ -102,16 +102,19 @@ Enum(UI_BoxFlag) Enum(UI_DebugBreakFlag) { UI_DebugBreakFlag_None = 0, - UI_DebugBreakFlag_CheckCursorHover = (1 << 0), - UI_DebugBreakFlag_BuildFeedback = (1 << 1), - UI_DebugBreakFlag_PrepLayout = (1 << 2), - UI_DebugBreakFlag_IndependentSolve = (1 << 3), - UI_DebugBreakFlag_UpwardsDependentSolveLayoutAxis = (1 << 4), - UI_DebugBreakFlag_DownwardsDependentSolve = (1 << 5), - UI_DebugBreakFlag_UpwardsDependentSolveNonLayoutAxis = (1 << 6), - UI_DebugBreakFlag_SolveViolations = (1 << 7), - UI_DebugBreakFlag_FinalSolve = (1 << 8), - UI_DebugBreakFlag_BuildGpuData = (1 << 9), + + UI_DebugBreakFlag_Misc = (1 << 0), + + UI_DebugBreakFlag_CheckCursorHover = (1 << 1), + UI_DebugBreakFlag_BuildFeedback = (1 << 2), + UI_DebugBreakFlag_PrepLayout = (1 << 3), + UI_DebugBreakFlag_IndependentSolve = (1 << 4), + UI_DebugBreakFlag_UpwardsDependentSolveLayoutAxis = (1 << 5), + UI_DebugBreakFlag_DownwardsDependentSolve = (1 << 6), + UI_DebugBreakFlag_UpwardsDependentSolveNonLayoutAxis = (1 << 7), + UI_DebugBreakFlag_SolveViolations = (1 << 8), + UI_DebugBreakFlag_FinalSolve = (1 << 9), + UI_DebugBreakFlag_BuildGpuData = (1 << 10), UI_DebugBreakFlag_All = 0xFFFFFFFF };