profiler tooltip

This commit is contained in:
jacob 2026-03-31 06:02:33 -05:00
parent b6adeb8861
commit 0706662050
10 changed files with 441 additions and 445 deletions

View File

@ -260,6 +260,7 @@
//- Time
#define NsFromSeconds(s) ((i64)((s) * 1000000000.0))
#define MsFromNs(ns) ((f64)((ns) / 1000000.0))
#define UsFromNs(ns) ((f64)((ns) / 1000.0))
#define SecondsFromNs(ns) ((f64)(ns) / 1000000000.0)
//- Busy-wait

View File

@ -43,65 +43,67 @@ void AsyncWorkerEntryPoint(WaveLaneCtx *lane)
for (;;)
{
AsyncWorkerCtx *w = &Base.async.worker;
//////////////////////////////
//- Begin tick
if (lane->idx == 0)
{
// Wait for signal
{
i64 passive_timeout_ns = NsFromSeconds(0.25);
i64 now_ns = TimeNs();
i64 passive_run_at_ns = now_ns + passive_timeout_ns;
//////////////////////////////
//- Begin tick
i64 cur_signal = Atomic64Fetch(&Base.async.signal.v);
while (cur_signal <= w->last_seen_signal && (passive_run_at_ns - now_ns) > 1000000)
{
FutexYieldNeq(&Base.async.signal.v, &cur_signal, sizeof(cur_signal), passive_run_at_ns - now_ns);
cur_signal = Atomic64Fetch(&Base.async.signal.v);
now_ns = TimeNs();
}
w->last_seen_signal = cur_signal;
}
// Collect callbacks
if (lane->idx == 0)
{
Lock lock = LockE(&Base.async.mutex);
// Wait for signal
{
w->callbacks_count = Base.async.callback_nodes_count;
w->callbacks = PushStructsNoZero(frame.arena, AsyncTickCallback, w->callbacks_count);
u64 callback_idx = 0;
for (AsyncTickCallbackNode *n = Base.async.first_callback_node; n; n = n->next)
i64 passive_timeout_ns = NsFromSeconds(0.25);
i64 now_ns = TimeNs();
i64 passive_run_at_ns = now_ns + passive_timeout_ns;
i64 cur_signal = Atomic64Fetch(&Base.async.signal.v);
while (cur_signal <= w->last_seen_signal && (passive_run_at_ns - now_ns) > 1000000)
{
w->callbacks[callback_idx] = n->callback;
++callback_idx;
FutexYieldNeq(&Base.async.signal.v, &cur_signal, sizeof(cur_signal), passive_run_at_ns - now_ns);
cur_signal = Atomic64Fetch(&Base.async.signal.v);
now_ns = TimeNs();
}
w->last_seen_signal = cur_signal;
}
Unlock(&lock);
// Collect callbacks
{
Lock lock = LockE(&Base.async.mutex);
{
w->callbacks_count = Base.async.callback_nodes_count;
w->callbacks = PushStructsNoZero(frame.arena, AsyncTickCallback, w->callbacks_count);
u64 callback_idx = 0;
for (AsyncTickCallbackNode *n = Base.async.first_callback_node; n; n = n->next)
{
w->callbacks[callback_idx] = n->callback;
++callback_idx;
}
}
Unlock(&lock);
}
}
WaveSync(lane);
//////////////////////////////
//- Run async callbacks
for (u64 callback_idx = 0; callback_idx < w->callbacks_count; ++callback_idx)
{
AsyncTickCallback *callback = &w->callbacks[callback_idx];
callback->func(lane, &frame);
}
//////////////////////////////
//- End tick
WaveSync(lane);
ResetArena(frame.arena);
{
Arena *old_frame_arena = frame.arena;
ZeroStruct(&frame);
frame.arena = old_frame_arena;
}
}
WaveSync(lane);
//////////////////////////////
//- Run async callbacks
for (u64 callback_idx = 0; callback_idx < w->callbacks_count; ++callback_idx)
{
AsyncTickCallback *callback = &w->callbacks[callback_idx];
callback->func(lane, &frame);
}
//////////////////////////////
//- End tick
WaveSync(lane);
ResetArena(frame.arena);
{
Arena *old_frame_arena = frame.arena;
ZeroStruct(&frame);
frame.arena = old_frame_arena;
}
}
}

