24#include <tess/diagnostics/diagnostics.h>
26#if defined(TESS_ENABLE_IMGUI) && TESS_DIAGNOSTICS_ENABLED
29#error "tess/debug/imgui/panels.h requires <imgui.h> to be included first"
32#include <tess/diagnostics/export.h>
33#include <tess/diagnostics/trace.h>
38namespace tess::debug::imgui {
41[[nodiscard]]
inline auto to_ull(std::uint64_t value)
noexcept
42 ->
unsigned long long {
43 return static_cast<unsigned long long>(value);
48[[nodiscard]]
inline auto category_name(
49 diagnostics::TraceCategory category)
noexcept ->
const char* {
51 case diagnostics::TraceCategory::General:
53 case diagnostics::TraceCategory::Path:
55 case diagnostics::TraceCategory::Topology:
57 case diagnostics::TraceCategory::Queued:
59 case diagnostics::TraceCategory::Planner:
61 case diagnostics::TraceCategory::Scheduler:
63 case diagnostics::TraceCategory::Render:
65 case diagnostics::TraceCategory::Count:
72inline void draw_timing_panel(
const diagnostics::TimingSnapshot& timing) {
73 ImGui::TextUnformatted(
"Timing (ns)");
75 for (std::size_t index = 0; index < diagnostics::trace_category_count;
77 const auto category =
static_cast<diagnostics::TraceCategory
>(index);
78 const auto& stats = timing.category(category);
80 stats.samples == 0 ? std::uint64_t{0} : stats.total_ns / stats.samples;
81 ImGui::Text(
"%-10s n=%llu total=%llu avg=%llu min=%llu max=%llu",
82 category_name(category), detail::to_ull(stats.samples),
83 detail::to_ull(stats.total_ns), detail::to_ull(average),
84 detail::to_ull(stats.min_ns), detail::to_ull(stats.max_ns));
89inline void draw_path_counters_panel(
const diagnostics::PathCounters& path) {
90 ImGui::TextUnformatted(
"Path counters");
92 ImGui::Text(
"heap push / pop: %llu / %llu", detail::to_ull(path.heap_pushes),
93 detail::to_ull(path.heap_pops));
94 ImGui::Text(
"relax ok / attempts: %llu / %llu",
95 detail::to_ull(path.relax_successes),
96 detail::to_ull(path.relax_attempts));
97 ImGui::Text(
"touched nodes: %llu", detail::to_ull(path.touched_nodes));
98 ImGui::Text(
"passability checks: %llu",
99 detail::to_ull(path.passability_checks));
103inline void draw_queued_counters_panel(
104 const diagnostics::QueuedPhaseCounters& queued) {
105 ImGui::TextUnformatted(
"Queued phase counters");
107 ImGui::Text(
"phase calls / ops: %llu / %llu",
108 detail::to_ull(queued.phase_calls),
109 detail::to_ull(queued.phase_operations));
110 ImGui::Text(
"failures: %llu", detail::to_ull(queued.phase_failures));
111 ImGui::Text(
"dirty merged: %llu", detail::to_ull(queued.dirty_chunks_merged));
115inline void draw_allocation_counters_panel(
116 const diagnostics::AllocationCounters& allocation) {
117 ImGui::TextUnformatted(
"Allocation counters");
119 ImGui::Text(
"alloc: %llu (%llu bytes)",
120 detail::to_ull(allocation.allocations),
121 detail::to_ull(allocation.allocation_bytes));
122 ImGui::Text(
"free: %llu (%llu bytes)",
123 detail::to_ull(allocation.deallocations),
124 detail::to_ull(allocation.deallocation_bytes));
128inline void draw_diagnostics_panel(
129 const diagnostics::DiagnosticsSnapshot& snapshot) {
130 draw_timing_panel(snapshot.timing);
132 draw_path_counters_panel(snapshot.path);
134 draw_queued_counters_panel(snapshot.queued);
136 draw_allocation_counters_panel(snapshot.allocation);