1
0
mirror of https://github.com/wolfpld/tracy synced 2025-04-30 12:53:51 +00:00

Compress frame images in a separate thread.

This commit is contained in:
Bartosz Taudul 2019-06-26 23:18:30 +02:00
parent 7ebd2162c6
commit bb35f9a897
5 changed files with 71 additions and 23 deletions

View File

@ -956,11 +956,9 @@ Profiler::Profiler()
, m_serialDequeue( 1024*1024 ) , m_serialDequeue( 1024*1024 )
, m_fiQueue( 16 ) , m_fiQueue( 16 )
, m_fiDequeue( 16 ) , m_fiDequeue( 16 )
, m_etc1Buf( nullptr ) , m_frameCount( 0 )
, m_etc1BufSize( 0 )
#ifdef TRACY_ON_DEMAND #ifdef TRACY_ON_DEMAND
, m_isConnected( false ) , m_isConnected( false )
, m_frameCount( 0 )
, m_connectionId( 0 ) , m_connectionId( 0 )
, m_deferredQueue( 64*1024 ) , m_deferredQueue( 64*1024 )
#endif #endif
@ -1040,7 +1038,6 @@ Profiler::~Profiler()
tracy_free( m_lz4Buf ); tracy_free( m_lz4Buf );
tracy_free( m_itemBuf ); tracy_free( m_itemBuf );
tracy_free( m_buffer ); tracy_free( m_buffer );
tracy_free( m_etc1Buf );
LZ4_freeStream( (LZ4_stream_t*)m_stream ); LZ4_freeStream( (LZ4_stream_t*)m_stream );
if( m_sock ) if( m_sock )
@ -1403,7 +1400,68 @@ void Profiler::Worker()
void Profiler::CompressWorker() void Profiler::CompressWorker()
{ {
for(;;)
{
const auto shouldExit = ShouldExit();
{
bool lockHeld = true;
while( !m_fiLock.try_lock() )
{
if( m_shutdownManual.load( std::memory_order_relaxed ) )
{
lockHeld = false;
break;
}
}
m_fiQueue.swap( m_fiDequeue );
if( lockHeld )
{
m_fiLock.unlock();
}
}
const auto sz = m_fiDequeue.size();
if( sz > 0 )
{
auto fi = m_fiDequeue.data();
auto end = fi + sz;
while( fi != end )
{
const auto w = fi->w;
const auto h = fi->h;
const auto csz = size_t( w * h / 2 );
auto etc1buf = (char*)tracy_malloc( csz );
CompressImageEtc1( (const char*)fi->image, etc1buf, w, h );
tracy_free( fi->image );
Magic magic;
auto token = GetToken();
auto& tail = token->get_tail_index();
auto item = token->enqueue_begin<tracy::moodycamel::CanAlloc>( magic );
MemWrite( &item->hdr.type, QueueType::FrameImage );
MemWrite( &item->frameImage.image, (uint64_t)etc1buf );
MemWrite( &item->frameImage.frame, fi->frame );
MemWrite( &item->frameImage.w, w );
MemWrite( &item->frameImage.h, h );
uint8_t flip = fi->flip;
MemWrite( &item->frameImage.flip, flip );
tail.store( magic + 1, std::memory_order_release );
fi++;
}
m_fiDequeue.clear();
}
else
{
std::this_thread::sleep_for( std::chrono::milliseconds( 20 ) );
}
if( shouldExit )
{
return;
}
}
} }
static void FreeAssociatedMemory( const QueueItem& item ) static void FreeAssociatedMemory( const QueueItem& item )
@ -1536,14 +1594,8 @@ Profiler::DequeueStatus Profiler::Dequeue( moodycamel::ConsumerToken& token )
const auto w = MemRead<uint16_t>( &item->frameImage.w ); const auto w = MemRead<uint16_t>( &item->frameImage.w );
const auto h = MemRead<uint16_t>( &item->frameImage.h ); const auto h = MemRead<uint16_t>( &item->frameImage.h );
const auto csz = size_t( w * h / 2 ); const auto csz = size_t( w * h / 2 );
if( csz > m_etc1BufSize ) SendLongString( ptr, (const char*)ptr, csz, QueueType::FrameImageData );
{
tracy_free( m_etc1Buf );
m_etc1Buf = (char*)tracy_malloc( csz );
}
CompressImageEtc1( (const char*)ptr, m_etc1Buf, w, h );
tracy_free( (void*)ptr ); tracy_free( (void*)ptr );
SendLongString( ptr, m_etc1Buf, csz, QueueType::FrameImageData );
break; break;
} }
default: default:

