99 lines
4.0 KiB
C
99 lines
4.0 KiB
C
#if !defined(DN_CORE_DEBUG_H)
|
|
#define DN_CORE_DEBUG_H
|
|
|
|
// NOTE: DN_StackTrace /////////////////////////////////////////////////////////////////////////////
|
|
// NOTE: DN_Debug //////////////////////////////////////////////////////////////////////////////////
|
|
enum DN_DebugAllocFlag
|
|
{
|
|
DN_DebugAllocFlag_Freed = 1 << 0,
|
|
DN_DebugAllocFlag_LeakPermitted = 1 << 1,
|
|
};
|
|
|
|
struct DN_DebugAlloc
|
|
{
|
|
void *ptr; // 8 Pointer to the allocation being tracked
|
|
DN_USize size; // 16 Size of the allocation
|
|
DN_USize freed_size; // 24 Store the size of the allocation when it is freed
|
|
DN_Str8 stack_trace; // 40 Stack trace at the point of allocation
|
|
DN_Str8 freed_stack_trace; // 56 Stack trace of where the allocation was freed
|
|
DN_U16 flags; // 72 Bit flags from `DN_DebugAllocFlag`
|
|
};
|
|
|
|
static_assert(sizeof(DN_DebugAlloc) == 64 || sizeof(DN_DebugAlloc) == 32, // NOTE: 64 bit vs 32 bit pointers respectively
|
|
"We aim to keep the allocation record as light as possible as "
|
|
"memory tracking can get expensive. Enforce that there is no "
|
|
"unexpected padding.");
|
|
|
|
// NOTE: DN_Profiler ///////////////////////////////////////////////////////////////////////////////
|
|
#if !defined(DN_NO_PROFILER)
|
|
#if !defined(DN_PROFILER_ANCHOR_BUFFER_SIZE)
|
|
#define DN_PROFILER_ANCHOR_BUFFER_SIZE 256
|
|
#endif
|
|
|
|
struct DN_ProfilerAnchor
|
|
{
|
|
// Inclusive refers to the time spent to complete the function call
|
|
// including all children functions.
|
|
//
|
|
// Exclusive refers to the time spent in the function, not including any
|
|
// time spent in children functions that we call that are also being
|
|
// profiled. If we recursively call into ourselves, the time we spent in
|
|
// our function is accumulated.
|
|
DN_U64 tsc_inclusive;
|
|
DN_U64 tsc_exclusive;
|
|
DN_U16 hit_count;
|
|
DN_Str8 name;
|
|
};
|
|
|
|
struct DN_ProfilerZone
|
|
{
|
|
DN_U16 anchor_index;
|
|
DN_U64 begin_tsc;
|
|
DN_U16 parent_zone;
|
|
DN_U64 elapsed_tsc_at_zone_start;
|
|
};
|
|
|
|
#if defined(__cplusplus)
|
|
struct DN_ProfilerZoneScope
|
|
{
|
|
DN_ProfilerZoneScope(DN_Str8 name, DN_U16 anchor_index);
|
|
~DN_ProfilerZoneScope();
|
|
DN_ProfilerZone zone;
|
|
};
|
|
|
|
#define DN_Profiler_ZoneScopeAtIndex(name, anchor_index) auto DN_UniqueName(profile_zone_) = DN_ProfilerZoneScope(DN_STR8(name), anchor_index)
|
|
#define DN_Profiler_ZoneScope(name) DN_Profiler_ZoneScopeAtIndex(name, __COUNTER__ + 1)
|
|
#endif
|
|
|
|
#define DN_Profiler_ZoneBlockIndex(name, index) \
|
|
for (DN_ProfilerZone DN_UniqueName(profile_zone__) = DN_Profiler_BeginZoneAtIndex(name, index), DN_UniqueName(dummy__) = {}; \
|
|
DN_UniqueName(dummy__).begin_tsc == 0; \
|
|
DN_Profiler_EndZone(DN_UniqueName(profile_zone__)), DN_UniqueName(dummy__).begin_tsc = 1)
|
|
|
|
#define DN_Profiler_ZoneBlock(name) DN_Profiler_ZoneBlockIndex(DN_STR8(name), __COUNTER__ + 1)
|
|
|
|
enum DN_ProfilerAnchorBuffer
|
|
{
|
|
DN_ProfilerAnchorBuffer_Back,
|
|
DN_ProfilerAnchorBuffer_Front,
|
|
};
|
|
|
|
struct DN_Profiler
|
|
{
|
|
DN_ProfilerAnchor anchors[2][DN_PROFILER_ANCHOR_BUFFER_SIZE];
|
|
DN_U8 active_anchor_buffer;
|
|
DN_U16 parent_zone;
|
|
};
|
|
|
|
DN_API DN_ProfilerAnchor * DN_Profiler_ReadBuffer ();
|
|
DN_API DN_ProfilerAnchor * DN_Profiler_WriteBuffer ();
|
|
#define DN_Profiler_BeginZone(name) DN_Profiler_BeginZoneAtIndex(DN_STR8(name), __COUNTER__ + 1)
|
|
DN_API DN_ProfilerZone DN_Profiler_BeginZoneAtIndex (DN_Str8 name, DN_U16 anchor_index);
|
|
DN_API void DN_Profiler_EndZone (DN_ProfilerZone zone);
|
|
DN_API DN_ProfilerAnchor * DN_Profiler_AnchorBuffer (DN_ProfilerAnchorBuffer buffer);
|
|
DN_API void DN_Profiler_SwapAnchorBuffer ();
|
|
DN_API void DN_Profiler_Dump (DN_U64 tsc_per_second);
|
|
|
|
#endif // !defined(DN_NO_PROFILER)
|
|
#endif // DN_CORE_DEBUG_H
|