diff --git a/Tracy.hpp b/Tracy.hpp index bad4f6db..4e1ab1d7 100644 --- a/Tracy.hpp +++ b/Tracy.hpp @@ -24,6 +24,8 @@ #define FrameMarkStart(x) #define FrameMarkEnd(x) +#define FrameImage(x,y,z) + #define TracyLockable( type, varname ) type varname; #define TracyLockableN( type, varname, desc ) type varname; #define TracySharedLockable( type, varname ) type varname; @@ -86,6 +88,8 @@ #define FrameMarkStart( name ) tracy::Profiler::SendFrameMark( name, tracy::QueueType::FrameMarkMsgStart ); #define FrameMarkEnd( name ) tracy::Profiler::SendFrameMark( name, tracy::QueueType::FrameMarkMsgEnd ); +#define FrameImage( image, width, height ) tracy::Profiler::SendFrameImage( image, width, height ); + #define TracyLockable( type, varname ) tracy::Lockable varname { [] () -> const tracy::SourceLocationData* { static const tracy::SourceLocationData srcloc { nullptr, #type " " #varname, __FILE__, __LINE__, 0 }; return &srcloc; }() }; #define TracyLockableN( type, varname, desc ) tracy::Lockable varname { [] () -> const tracy::SourceLocationData* { static const tracy::SourceLocationData srcloc { nullptr, desc, __FILE__, __LINE__, 0 }; return &srcloc; }() }; #define TracySharedLockable( type, varname ) tracy::SharedLockable varname { [] () -> const tracy::SourceLocationData* { static const tracy::SourceLocationData srcloc { nullptr, #type " " #varname, __FILE__, __LINE__, 0 }; return &srcloc; }() }; diff --git a/client/TracyProfiler.cpp b/client/TracyProfiler.cpp index 6b7a9c39..137806af 100644 --- a/client/TracyProfiler.cpp +++ b/client/TracyProfiler.cpp @@ -1362,6 +1362,10 @@ static void FreeAssociatedMemory( const QueueItem& item ) ptr = MemRead( &item.callstackAlloc.ptr ); tracy_free( (void*)ptr ); break; + case QueueType::FrameImage: + ptr = MemRead( &item.frameImage.image ); + tracy_free( (void*)ptr ); + break; default: assert( false ); break; @@ -1446,6 +1450,11 @@ Profiler::DequeueStatus Profiler::Dequeue( moodycamel::ConsumerToken& token ) SendCallstackAlloc( ptr ); tracy_free( (void*)ptr ); break; + case QueueType::FrameImage: + ptr = MemRead( &item->frameImage.image ); + SendLongString( ptr, (const char*)ptr, QueueType::FrameImageData ); + tracy_free( (void*)ptr ); + break; default: assert( false ); break; @@ -1567,6 +1576,26 @@ void Profiler::SendString( uint64_t str, const char* ptr, QueueType type ) AppendDataUnsafe( ptr, l16 ); } +void Profiler::SendLongString( uint64_t str, const char* ptr, QueueType type ) +{ + assert( type == QueueType::FrameImageData ); + + QueueItem item; + MemWrite( &item.hdr.type, type ); + MemWrite( &item.stringTransfer.ptr, str ); + + auto len = strlen( ptr ); + assert( len <= std::numeric_limits::max() ); + assert( QueueDataSize[(int)type] + sizeof( uint32_t ) + len <= TargetFrameSize ); + auto l32 = uint32_t( len ); + + NeedDataSize( QueueDataSize[(int)type] + sizeof( l32 ) + l32 ); + + AppendDataUnsafe( &item, QueueDataSize[(int)type] ); + AppendDataUnsafe( &l32, sizeof( l32 ) ); + AppendDataUnsafe( ptr, l32 ); +} + void Profiler::SendSourceLocation( uint64_t ptr ) { auto srcloc = (const SourceLocationData*)ptr; diff --git a/client/TracyProfiler.hpp b/client/TracyProfiler.hpp index 5bc57b8e..38c7dabb 100644 --- a/client/TracyProfiler.hpp +++ b/client/TracyProfiler.hpp @@ -170,6 +170,25 @@ public: GetProfiler().m_serialLock.unlock(); } + static tracy_force_inline void SendFrameImage( void* image, uint16_t w, uint16_t h ) + { +#ifdef TRACY_ON_DEMAND + if( !GetProfiler().IsConnected() ) return; +#endif + const auto sz = size_t( w ) * size_t( h ) * 4; + Magic magic; + auto token = GetToken(); + auto ptr = (char*)tracy_malloc( sz ); + memcpy( ptr, image, sz ); + auto& tail = token->get_tail_index(); + auto item = token->enqueue_begin( magic ); + MemWrite( &item->hdr.type, QueueType::FrameImage ); + MemWrite( &item->frameImage.image, (uint64_t)ptr ); + MemWrite( &item->frameImage.w, w ); + MemWrite( &item->frameImage.h, h ); + tail.store( magic + 1, std::memory_order_release ); + } + static tracy_force_inline void PlotData( const char* name, int64_t val ) { #ifdef TRACY_ON_DEMAND @@ -422,6 +441,7 @@ private: bool SendData( const char* data, size_t len ); void SendString( uint64_t ptr, const char* str, QueueType type ); + void SendLongString( uint64_t ptr, const char* str, QueueType type ); void SendSourceLocation( uint64_t ptr ); void SendSourceLocationPayload( uint64_t ptr ); void SendCallstackPayload( uint64_t ptr ); diff --git a/common/TracyProtocol.hpp b/common/TracyProtocol.hpp index 6ed43394..cc59d2fb 100644 --- a/common/TracyProtocol.hpp +++ b/common/TracyProtocol.hpp @@ -9,7 +9,7 @@ namespace tracy { -enum : uint32_t { ProtocolVersion = 6 }; +enum : uint32_t { ProtocolVersion = 7 }; using lz4sz_t = uint32_t; diff --git a/common/TracyQueue.hpp b/common/TracyQueue.hpp index e8328815..51ad6249 100644 --- a/common/TracyQueue.hpp +++ b/common/TracyQueue.hpp @@ -17,6 +17,7 @@ enum class QueueType : uint8_t CallstackMemory, Callstack, CallstackAlloc, + FrameImage, Terminate, KeepAlive, Crash, @@ -61,6 +62,7 @@ enum class QueueType : uint8_t CallstackPayload, CallstackAllocPayload, FrameName, + FrameImageData, NUM_TYPES }; @@ -98,6 +100,13 @@ struct QueueFrameMark uint64_t name; // ptr }; +struct QueueFrameImage +{ + uint64_t image; // ptr + uint16_t w; + uint16_t h; +}; + struct QueueSourceLocation { uint64_t name; @@ -310,6 +319,7 @@ struct QueueItem QueueZoneValidation zoneValidation; QueueStringTransfer stringTransfer; QueueFrameMark frameMark; + QueueFrameImage frameImage; QueueSourceLocation srcloc; QueueZoneText zoneText; QueueLockAnnounce lockAnnounce; @@ -351,6 +361,7 @@ static const size_t QueueDataSize[] = { sizeof( QueueHeader ) + sizeof( QueueCallstackMemory ), sizeof( QueueHeader ) + sizeof( QueueCallstack ), sizeof( QueueHeader ) + sizeof( QueueCallstackAlloc ), + sizeof( QueueHeader ) + sizeof( QueueFrameImage ), // above items must be first sizeof( QueueHeader ), // terminate sizeof( QueueHeader ), // keep alive @@ -397,6 +408,7 @@ static const size_t QueueDataSize[] = { sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // callstack payload sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // callstack alloc payload sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // frame name + sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // frame image data }; static_assert( QueueItemSize == 32, "Queue item size not 32 bytes" ); diff --git a/server/TracyEvent.hpp b/server/TracyEvent.hpp index a4a16108..843838ee 100644 --- a/server/TracyEvent.hpp +++ b/server/TracyEvent.hpp @@ -356,6 +356,12 @@ struct SourceLocationComparator } }; +struct FrameImage +{ + const char* ptr; + uint16_t w, h; +}; + } #endif diff --git a/server/TracyWorker.cpp b/server/TracyWorker.cpp index 9080c1d5..34596453 100644 --- a/server/TracyWorker.cpp +++ b/server/TracyWorker.cpp @@ -1825,7 +1825,8 @@ void Worker::Exec() if( m_terminate ) { if( m_pendingStrings != 0 || m_pendingThreads != 0 || m_pendingSourceLocation != 0 || m_pendingCallstackFrames != 0 || - !m_pendingCustomStrings.empty() || m_data.plots.IsPending() || m_pendingCallstackPtr != 0 || m_pendingCallstackSubframes != 0 ) + !m_pendingCustomStrings.empty() || m_data.plots.IsPending() || m_pendingCallstackPtr != 0 || + m_pendingCallstackSubframes != 0 || !m_pendingFrameImageData.empty() ) { continue; } @@ -1871,44 +1872,55 @@ bool Worker::DispatchProcess( const QueueItem& ev, char*& ptr ) if( ev.hdr.idx >= (int)QueueType::StringData ) { ptr += sizeof( QueueHeader ) + sizeof( QueueStringTransfer ); - uint16_t sz; - memcpy( &sz, ptr, sizeof( sz ) ); - ptr += sizeof( sz ); - switch( ev.hdr.type ) + if( ev.hdr.type == QueueType::FrameImageData ) { - case QueueType::CustomStringData: - AddCustomString( ev.stringTransfer.ptr, ptr, sz ); - break; - case QueueType::StringData: - AddString( ev.stringTransfer.ptr, ptr, sz ); - m_serverQuerySpaceLeft++; - break; - case QueueType::ThreadName: - AddThreadString( ev.stringTransfer.ptr, ptr, sz ); - m_serverQuerySpaceLeft++; - break; - case QueueType::PlotName: - HandlePlotName( ev.stringTransfer.ptr, ptr, sz ); - m_serverQuerySpaceLeft++; - break; - case QueueType::SourceLocationPayload: - AddSourceLocationPayload( ev.stringTransfer.ptr, ptr, sz ); - break; - case QueueType::CallstackPayload: - AddCallstackPayload( ev.stringTransfer.ptr, ptr, sz ); - break; - case QueueType::FrameName: - HandleFrameName( ev.stringTransfer.ptr, ptr, sz ); - m_serverQuerySpaceLeft++; - break; - case QueueType::CallstackAllocPayload: - AddCallstackAllocPayload( ev.stringTransfer.ptr, ptr, sz ); - break; - default: - assert( false ); - break; + uint32_t sz; + memcpy( &sz, ptr, sizeof( sz ) ); + ptr += sizeof( sz ); + AddFrameImageData( ev.stringTransfer.ptr, ptr, sz ); + ptr += sz; + } + else + { + uint16_t sz; + memcpy( &sz, ptr, sizeof( sz ) ); + ptr += sizeof( sz ); + switch( ev.hdr.type ) + { + case QueueType::CustomStringData: + AddCustomString( ev.stringTransfer.ptr, ptr, sz ); + break; + case QueueType::StringData: + AddString( ev.stringTransfer.ptr, ptr, sz ); + m_serverQuerySpaceLeft++; + break; + case QueueType::ThreadName: + AddThreadString( ev.stringTransfer.ptr, ptr, sz ); + m_serverQuerySpaceLeft++; + break; + case QueueType::PlotName: + HandlePlotName( ev.stringTransfer.ptr, ptr, sz ); + m_serverQuerySpaceLeft++; + break; + case QueueType::SourceLocationPayload: + AddSourceLocationPayload( ev.stringTransfer.ptr, ptr, sz ); + break; + case QueueType::CallstackPayload: + AddCallstackPayload( ev.stringTransfer.ptr, ptr, sz ); + break; + case QueueType::FrameName: + HandleFrameName( ev.stringTransfer.ptr, ptr, sz ); + m_serverQuerySpaceLeft++; + break; + case QueueType::CallstackAllocPayload: + AddCallstackAllocPayload( ev.stringTransfer.ptr, ptr, sz ); + break; + default: + assert( false ); + break; + } + ptr += sz; } - ptr += sz; return true; } else @@ -2223,6 +2235,14 @@ void Worker::AddCustomString( uint64_t ptr, char* str, size_t sz ) m_pendingCustomStrings.emplace( ptr, StoreString( str, sz ) ); } +void Worker::AddFrameImageData( uint64_t ptr, char* data, size_t sz ) +{ + assert( m_pendingFrameImageData.find( ptr ) == m_pendingFrameImageData.end() ); + auto image = m_slab.AllocBig( sz ); + memcpy( image, data, sz ); + m_pendingFrameImageData.emplace( ptr, image ); +} + uint64_t Worker::GetCanonicalPointer( const CallstackFrameId& id ) const { assert( id.sel == 0 ); @@ -2486,6 +2506,9 @@ bool Worker::Process( const QueueItem& ev ) case QueueType::FrameMarkMsgEnd: ProcessFrameMarkEnd( ev.frameMark ); break; + case QueueType::FrameImage: + ProcessFrameImage( ev.frameImage ); + break; case QueueType::SourceLocation: AddSourceLocation( ev.srcloc ); m_serverQuerySpaceLeft++; @@ -2848,6 +2871,22 @@ void Worker::ProcessFrameMarkEnd( const QueueFrameMark& ev ) m_data.lastTime = std::max( m_data.lastTime, time ); } +void Worker::ProcessFrameImage( const QueueFrameImage& ev ) +{ + auto it = m_pendingFrameImageData.find( ev.image ); + assert( it != m_pendingFrameImageData.end() ); + + auto fi = m_slab.Alloc(); + fi->ptr = (const char*)it->second; + fi->w = ev.w; + fi->h = ev.h; + + const auto idx = m_data.frameImage.size(); + m_data.frameImage.push_back( fi ); + + m_pendingFrameImageData.erase( it ); +} + void Worker::ProcessZoneText( const QueueZoneText& ev ) { auto tit = m_threadMap.find( ev.thread ); diff --git a/server/TracyWorker.hpp b/server/TracyWorker.hpp index f2267678..bfe6fb9f 100644 --- a/server/TracyWorker.hpp +++ b/server/TracyWorker.hpp @@ -181,6 +181,8 @@ private: Vector> zoneVectorCache; + Vector frameImage; + CrashEvent crashEvent; }; @@ -354,6 +356,7 @@ private: tracy_force_inline void ProcessFrameMark( const QueueFrameMark& ev ); tracy_force_inline void ProcessFrameMarkStart( const QueueFrameMark& ev ); tracy_force_inline void ProcessFrameMarkEnd( const QueueFrameMark& ev ); + tracy_force_inline void ProcessFrameImage( const QueueFrameImage& ev ); tracy_force_inline void ProcessZoneText( const QueueZoneText& ev ); tracy_force_inline void ProcessZoneName( const QueueZoneText& ev ); tracy_force_inline void ProcessLockAnnounce( const QueueLockAnnounce& ev ); @@ -425,6 +428,7 @@ private: void AddString( uint64_t ptr, char* str, size_t sz ); void AddThreadString( uint64_t id, char* str, size_t sz ); void AddCustomString( uint64_t ptr, char* str, size_t sz ); + void AddFrameImageData( uint64_t ptr, char* data, size_t sz ); tracy_force_inline void AddCallstackPayload( uint64_t ptr, char* data, size_t sz ); tracy_force_inline void AddCallstackAllocPayload( uint64_t ptr, char* data, size_t sz ); @@ -491,6 +495,7 @@ private: flat_hash_map> m_sourceLocationShrink; flat_hash_map> m_threadMap; flat_hash_map> m_nextCallstack; + flat_hash_map> m_pendingFrameImageData; uint32_t m_pendingStrings; uint32_t m_pendingThreads;