use rdtsc for profiler timestamps

This commit is contained in:
jacob 2026-03-31 17:37:22 -05:00
parent 0706662050
commit db3f0e6b2d
13 changed files with 557 additions and 442 deletions

View File

@ -226,7 +226,7 @@
#define ThreadLocal __thread #define ThreadLocal __thread
#endif #endif
//- Compiler memory barriers //- Compiler reordering barriers
#if IsCompilerMsvc #if IsCompilerMsvc
#define CompilerBarrier() _ReadWriteBarrier() #define CompilerBarrier() _ReadWriteBarrier()
#elif IsArchX64 #elif IsArchX64
@ -263,12 +263,6 @@
#define UsFromNs(ns) ((f64)((ns) / 1000.0)) #define UsFromNs(ns) ((f64)((ns) / 1000.0))
#define SecondsFromNs(ns) ((f64)(ns) / 1000000000.0) #define SecondsFromNs(ns) ((f64)(ns) / 1000000000.0)
//- Busy-wait
#if IsArchX64
#define YieldCpu()
#else
#endif
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Linked list helper macros //~ Linked list helper macros
@ -556,7 +550,7 @@ Inline b32 MatchU128(u128 a, u128 b) { return a.lo == b.lo && a.hi == b.hi; }
AlignedStruct(IsolatedAtomic32, IsolationSize) { Atomic32 v; }; AlignedStruct(IsolatedAtomic32, IsolationSize) { Atomic32 v; };
AlignedStruct(IsolatedAtomic64, IsolationSize) { Atomic64 v; }; AlignedStruct(IsolatedAtomic64, IsolationSize) { Atomic64 v; };
#define Unatomic(atomic) (&(atomic)->_atom) #define NonAtomic(atomic) (&(atomic)->_atom)
#if IsPlatformWindows && IsArchX64 #if IsPlatformWindows && IsArchX64
//- 8 bit atomic ops //- 8 bit atomic ops
@ -822,11 +816,14 @@ Inline u64 MixU64s(u64 seed_a, u64 seed_b)
//~ @hookdecl Core api //~ @hookdecl Core api
#if IsCpu #if IsCpu
//- Application context
StringList GetRawCommandline(void); StringList GetRawCommandline(void);
String GetAppName(void); String GetAppName(void);
String GetEngineDirectory(void); String GetEngineDirectory(void);
String GetLibsDirectory(void); String GetLibsDirectory(void);
String GetAppDirectory(void); String GetAppDirectory(void);
//- Program context
void LoadApi(ApiDesc api); void LoadApi(ApiDesc api);
void Echo(String msg); void Echo(String msg);
b32 Panic(String msg); b32 Panic(String msg);
@ -834,7 +831,15 @@ Inline u64 MixU64s(u64 seed_a, u64 seed_b)
Callstack CaptureCallstack(u64 skip_frames); Callstack CaptureCallstack(u64 skip_frames);
b32 IsRunningInDebugger(void); b32 IsRunningInDebugger(void);
b32 IsRunningInWine(void); b32 IsRunningInWine(void);
//- Time
i64 TimeNs(void); i64 TimeNs(void);
u64 BeginTsc(void);
u64 EndTsc(void);
u64 GetStartupTsc(void);
f64 GetNsPerTsc(void);
//- Misc
void TrueRand(String buffer); void TrueRand(String buffer);
CpuTopologyInfo GetCpuTopologyInfo(void); CpuTopologyInfo GetCpuTopologyInfo(void);
void SleepSeconds(f64 seconds); void SleepSeconds(f64 seconds);

View File

