diff --git a/Tracy.hpp b/Tracy.hpp index 01934794..1c757230 100644 --- a/Tracy.hpp +++ b/Tracy.hpp @@ -66,9 +66,19 @@ #define TracyFree( ptr ) tracy::Profiler::MemFree( ptr ); #ifdef TRACY_HAS_CALLSTACK +# define ZoneScopedS( depth ) static const tracy::SourceLocation __tracy_source_location { nullptr, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; tracy::ScopedZone ___tracy_scoped_zone( &__tracy_source_location, depth ); +# define ZoneScopedNS( name, depth ) static const tracy::SourceLocation __tracy_source_location { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; tracy::ScopedZone ___tracy_scoped_zone( &__tracy_source_location, depth ); +# define ZoneScopedCS( color, depth ) __tracy_source_location { nullptr, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; tracy::ScopedZone ___tracy_scoped_zone( &__tracy_source_location, depth ); +# define ZoneScopedNCS( name, color, depth ) static const tracy::SourceLocation __tracy_source_location { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; tracy::ScopedZone ___tracy_scoped_zone( &__tracy_source_location, depth ); + # define TracyAllocS( ptr, size, depth ) tracy::Profiler::MemAllocCallstack( ptr, size, depth ); # define TracyFreeS( ptr, depth ) tracy::Profiler::MemFreeCallstack( ptr, depth ); #else +# define ZoneScopedS( depth ) ZoneScoped +# define ZoneScopedNS( name, depth ) ZoneScopedN( name ) +# define ZoneScopedCS( color, depth ) ZoneScopedC( color ) +# define ZoneScopedNCS( name, color, depth ) ZoneScopedNC( name, color ) + # define TracyAllocS( ptr, size, depth ) TracyAlloc( ptr, size ) # define TracyFreeS( ptr, depth ) TracyFree( ptr ) #endif diff --git a/client/TracyProfiler.cpp b/client/TracyProfiler.cpp index e7c87ea5..bc64b886 100644 --- a/client/TracyProfiler.cpp +++ b/client/TracyProfiler.cpp @@ -389,6 +389,11 @@ Profiler::DequeueStatus Profiler::Dequeue( moodycamel::ConsumerToken& token ) SendSourceLocationPayload( ptr ); tracy_free( (void*)ptr ); break; + case QueueType::Callstack: + ptr = MemRead( &item->callstack.ptr ); + SendCallstackPayload( ptr ); + tracy_free( (void*)ptr ); + break; default: assert( false ); break; diff --git a/client/TracyProfiler.hpp b/client/TracyProfiler.hpp index e58ae3e6..b6f32695 100644 --- a/client/TracyProfiler.hpp +++ b/client/TracyProfiler.hpp @@ -238,6 +238,21 @@ public: s_profiler.m_serialLock.unlock(); } + static tracy_force_inline void SendCallstack( int depth, uint64_t thread ) + { +#ifdef TRACY_HAS_CALLSTACK + auto ptr = Callstack( depth ); + Magic magic; + auto& token = s_token.ptr; + auto& tail = token->get_tail_index(); + auto item = token->enqueue_begin( magic ); + MemWrite( &item->hdr.type, QueueType::Callstack ); + MemWrite( &item->callstack.ptr, ptr ); + MemWrite( &item->callstack.thread, thread ); + tail.store( magic + 1, std::memory_order_release ); +#endif + } + static bool ShouldExit(); private: diff --git a/client/TracyScoped.hpp b/client/TracyScoped.hpp index 4007e7c8..12a87993 100644 --- a/client/TracyScoped.hpp +++ b/client/TracyScoped.hpp @@ -36,6 +36,29 @@ public: tail.store( magic + 1, std::memory_order_release ); } + tracy_force_inline ScopedZone( const SourceLocation* srcloc, int depth ) + { + const auto thread = GetThreadHandle(); + m_thread = thread; + Magic magic; + auto& token = s_token.ptr; + auto& tail = token->get_tail_index(); + auto item = token->enqueue_begin( magic ); + MemWrite( &item->hdr.type, QueueType::ZoneBeginCallstack ); +#ifdef TRACY_RDTSCP_OPT + MemWrite( &item->zoneBegin.time, Profiler::GetTime( item->zoneBegin.cpu ) ); +#else + uint32_t cpu; + MemWrite( &item->zoneBegin.time, Profiler::GetTime( cpu ) ); + MemWrite( &item->zoneBegin.cpu, cpu ); +#endif + MemWrite( &item->zoneBegin.thread, thread ); + MemWrite( &item->zoneBegin.srcloc, (uint64_t)srcloc ); + tail.store( magic + 1, std::memory_order_release ); + + s_profiler.SendCallstack( depth, thread ); + } + tracy_force_inline ~ScopedZone() { Magic magic; diff --git a/common/TracyQueue.hpp b/common/TracyQueue.hpp index 85f52544..aa7976fb 100644 --- a/common/TracyQueue.hpp +++ b/common/TracyQueue.hpp @@ -12,8 +12,10 @@ enum class QueueType : uint8_t Message, ZoneBeginAllocSrcLoc, CallstackMemory, + Callstack, Terminate, ZoneBegin, + ZoneBeginCallstack, ZoneEnd, FrameMarkMsg, SourceLocation, @@ -216,6 +218,12 @@ struct QueueCallstackMemory uint64_t ptr; }; +struct QueueCallstack +{ + uint64_t ptr; + uint64_t thread; +}; + struct QueueCallstackFrame { uint64_t ptr; @@ -259,6 +267,7 @@ struct QueueItem QueueMemAlloc memAlloc; QueueMemFree memFree; QueueCallstackMemory callstackMemory; + QueueCallstack callstack; QueueCallstackFrame callstackFrame; }; }; @@ -272,9 +281,11 @@ static const size_t QueueDataSize[] = { sizeof( QueueHeader ) + sizeof( QueueMessage ), sizeof( QueueHeader ) + sizeof( QueueZoneBegin ), // allocated source location sizeof( QueueHeader ) + sizeof( QueueCallstackMemory ), + sizeof( QueueHeader ) + sizeof( QueueCallstack ), // above items must be first sizeof( QueueHeader ), // terminate sizeof( QueueHeader ) + sizeof( QueueZoneBegin ), + sizeof( QueueHeader ) + sizeof( QueueZoneBegin ), // callstack sizeof( QueueHeader ) + sizeof( QueueZoneEnd ), sizeof( QueueHeader ) + sizeof( QueueFrameMark ), sizeof( QueueHeader ) + sizeof( QueueSourceLocation ),