View File

@ -92,7 +92,7 @@ class Profiler
struct FrameImageQueueItem struct FrameImageQueueItem
{ {
void* image; void* image;
int64_t time; uint64_t frame;
uint16_t w; uint16_t w;
uint16_t h; uint16_t h;
uint8_t offset; uint8_t offset;
@ -154,8 +154,8 @@ public:
static tracy_force_inline void SendFrameMark( const char* name ) static tracy_force_inline void SendFrameMark( const char* name )
{ {
#ifdef TRACY_ON_DEMAND
if( !name ) GetProfiler().m_frameCount.fetch_add( 1, std::memory_order_relaxed ); if( !name ) GetProfiler().m_frameCount.fetch_add( 1, std::memory_order_relaxed );
#ifdef TRACY_ON_DEMAND
if( !GetProfiler().IsConnected() ) return; if( !GetProfiler().IsConnected() ) return;
#endif #endif
Magic magic; Magic magic;
@ -189,7 +189,6 @@ public:
#ifdef TRACY_ON_DEMAND #ifdef TRACY_ON_DEMAND
if( !profiler.IsConnected() ) return; if( !profiler.IsConnected() ) return;
#endif #endif
const auto time = GetTime();
const auto sz = size_t( w ) * size_t( h ) * 4; const auto sz = size_t( w ) * size_t( h ) * 4;
auto ptr = (char*)tracy_malloc( sz ); auto ptr = (char*)tracy_malloc( sz );
memcpy( ptr, image, sz ); memcpy( ptr, image, sz );
@ -197,10 +196,9 @@ public:
profiler.m_fiLock.lock(); profiler.m_fiLock.lock();
auto fi = profiler.m_fiQueue.prepare_next(); auto fi = profiler.m_fiQueue.prepare_next();
fi->image = ptr; fi->image = ptr;
fi->time = time; fi->frame = profiler.m_frameCount.load( std::memory_order_relaxed ) - offset;
fi->w = w; fi->w = w;
fi->h = h; fi->h = h;
fi->offset = offset;
fi->flip = flip; fi->flip = flip;
profiler.m_fiQueue.commit_next(); profiler.m_fiQueue.commit_next();
profiler.m_fiLock.unlock(); profiler.m_fiLock.unlock();
@ -554,12 +552,9 @@ private:
FastVector<FrameImageQueueItem> m_fiQueue, m_fiDequeue; FastVector<FrameImageQueueItem> m_fiQueue, m_fiDequeue;
TracyMutex m_fiLock; TracyMutex m_fiLock;
char* m_etc1Buf; std::atomic<uint64_t> m_frameCount;
size_t m_etc1BufSize;
#ifdef TRACY_ON_DEMAND #ifdef TRACY_ON_DEMAND
std::atomic<bool> m_isConnected; std::atomic<bool> m_isConnected;
std::atomic<uint64_t> m_frameCount;
std::atomic<uint64_t> m_connectionId; std::atomic<uint64_t> m_connectionId;
TracyMutex m_deferredLock; TracyMutex m_deferredLock;

View File

@ -9,7 +9,7 @@
namespace tracy namespace tracy
{ {
enum : uint32_t { ProtocolVersion = 9 }; enum : uint32_t { ProtocolVersion = 10 };
enum : uint32_t { BroadcastVersion = 0 }; enum : uint32_t { BroadcastVersion = 0 };
using lz4sz_t = uint32_t; using lz4sz_t = uint32_t;

View File

@ -103,9 +103,9 @@ struct QueueFrameMark
struct QueueFrameImage struct QueueFrameImage
{ {
uint64_t image; // ptr uint64_t image; // ptr
uint64_t frame;
uint16_t w; uint16_t w;
uint16_t h; uint16_t h;
uint8_t offset;
uint8_t flip; uint8_t flip;
}; };

View File

@ -3005,7 +3005,8 @@ void Worker::ProcessFrameImage( const QueueFrameImage& ev )
assert( it != m_pendingFrameImageData.end() ); assert( it != m_pendingFrameImageData.end() );
auto& frames = m_data.framesBase->frames; auto& frames = m_data.framesBase->frames;
const auto fidx = (int64_t)frames.size() - 1 - ev.offset; const auto fidx = ev.frame - m_data.frameOffset + 1;
assert( fidx < frames.size() );
if( m_onDemand && fidx <= 1 ) if( m_onDemand && fidx <= 1 )
{ {
m_pendingFrameImageData.erase( it ); m_pendingFrameImageData.erase( it );