@ -1,7 +1,39 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Profile zone //~ Profile zone
void PushProfZoneEx(char *name_cstr_lit, b32 end_zone) // void PushProfZoneEx(char *name_cstr_lit, b32 end_zone)
// {
// ProfTrack *track = Base_tl.prof.thread_track;
// if (!track)
// {
// Arena *perm = PermArena();
// {
// track = PushStruct(perm, ProfTrack);
// Base_tl.prof.thread_track = track;
// }
// LockTicketMutex(&Base.prof.register_track_tm);
// {
// Base_tl.prof.track_idx = Atomic32Fetch(&Base.prof.tracks_count);
// Base.prof.tracks[Base_tl.prof.track_idx] = track;
// Atomic32FetchAdd(&Base.prof.tracks_count, 1);
// }
// UnlockTicketMutex(&Base.prof.register_track_tm);
// }
// u64 sample_seq = track->top_sample_seq;
// ProfSample *sample = &track->samples[sample_seq % ProfTrackSamplesCap];
// {
// // TODO: Wrap rdtsc for cpu-relative <-> program-relative timestamp conversion
// sample->stamp = __rdtsc() | ((u64)(!!end_zone) << 63);
// // sample->stamp = TimeNs() | ((u64)(!!end_zone) << 63);
// sample->name_cstr_lit = name_cstr_lit;
// }
// track->top_sample_seq = sample_seq + 1;
// }
void BeginProfZone(char *name_cstr_lit)
{ {
ProfTrack *track = Base_tl.prof.thread_track; ProfTrack *track = Base_tl.prof.thread_track;
if (!track) if (!track)
@ -19,16 +51,28 @@ void PushProfZoneEx(char *name_cstr_lit, b32 end_zone)
} }
UnlockTicketMutex(&Base.prof.register_track_tm); UnlockTicketMutex(&Base.prof.register_track_tm);
} }
u64 sample_seq = *NonAtomic(&track->top_sample_seq);
u64 sample_seq = track->top_sample_seq;
ProfSample *sample = &track->samples[sample_seq % ProfTrackSamplesCap]; ProfSample *sample = &track->samples[sample_seq % ProfTrackSamplesCap];
{ {
// TODO: Wrap rdtsc for cpu-relative <-> program-relative timestamp conversion sample->flags = 0;
// sample->stamp = __rdtsc() | ((u64)end_zone << 63);
sample->stamp = TimeNs() | ((u64)end_zone << 63);
sample->name_cstr_lit = name_cstr_lit; sample->name_cstr_lit = name_cstr_lit;
sample->tsc = BeginTsc();
} }
track->top_sample_seq = sample_seq + 1; Atomic64Set(&track->top_sample_seq, sample_seq + 1);
}
void EndProfZone(void)
{
i64 tsc = EndTsc();
ProfTrack *track = Base_tl.prof.thread_track;
u64 sample_seq = *NonAtomic(&track->top_sample_seq);
ProfSample *sample = &track->samples[sample_seq % ProfTrackSamplesCap];
{
sample->flags = ProfSampleFlag_EndZone;
sample->tsc = tsc;
sample->name_cstr_lit = 0;
}
Atomic64Set(&track->top_sample_seq, sample_seq + 1);
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -4,18 +4,23 @@
#define ProfTrackSamplesCap Kibi(256) #define ProfTrackSamplesCap Kibi(256)
#define MaxRegisteredProfTracks Kibi(32) #define MaxRegisteredProfTracks Kibi(32)
#define NsFromProfStamp(stamp) (stamp & ~((u64)1 << 63)) Enum(ProfSampleFlag)
{
ProfSampleFlag_None = 0,
ProfSampleFlag_EndZone = (1 << 0)
};
Struct(ProfSample) Struct(ProfSample)
{ {
// Bit 63: zone-end, Bits 62-0: timestamp ProfSampleFlag flags;
u64 stamp; u8 _pad[4];
u64 tsc;
char *name_cstr_lit; char *name_cstr_lit;
}; };
Struct(ProfTrack) Struct(ProfTrack)
{ {
u64 top_sample_seq; Atomic64 top_sample_seq;
ProfSample samples[ProfTrackSamplesCap]; ProfSample samples[ProfTrackSamplesCap];
}; };
@ -45,10 +50,11 @@ Struct(ThreadLocalProfCtx)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Profile zone //~ Profile zone
void PushProfZoneEx(char *name_cstr_lit, b32 end_zone); void BeginProfZone(char *name_cstr_lit);
void EndProfZone(void);
#if PROFILING_ENABLED #if PROFILING_ENABLED
#define ProfZoneDF(name_cstr_lit) DeferFor(PushProfZoneEx(name_cstr_lit"\0", 0), PushProfZoneEx(name_cstr_lit"\0", 1)) #define ProfZoneDF(name_cstr_lit) DeferFor(BeginProfZone(name_cstr_lit"\0"), EndProfZone())
#else #else
#define ProfZoneDF(...) #define ProfZoneDF(...)
#endif #endif

View File

@ -217,12 +217,17 @@ String StringFromTimeNs(Arena *arena, i64 time_ns, u32 precision)
{ {
String result = Zi; String result = Zi;
u64 abs_time_ns = AbsI64(time_ns); u64 abs_time_ns = AbsI64(time_ns);
if (abs_time_ns <= 999 * 1000) if (abs_time_ns < 1000)
{
// Nanoseconds
result = StringF(arena, "%F ns", FmtSint(time_ns));
}
else if (abs_time_ns <= 1000 * 1000)
{ {
// Microseconds // Microseconds
result = StringF(arena, "%F µs", FmtFloat(UsFromNs(time_ns), .p = precision)); result = StringF(arena, "%F µs", FmtFloat(UsFromNs(time_ns), .p = precision));
} }
else if (abs_time_ns <= 999 * 1000000) else if (abs_time_ns <= 1000 * 1000 * 1000)
{ {
// Milliseconds // Milliseconds
result = StringF(arena, "%F ms", FmtFloat(MsFromNs(time_ns), .p = precision)); result = StringF(arena, "%F ms", FmtFloat(MsFromNs(time_ns), .p = precision));

View File

@ -199,9 +199,36 @@ b32 IsRunningInWine(void)
i64 TimeNs(void) i64 TimeNs(void)
{ {
LARGE_INTEGER qpc; LARGE_INTEGER qpc;
CompilerBarrier();
{
QueryPerformanceCounter(&qpc); QueryPerformanceCounter(&qpc);
i64 result = (qpc.QuadPart - W32.timer_start_qpc) * W32.ns_per_qpc; }
return result; CompilerBarrier();
return (qpc.QuadPart - W32.startup_qpc) * W32.ns_per_qpc;
}
u64 BeginTsc(void)
{
_mm_lfence();
return __rdtsc();
}
u64 EndTsc(void)
{
u32 aux;
u64 tsc = __rdtscp(&aux);
_mm_lfence();
return tsc;
}
u64 GetStartupTsc(void)
{
return W32.startup_tsc;
}
f64 GetNsPerTsc(void)
{
return W32.ns_per_tsc;
} }
void TrueRand(String buffer) void TrueRand(String buffer)
@ -557,16 +584,39 @@ i32 W32_Main(void)
} }
#endif #endif
// Init time // Calibrate QPC
{ {
LARGE_INTEGER qpf = Zi; LARGE_INTEGER qpf = Zi;
QueryPerformanceFrequency(&qpf); QueryPerformanceFrequency(&qpf);
W32.ns_per_qpc = 1000000000 / qpf.QuadPart; W32.ns_per_qpc = 1000000000.0 / qpf.QuadPart;
} }
{ {
LARGE_INTEGER qpc = Zi; LARGE_INTEGER qpc = Zi;
QueryPerformanceCounter(&qpc); QueryPerformanceCounter(&qpc);
W32.timer_start_qpc = qpc.QuadPart; W32.startup_qpc = qpc.QuadPart;
}
// Calibrate TSC
{
LARGE_INTEGER start_qpc;
LARGE_INTEGER end_qpc;
i64 start_tsc;
i64 end_tsc;
// Collect samples
u32 tsc_sleep_calibration_ms = 20;
{
start_tsc = __rdtsc();
QueryPerformanceCounter(&start_qpc);
{
Sleep(tsc_sleep_calibration_ms);
}
QueryPerformanceCounter(&end_qpc);
end_tsc = __rdtsc();
}
f64 elapsed_ns = (end_qpc.QuadPart - start_qpc.QuadPart) * W32.ns_per_qpc;
f64 elapsed_tsc = end_tsc - start_tsc;
W32.ns_per_tsc = elapsed_ns / elapsed_tsc;
W32.startup_tsc = end_tsc;
} }
// Load module funcs // Load module funcs

View File

@ -88,8 +88,10 @@ Struct(W32_Ctx)
Atomic32 shutdown; Atomic32 shutdown;
Atomic32 exit_code; Atomic32 exit_code;
i64 timer_start_qpc; u64 startup_qpc;
i64 ns_per_qpc; u64 startup_tsc;
u64 ns_per_qpc;
f64 ns_per_tsc;
StringList raw_command_line; StringList raw_command_line;
String app_name; String app_name;

View File

@ -1412,26 +1412,6 @@ G_BaseDescriptorIndex G_PushMemory(G_CommandListHandle cl_handle, G_ArenaHandle
} }
} }
// FIXME: Remove this
if (memory_desc.buffer.stride == 52)
{
DEBUGBREAKABLE;
}
// TODO: Less stringent reuse constraints. We could even create textures as placed resources and reset their underlying heaps. // TODO: Less stringent reuse constraints. We could even create textures as placed resources and reset their underlying heaps.
can_reuse = can_reuse && MatchStruct(&compare_d3d_desc, &d3d_desc); can_reuse = can_reuse && MatchStruct(&compare_d3d_desc, &d3d_desc);
b32 can_reuse_descriptor = can_reuse && (!is_buffer || (MaxU64(memory_desc.buffer.stride, 1) == old_buffer_stride)); b32 can_reuse_descriptor = can_reuse && (!is_buffer || (MaxU64(memory_desc.buffer.stride, 1) == old_buffer_stride));

