1 #ifndef __TRACYPROFILER_HPP__
2 #define __TRACYPROFILER_HPP__
14 #include "../common/TracyQueue.hpp"
15 #include "../common/TracyAlign.hpp"
16 #include "../common/TracyAlloc.hpp"
17 #include "../common/TracyMutex.hpp"
18 #include "../common/TracyProtocol.hpp"
20 #if defined _WIN32 || defined __CYGWIN__
24 # include <TargetConditionals.h>
25 # include <mach/mach_time.h>
28 #if defined _WIN32 || defined __CYGWIN__ || ( defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64 ) || ( defined TARGET_OS_IOS && TARGET_OS_IOS == 1 )
29 # define TRACY_HW_TIMER
32 #if !defined TRACY_HW_TIMER
37 # define TracyConcat(x,y) TracyConcatIndirect(x,y)
39 #ifndef TracyConcatIndirect
40 # define TracyConcatIndirect(x,y) x##y
45 #if defined(TRACY_DELAYED_INIT) && defined(TRACY_MANUAL_LIFETIME)
46 void StartupProfiler();
47 void ShutdownProfiler();
79 #ifdef TRACY_ON_DEMAND
88 #define TracyLfqPrepare( _type ) \
89 moodycamel::ConcurrentQueueDefaultTraits::index_t __magic; \
90 auto __token = GetToken(); \
91 auto& __tail = __token->get_tail_index(); \
92 auto item = __token->enqueue_begin( __magic ); \
93 MemWrite( &item->hdr.type, _type );
95 #define TracyLfqCommit \
96 __tail.store( __magic + 1, std::memory_order_release );
98 #define TracyLfqPrepareC( _type ) \
99 tracy::moodycamel::ConcurrentQueueDefaultTraits::index_t __magic; \
100 auto __token = tracy::GetToken(); \
101 auto& __tail = __token->get_tail_index(); \
102 auto item = __token->enqueue_begin( __magic ); \
103 tracy::MemWrite( &item->hdr.type, _type );
105 #define TracyLfqCommitC \
106 __tail.store( __magic + 1, std::memory_order_release );
131 #ifdef TRACY_HW_TIMER
132 # if defined TARGET_OS_IOS && TARGET_OS_IOS == 1
133 return mach_absolute_time();
134 # elif defined _WIN32 || defined __CYGWIN__
135 # ifdef TRACY_TIMER_QPC
140 # elif defined __i386 || defined _M_IX86
142 asm volatile (
"rdtsc" :
"=a" (eax),
"=d" (edx) );
144 # elif defined __x86_64__ || defined _M_X64
146 asm volatile (
"rdtsc" :
"=a" (rax),
"=d" (rdx) );
147 return ( rdx << 32 ) + rax;
149 # error "TRACY_HW_TIMER detection logic needs fixing"
152 # if defined __linux__ && defined CLOCK_MONOTONIC_RAW
154 clock_gettime( CLOCK_MONOTONIC_RAW, &ts );
155 return int64_t( ts.tv_sec ) * 1000000000ll +
int64_t( ts.tv_nsec );
157 return std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).
count();
164 return m_zoneId.fetch_add( 1, std::memory_order_relaxed );
170 p.m_serialLock.lock();
171 return p.m_serialQueue.prepare_next();
177 p.m_serialQueue.commit_next();
178 p.m_serialLock.unlock();
184 #ifdef TRACY_ON_DEMAND
195 assert( type == QueueType::FrameMarkMsgStart || type == QueueType::FrameMarkMsgEnd );
196 #ifdef TRACY_ON_DEMAND
210 #ifdef TRACY_ON_DEMAND
211 if( !profiler.IsConnected() )
return;
213 const auto sz = size_t( w ) * size_t( h ) * 4;
215 memcpy( ptr, image, sz );
217 profiler.m_fiLock.lock();
218 auto fi = profiler.m_fiQueue.prepare_next();
220 fi->frame =
uint32_t( profiler.m_frameCount.load( std::memory_order_relaxed ) -
offset );
224 profiler.m_fiQueue.commit_next();
225 profiler.m_fiLock.unlock();
230 #ifdef TRACY_ON_DEMAND
236 MemWrite( &item->plotData.type, PlotDataType::Int );
237 MemWrite( &item->plotData.data.i, val );
243 #ifdef TRACY_ON_DEMAND
249 MemWrite( &item->plotData.type, PlotDataType::Float );
250 MemWrite( &item->plotData.data.f, val );
256 #ifdef TRACY_ON_DEMAND
262 MemWrite( &item->plotData.type, PlotDataType::Double );
263 MemWrite( &item->plotData.data.d, val );
273 #ifdef TRACY_ON_DEMAND
283 #ifdef TRACY_ON_DEMAND
286 TracyLfqPrepare( callstack == 0 ? QueueType::Message : QueueType::MessageCallstack );
288 memcpy( ptr, txt, size );
299 #ifdef TRACY_ON_DEMAND
302 TracyLfqPrepare( callstack == 0 ? QueueType::MessageLiteral : QueueType::MessageLiteralCallstack );
313 #ifdef TRACY_ON_DEMAND
316 TracyLfqPrepare( callstack == 0 ? QueueType::MessageColor : QueueType::MessageColorCallstack );
318 memcpy( ptr, txt, size );
322 MemWrite( &item->messageColorFat.g,
uint8_t( ( color >> 8 ) & 0xFF ) );
323 MemWrite( &item->messageColorFat.b,
uint8_t( ( color >> 16 ) & 0xFF ) );
332 #ifdef TRACY_ON_DEMAND
335 TracyLfqPrepare( callstack == 0 ? QueueType::MessageLiteralColor : QueueType::MessageLiteralColorCallstack );
339 MemWrite( &item->messageColorLiteral.g,
uint8_t( ( color >> 8 ) & 0xFF ) );
340 MemWrite( &item->messageColorLiteral.b,
uint8_t( ( color >> 16 ) & 0xFF ) );
351 memcpy( ptr, txt, size );
357 #ifdef TRACY_ON_DEMAND
367 #ifdef TRACY_ON_DEMAND
380 #ifdef TRACY_ON_DEMAND
393 #ifdef TRACY_HAS_CALLSTACK
395 # ifdef TRACY_ON_DEMAND
396 if( !profiler.IsConnected() )
return;
401 auto callstack = Callstack( depth );
403 profiler.m_serialLock.lock();
404 SendMemAlloc( QueueType::MemAllocCallstack, thread, ptr, size );
406 profiler.m_serialLock.unlock();
415 #ifdef TRACY_HAS_CALLSTACK
417 # ifdef TRACY_ON_DEMAND
418 if( !profiler.IsConnected() )
return;
423 auto callstack = Callstack( depth );
425 profiler.m_serialLock.lock();
426 SendMemFree( QueueType::MemFreeCallstack, thread, ptr );
428 profiler.m_serialLock.unlock();
436 #ifdef TRACY_HAS_CALLSTACK
437 auto ptr = Callstack( depth );
453 #ifdef TRACY_ON_DEMAND
461 static void CutCallstack(
void* callstack,
const char* skipBefore );
470 #ifdef TRACY_ON_DEMAND
473 return m_connectionId.load( std::memory_order_acquire );
478 m_deferredLock.lock();
479 auto dst = m_deferredQueue.push_next();
480 memcpy(
dst, &item,
sizeof( item ) );
481 m_deferredLock.unlock();
513 return AllocSourceLocation( line, source, strlen(source),
function, strlen(
function), name, nameSz );
523 const auto sz32 =
uint32_t( 2 + 4 + 4 + functionSz + 1 + sourceSz + 1 + nameSz );
527 memcpy( ptr, &sz, 2 );
528 memset( ptr + 2, 0, 4 );
529 memcpy( ptr + 6, &line, 4 );
530 memcpy( ptr + 10,
function, functionSz );
531 ptr[10 + functionSz] =
'\0';
532 memcpy( ptr + 10 + functionSz + 1, source, sourceSz );
533 ptr[10 + functionSz + 1 + sourceSz] =
'\0';
536 memcpy( ptr + 10 + functionSz + 1 + sourceSz + 1, name, nameSz );
603 #ifdef TRACY_HAS_CALLSTACK
605 MemWrite( &item->hdr.type, QueueType::CallstackMemory );
618 MemWrite( &item->memAlloc.thread, thread );
620 if( compile_time_condition<
sizeof( size ) == 4>::
value )
622 memcpy( &item->memAlloc.size, &size, 4 );
623 memset( &item->memAlloc.size + 4, 0, 2 );
627 assert(
sizeof( size ) == 8 );
628 memcpy( &item->memAlloc.size, &size, 4 );
629 memcpy( ((
char*)&item->memAlloc.size)+4, ((
char*)&size)+4, 2 );
641 MemWrite( &item->memFree.thread, thread );
646 #if ( defined _WIN32 || defined __CYGWIN__ ) && defined TRACY_TIMER_QPC
687 #ifdef TRACY_ON_DEMAND
688 std::atomic<uint64_t> m_connectionId;
690 TracyMutex m_deferredLock;
694 #ifdef TRACY_HAS_SYSTIME