View File

@ -213,6 +213,28 @@ String StringFromUid(Arena *arena, Uid uid)
return result;
}
String StringFromTimeNs(Arena *arena, i64 time_ns, u32 precision)
{
String result = Zi;
u64 abs_time_ns = AbsI64(time_ns);
if (abs_time_ns <= 999 * 1000)
{
// Microseconds
result = StringF(arena, "%F µs", FmtFloat(UsFromNs(time_ns), .p = precision));
}
else if (abs_time_ns <= 999 * 1000000)
{
// Milliseconds
result = StringF(arena, "%F ms", FmtFloat(MsFromNs(time_ns), .p = precision));
}
else
{
// Seconds
result = StringF(arena, "%F s", FmtFloat(SecondsFromNs(time_ns), .p = precision));
}
return result;
}
////////////////////////////////////////////////////////////
//~ String helpers
@ -790,6 +812,11 @@ String FormatString(Arena *arena, String fmt, FmtArgArray args)
parsed_arg = StringFromUid(arena, arg.value.uid);
} break;
case FmtArgKind_TimeNs:
{
parsed_arg = StringFromTimeNs(arena, arg.value.time_ns, arg.p);
} break;
case FmtArgKind_End:
{
// Unexpected end. Not enough FMT args passed to function.
@ -881,6 +908,7 @@ FmtArgArray FmtArgsFromVaList(Arena *arena, va_list args)
case FmtArgKind_Ptr:
case FmtArgKind_Uid:
case FmtArgKind_Handle:
case FmtArgKind_TimeNs:
{
// Continue
} break;

View File

@ -31,6 +31,7 @@ Enum(FmtArgKind)
FmtArgKind_Ptr = 0xc4519e4,
FmtArgKind_Uid = 0xd1cd407,
FmtArgKind_Handle = 0xead3bec,
FmtArgKind_TimeNs = 0x49456f44,
FmtArgKind_End = 0xecbc5ae
};
@ -48,8 +49,9 @@ Struct(FmtArg)
Vec4I64 sints;
Vec4F64 floats;
void *ptr;
Uid uid;
u64 handle;
Uid uid;
i64 time_ns;
} value;
};
@ -85,6 +87,7 @@ String StringFromFloats(Arena *arena, u64 floats_count, f64 *floats, u32 precisi
String StringFromPtr(Arena *arena, void *ptr);
String StringFromhandle(Arena *arena, u64 v);
String StringFromUid(Arena *arena, Uid uid);
String StringFromTimeNs(Arena *arena, i64 time_ns, u32 precision);
////////////////////////////////////////////////////////////
//~ String helpers
@ -131,28 +134,29 @@ String StringFromList(Arena *arena, StringList l, String separator);
#define FMTARG(_kind, ...) ((FmtArg) { .kind = (_kind), .p = DefaultFmtPrecision, __VA_ARGS__ })
#define FmtChar(v, ...) FMTARG(FmtArgKind_Char, .value.c = (v), __VA_ARGS__)
#define FmtString(v, ...) FMTARG(FmtArgKind_String, .value.string = (v), __VA_ARGS__)
#define FmtChar(v, ...) FMTARG(FmtArgKind_Char, .value.c = (v), __VA_ARGS__)
#define FmtString(v, ...) FMTARG(FmtArgKind_String, .value.string = (v), __VA_ARGS__)
#define FmtUint(v, ...) FMTARG(FmtArgKind_Uint, .value.uints = VEC4U64((v), 0, 0, 0), __VA_ARGS__)
#define FmtUint2(v, ...) FMTARG(FmtArgKind_Uint2, .value.uints = VEC4U64((v).x, (v).y, 0, 0), __VA_ARGS__)
#define FmtUint3(v, ...) FMTARG(FmtArgKind_Uint3, .value.uints = VEC4U64((v).x, (v).y, (v).z, 0), __VA_ARGS__)
#define FmtUint4(v, ...) FMTARG(FmtArgKind_Uint4, .value.uints = VEC4U64((v).x, (v).y, (v).z, (v).w), __VA_ARGS__)
#define FmtUint(v, ...) FMTARG(FmtArgKind_Uint, .value.uints = VEC4U64((v), 0, 0, 0), __VA_ARGS__)
#define FmtUint2(v, ...) FMTARG(FmtArgKind_Uint2, .value.uints = VEC4U64((v).x, (v).y, 0, 0), __VA_ARGS__)
#define FmtUint3(v, ...) FMTARG(FmtArgKind_Uint3, .value.uints = VEC4U64((v).x, (v).y, (v).z, 0), __VA_ARGS__)
#define FmtUint4(v, ...) FMTARG(FmtArgKind_Uint4, .value.uints = VEC4U64((v).x, (v).y, (v).z, (v).w), __VA_ARGS__)
#define FmtSint(v, ...) FMTARG(FmtArgKind_Sint, .value.sints = VEC4I64((v), 0, 0, 0), __VA_ARGS__)
#define FmtSint2(v, ...) FMTARG(FmtArgKind_Sint2, .value.sints = VEC4I64((v).x, (v).y, 0, 0), __VA_ARGS__)
#define FmtSint3(v, ...) FMTARG(FmtArgKind_Sint3, .value.sints = VEC4I64((v).x, (v).y, (v).z, 0), __VA_ARGS__)
#define FmtSint4(v, ...) FMTARG(FmtArgKind_Sint4, .value.sints = VEC4I64((v).x, (v).y, (v).z, (v).w), __VA_ARGS__)
#define FmtSint(v, ...) FMTARG(FmtArgKind_Sint, .value.sints = VEC4I64((v), 0, 0, 0), __VA_ARGS__)
#define FmtSint2(v, ...) FMTARG(FmtArgKind_Sint2, .value.sints = VEC4I64((v).x, (v).y, 0, 0), __VA_ARGS__)
#define FmtSint3(v, ...) FMTARG(FmtArgKind_Sint3, .value.sints = VEC4I64((v).x, (v).y, (v).z, 0), __VA_ARGS__)
#define FmtSint4(v, ...) FMTARG(FmtArgKind_Sint4, .value.sints = VEC4I64((v).x, (v).y, (v).z, (v).w), __VA_ARGS__)
#define FmtFloat(v, ...) FMTARG(FmtArgKind_Float, .value.floats = VEC4F64((v), 0, 0, 0), __VA_ARGS__)
#define FmtFloat2(v, ...) FMTARG(FmtArgKind_Float2, .value.floats = VEC4F64((v).x, (v).y, 0, 0), __VA_ARGS__)
#define FmtFloat3(v, ...) FMTARG(FmtArgKind_Float3, .value.floats = VEC4F64((v).x, (v).y, (v).z, 0), __VA_ARGS__)
#define FmtFloat4(v, ...) FMTARG(FmtArgKind_Float4, .value.floats = VEC4F64((v).x, (v).y, (v).z, (v).w), __VA_ARGS__)
#define FmtFloat(v, ...) FMTARG(FmtArgKind_Float, .value.floats = VEC4F64((v), 0, 0, 0), __VA_ARGS__)
#define FmtFloat2(v, ...) FMTARG(FmtArgKind_Float2, .value.floats = VEC4F64((v).x, (v).y, 0, 0), __VA_ARGS__)
#define FmtFloat3(v, ...) FMTARG(FmtArgKind_Float3, .value.floats = VEC4F64((v).x, (v).y, (v).z, 0), __VA_ARGS__)
#define FmtFloat4(v, ...) FMTARG(FmtArgKind_Float4, .value.floats = VEC4F64((v).x, (v).y, (v).z, (v).w), __VA_ARGS__)
#define FmtHex(v, ...) FMTARG(FmtArgKind_Hex, .value.uints.x = (v), __VA_ARGS__)
#define FmtPtr(v, ...) FMTARG(FmtArgKind_Ptr, .value.ptr = (v), __VA_ARGS__)
#define FmtHandle(v, ...) FMTARG(FmtArgKind_Handle, .value.handle = (v), __VA_ARGS__)
#define FmtUid(v, ...) FMTARG(FmtArgKind_Uid, .value.uid = (v), __VA_ARGS__)
#define FmtHex(v, ...) FMTARG(FmtArgKind_Hex, .value.uints.x = (v), __VA_ARGS__)
#define FmtPtr(v, ...) FMTARG(FmtArgKind_Ptr, .value.ptr = (v), __VA_ARGS__)
#define FmtHandle(v, ...) FMTARG(FmtArgKind_Handle, .value.handle = (v), __VA_ARGS__)
#define FmtUid(v, ...) FMTARG(FmtArgKind_Uid, .value.uid = (v), __VA_ARGS__)
#define FmtTimeNs(v, ...) FMTARG(FmtArgKind_TimeNs, .value.time_ns = (v), __VA_ARGS__)
#define FmtEnd FMTARG(FmtArgKind_End) // Denotes end of VA list

View File

@ -86,7 +86,7 @@ void S_TickForever(WaveLaneCtx *lane)
b32 shutdown = 0;
while (!shutdown)
ProfZoneDF("Sim Frame")
ProfZoneDF("Sim tick")
{
shutdown = Atomic32Fetch(&S.shutdown);
P_tl.debug_draw_enabled = TweakBool("Simulation debug draw", 0);

File diff suppressed because it is too large Load Diff

View File

@ -37,6 +37,7 @@ Struct(V_WidgetTheme)
f32 ui_font_size;
f32 chat_font_size;
Vec2 tooltip_offset_px;
f32 h1;
f32 h2;
@ -238,6 +239,25 @@ Struct(V_Palette)
////////////////////////////////////////////////////////////
//~ Profiler types
Struct(V_ZoneDesc)
{
V_ZoneDesc *prev;
V_ZoneDesc *next;
V_ZoneDesc *prev_in_row;
V_ZoneDesc *next_in_row;
String name;
u64 start_sample_seq;
u64 end_sample_seq;
u32 depth;
Vec4 color;
i64 start_ns;
i64 end_ns;
};
Struct(V_Profiler)
{
Vec2 graph_dims;

View File

@ -326,8 +326,8 @@ void UI_PushDefaults(void)
{
default: break;
case UI_StyleKind_Parent: { desc.style.Parent = UI_RootKey; } break;
case UI_StyleKind_Width: { desc.style.Width = UI_GROW(1, 0); } break;
case UI_StyleKind_Height: { desc.style.Height = UI_GROW(1, 0); } break;
case UI_StyleKind_Width: { desc.style.Width = UI_Grow(1, 0); } break;
case UI_StyleKind_Height: { desc.style.Height = UI_Grow(1, 0); } break;
case UI_StyleKind_Scale: { desc.style.Scale = VEC2(1, 1); } break;
case UI_StyleKind_Font: { desc.style.Font = UI_BuiltinTextFont(); } break;
case UI_StyleKind_FontSize: { desc.style.FontSize = 16.0f; } break;
@ -876,8 +876,8 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags)
//- Build root box
{
UI_SetNext(Width, UI_PIX(frame->window_frame.draw_size.x, 1));
UI_SetNext(Height, UI_PIX(frame->window_frame.draw_size.y, 1));
UI_SetNext(Width, UI_Px(frame->window_frame.draw_size.x, 1));
UI_SetNext(Height, UI_Px(frame->window_frame.draw_size.y, 1));
UI_SetNext(Parent, UI_NilKey);
UI_BuildBoxEx(UI_RootKey);
}

View File

@ -532,18 +532,18 @@ UI_Checkpoint UI_TopCp(void);
#define UI_SIZE(_kind, _v, _s) (UI_Size) { .kind = (_kind), .v = (_v), .strictness = (_s) }
#define UI_PIX(_v, _s) UI_SIZE(UI_SizeKind_Pixel, (_v), (_s))
#define UI_SHRINK(_v, _s) UI_SIZE(UI_SizeKind_Shrink, (_v), (_s))
#define UI_GROW(_v, _s) UI_SIZE(UI_SizeKind_Grow, (_v), (_s))
#define UI_FNT(_v, _s) UI_SIZE(UI_SizeKind_Pixel, (f32)UI_PeekTop(FontSize) * (_v), (_s))
#define UI_Px(_v, _s) UI_SIZE(UI_SizeKind_Pixel, (_v), (_s))
#define UI_Shrink(_v, _s) UI_SIZE(UI_SizeKind_Shrink, (_v), (_s))
#define UI_Grow(_v, _s) UI_SIZE(UI_SizeKind_Grow, (_v), (_s))
#define UI_Fnt(_v, _s) UI_SIZE(UI_SizeKind_Pixel, (f32)UI_PeekTop(FontSize) * (_v), (_s))
////////////////////////////////////////////////////////////
//~ Rounding helpers
#define UI_ROUND(_kind, _v) (UI_Round) { .kind = (_kind), .v = (_v)}
#define UI_RPIX(_v) UI_ROUND(UI_RoundKind_Pixel, (_v))
#define UI_RGROW(_v) UI_ROUND(UI_RoundKind_Grow, (_v))
#define UI_Rpx(_v) UI_ROUND(UI_RoundKind_Pixel, (_v))
#define UI_Rgrow(_v) UI_ROUND(UI_RoundKind_Grow, (_v))
////////////////////////////////////////////////////////////
//~ Command helpers

View File

@ -36,8 +36,8 @@ UI_Key UI_BuildLabel(String text)
UI_Push(Font, font);
UI_Push(FontSize, font_size);
UI_Push(TextColor, text_color);
UI_Push(Width, UI_SHRINK(0, 1));
UI_Push(Height, UI_SHRINK(0, 1));
UI_Push(Width, UI_Shrink(0, 1));
UI_Push(Height, UI_Shrink(0, 1));
UI_Push(Text, text);
UI_Push(ChildAlignment, alignment);
UI_Push(Flags, UI_BoxFlag_DrawText);
@ -88,7 +88,7 @@ UI_Key UI_BuildSpacer(UI_Size size, Axis axis)
UI_Push(Parent, parent);
UI_Push(Scale, scale);
UI_Push(Tint, 0);
UI_Push(AxisSize, UI_GROW(1, 0), .axis = !axis);
UI_Push(AxisSize, UI_Grow(1, 0), .axis = !axis);
UI_Push(AxisSize, size, .axis = axis);
key = UI_BuildBox();
}
@ -111,7 +111,7 @@ UI_Key UI_BuildDivider(UI_Size size, Vec4 color, Axis axis)
UI_Push(Tint, tint);
UI_Push(Opacity, opacity);
UI_Push(BackgroundColor, color);
UI_Push(AxisSize, UI_GROW(1, 0), .axis = !axis);
UI_Push(AxisSize, UI_Grow(1, 0), .axis = !axis);
UI_Push(AxisSize, size, .axis = axis);
key = UI_BuildBox();
}