Skip to content

Commit

Permalink
debug: Add stats plot tooltip (#1040)
Browse files Browse the repository at this point in the history
* debug: Fix plot alignment

* debug: Initialize plot to the first added value

* ui: Handle empty tooltip text

* ui: Fix typo

* asset: Fix inconsistent f32 type usage

* debug: Add plot tooltip
  • Loading branch information
BastianBlokland authored Sep 19, 2024
1 parent cf03a3d commit 576f640
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 20 deletions.
2 changes: 1 addition & 1 deletion libs/asset/src/loader_texture_array.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ typedef struct {

static CubePoint arraytex_cube_lookup(const GeoVector dir) {
CubePoint res;
float scale;
f32 scale;
const GeoVector dirAbs = geo_vector_abs(dir);
if (dirAbs.z >= dirAbs.x && dirAbs.z >= dirAbs.y) {
res.face = dir.z < 0.0f ? 5 : 4;
Expand Down
92 changes: 76 additions & 16 deletions libs/debug/src/stats.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,9 @@ typedef enum {
} DebugBgFlags;

typedef struct {
f32 values[stats_plot_size];
u32 cur;
ALIGNAS(16) f32 values[stats_plot_size];
u32 cur;
bool initialized;
} DebugStatPlot;

typedef struct {
Expand Down Expand Up @@ -138,7 +139,25 @@ static DebugStatPlot* debug_plot_alloc(Allocator* alloc) {
return plot;
}

static void debug_plot_set(DebugStatPlot* plot, const f32 value) {
#ifdef VOLO_SIMD
ASSERT((stats_plot_size % 4) == 0, "Only multiple of 4 plot sizes are supported");
const SimdVec valueVec = simd_vec_broadcast(value);
for (u32 i = 0; i != stats_plot_size; i += 4) {
simd_vec_store(valueVec, plot->values + i);
}
#else
for (u32 i = 0; i != stats_plot_size; ++i) {
plot->values[i] = value;
}
#endif
}

static void debug_plot_add(DebugStatPlot* plot, const f32 value) {
if (UNLIKELY(!plot->initialized)) {
debug_plot_set(plot, value);
plot->initialized = true;
}
plot->values[plot->cur] = value;
plot->cur = (plot->cur + 1) % stats_plot_size;
}
Expand All @@ -147,10 +166,14 @@ static void debug_plot_add_dur(DebugStatPlot* plot, const TimeDuration value) {
debug_plot_add(plot, (f32)(value / (f64)time_microsecond));
}

static f32 debug_plot_newest(const DebugStatPlot* plot) {
const u32 newestIndex = (plot->cur + stats_plot_size - 1) % stats_plot_size;
return plot->values[newestIndex];
}

static f32 debug_plot_min(const DebugStatPlot* plot) {
#ifdef VOLO_SIMD
ASSERT((stats_plot_size % 4) == 0, "Only multiple of 4 plot sizes are supported");

SimdVec min = simd_vec_broadcast(plot->values[0]);
for (u32 i = 0; i != stats_plot_size; i += 4) {
min = simd_vec_min(min, simd_vec_min_comp(simd_vec_load(plot->values + i)));
Expand All @@ -170,7 +193,6 @@ static f32 debug_plot_min(const DebugStatPlot* plot) {
static f32 debug_plot_max(const DebugStatPlot* plot) {
#ifdef VOLO_SIMD
ASSERT((stats_plot_size % 4) == 0, "Only multiple of 4 plot sizes are supported");

SimdVec max = simd_vec_broadcast(plot->values[0]);
for (u32 i = 0; i != stats_plot_size; i += 4) {
max = simd_vec_max(max, simd_vec_max_comp(simd_vec_load(plot->values + i)));
Expand All @@ -194,7 +216,6 @@ static f32 debug_plot_var(const DebugStatPlot* plot) {
static f32 debug_plot_sum(const DebugStatPlot* plot) {
#ifdef VOLO_SIMD
ASSERT((stats_plot_size % 4) == 0, "Only multiple of 4 plot sizes are supported");

SimdVec accum = simd_vec_zero();
for (u32 i = 0; i != stats_plot_size; i += 4) {
accum = simd_vec_add(accum, simd_vec_add_comp(simd_vec_load(plot->values + i)));
Expand Down Expand Up @@ -301,8 +322,39 @@ static bool stats_draw_section(UiCanvasComp* c, const String label) {
return isOpen;
}

static void
stats_draw_plot(UiCanvasComp* c, const DebugStatPlot* plot, const f32 minVal, const f32 maxVal) {
typedef void (*PlotValueWriter)(DynString*, f32 value);

static void stats_draw_plot_tooltip(
UiCanvasComp* c, const DebugStatPlot* plot, const PlotValueWriter valWriter) {
Mem bufferMem = alloc_alloc(g_allocScratch, usize_kibibyte, 1);
DynString buffer = dynstring_create_over(bufferMem);

#define APPEND_PLOT_VAL(_TITLE_, _FUNC_) \
do { \
dynstring_append(&buffer, string_lit("\a.b" _TITLE_ "\ar:\a>09")); \
valWriter(&buffer, _FUNC_(plot)); \
dynstring_append_char(&buffer, '\n'); \
} while (false)

if (plot->initialized) {
APPEND_PLOT_VAL("Newest", debug_plot_newest);
APPEND_PLOT_VAL("Average", debug_plot_avg);
APPEND_PLOT_VAL("Min", debug_plot_min);
APPEND_PLOT_VAL("Max", debug_plot_max);
APPEND_PLOT_VAL("Variance", debug_plot_var);
}

const UiId id = ui_canvas_id_peek(c);
ui_canvas_draw_glyph(c, UiShape_Empty, 0, UiFlags_Interactable); // Invisible rect.
ui_tooltip(c, id, dynstring_view(&buffer), .variation = UiVariation_Monospace);
}

static void stats_draw_plot(
UiCanvasComp* c,
const DebugStatPlot* plot,
const f32 minVal,
const f32 maxVal,
const PlotValueWriter valWriter) {
static const f32 g_stepX = 1.0f / stats_plot_size;
static const f32 g_statRows = 2.0f; // Amount of rows the plot takes up.

Expand Down Expand Up @@ -343,17 +395,25 @@ stats_draw_plot(UiCanvasComp* c, const DebugStatPlot* plot, const f32 minVal, co
ui_canvas_draw_glyph(c, UiShape_Square, 0, UiFlags_None);
}

ui_layout_inner(c, UiBase_Container, UiAlign_BottomLeft, ui_vector(1, 1), UiBase_Container);
stats_draw_plot_tooltip(c, plot, valWriter);

ui_style_pop(c);
ui_layout_container_pop(c);
ui_layout_pop(c);
ui_layout_move_dir(c, Ui_Down, g_statRows, UiBase_Current);
}

static void stats_dur_val_writer(DynString* str, const f32 value) {
const TimeDuration valueDur = (TimeDuration)(value * (f64)time_microsecond);
fmt_write(str, "{>8}", fmt_duration(valueDur, .minDecDigits = 1, .maxDecDigits = 1));
}

static void stats_draw_plot_dur(
UiCanvasComp* c, const DebugStatPlot* plot, const TimeDuration min, const TimeDuration max) {
const f32 minUs = (f32)(min / (f64)time_microsecond);
const f32 maxUs = (f32)(max / (f64)time_microsecond);
stats_draw_plot(c, plot, minUs, maxUs);
stats_draw_plot(c, plot, minUs, maxUs, stats_dur_val_writer);
}

static void stats_draw_frametime(UiCanvasComp* c, const DebugStatsComp* stats) {
Expand Down Expand Up @@ -449,11 +509,11 @@ stats_draw_cpu_chart(UiCanvasComp* c, const DebugStatsComp* st, const RendStatsC
{st->rendLimiterFrac, ui_color(128, 128, 128, 64)},
};
const String tooltip = fmt_write_scratch(
"\a~red\a.bWait for gpu\ar:\a>12{>8}\n"
"\a~purple\a.bPresent acquire\ar:\a>12{>8}\n"
"\a~blue\a.bPresent enqueue\ar:\a>12{>8}\n"
"\a~teal\a.bPresent wait\ar:\a>12{>8}\n"
"\a.bLimiter\ar:\a>12{>8}",
"\a~red\a.bWait for gpu\ar:\a>10{>8}\n"
"\a~purple\a.bPresent acquire\ar:\a>10{>8}\n"
"\a~blue\a.bPresent enqueue\ar:\a>10{>8}\n"
"\a~teal\a.bPresent wait\ar:\a>10{>8}\n"
"\a.bLimiter\ar:\a>10{>8}",
fmt_duration(rendSt->waitForGpuDur, .minDecDigits = 1, .maxDecDigits = 1),
fmt_duration(rendSt->presentAcquireDur, .minDecDigits = 1, .maxDecDigits = 1),
fmt_duration(rendSt->presentEnqueueDur, .minDecDigits = 1, .maxDecDigits = 1),
Expand Down Expand Up @@ -497,7 +557,7 @@ stats_draw_gpu_chart(UiCanvasComp* c, const DebugStatsComp* st, const RendStatsC

fmt_write(
&tooltip,
"{}\a.b{}\ar:\a>13{>7}\n",
"{}\a.b{}\ar:\a>0A{>7}\n",
fmt_ui_color(passColor),
fmt_text(passName),
fmt_duration(passDuration, .minDecDigits = 1, .maxDecDigits = 1));
Expand All @@ -512,8 +572,8 @@ stats_draw_gpu_chart(UiCanvasComp* c, const DebugStatsComp* st, const RendStatsC
};
fmt_write(
&tooltip,
"\a.bTotal\ar:\a>13{>7}\n"
"\a~teal\a.bWait\ar:\a>13{>7}",
"\a.bTotal\ar:\a>0A{>7}\n"
"\a~teal\a.bWait\ar:\a>0A{>7}",
fmt_duration(rendSt->gpuExecDur, .minDecDigits = 1, .maxDecDigits = 1),
fmt_duration(rendSt->gpuWaitDur, .minDecDigits = 1, .maxDecDigits = 1));

Expand Down
6 changes: 3 additions & 3 deletions libs/ui/src/widget.c
Original file line number Diff line number Diff line change
Expand Up @@ -543,8 +543,8 @@ static void ui_tooltip_text(

if (dir == Ui_Left) {
/**
* Because we always draw the text left aligned it needs to be offsetted if the tooltip should
* be on the left side of the input.
* Because we always draw the text left aligned it needs to be offset if the tooltip should be
* on the left side of the input.
*/
ui_layout_move_dir(canvas, Ui_Right, opts->maxSize.width - lastRect.width, UiBase_Absolute);
}
Expand Down Expand Up @@ -577,7 +577,7 @@ static bool ui_tooltip_show(UiCanvasComp* canvas, const UiId id, const UiTooltip
bool ui_tooltip_with_opts(
UiCanvasComp* canvas, const UiId id, const String text, const UiTooltipOpts* opts) {

if (!ui_tooltip_show(canvas, id, opts)) {
if (string_is_empty(text) || !ui_tooltip_show(canvas, id, opts)) {
ui_canvas_id_skip(canvas, 2);
return false;
}
Expand Down

0 comments on commit 576f640

Please sign in to comment.