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 //- Time
#define NsFromSeconds(s) ((i64)((s) * 1000000000.0)) #define NsFromSeconds(s) ((i64)((s) * 1000000000.0))
#define MsFromNs(ns) ((f64)((ns) / 1000000.0)) #define MsFromNs(ns) ((f64)((ns) / 1000000.0))
#define UsFromNs(ns) ((f64)((ns) / 1000.0))
#define SecondsFromNs(ns) ((f64)(ns) / 1000000000.0) #define SecondsFromNs(ns) ((f64)(ns) / 1000000000.0)
//- Busy-wait //- Busy-wait

View File

@ -43,65 +43,67 @@ void AsyncWorkerEntryPoint(WaveLaneCtx *lane)
for (;;) for (;;)
{ {
AsyncWorkerCtx *w = &Base.async.worker; AsyncWorkerCtx *w = &Base.async.worker;
//////////////////////////////
//- Begin tick
if (lane->idx == 0)
{ {
// Wait for signal //////////////////////////////
{ //- Begin tick
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); if (lane->idx == 0)
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
{ {
Lock lock = LockE(&Base.async.mutex); // Wait for signal
{ {
w->callbacks_count = Base.async.callback_nodes_count; i64 passive_timeout_ns = NsFromSeconds(0.25);
w->callbacks = PushStructsNoZero(frame.arena, AsyncTickCallback, w->callbacks_count); i64 now_ns = TimeNs();
u64 callback_idx = 0; i64 passive_run_at_ns = now_ns + passive_timeout_ns;
for (AsyncTickCallbackNode *n = Base.async.first_callback_node; n; n = n->next)
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; FutexYieldNeq(&Base.async.signal.v, &cur_signal, sizeof(cur_signal), passive_run_at_ns - now_ns);
++callback_idx; 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; 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 //~ String helpers
@ -790,6 +812,11 @@ String FormatString(Arena *arena, String fmt, FmtArgArray args)
parsed_arg = StringFromUid(arena, arg.value.uid); parsed_arg = StringFromUid(arena, arg.value.uid);
} break; } break;
case FmtArgKind_TimeNs:
{
parsed_arg = StringFromTimeNs(arena, arg.value.time_ns, arg.p);
} break;
case FmtArgKind_End: case FmtArgKind_End:
{ {
// Unexpected end. Not enough FMT args passed to function. // 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_Ptr:
case FmtArgKind_Uid: case FmtArgKind_Uid:
case FmtArgKind_Handle: case FmtArgKind_Handle:
case FmtArgKind_TimeNs:
{ {
// Continue // Continue
} break; } break;

View File

@ -31,6 +31,7 @@ Enum(FmtArgKind)
FmtArgKind_Ptr = 0xc4519e4, FmtArgKind_Ptr = 0xc4519e4,
FmtArgKind_Uid = 0xd1cd407, FmtArgKind_Uid = 0xd1cd407,
FmtArgKind_Handle = 0xead3bec, FmtArgKind_Handle = 0xead3bec,
FmtArgKind_TimeNs = 0x49456f44,
FmtArgKind_End = 0xecbc5ae FmtArgKind_End = 0xecbc5ae
}; };
@ -48,8 +49,9 @@ Struct(FmtArg)
Vec4I64 sints; Vec4I64 sints;
Vec4F64 floats; Vec4F64 floats;
void *ptr; void *ptr;
Uid uid;
u64 handle; u64 handle;
Uid uid;
i64 time_ns;
} value; } value;
}; };
@ -85,6 +87,7 @@ String StringFromFloats(Arena *arena, u64 floats_count, f64 *floats, u32 precisi
String StringFromPtr(Arena *arena, void *ptr); String StringFromPtr(Arena *arena, void *ptr);
String StringFromhandle(Arena *arena, u64 v); String StringFromhandle(Arena *arena, u64 v);
String StringFromUid(Arena *arena, Uid uid); String StringFromUid(Arena *arena, Uid uid);
String StringFromTimeNs(Arena *arena, i64 time_ns, u32 precision);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ String helpers //~ 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 FMTARG(_kind, ...) ((FmtArg) { .kind = (_kind), .p = DefaultFmtPrecision, __VA_ARGS__ })
#define FmtChar(v, ...) FMTARG(FmtArgKind_Char, .value.c = (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 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 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 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 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 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 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 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 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 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 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 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 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 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 FmtHex(v, ...) FMTARG(FmtArgKind_Hex, .value.uints.x = (v), __VA_ARGS__)
#define FmtPtr(v, ...) FMTARG(FmtArgKind_Ptr, .value.ptr = (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 FmtHandle(v, ...) FMTARG(FmtArgKind_Handle, .value.handle = (v), __VA_ARGS__)
#define FmtUid(v, ...) FMTARG(FmtArgKind_Uid, .value.uid = (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 #define FmtEnd FMTARG(FmtArgKind_End) // Denotes end of VA list

View File

@ -86,7 +86,7 @@ void S_TickForever(WaveLaneCtx *lane)
b32 shutdown = 0; b32 shutdown = 0;
while (!shutdown) while (!shutdown)
ProfZoneDF("Sim Frame") ProfZoneDF("Sim tick")
{ {
shutdown = Atomic32Fetch(&S.shutdown); shutdown = Atomic32Fetch(&S.shutdown);
P_tl.debug_draw_enabled = TweakBool("Simulation debug draw", 0); 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 ui_font_size;
f32 chat_font_size; f32 chat_font_size;
Vec2 tooltip_offset_px;
f32 h1; f32 h1;
f32 h2; f32 h2;
@ -238,6 +239,25 @@ Struct(V_Palette)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Profiler types //~ 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) Struct(V_Profiler)
{ {
Vec2 graph_dims; Vec2 graph_dims;

View File

@ -326,8 +326,8 @@ void UI_PushDefaults(void)
{ {
default: break; default: break;
case UI_StyleKind_Parent: { desc.style.Parent = UI_RootKey; } 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_Width: { desc.style.Width = UI_Grow(1, 0); } break;
case UI_StyleKind_Height: { desc.style.Height = 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_Scale: { desc.style.Scale = VEC2(1, 1); } break;
case UI_StyleKind_Font: { desc.style.Font = UI_BuiltinTextFont(); } break; case UI_StyleKind_Font: { desc.style.Font = UI_BuiltinTextFont(); } break;
case UI_StyleKind_FontSize: { desc.style.FontSize = 16.0f; } 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 //- Build root box
{ {
UI_SetNext(Width, UI_PIX(frame->window_frame.draw_size.x, 1)); UI_SetNext(Width, UI_Px(frame->window_frame.draw_size.x, 1));
UI_SetNext(Height, UI_PIX(frame->window_frame.draw_size.y, 1)); UI_SetNext(Height, UI_Px(frame->window_frame.draw_size.y, 1));
UI_SetNext(Parent, UI_NilKey); UI_SetNext(Parent, UI_NilKey);
UI_BuildBoxEx(UI_RootKey); 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_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_Px(_v, _s) UI_SIZE(UI_SizeKind_Pixel, (_v), (_s))
#define UI_SHRINK(_v, _s) UI_SIZE(UI_SizeKind_Shrink, (_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_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_Fnt(_v, _s) UI_SIZE(UI_SizeKind_Pixel, (f32)UI_PeekTop(FontSize) * (_v), (_s))
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Rounding helpers //~ Rounding helpers
#define UI_ROUND(_kind, _v) (UI_Round) { .kind = (_kind), .v = (_v)} #define UI_ROUND(_kind, _v) (UI_Round) { .kind = (_kind), .v = (_v)}
#define UI_RPIX(_v) UI_ROUND(UI_RoundKind_Pixel, (_v)) #define UI_Rpx(_v) UI_ROUND(UI_RoundKind_Pixel, (_v))
#define UI_RGROW(_v) UI_ROUND(UI_RoundKind_Grow, (_v)) #define UI_Rgrow(_v) UI_ROUND(UI_RoundKind_Grow, (_v))
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Command helpers //~ Command helpers

View File

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