View File

@ -67,7 +67,7 @@ void PLT_W32_SyncTimerForever(WaveLaneCtx *lane)
for (;;) for (;;)
{ {
{ {
// TODO: Minimum timer frequency in case timers ever become ultra precise in the future // TODO: Clamp timer frequency in case timers ever become ultra precise in the future
LARGE_INTEGER due = Zi; LARGE_INTEGER due = Zi;
due.QuadPart = -1; due.QuadPart = -1;
//due.QuadPart = -10000; //due.QuadPart = -10000;

View File

@ -85,8 +85,7 @@ void S_TickForever(WaveLaneCtx *lane)
//- Sim loop //- Sim loop
b32 shutdown = 0; b32 shutdown = 0;
while (!shutdown) while (!shutdown) ProfZoneDF("Sim tick")
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);
@ -982,6 +981,7 @@ void S_TickForever(WaveLaneCtx *lane)
//- Sleep //- Sleep
if (!shutdown) if (!shutdown)
ProfZoneDF("Sleep sim")
{ {
i64 step_dt_ns = SIM_TICK_INTERVAL_NS; i64 step_dt_ns = SIM_TICK_INTERVAL_NS;
PLT_SleepFrame(begin_time_ns, step_dt_ns); PLT_SleepFrame(begin_time_ns, step_dt_ns);

View File

@ -871,8 +871,7 @@ void V_TickForever(WaveLaneCtx *lane)
//- Begin vis loop //- Begin vis loop
b32 shutdown = 0; b32 shutdown = 0;
while (!shutdown) while (!shutdown) ProfZoneDF("Vis tick")
ProfZoneDF("Vis tick")
{ {
shutdown = Atomic32Fetch(&V.shutdown); shutdown = Atomic32Fetch(&V.shutdown);
P_tl.debug_draw_enabled = TweakBool("Vis debug draw", 0); P_tl.debug_draw_enabled = TweakBool("Vis debug draw", 0);
@ -3632,7 +3631,7 @@ void V_TickForever(WaveLaneCtx *lane)
////////////////////////////// //////////////////////////////
//- Build panels //- Build panels
UI_PushDF(Parent, vis_game_box) UI_SetDF(Parent, vis_game_box)
// if (show_editor_ui && frame->is_editing) // if (show_editor_ui && frame->is_editing)
{ {
Struct(PanelDfsNode) { PanelDfsNode *next; b32 visited; V_Panel *panel; UI_Checkpoint cp; }; Struct(PanelDfsNode) { PanelDfsNode *next; b32 visited; V_Panel *panel; UI_Checkpoint cp; };
@ -4322,7 +4321,7 @@ void V_TickForever(WaveLaneCtx *lane)
//- Build command palette //- Build command palette
V_Palette *palette = &frame->palette; V_Palette *palette = &frame->palette;
UI_PushDF(Parent, UI_RootKey) UI_SetDF(Parent, UI_RootKey)
{ {
UI_Push(Tag, HashF("developer command palette")); UI_Push(Tag, HashF("developer command palette"));
@ -5393,7 +5392,7 @@ void V_TickForever(WaveLaneCtx *lane)
profiler->ns_per_px = ClampF64(profiler->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_Key profiler_graph_box = UI_KeyF("graph");
UI_PushDF(OmitFlags, UI_BoxFlag_CaptureMouse * !!(frame->is_looking)) UI_SetDF(OmitFlags, UI_BoxFlag_CaptureMouse * !!(frame->is_looking))
if (TweakBool("Show profiler", 1)) if (TweakBool("Show profiler", 1))
{ {
profiler->is_showing = 1; profiler->is_showing = 1;
@ -5472,8 +5471,8 @@ void V_TickForever(WaveLaneCtx *lane)
//- Build profiler //- Build profiler
UI_Key profiler_box = UI_KeyF("profiler"); UI_Key profiler_box = UI_KeyF("profiler");
UI_PushDF(Tag, profiler_box.v) UI_SetDF(Tag, profiler_box.v)
UI_PushDF(Parent, profiler_box) UI_SetDF(Parent, profiler_box)
{ {
UI_Key main_box = UI_KeyF("main"); UI_Key main_box = UI_KeyF("main");
@ -5628,22 +5627,22 @@ void V_TickForever(WaveLaneCtx *lane)
UI_SetNext(Height, profiler_height); UI_SetNext(Height, profiler_height);
UI_SetNext(Flags, UI_BoxFlag_CaptureMouse); UI_SetNext(Flags, UI_BoxFlag_CaptureMouse);
UI_SetNext(Opacity, profiler_opacity); UI_SetNext(Opacity, profiler_opacity);
UI_PushDF(Width, UI_Grow(1, 0)) UI_SetDF(Width, UI_Grow(1, 0))
UI_PushDF(Parent, UI_BuildColumnEx(profiler_box)) UI_SetDF(Parent, UI_BuildColumnEx(profiler_box))
UI_PushDF(Parent, UI_BuildRow()) UI_SetDF(Parent, UI_BuildRow())
{ {
UI_BuildSpacer(window_padding, Axis_X); UI_BuildSpacer(window_padding, Axis_X);
UI_PushDF(Parent, UI_BuildColumn()) UI_SetDF(Parent, UI_BuildColumn())
{ {
//- Header //- Header
// UI_PushDF(BackgroundColor, Color_Red) // UI_SetDF(BackgroundColor, Color_Red)
// UI_SetNext(BorderColor, Color_Red); // UI_SetNext(BorderColor, Color_Red);
// UI_SetNext(BorderSize, 1); // UI_SetNext(BorderSize, 1);
UI_SetNext(ChildAlignment, UI_Region_Center); UI_SetNext(ChildAlignment, UI_Region_Center);
UI_PushDF(Height, header_height) UI_SetDF(Height, header_height)
UI_PushDF(Parent, UI_BuildBoxEx(UI_KeyF("profiler header"))) UI_SetDF(Parent, UI_BuildBoxEx(UI_KeyF("profiler header")))
{ {
UI_PushDF(TextColor, theme.col.hint) UI_SetDF(TextColor, theme.col.hint)
UI_BuildLabelF("Profiler"); UI_BuildLabelF("Profiler");
} }
UI_BuildDivider(UI_Px(1, 1), theme.col.divider, Axis_Y); UI_BuildDivider(UI_Px(1, 1), theme.col.divider, Axis_Y);
@ -5651,7 +5650,7 @@ void V_TickForever(WaveLaneCtx *lane)
//- Graph //- Graph
// UI_SetNext(BackgroundColor, Color_Cyan); // UI_SetNext(BackgroundColor, Color_Cyan);
UI_SetNext(Height, graph_height); UI_SetNext(Height, graph_height);
UI_PushDF(Parent, UI_BuildBoxEx(profiler_graph_box)) UI_SetDF(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);
@ -5667,16 +5666,19 @@ void V_TickForever(WaveLaneCtx *lane)
UI_SetNext(Rounding, UI_Rpx(4)); UI_SetNext(Rounding, UI_Rpx(4));
UI_SetNext(Flags, UI_BoxFlag_CaptureMouse | UI_BoxFlag_CaptureThroughChildren | UI_BoxFlag_Scissor); UI_SetNext(Flags, UI_BoxFlag_CaptureMouse | UI_BoxFlag_CaptureThroughChildren | UI_BoxFlag_Scissor);
// UI_SetNext(Flags, UI_BoxFlag_CaptureMouse); // UI_SetNext(Flags, UI_BoxFlag_CaptureMouse);
UI_PushDF(Parent, UI_BuildColumnEx(main_box)) UI_SetDF(Parent, UI_BuildColumnEx(main_box))
{ {
RegisteredProfTracksArray tracks = FetchRegisteredProfTracks(frame->arena); RegisteredProfTracksArray tracks = FetchRegisteredProfTracks(frame->arena);
for (u64 track_idx = 0; track_idx < tracks.count; ++track_idx) for (u64 track_idx = 0; track_idx < tracks.count; ++track_idx)
{ {
// FIXME: Remove this
// if (track_idx != 0) continue;
UI_Key track_box = UI_KeyF("track %F", FmtUint(track_idx)); UI_Key track_box = UI_KeyF("track %F", FmtUint(track_idx));
UI_SetNext(Height, track_height); UI_SetNext(Height, track_height);
// UI_SetNext(Flags, UI_BoxFlag_CaptureMouse); // UI_SetNext(Flags, UI_BoxFlag_CaptureMouse);
UI_PushDF(Tag, track_box.v) UI_SetDF(Tag, track_box.v)
UI_PushDF(Parent, UI_BuildColumnEx(track_box)) UI_SetDF(Parent, UI_BuildColumnEx(track_box))
{ {
ProfTrack *track = tracks.tracks[track_idx]; ProfTrack *track = tracks.tracks[track_idx];
@ -5728,14 +5730,15 @@ void V_TickForever(WaveLaneCtx *lane)
// FIXME: Atomic // FIXME: Atomic
u64 track_top_sample_seq = Atomic64Fetch(&track->top_sample_seq);
ProfSample *samples = track->samples; ProfSample *samples = track->samples;
u64 samples_start_seq = track->top_sample_seq - MinU64(track->top_sample_seq, ProfTrackSamplesCap); u64 samples_start_seq = track_top_sample_seq - MinU64(track_top_sample_seq, ProfTrackSamplesCap);
u64 samples_end_seq = track->top_sample_seq; u64 samples_end_seq = track_top_sample_seq;
// samples_end_seq = MinU64(samples_end_seq, samples_start_seq + 512); samples_end_seq = MinU64(samples_end_seq, samples_start_seq + 512);
samples_end_seq = MinU64(samples_end_seq, samples_start_seq + 64); // samples_end_seq = MinU64(samples_end_seq, samples_start_seq + 64);
// samples_end_seq = MinU64(samples_end_seq, samples_start_seq + Kibi(16)); // samples_end_seq = MinU64(samples_end_seq, samples_start_seq + Kibi(16));
@ -5758,9 +5761,11 @@ void V_TickForever(WaveLaneCtx *lane)
{ {
ProfSample *sample = &samples[sample_seq % ProfTrackSamplesCap]; ProfSample *sample = &samples[sample_seq % ProfTrackSamplesCap];
i64 time_ns = NsFromProfStamp(sample->stamp);
b32 is_end = !!(sample->stamp & ((u64)1 << 63)); // u64 elapsed_ns = NsFromTsc
i64 time_ns = (sample->tsc - GetStartupTsc()) * GetNsPerTsc();
b32 is_end = !!(sample->flags & ProfSampleFlag_EndZone);
if (is_end) if (is_end)
{ {
depth -= 1; depth -= 1;
@ -5832,7 +5837,7 @@ void V_TickForever(WaveLaneCtx *lane)
//- Zone row //- Zone row
// UI_SetNext(Height, zone_height); // UI_SetNext(Height, zone_height);
UI_SetNext(Height, zone_height); UI_SetNext(Height, zone_height);
UI_PushDF(Parent, UI_BuildRow()) UI_SetDF(Parent, UI_BuildRow())
{ {
//- Zones in row //- Zones in row
u64 zone_idx = 0; u64 zone_idx = 0;
@ -5848,14 +5853,18 @@ void V_TickForever(WaveLaneCtx *lane)
} }
// TODO: Dim in HSV space // TODO: Dim in HSV space
Vec4 zone_color_dim = VEC4(0.15, 0.15, 0.15, 0);
Vec4 zone_color = zone->color; Vec4 zone_color = zone->color;
// Vec4 zone_color_bd = Zi; // Vec4 zone_color_bd = Zi;
Vec4 zone_color_bd = zone_color; Vec4 zone_color_bd = zone_color;
zone_color_bd.r -= zone_color_dim.r;
zone_color_bd.g -= zone_color_dim.g; // Vec4 zone_color_dim = VEC4(0.15, 0.15, 0.15, 0);
zone_color_bd.b -= zone_color_dim.b; // zone_color_bd.r -= zone_color_dim.r;
// zone_color_bd.g -= zone_color_dim.g;
// zone_color_bd.b -= zone_color_dim.b;
zone_color_bd = MulVec4(zone_color_bd, 0.65);
zone_color_bd.a = 1;
Vec4 zone_text_color = UI_Top(TextColor); Vec4 zone_text_color = UI_Top(TextColor);
zone_text_color.a *= 0.75; zone_text_color.a *= 0.75;
@ -5890,7 +5899,7 @@ void V_TickForever(WaveLaneCtx *lane)
UI_SetNext(ChildAlignment, UI_Region_Center); 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(Flags, UI_BoxFlag_Floating | UI_BoxFlag_DontClampFloatingX | UI_BoxFlag_DontClampFloatingY | UI_BoxFlag_CaptureMouse | UI_BoxFlag_Scissor);
// UI_SetNext(Flags, UI_BoxFlag_Floating | UI_BoxFlag_DontClampFloatingX | UI_BoxFlag_DontClampFloatingY); // UI_SetNext(Flags, UI_BoxFlag_Floating | UI_BoxFlag_DontClampFloatingX | UI_BoxFlag_DontClampFloatingY);
UI_PushDF(Parent, UI_BuildRowEx(zone_box)) UI_SetDF(Parent, UI_BuildRowEx(zone_box))
{ {
UI_BuildSpacer(UI_Px(zone_text_padding_px, 0.25), Axis_X); UI_BuildSpacer(UI_Px(zone_text_padding_px, 0.25), Axis_X);
@ -5949,7 +5958,7 @@ void V_TickForever(WaveLaneCtx *lane)
// UI_SetNext(FloatingPos, zone_pos); // UI_SetNext(FloatingPos, zone_pos);
// UI_SetNext(Flags, UI_BoxFlag_Floating | UI_BoxFlag_DontClampFloatingX | UI_BoxFlag_DontClampFloatingY | UI_BoxFlag_CaptureMouse); // UI_SetNext(Flags, UI_BoxFlag_Floating | UI_BoxFlag_DontClampFloatingX | UI_BoxFlag_DontClampFloatingY | UI_BoxFlag_CaptureMouse);
// // UI_SetNext(Flags, UI_BoxFlag_Floating | UI_BoxFlag_DontClampFloatingX | UI_BoxFlag_DontClampFloatingY); // // UI_SetNext(Flags, UI_BoxFlag_Floating | UI_BoxFlag_DontClampFloatingX | UI_BoxFlag_DontClampFloatingY);
// UI_PushDF(Parent, UI_BuildBoxEx(zone_box)) // UI_SetDF(Parent, UI_BuildBoxEx(zone_box))
// { // {
// } // }
// } // }
@ -6008,13 +6017,13 @@ void V_TickForever(WaveLaneCtx *lane)
UI_SetNext(Opacity, tooltip_opacity); UI_SetNext(Opacity, tooltip_opacity);
UI_SetNext(FloatingPos, tooltip_pos); UI_SetNext(FloatingPos, tooltip_pos);
UI_SetNext(Flags, UI_BoxFlag_Floating); UI_SetNext(Flags, UI_BoxFlag_Floating);
UI_PushDF(Parent, UI_BuildRowEx(tooltip_box)) UI_SetDF(Parent, UI_BuildRowEx(tooltip_box))
{ {
UI_BuildSpacer(window_padding, Axis_X); UI_BuildSpacer(window_padding, Axis_X);
UI_SetNext(Width, UI_Shrink(0, 1)); UI_SetNext(Width, UI_Shrink(0, 1));
UI_SetNext(Height, UI_Shrink(0, 1)); UI_SetNext(Height, UI_Shrink(0, 1));
UI_PushDF(Parent, UI_BuildColumn()) UI_SetDF(Parent, UI_BuildColumn())
{ {
if (hovered_zone) if (hovered_zone)
{ {
@ -6040,9 +6049,9 @@ void V_TickForever(WaveLaneCtx *lane)
// UI_BuildSpacer(window_padding, Axis_Y); // UI_BuildSpacer(window_padding, Axis_Y);
//- Footer //- Footer
UI_PushDF(Height, footer_height) UI_SetDF(Height, footer_height)
UI_PushDF(ChildAlignment, UI_Region_Center) UI_SetDF(ChildAlignment, UI_Region_Center)
UI_PushDF(Parent, UI_BuildRow()) UI_SetDF(Parent, UI_BuildRow())
{ {
UI_BuildSpacer(UI_Grow(1, 0), Axis_X); UI_BuildSpacer(UI_Grow(1, 0), Axis_X);

View File

@ -534,8 +534,6 @@ void UI_SetRawTexture(UI_Key key, G_TextureRef tex, Rng2 uv)
//~ Begin frame //~ Begin frame
UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags) UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags)
{
ProfZoneDF("Begin UI")
{ {
////////////////////////////// //////////////////////////////
//- Init persistent state //- Init persistent state
@ -579,6 +577,9 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags)
frame->rects_arena = old_rects_arena; frame->rects_arena = old_rects_arena;
} }
frame->window_frame = WND_BeginFrame(G_Format_R16G16B16A16_Float, WND_BackbufferSizeMode_MatchMonitor); frame->window_frame = WND_BeginFrame(G_Format_R16G16B16A16_Float, WND_BackbufferSizeMode_MatchMonitor);
ProfZoneDF("Begin UI")
{
UI.cl = G_PrepareCommandList(G_QueueKind_Direct); UI.cl = G_PrepareCommandList(G_QueueKind_Direct);
ResetArena(frame->arena); ResetArena(frame->arena);
ResetArena(frame->rects_arena); ResetArena(frame->rects_arena);

View File

@ -510,7 +510,7 @@ UI_Style UI_PopStyle(UI_StyleDesc desc);
#define UI_PeekTop(name, ...) UI_PopStyle(UI_STYLEDESC(name, __VA_ARGS__)).name #define UI_PeekTop(name, ...) UI_PopStyle(UI_STYLEDESC(name, __VA_ARGS__)).name
#define UI_Top(name, ...) UI_PopStyle(UI_STYLEDESC(name, .use = 1, __VA_ARGS__)).name #define UI_Top(name, ...) UI_PopStyle(UI_STYLEDESC(name, .use = 1, __VA_ARGS__)).name
#define UI_PushDF(name, ...) DeferFor(UI_Push(name, __VA_ARGS__), UI_Pop(name)) #define UI_SetDF(name, ...) DeferFor(UI_Push(name, __VA_ARGS__), UI_Pop(name))
#define UI_PushCopy(name, src, ...) do { \ #define UI_PushCopy(name, src, ...) do { \
UI_StyleDesc _new = src; \ UI_StyleDesc _new = src; \

View File

@ -472,7 +472,8 @@ WND_Frame WND_BeginFrame(G_Format backbuffer_format, WND_BackbufferSizeMode back
{ {
WND_W32_Window *window = &WND_W32.window; WND_W32_Window *window = &WND_W32.window;
WND_Frame result = Zi; WND_Frame result = Zi;
ProfZoneDF("Begin window")
{
while (!Atomic32Fetch(&window->is_ready)) while (!Atomic32Fetch(&window->is_ready))
{ {
_mm_pause(); _mm_pause();
@ -513,7 +514,11 @@ WND_Frame WND_BeginFrame(G_Format backbuffer_format, WND_BackbufferSizeMode back
{ {
backbuffer_size = result.monitor_size; backbuffer_size = result.monitor_size;
} }
ProfZoneDF("Prepare backbuffer")
{
result.backbuffer = G_PrepareBackbuffer(window->swapchain, backbuffer_format, backbuffer_size); result.backbuffer = G_PrepareBackbuffer(window->swapchain, backbuffer_format, backbuffer_size);
}
// Reset per-frame data // Reset per-frame data
if (!window->frame_arena) if (!window->frame_arena)
@ -587,13 +592,17 @@ WND_Frame WND_BeginFrame(G_Format backbuffer_format, WND_BackbufferSizeMode back
result.restore = PushString(window->frame_arena, StringFromStruct(&restore)); result.restore = PushString(window->frame_arena, StringFromStruct(&restore));
} }
}
return result; return result;
} }
void WND_EndFrame(WND_Frame frame, Vec2I32 backbuffer_pos, G_TextureRef src, Rng2I32 src_range, i32 vsync) void WND_EndFrame(WND_Frame frame, Vec2I32 backbuffer_pos, G_TextureRef src, Rng2I32 src_range, i32 vsync)
{ {
TempArena scratch = BeginScratchNoConflict(); TempArena scratch = BeginScratchNoConflict();
WND_W32_Window *window = WND_W32_WindowFromHandle(frame.window); WND_W32_Window *window = WND_W32_WindowFromHandle(frame.window);
ProfZoneDF("End window")
{
HWND hwnd = window->hwnd; HWND hwnd = window->hwnd;
// Process cmds // Process cmds
@ -835,8 +844,12 @@ void WND_EndFrame(WND_Frame frame, Vec2I32 backbuffer_pos, G_TextureRef src, Rng
} }
// Commit backbuffer // Commit backbuffer
ProfZoneDF("Commit backbuffer")
{
G_CommitBackbuffer(frame.backbuffer, backbuffer_pos, src, src_range, vsync); G_CommitBackbuffer(frame.backbuffer, backbuffer_pos, src, src_range, vsync);
}
++window->frame_gen; ++window->frame_gen;
}
EndScratch(scratch); EndScratch(scratch);
} }