2017-09-10 15:43:56 +00:00
# ifndef __TRACYPROFILER_HPP__
# define __TRACYPROFILER_HPP__
2018-08-05 00:09:59 +00:00
# include <assert.h>
2017-09-10 15:43:56 +00:00
# include <atomic>
2017-09-10 18:08:42 +00:00
# include <stdint.h>
2017-10-14 15:20:37 +00:00
# include <string.h>
2020-08-12 14:48:36 +00:00
# include <time.h>
2017-09-10 15:43:56 +00:00
2019-07-29 19:47:50 +00:00
# include "tracy_concurrentqueue.h"
2021-11-14 17:50:59 +00:00
# include "tracy_SPSCQueue.h"
2018-06-19 16:51:21 +00:00
# include "TracyCallstack.hpp"
2024-05-26 18:48:55 +00:00
# include "TracyKCore.hpp"
2023-03-09 21:31:31 +00:00
# include "TracySysPower.hpp"
2019-02-21 20:59:02 +00:00
# include "TracySysTime.hpp"
2018-04-01 17:53:05 +00:00
# include "TracyFastVector.hpp"
2017-09-13 20:56:08 +00:00
# include "../common/TracyQueue.hpp"
2018-03-31 12:03:55 +00:00
# include "../common/TracyAlign.hpp"
2017-10-18 17:08:19 +00:00
# include "../common/TracyAlloc.hpp"
2018-07-13 22:39:01 +00:00
# include "../common/TracyMutex.hpp"
2020-02-23 13:44:19 +00:00
# include "../common/TracyProtocol.hpp"
2017-09-10 18:09:14 +00:00
2021-10-07 21:28:40 +00:00
# if defined _WIN32
2017-09-25 22:42:09 +00:00
# include <intrin.h>
# endif
2019-02-21 13:45:13 +00:00
# ifdef __APPLE__
# include <TargetConditionals.h>
# include <mach / mach_time.h>
# endif
2017-09-25 22:42:09 +00:00
2022-02-11 14:01:56 +00:00
# if ( defined _WIN32 || ( defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64 ) || ( defined TARGET_OS_IOS && TARGET_OS_IOS == 1 ) )
2018-04-26 14:03:31 +00:00
# define TRACY_HW_TIMER
# endif
2022-05-01 20:51:22 +00:00
# ifdef __linux__
# include <signal.h>
# endif
2022-02-11 14:01:56 +00:00
# if defined TRACY_TIMER_FALLBACK || !defined TRACY_HW_TIMER
2021-01-28 17:49:12 +00:00
# include <chrono>
2019-11-05 19:09:40 +00:00
# endif
2019-01-14 19:55:37 +00:00
# ifndef TracyConcat
# define TracyConcat(x,y) TracyConcatIndirect(x,y)
# endif
# ifndef TracyConcatIndirect
# define TracyConcatIndirect(x,y) x##y
# endif
2018-07-26 17:52:27 +00:00
2017-09-10 15:43:56 +00:00
namespace tracy
{
2020-07-12 17:12:50 +00:00
# if defined(TRACY_DELAYED_INIT) && defined(TRACY_MANUAL_LIFETIME)
2021-03-08 01:39:51 +00:00
TRACY_API void StartupProfiler ( ) ;
TRACY_API void ShutdownProfiler ( ) ;
2023-10-25 09:53:37 +00:00
TRACY_API bool IsProfilerStarted ( ) ;
# define TracyIsStarted tracy::IsProfilerStarted()
# else
# define TracyIsStarted true
2020-07-07 07:39:09 +00:00
# endif
2017-09-10 15:43:56 +00:00
2019-02-19 18:33:37 +00:00
class GpuCtx ;
2019-02-19 17:38:08 +00:00
class Profiler ;
2017-09-14 17:07:56 +00:00
class Socket ;
2019-06-17 00:25:09 +00:00
class UdpBroadcast ;
2017-09-14 17:07:56 +00:00
2019-02-19 18:33:37 +00:00
struct GpuCtxWrapper
2017-09-26 00:28:14 +00:00
{
2019-02-19 18:33:37 +00:00
GpuCtx * ptr ;
2017-09-26 00:28:14 +00:00
} ;
2019-06-07 13:56:46 +00:00
TRACY_API moodycamel : : ConcurrentQueue < QueueItem > : : ExplicitProducer * GetToken ( ) ;
TRACY_API Profiler & GetProfiler ( ) ;
TRACY_API std : : atomic < uint32_t > & GetLockCounter ( ) ;
TRACY_API std : : atomic < uint8_t > & GetGpuCtxCounter ( ) ;
TRACY_API GpuCtxWrapper & GetGpuCtx ( ) ;
2021-10-07 22:42:52 +00:00
TRACY_API uint32_t GetThreadHandle ( ) ;
2020-06-23 23:32:57 +00:00
TRACY_API bool ProfilerAvailable ( ) ;
2022-02-14 16:53:27 +00:00
TRACY_API bool ProfilerAllocatorAvailable ( ) ;
2020-07-07 19:24:44 +00:00
TRACY_API int64_t GetFrequencyQpc ( ) ;
2019-02-19 19:43:14 +00:00
2022-02-11 14:01:56 +00:00
# if defined TRACY_TIMER_FALLBACK && defined TRACY_HW_TIMER && ( defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64 )
2022-02-19 08:44:15 +00:00
TRACY_API bool HardwareSupportsInvariantTSC ( ) ; // check, if we need fallback scenario
2022-02-11 14:01:56 +00:00
# else
# if defined TRACY_HW_TIMER
2022-02-19 08:44:15 +00:00
tracy_force_inline bool HardwareSupportsInvariantTSC ( )
2022-02-11 14:01:56 +00:00
{
return true ; // this is checked at startup
}
# else
2022-02-19 08:44:15 +00:00
tracy_force_inline bool HardwareSupportsInvariantTSC ( )
2022-02-11 14:01:56 +00:00
{
return false ;
}
# endif
# endif
2019-02-19 18:33:37 +00:00
struct SourceLocationData
2017-11-14 22:29:48 +00:00
{
2019-02-19 18:33:37 +00:00
const char * name ;
const char * function ;
const char * file ;
uint32_t line ;
uint32_t color ;
2017-11-14 22:29:48 +00:00
} ;
2018-07-13 18:20:37 +00:00
# ifdef TRACY_ON_DEMAND
struct LuaZoneState
{
uint32_t counter ;
bool active ;
} ;
# endif
2020-01-19 14:06:11 +00:00
# define TracyLfqPrepare( _type ) \
moodycamel : : ConcurrentQueueDefaultTraits : : index_t __magic ; \
auto __token = GetToken ( ) ; \
auto & __tail = __token - > get_tail_index ( ) ; \
auto item = __token - > enqueue_begin ( __magic ) ; \
MemWrite ( & item - > hdr . type , _type ) ;
# define TracyLfqCommit \
__tail . store ( __magic + 1 , std : : memory_order_release ) ;
# define TracyLfqPrepareC( _type ) \
tracy : : moodycamel : : ConcurrentQueueDefaultTraits : : index_t __magic ; \
auto __token = tracy : : GetToken ( ) ; \
auto & __tail = __token - > get_tail_index ( ) ; \
auto item = __token - > enqueue_begin ( __magic ) ; \
tracy : : MemWrite ( & item - > hdr . type , _type ) ;
# define TracyLfqCommitC \
__tail . store ( __magic + 1 , std : : memory_order_release ) ;
2017-10-03 12:50:55 +00:00
2018-04-01 17:53:05 +00:00
2021-10-09 12:55:32 +00:00
# ifdef TRACY_FIBERS
# define TracyQueuePrepare( _type ) \
auto item = Profiler : : QueueSerial ( ) ; \
MemWrite ( & item - > hdr . type , _type ) ;
# define TracyQueueCommit( _name ) \
MemWrite ( & item - > _name . thread , GetThreadHandle ( ) ) ; \
Profiler : : QueueSerialFinish ( ) ;
2021-10-09 13:50:30 +00:00
# define TracyQueuePrepareC( _type ) \
auto item = tracy : : Profiler : : QueueSerial ( ) ; \
tracy : : MemWrite ( & item - > hdr . type , _type ) ;
# define TracyQueueCommitC( _name ) \
tracy : : MemWrite ( & item - > _name . thread , tracy : : GetThreadHandle ( ) ) ; \
tracy : : Profiler : : QueueSerialFinish ( ) ;
2021-10-09 12:55:32 +00:00
# else
# define TracyQueuePrepare( _type ) TracyLfqPrepare( _type )
# define TracyQueueCommit( _name ) TracyLfqCommit
2021-10-09 13:50:30 +00:00
# define TracyQueuePrepareC( _type ) TracyLfqPrepareC( _type )
# define TracyQueueCommitC( _name ) TracyLfqCommitC
2021-10-09 12:55:32 +00:00
# endif
2022-08-25 22:46:01 +00:00
typedef void ( * ParameterCallback ) ( void * data , uint32_t idx , int32_t val ) ;
2022-08-17 13:36:54 +00:00
typedef char * ( * SourceContentsCallback ) ( void * data , const char * filename , size_t & size ) ;
2019-11-25 22:59:48 +00:00
2017-09-10 15:43:56 +00:00
class Profiler
{
2019-06-26 20:50:56 +00:00
struct FrameImageQueueItem
{
void * image ;
2020-07-26 11:23:44 +00:00
uint32_t frame ;
2019-06-26 20:50:56 +00:00
uint16_t w ;
uint16_t h ;
bool flip ;
} ;
2021-10-22 20:22:27 +00:00
enum class SymbolQueueItemType
{
CallstackFrame ,
SymbolQuery ,
2021-11-25 22:12:41 +00:00
ExternalName ,
2022-10-12 22:27:28 +00:00
KernelCode ,
SourceCode
2021-10-22 20:22:27 +00:00
} ;
struct SymbolQueueItem
{
SymbolQueueItemType type ;
uint64_t ptr ;
2022-10-12 20:23:06 +00:00
uint64_t extra ;
2022-10-13 17:00:22 +00:00
uint32_t id ;
2021-10-22 20:22:27 +00:00
} ;
2017-09-10 15:43:56 +00:00
public :
Profiler ( ) ;
~ Profiler ( ) ;
2020-07-07 07:39:09 +00:00
void SpawnWorkerThreads ( ) ;
2018-04-26 13:30:53 +00:00
static tracy_force_inline int64_t GetTime ( )
2017-10-29 15:12:16 +00:00
{
2018-04-26 13:30:53 +00:00
# ifdef TRACY_HW_TIMER
2020-05-22 12:53:09 +00:00
# if defined TARGET_OS_IOS && TARGET_OS_IOS == 1
2022-02-19 08:44:15 +00:00
if ( HardwareSupportsInvariantTSC ( ) ) return mach_absolute_time ( ) ;
2021-10-07 21:28:40 +00:00
# elif defined _WIN32
2020-04-07 20:01:31 +00:00
# ifdef TRACY_TIMER_QPC
return GetTimeQpc ( ) ;
# else
2022-02-19 08:44:15 +00:00
if ( HardwareSupportsInvariantTSC ( ) ) return int64_t ( __rdtsc ( ) ) ;
2020-04-07 20:01:31 +00:00
# endif
2019-10-20 23:13:55 +00:00
# elif defined __i386 || defined _M_IX86
2022-02-19 08:44:15 +00:00
if ( HardwareSupportsInvariantTSC ( ) )
2022-02-11 14:01:56 +00:00
{
uint32_t eax , edx ;
asm volatile ( " rdtsc " : " =a " ( eax ) , " =d " ( edx ) ) ;
return ( uint64_t ( edx ) < < 32 ) + uint64_t ( eax ) ;
}
2019-10-20 23:13:55 +00:00
# elif defined __x86_64__ || defined _M_X64
2022-02-19 08:44:15 +00:00
if ( HardwareSupportsInvariantTSC ( ) )
2022-02-11 14:01:56 +00:00
{
uint64_t rax , rdx ;
2023-08-19 01:40:18 +00:00
# ifdef TRACY_PATCHABLE_NOPSLEDS
// Some external tooling (such as rr) wants to patch our rdtsc and replace it by a
// branch to control the external input seen by a program. This kind of patching is
// not generally possible depending on the surrounding code and can lead to significant
// slowdowns if the compiler generated unlucky code and rr and tracy are used together.
// To avoid this, use the rr-safe `nopl 0(%rax, %rax, 1); rdtsc` instruction sequence,
// which rr promises will be patchable independent of the surrounding code.
asm volatile (
// This is nopl 0(%rax, %rax, 1), but assemblers are inconsistent about whether
// they emit that as a 4 or 5 byte sequence and we need to be guaranteed to use
// the 5 byte one.
" .byte 0x0f, 0x1f, 0x44, 0x00, 0x00 \n \t "
" rdtsc " : " =a " ( rax ) , " =d " ( rdx ) ) ;
# else
2022-02-11 14:01:56 +00:00
asm volatile ( " rdtsc " : " =a " ( rax ) , " =d " ( rdx ) ) ;
2023-08-19 01:40:18 +00:00
# endif
2022-02-11 14:01:56 +00:00
return ( int64_t ) ( ( rdx < < 32 ) + rax ) ;
}
2020-08-12 14:48:36 +00:00
# else
# error "TRACY_HW_TIMER detection logic needs fixing"
2018-04-26 13:30:53 +00:00
# endif
2022-02-11 14:01:56 +00:00
# endif
# if !defined TRACY_HW_TIMER || defined TRACY_TIMER_FALLBACK
2020-08-12 14:48:36 +00:00
# if defined __linux__ && defined CLOCK_MONOTONIC_RAW
struct timespec ts ;
clock_gettime ( CLOCK_MONOTONIC_RAW , & ts ) ;
return int64_t ( ts . tv_sec ) * 1000000000ll + int64_t ( ts . tv_nsec ) ;
# else
2017-10-29 15:12:16 +00:00
return std : : chrono : : duration_cast < std : : chrono : : nanoseconds > ( std : : chrono : : high_resolution_clock : : now ( ) . time_since_epoch ( ) ) . count ( ) ;
2020-08-12 14:48:36 +00:00
# endif
2017-10-29 15:12:16 +00:00
# endif
2022-02-11 14:01:56 +00:00
2022-05-02 23:35:48 +00:00
# if !defined TRACY_TIMER_FALLBACK
return 0 ; // unreachable branch
# endif
2017-10-29 15:12:16 +00:00
}
2019-01-14 21:23:24 +00:00
tracy_force_inline uint32_t GetNextZoneId ( )
{
return m_zoneId . fetch_add ( 1 , std : : memory_order_relaxed ) ;
}
2019-08-12 11:27:15 +00:00
static tracy_force_inline QueueItem * QueueSerial ( )
{
auto & p = GetProfiler ( ) ;
p . m_serialLock . lock ( ) ;
return p . m_serialQueue . prepare_next ( ) ;
}
2021-01-15 20:39:50 +00:00
static tracy_force_inline QueueItem * QueueSerialCallstack ( void * ptr )
{
auto & p = GetProfiler ( ) ;
p . m_serialLock . lock ( ) ;
p . SendCallstackSerial ( ptr ) ;
return p . m_serialQueue . prepare_next ( ) ;
}
2019-08-12 11:27:15 +00:00
static tracy_force_inline void QueueSerialFinish ( )
{
auto & p = GetProfiler ( ) ;
p . m_serialQueue . commit_next ( ) ;
p . m_serialLock . unlock ( ) ;
}
2019-02-28 18:21:23 +00:00
static tracy_force_inline void SendFrameMark ( const char * name )
2017-10-03 12:19:32 +00:00
{
2019-06-09 13:23:01 +00:00
if ( ! name ) GetProfiler ( ) . m_frameCount . fetch_add ( 1 , std : : memory_order_relaxed ) ;
2019-06-26 21:18:30 +00:00
# ifdef TRACY_ON_DEMAND
2019-02-19 17:38:08 +00:00
if ( ! GetProfiler ( ) . IsConnected ( ) ) return ;
2018-07-10 20:23:27 +00:00
# endif
2021-11-05 00:13:24 +00:00
auto item = QueueSerial ( ) ;
MemWrite ( & item - > hdr . type , QueueType : : FrameMarkMsg ) ;
2018-03-31 12:03:55 +00:00
MemWrite ( & item - > frameMark . time , GetTime ( ) ) ;
2019-02-28 18:21:23 +00:00
MemWrite ( & item - > frameMark . name , uint64_t ( name ) ) ;
2021-11-05 00:13:24 +00:00
QueueSerialFinish ( ) ;
2017-10-03 12:19:32 +00:00
}
2017-09-10 18:09:14 +00:00
2018-08-05 00:09:59 +00:00
static tracy_force_inline void SendFrameMark ( const char * name , QueueType type )
2018-08-04 13:04:18 +00:00
{
2019-02-28 18:21:23 +00:00
assert ( type = = QueueType : : FrameMarkMsgStart | | type = = QueueType : : FrameMarkMsgEnd ) ;
2018-08-04 13:04:18 +00:00
# ifdef TRACY_ON_DEMAND
2019-02-19 17:38:08 +00:00
if ( ! GetProfiler ( ) . IsConnected ( ) ) return ;
2018-08-04 13:04:18 +00:00
# endif
2019-08-12 11:27:15 +00:00
auto item = QueueSerial ( ) ;
2018-08-05 00:09:59 +00:00
MemWrite ( & item - > hdr . type , type ) ;
2018-08-04 13:04:18 +00:00
MemWrite ( & item - > frameMark . time , GetTime ( ) ) ;
MemWrite ( & item - > frameMark . name , uint64_t ( name ) ) ;
2019-08-12 11:27:15 +00:00
QueueSerialFinish ( ) ;
2018-08-04 13:04:18 +00:00
}
2019-07-13 10:33:55 +00:00
static tracy_force_inline void SendFrameImage ( const void * image , uint16_t w , uint16_t h , uint8_t offset , bool flip )
2019-06-06 19:39:54 +00:00
{
2021-04-29 18:55:16 +00:00
# ifndef TRACY_NO_FRAME_IMAGE
2019-06-26 20:50:56 +00:00
auto & profiler = GetProfiler ( ) ;
2023-08-17 08:03:52 +00:00
assert ( profiler . m_frameCount . load ( std : : memory_order_relaxed ) < ( std : : numeric_limits < uint32_t > : : max ) ( ) ) ;
2021-04-29 18:55:16 +00:00
# ifdef TRACY_ON_DEMAND
2019-06-26 20:50:56 +00:00
if ( ! profiler . IsConnected ( ) ) return ;
2021-04-29 18:55:16 +00:00
# endif
2019-06-06 19:39:54 +00:00
const auto sz = size_t ( w ) * size_t ( h ) * 4 ;
auto ptr = ( char * ) tracy_malloc ( sz ) ;
memcpy ( ptr , image , sz ) ;
2019-06-26 20:50:56 +00:00
2021-10-20 21:18:03 +00:00
profiler . m_fiLock . lock ( ) ;
auto fi = profiler . m_fiQueue . prepare_next ( ) ;
fi - > image = ptr ;
fi - > frame = uint32_t ( profiler . m_frameCount . load ( std : : memory_order_relaxed ) - offset ) ;
fi - > w = w ;
fi - > h = h ;
fi - > flip = flip ;
profiler . m_fiQueue . commit_next ( ) ;
profiler . m_fiLock . unlock ( ) ;
2023-09-07 08:06:42 +00:00
# else
static_cast < void > ( image ) ; // unused
static_cast < void > ( w ) ; // unused
static_cast < void > ( h ) ; // unused
static_cast < void > ( offset ) ; // unused
static_cast < void > ( flip ) ; // unused
2021-04-29 18:55:16 +00:00
# endif
2019-06-06 19:39:54 +00:00
}
2017-10-13 00:21:29 +00:00
static tracy_force_inline void PlotData ( const char * name , int64_t val )
{
2018-07-10 21:06:27 +00:00
# ifdef TRACY_ON_DEMAND
2019-02-19 17:38:08 +00:00
if ( ! GetProfiler ( ) . IsConnected ( ) ) return ;
2018-07-10 21:06:27 +00:00
# endif
2022-07-24 11:00:36 +00:00
TracyLfqPrepare ( QueueType : : PlotDataInt ) ;
MemWrite ( & item - > plotDataInt . name , ( uint64_t ) name ) ;
MemWrite ( & item - > plotDataInt . time , GetTime ( ) ) ;
MemWrite ( & item - > plotDataInt . val , val ) ;
2020-01-19 14:06:11 +00:00
TracyLfqCommit ;
2017-10-13 00:21:29 +00:00
}
static tracy_force_inline void PlotData ( const char * name , float val )
{
2018-07-10 21:06:27 +00:00
# ifdef TRACY_ON_DEMAND
2019-02-19 17:38:08 +00:00
if ( ! GetProfiler ( ) . IsConnected ( ) ) return ;
2018-07-10 21:06:27 +00:00
# endif
2022-07-24 11:00:36 +00:00
TracyLfqPrepare ( QueueType : : PlotDataFloat ) ;
MemWrite ( & item - > plotDataFloat . name , ( uint64_t ) name ) ;
MemWrite ( & item - > plotDataFloat . time , GetTime ( ) ) ;
MemWrite ( & item - > plotDataFloat . val , val ) ;
2020-01-19 14:06:11 +00:00
TracyLfqCommit ;
2017-10-13 00:21:29 +00:00
}
2017-10-13 00:07:03 +00:00
static tracy_force_inline void PlotData ( const char * name , double val )
{
2018-07-10 21:06:27 +00:00
# ifdef TRACY_ON_DEMAND
2019-02-19 17:38:08 +00:00
if ( ! GetProfiler ( ) . IsConnected ( ) ) return ;
2018-07-10 21:06:27 +00:00
# endif
2022-07-24 11:00:36 +00:00
TracyLfqPrepare ( QueueType : : PlotDataDouble ) ;
MemWrite ( & item - > plotDataDouble . name , ( uint64_t ) name ) ;
MemWrite ( & item - > plotDataDouble . time , GetTime ( ) ) ;
MemWrite ( & item - > plotDataDouble . val , val ) ;
2020-01-19 14:06:11 +00:00
TracyLfqCommit ;
2017-10-13 00:07:03 +00:00
}
2022-07-24 11:32:21 +00:00
static tracy_force_inline void ConfigurePlot ( const char * name , PlotFormatType type , bool step , bool fill , uint32_t color )
2019-11-05 15:47:41 +00:00
{
2020-01-19 14:06:11 +00:00
TracyLfqPrepare ( QueueType : : PlotConfig ) ;
2019-11-05 15:47:41 +00:00
MemWrite ( & item - > plotConfig . name , ( uint64_t ) name ) ;
MemWrite ( & item - > plotConfig . type , ( uint8_t ) type ) ;
2022-07-24 11:05:01 +00:00
MemWrite ( & item - > plotConfig . step , ( uint8_t ) step ) ;
MemWrite ( & item - > plotConfig . fill , ( uint8_t ) fill ) ;
2022-07-24 11:32:21 +00:00
MemWrite ( & item - > plotConfig . color , color ) ;
2019-11-05 15:47:41 +00:00
# ifdef TRACY_ON_DEMAND
GetProfiler ( ) . DeferItem ( * item ) ;
# endif
2020-01-19 14:06:11 +00:00
TracyLfqCommit ;
2019-11-05 15:47:41 +00:00
}
2019-11-14 22:40:41 +00:00
static tracy_force_inline void Message ( const char * txt , size_t size , int callstack )
2017-10-14 11:23:13 +00:00
{
2023-08-17 08:03:52 +00:00
assert ( size < ( std : : numeric_limits < uint16_t > : : max ) ( ) ) ;
2018-07-10 21:09:59 +00:00
# ifdef TRACY_ON_DEMAND
2019-02-19 17:38:08 +00:00
if ( ! GetProfiler ( ) . IsConnected ( ) ) return ;
2018-07-10 21:09:59 +00:00
# endif
2021-01-27 01:14:23 +00:00
if ( callstack ! = 0 )
{
tracy : : GetProfiler ( ) . SendCallstack ( callstack ) ;
}
2020-09-29 14:39:56 +00:00
2020-07-21 18:22:59 +00:00
auto ptr = ( char * ) tracy_malloc ( size ) ;
2017-10-14 11:23:13 +00:00
memcpy ( ptr , txt , size ) ;
2021-10-10 13:54:21 +00:00
TracyQueuePrepare ( callstack = = 0 ? QueueType : : Message : QueueType : : MessageCallstack ) ;
2020-07-21 18:22:59 +00:00
MemWrite ( & item - > messageFat . time , GetTime ( ) ) ;
MemWrite ( & item - > messageFat . text , ( uint64_t ) ptr ) ;
MemWrite ( & item - > messageFat . size , ( uint16_t ) size ) ;
2021-10-10 13:54:21 +00:00
TracyQueueCommit ( messageFatThread ) ;
2017-10-14 11:23:13 +00:00
}
2019-11-14 22:40:41 +00:00
static tracy_force_inline void Message ( const char * txt , int callstack )
2017-10-15 11:06:49 +00:00
{
2018-07-10 21:09:59 +00:00
# ifdef TRACY_ON_DEMAND
2019-02-19 17:38:08 +00:00
if ( ! GetProfiler ( ) . IsConnected ( ) ) return ;
2018-07-10 21:09:59 +00:00
# endif
2021-01-27 01:14:23 +00:00
if ( callstack ! = 0 )
{
tracy : : GetProfiler ( ) . SendCallstack ( callstack ) ;
}
2020-09-29 14:39:56 +00:00
2021-10-10 13:54:21 +00:00
TracyQueuePrepare ( callstack = = 0 ? QueueType : : MessageLiteral : QueueType : : MessageLiteralCallstack ) ;
2020-07-25 23:15:11 +00:00
MemWrite ( & item - > messageLiteral . time , GetTime ( ) ) ;
MemWrite ( & item - > messageLiteral . text , ( uint64_t ) txt ) ;
2021-10-10 13:54:21 +00:00
TracyQueueCommit ( messageLiteralThread ) ;
2017-10-15 11:06:49 +00:00
}
2019-11-14 22:40:41 +00:00
static tracy_force_inline void MessageColor ( const char * txt , size_t size , uint32_t color , int callstack )
2019-05-10 18:17:44 +00:00
{
2023-08-17 08:03:52 +00:00
assert ( size < ( std : : numeric_limits < uint16_t > : : max ) ( ) ) ;
2019-05-10 18:17:44 +00:00
# ifdef TRACY_ON_DEMAND
if ( ! GetProfiler ( ) . IsConnected ( ) ) return ;
# endif
2021-01-27 01:14:23 +00:00
if ( callstack ! = 0 )
{
tracy : : GetProfiler ( ) . SendCallstack ( callstack ) ;
}
2020-09-29 14:39:56 +00:00
2020-07-21 18:22:59 +00:00
auto ptr = ( char * ) tracy_malloc ( size ) ;
2019-05-10 18:17:44 +00:00
memcpy ( ptr , txt , size ) ;
2021-10-10 13:54:21 +00:00
TracyQueuePrepare ( callstack = = 0 ? QueueType : : MessageColor : QueueType : : MessageColorCallstack ) ;
2020-07-21 18:22:59 +00:00
MemWrite ( & item - > messageColorFat . time , GetTime ( ) ) ;
MemWrite ( & item - > messageColorFat . text , ( uint64_t ) ptr ) ;
2023-01-23 00:07:07 +00:00
MemWrite ( & item - > messageColorFat . b , uint8_t ( ( color ) & 0xFF ) ) ;
2020-07-21 18:22:59 +00:00
MemWrite ( & item - > messageColorFat . g , uint8_t ( ( color > > 8 ) & 0xFF ) ) ;
2023-01-23 00:07:07 +00:00
MemWrite ( & item - > messageColorFat . r , uint8_t ( ( color > > 16 ) & 0xFF ) ) ;
2020-07-21 18:22:59 +00:00
MemWrite ( & item - > messageColorFat . size , ( uint16_t ) size ) ;
2021-10-10 13:54:21 +00:00
TracyQueueCommit ( messageColorFatThread ) ;
2019-05-10 18:17:44 +00:00
}
2019-11-14 22:40:41 +00:00
static tracy_force_inline void MessageColor ( const char * txt , uint32_t color , int callstack )
2019-05-10 18:17:44 +00:00
{
# ifdef TRACY_ON_DEMAND
if ( ! GetProfiler ( ) . IsConnected ( ) ) return ;
# endif
2021-01-27 01:14:23 +00:00
if ( callstack ! = 0 )
{
tracy : : GetProfiler ( ) . SendCallstack ( callstack ) ;
}
2020-09-29 14:39:56 +00:00
2021-10-10 13:54:21 +00:00
TracyQueuePrepare ( callstack = = 0 ? QueueType : : MessageLiteralColor : QueueType : : MessageLiteralColorCallstack ) ;
2020-07-25 23:15:11 +00:00
MemWrite ( & item - > messageColorLiteral . time , GetTime ( ) ) ;
MemWrite ( & item - > messageColorLiteral . text , ( uint64_t ) txt ) ;
2023-01-23 00:07:07 +00:00
MemWrite ( & item - > messageColorLiteral . b , uint8_t ( ( color ) & 0xFF ) ) ;
2020-07-25 23:15:11 +00:00
MemWrite ( & item - > messageColorLiteral . g , uint8_t ( ( color > > 8 ) & 0xFF ) ) ;
2023-01-23 00:07:07 +00:00
MemWrite ( & item - > messageColorLiteral . r , uint8_t ( ( color > > 16 ) & 0xFF ) ) ;
2021-10-10 13:54:21 +00:00
TracyQueueCommit ( messageColorLiteralThread ) ;
2019-05-10 18:17:44 +00:00
}
2019-07-12 16:14:42 +00:00
static tracy_force_inline void MessageAppInfo ( const char * txt , size_t size )
{
2023-08-17 08:03:52 +00:00
assert ( size < ( std : : numeric_limits < uint16_t > : : max ) ( ) ) ;
2020-07-25 23:15:11 +00:00
auto ptr = ( char * ) tracy_malloc ( size ) ;
2019-07-12 16:14:42 +00:00
memcpy ( ptr , txt , size ) ;
2020-01-19 14:06:11 +00:00
TracyLfqPrepare ( QueueType : : MessageAppInfo ) ;
2020-07-25 23:15:11 +00:00
MemWrite ( & item - > messageFat . time , GetTime ( ) ) ;
MemWrite ( & item - > messageFat . text , ( uint64_t ) ptr ) ;
MemWrite ( & item - > messageFat . size , ( uint16_t ) size ) ;
2019-07-12 16:14:42 +00:00
# ifdef TRACY_ON_DEMAND
GetProfiler ( ) . DeferItem ( * item ) ;
# endif
2020-01-19 14:06:11 +00:00
TracyLfqCommit ;
2019-07-12 16:14:42 +00:00
}
2020-06-23 23:33:26 +00:00
static tracy_force_inline void MemAlloc ( const void * ptr , size_t size , bool secure )
2018-03-31 19:56:05 +00:00
{
2020-06-23 23:33:26 +00:00
if ( secure & & ! ProfilerAvailable ( ) ) return ;
2018-07-11 23:36:01 +00:00
# ifdef TRACY_ON_DEMAND
2019-02-19 17:38:08 +00:00
if ( ! GetProfiler ( ) . IsConnected ( ) ) return ;
2018-07-11 23:36:01 +00:00
# endif
2018-04-01 17:53:24 +00:00
const auto thread = GetThreadHandle ( ) ;
2019-02-19 17:38:08 +00:00
GetProfiler ( ) . m_serialLock . lock ( ) ;
2018-06-20 21:29:44 +00:00
SendMemAlloc ( QueueType : : MemAlloc , thread , ptr , size ) ;
2019-02-19 17:38:08 +00:00
GetProfiler ( ) . m_serialLock . unlock ( ) ;
2018-03-31 19:56:05 +00:00
}
2020-06-23 23:33:26 +00:00
static tracy_force_inline void MemFree ( const void * ptr , bool secure )
2018-03-31 19:56:05 +00:00
{
2020-06-23 23:33:26 +00:00
if ( secure & & ! ProfilerAvailable ( ) ) return ;
2018-07-11 23:36:01 +00:00
# ifdef TRACY_ON_DEMAND
2019-02-19 17:38:08 +00:00
if ( ! GetProfiler ( ) . IsConnected ( ) ) return ;
2018-07-11 23:36:01 +00:00
# endif
2018-04-01 17:53:24 +00:00
const auto thread = GetThreadHandle ( ) ;
2019-02-19 17:38:08 +00:00
GetProfiler ( ) . m_serialLock . lock ( ) ;
2018-06-20 21:29:44 +00:00
SendMemFree ( QueueType : : MemFree , thread , ptr ) ;
2019-02-19 17:38:08 +00:00
GetProfiler ( ) . m_serialLock . unlock ( ) ;
2018-03-31 19:56:05 +00:00
}
2020-06-23 23:33:26 +00:00
static tracy_force_inline void MemAllocCallstack ( const void * ptr , size_t size , int depth , bool secure )
2018-06-19 16:51:21 +00:00
{
2020-06-23 23:33:26 +00:00
if ( secure & & ! ProfilerAvailable ( ) ) return ;
2018-06-22 21:00:03 +00:00
# ifdef TRACY_HAS_CALLSTACK
2019-10-05 00:11:45 +00:00
auto & profiler = GetProfiler ( ) ;
2018-07-11 23:36:01 +00:00
# ifdef TRACY_ON_DEMAND
2019-02-19 19:43:14 +00:00
if ( ! profiler . IsConnected ( ) ) return ;
2018-07-11 23:36:01 +00:00
# endif
2018-06-19 16:51:21 +00:00
const auto thread = GetThreadHandle ( ) ;
2018-06-22 21:00:03 +00:00
auto callstack = Callstack ( depth ) ;
2019-02-19 19:43:14 +00:00
profiler . m_serialLock . lock ( ) ;
2021-01-15 19:49:39 +00:00
SendCallstackSerial ( callstack ) ;
2020-09-29 14:39:56 +00:00
SendMemAlloc ( QueueType : : MemAllocCallstack , thread , ptr , size ) ;
2019-02-19 19:43:14 +00:00
profiler . m_serialLock . unlock ( ) ;
2018-06-22 21:00:03 +00:00
# else
2021-11-04 15:24:58 +00:00
static_cast < void > ( depth ) ; // unused
2020-07-02 15:17:01 +00:00
MemAlloc ( ptr , size , secure ) ;
2018-06-22 21:00:03 +00:00
# endif
2018-06-19 16:51:21 +00:00
}
2020-06-23 23:33:26 +00:00
static tracy_force_inline void MemFreeCallstack ( const void * ptr , int depth , bool secure )
2018-06-19 16:51:21 +00:00
{
2020-06-23 23:33:26 +00:00
if ( secure & & ! ProfilerAvailable ( ) ) return ;
Check if memory can be allocated in a thread.
Consider running the following code with operator new and delete overloaded to
track allocations with call stacks:
std::thread( []({ thread_local std::string str; });
Each call stack requires a memory allocation to be performed by the profiler,
to make the stack available at a later time. When the thread is created, the
TLS block is initialized and the std::string buffer can be allocated. To track
this allocation, rpmalloc has to be initialized. This initialization also
happens within the TLS block.
Now, when the thread exits, the heap managed by rpmalloc may be released first
during the TLS block destruction (and if the destruction is performed in
reverse creation order, then it *will* be destroyed first, as rpmalloc was
initialized only after the std::string initialization, to track the allocation
performed within). The next thing to happen is destruction of std::string and
release of the memory block it contains.
The release is tracked by the profiler, and as mentioned earlier, to save the
call stack for later use, a memory allocation is needed. But the allocator is
no longer available in this thread, because rpmalloc was released just before!
As a solution to this issue, profiler will detect whether the allocator is
still available and will ignore the call stack, if it's not. The other
solution is to disable the rpmalloc thread cleanup, which may potentially
cause leak-like behavior, in case a large number of threads is spawned and
destroyed.
Note that this is not a water-tight solution. Other functions will still want
to allocate memory for call stacks, but it is rather unlikely that such calls
would be performed during TLS block destruction. It is also possible that the
event queue will run out of allocated space for events at this very moment,
and in such a case the allocator will also fail.
2022-02-14 16:55:46 +00:00
if ( ! ProfilerAllocatorAvailable ( ) )
{
MemFree ( ptr , secure ) ;
return ;
}
2018-06-22 21:00:03 +00:00
# ifdef TRACY_HAS_CALLSTACK
2019-10-05 00:11:45 +00:00
auto & profiler = GetProfiler ( ) ;
2018-07-11 23:36:01 +00:00
# ifdef TRACY_ON_DEMAND
2019-02-19 19:43:14 +00:00
if ( ! profiler . IsConnected ( ) ) return ;
2018-07-11 23:36:01 +00:00
# endif
2018-06-19 16:51:21 +00:00
const auto thread = GetThreadHandle ( ) ;
2018-06-22 21:00:03 +00:00
auto callstack = Callstack ( depth ) ;
2019-02-19 19:43:14 +00:00
profiler . m_serialLock . lock ( ) ;
2021-01-15 19:49:39 +00:00
SendCallstackSerial ( callstack ) ;
2020-09-29 14:39:56 +00:00
SendMemFree ( QueueType : : MemFreeCallstack , thread , ptr ) ;
2019-02-19 19:43:14 +00:00
profiler . m_serialLock . unlock ( ) ;
2018-06-22 21:00:03 +00:00
# else
2021-11-04 15:24:58 +00:00
static_cast < void > ( depth ) ; // unused
2020-07-02 15:17:01 +00:00
MemFree ( ptr , secure ) ;
2018-06-22 21:00:03 +00:00
# endif
2018-06-19 16:51:21 +00:00
}
2020-09-22 16:22:34 +00:00
static tracy_force_inline void MemAllocNamed ( const void * ptr , size_t size , bool secure , const char * name )
{
if ( secure & & ! ProfilerAvailable ( ) ) return ;
# ifdef TRACY_ON_DEMAND
if ( ! GetProfiler ( ) . IsConnected ( ) ) return ;
# endif
const auto thread = GetThreadHandle ( ) ;
GetProfiler ( ) . m_serialLock . lock ( ) ;
SendMemName ( name ) ;
SendMemAlloc ( QueueType : : MemAllocNamed , thread , ptr , size ) ;
GetProfiler ( ) . m_serialLock . unlock ( ) ;
}
static tracy_force_inline void MemFreeNamed ( const void * ptr , bool secure , const char * name )
{
if ( secure & & ! ProfilerAvailable ( ) ) return ;
# ifdef TRACY_ON_DEMAND
if ( ! GetProfiler ( ) . IsConnected ( ) ) return ;
# endif
const auto thread = GetThreadHandle ( ) ;
GetProfiler ( ) . m_serialLock . lock ( ) ;
SendMemName ( name ) ;
SendMemFree ( QueueType : : MemFreeNamed , thread , ptr ) ;
GetProfiler ( ) . m_serialLock . unlock ( ) ;
}
static tracy_force_inline void MemAllocCallstackNamed ( const void * ptr , size_t size , int depth , bool secure , const char * name )
{
if ( secure & & ! ProfilerAvailable ( ) ) return ;
# ifdef TRACY_HAS_CALLSTACK
auto & profiler = GetProfiler ( ) ;
# ifdef TRACY_ON_DEMAND
if ( ! profiler . IsConnected ( ) ) return ;
# endif
const auto thread = GetThreadHandle ( ) ;
auto callstack = Callstack ( depth ) ;
profiler . m_serialLock . lock ( ) ;
2021-01-15 19:49:39 +00:00
SendCallstackSerial ( callstack ) ;
2020-09-22 16:22:34 +00:00
SendMemName ( name ) ;
SendMemAlloc ( QueueType : : MemAllocCallstackNamed , thread , ptr , size ) ;
profiler . m_serialLock . unlock ( ) ;
# else
2021-11-04 15:24:58 +00:00
static_cast < void > ( depth ) ; // unused
2024-03-21 12:53:27 +00:00
MemAllocNamed ( ptr , size , secure , name ) ;
2020-09-22 16:22:34 +00:00
# endif
}
static tracy_force_inline void MemFreeCallstackNamed ( const void * ptr , int depth , bool secure , const char * name )
{
if ( secure & & ! ProfilerAvailable ( ) ) return ;
# ifdef TRACY_HAS_CALLSTACK
auto & profiler = GetProfiler ( ) ;
# ifdef TRACY_ON_DEMAND
if ( ! profiler . IsConnected ( ) ) return ;
# endif
const auto thread = GetThreadHandle ( ) ;
auto callstack = Callstack ( depth ) ;
profiler . m_serialLock . lock ( ) ;
2021-01-15 19:49:39 +00:00
SendCallstackSerial ( callstack ) ;
2020-09-22 16:22:34 +00:00
SendMemName ( name ) ;
SendMemFree ( QueueType : : MemFreeCallstackNamed , thread , ptr ) ;
profiler . m_serialLock . unlock ( ) ;
# else
2021-11-04 15:24:58 +00:00
static_cast < void > ( depth ) ; // unused
2024-03-21 12:53:27 +00:00
MemFreeNamed ( ptr , secure , name ) ;
2020-09-22 16:22:34 +00:00
# endif
}
2019-07-29 22:42:31 +00:00
static tracy_force_inline void SendCallstack ( int depth )
2018-06-21 22:56:01 +00:00
{
# ifdef TRACY_HAS_CALLSTACK
auto ptr = Callstack ( depth ) ;
2021-10-10 14:14:17 +00:00
TracyQueuePrepare ( QueueType : : Callstack ) ;
2020-07-26 12:15:16 +00:00
MemWrite ( & item - > callstackFat . ptr , ( uint64_t ) ptr ) ;
2021-10-10 14:14:17 +00:00
TracyQueueCommit ( callstackFatThread ) ;
2021-11-04 15:24:58 +00:00
# else
static_cast < void > ( depth ) ; // unused
2018-06-21 22:56:01 +00:00
# endif
}
2022-08-25 22:46:01 +00:00
static tracy_force_inline void ParameterRegister ( ParameterCallback cb , void * data )
{
auto & profiler = GetProfiler ( ) ;
profiler . m_paramCallback = cb ;
profiler . m_paramCallbackData = data ;
}
2020-01-25 15:51:17 +00:00
static tracy_force_inline void ParameterSetup ( uint32_t idx , const char * name , bool isBool , int32_t val )
{
TracyLfqPrepare ( QueueType : : ParamSetup ) ;
tracy : : MemWrite ( & item - > paramSetup . idx , idx ) ;
tracy : : MemWrite ( & item - > paramSetup . name , ( uint64_t ) name ) ;
tracy : : MemWrite ( & item - > paramSetup . isBool , ( uint8_t ) isBool ) ;
tracy : : MemWrite ( & item - > paramSetup . val , val ) ;
# ifdef TRACY_ON_DEMAND
GetProfiler ( ) . DeferItem ( * item ) ;
# endif
TracyLfqCommit ;
}
2019-11-25 22:59:48 +00:00
2022-08-17 13:36:54 +00:00
static tracy_force_inline void SourceCallbackRegister ( SourceContentsCallback cb , void * data )
{
auto & profiler = GetProfiler ( ) ;
profiler . m_sourceCallback = cb ;
profiler . m_sourceCallbackData = data ;
}
2021-11-01 22:56:19 +00:00
# ifdef TRACY_FIBERS
static tracy_force_inline void EnterFiber ( const char * fiber )
{
TracyQueuePrepare ( QueueType : : FiberEnter ) ;
MemWrite ( & item - > fiberEnter . time , GetTime ( ) ) ;
MemWrite ( & item - > fiberEnter . fiber , ( uint64_t ) fiber ) ;
TracyQueueCommit ( fiberEnter ) ;
}
static tracy_force_inline void LeaveFiber ( )
{
TracyQueuePrepare ( QueueType : : FiberLeave ) ;
MemWrite ( & item - > fiberLeave . time , GetTime ( ) ) ;
TracyQueueCommit ( fiberLeave ) ;
}
# endif
2019-07-29 22:42:31 +00:00
void SendCallstack ( int depth , const char * skipBefore ) ;
2019-03-05 01:15:13 +00:00
static void CutCallstack ( void * callstack , const char * skipBefore ) ;
2018-08-20 20:20:44 +00:00
2017-09-14 17:23:50 +00:00
static bool ShouldExit ( ) ;
2019-06-09 15:15:47 +00:00
tracy_force_inline bool IsConnected ( ) const
2018-07-10 19:50:00 +00:00
{
2019-06-09 14:48:00 +00:00
return m_isConnected . load ( std : : memory_order_acquire ) ;
2018-07-10 19:50:00 +00:00
}
2018-07-11 10:21:39 +00:00
2023-03-30 19:51:00 +00:00
tracy_force_inline void SetProgramName ( const char * name )
{
m_programNameLock . lock ( ) ;
m_programName = name ;
m_programNameLock . unlock ( ) ;
}
2020-07-16 09:22:06 +00:00
# ifdef TRACY_ON_DEMAND
2019-06-09 15:15:47 +00:00
tracy_force_inline uint64_t ConnectionId ( ) const
{
return m_connectionId . load ( std : : memory_order_acquire ) ;
}
2018-07-11 10:21:39 +00:00
tracy_force_inline void DeferItem ( const QueueItem & item )
{
m_deferredLock . lock ( ) ;
auto dst = m_deferredQueue . push_next ( ) ;
memcpy ( dst , & item , sizeof ( item ) ) ;
m_deferredLock . unlock ( ) ;
}
2018-07-10 19:50:00 +00:00
# endif
2018-08-20 19:49:23 +00:00
void RequestShutdown ( ) { m_shutdown . store ( true , std : : memory_order_relaxed ) ; m_shutdownManual . store ( true , std : : memory_order_relaxed ) ; }
2018-08-19 23:02:27 +00:00
bool HasShutdownFinished ( ) const { return m_shutdownFinished . load ( std : : memory_order_relaxed ) ; }
2020-07-21 00:19:22 +00:00
void SendString ( uint64_t str , const char * ptr , QueueType type ) { SendString ( str , ptr , strlen ( ptr ) , type ) ; }
void SendString ( uint64_t str , const char * ptr , size_t len , QueueType type ) ;
2020-07-25 21:13:01 +00:00
void SendSingleString ( const char * ptr ) { SendSingleString ( ptr , strlen ( ptr ) ) ; }
void SendSingleString ( const char * ptr , size_t len ) ;
2020-07-25 23:32:49 +00:00
void SendSecondString ( const char * ptr ) { SendSecondString ( ptr , strlen ( ptr ) ) ; }
void SendSecondString ( const char * ptr , size_t len ) ;
2019-08-16 17:22:23 +00:00
2019-12-05 23:15:46 +00:00
// Allocated source location data layout:
2020-07-05 15:11:15 +00:00
// 2b payload size
2019-12-05 23:15:46 +00:00
// 4b color
// 4b source line
// fsz function name
// 1b null terminator
// ssz source file name
// 1b null terminator
// nsz zone name (optional)
2024-03-17 14:13:23 +00:00
static tracy_force_inline uint64_t AllocSourceLocation ( uint32_t line , const char * source , const char * function , uint32_t color = 0 )
2019-12-05 23:15:46 +00:00
{
2024-03-17 14:13:23 +00:00
return AllocSourceLocation ( line , source , function , nullptr , 0 , color ) ;
2019-12-05 23:15:46 +00:00
}
2024-03-17 14:13:23 +00:00
static tracy_force_inline uint64_t AllocSourceLocation ( uint32_t line , const char * source , const char * function , const char * name , size_t nameSz , uint32_t color = 0 )
2019-12-05 23:15:46 +00:00
{
2024-03-17 14:13:23 +00:00
return AllocSourceLocation ( line , source , strlen ( source ) , function , strlen ( function ) , name , nameSz , color ) ;
2020-06-20 14:31:12 +00:00
}
2024-03-17 14:13:23 +00:00
static tracy_force_inline uint64_t AllocSourceLocation ( uint32_t line , const char * source , size_t sourceSz , const char * function , size_t functionSz , uint32_t color = 0 )
2020-06-20 14:31:12 +00:00
{
2024-03-17 14:13:23 +00:00
return AllocSourceLocation ( line , source , sourceSz , function , functionSz , nullptr , 0 , color ) ;
2020-06-20 14:31:12 +00:00
}
2024-03-17 14:13:23 +00:00
static tracy_force_inline uint64_t AllocSourceLocation ( uint32_t line , const char * source , size_t sourceSz , const char * function , size_t functionSz , const char * name , size_t nameSz , uint32_t color = 0 )
2020-06-20 14:31:12 +00:00
{
2020-07-05 15:11:15 +00:00
const auto sz32 = uint32_t ( 2 + 4 + 4 + functionSz + 1 + sourceSz + 1 + nameSz ) ;
2023-08-17 08:03:52 +00:00
assert ( sz32 < = ( std : : numeric_limits < uint16_t > : : max ) ( ) ) ;
2020-07-05 15:11:15 +00:00
const auto sz = uint16_t ( sz32 ) ;
2019-12-05 23:15:46 +00:00
auto ptr = ( char * ) tracy_malloc ( sz ) ;
2020-07-05 15:11:15 +00:00
memcpy ( ptr , & sz , 2 ) ;
2024-03-17 14:13:23 +00:00
memcpy ( ptr + 2 , & color , 4 ) ;
2020-07-05 15:11:15 +00:00
memcpy ( ptr + 6 , & line , 4 ) ;
memcpy ( ptr + 10 , function , functionSz ) ;
ptr [ 10 + functionSz ] = ' \0 ' ;
memcpy ( ptr + 10 + functionSz + 1 , source , sourceSz ) ;
ptr [ 10 + functionSz + 1 + sourceSz ] = ' \0 ' ;
2020-06-20 14:31:12 +00:00
if ( nameSz ! = 0 )
{
2020-07-05 15:11:15 +00:00
memcpy ( ptr + 10 + functionSz + 1 + sourceSz + 1 , name , nameSz ) ;
2020-06-20 14:31:12 +00:00
}
2019-12-05 23:15:46 +00:00
return uint64_t ( ptr ) ;
}
2017-09-10 15:43:56 +00:00
private :
2019-11-14 17:24:29 +00:00
enum class DequeueStatus { DataDequeued , ConnectionLost , QueueEmpty } ;
2021-10-09 13:16:36 +00:00
enum class ThreadCtxStatus { Same , Changed , ConnectionLost } ;
2017-10-18 16:48:51 +00:00
2017-10-16 19:13:57 +00:00
static void LaunchWorker ( void * ptr ) { ( ( Profiler * ) ptr ) - > Worker ( ) ; }
2017-09-10 15:43:56 +00:00
void Worker ( ) ;
2021-04-29 18:55:16 +00:00
# ifndef TRACY_NO_FRAME_IMAGE
2019-06-26 20:57:24 +00:00
static void LaunchCompressWorker ( void * ptr ) { ( ( Profiler * ) ptr ) - > CompressWorker ( ) ; }
void CompressWorker ( ) ;
2021-04-29 18:55:16 +00:00
# endif
2019-06-26 20:57:24 +00:00
2021-10-22 20:25:09 +00:00
# ifdef TRACY_HAS_CALLSTACK
static void LaunchSymbolWorker ( void * ptr ) { ( ( Profiler * ) ptr ) - > SymbolWorker ( ) ; }
void SymbolWorker ( ) ;
2021-10-22 23:35:01 +00:00
void HandleSymbolQueueItem ( const SymbolQueueItem & si ) ;
2021-10-22 20:25:09 +00:00
# endif
2024-01-24 14:25:57 +00:00
void InstallCrashHandler ( ) ;
void RemoveCrashHandler ( ) ;
2018-07-13 18:01:27 +00:00
void ClearQueues ( tracy : : moodycamel : : ConsumerToken & token ) ;
2019-08-14 20:39:12 +00:00
void ClearSerial ( ) ;
2018-07-13 18:01:27 +00:00
DequeueStatus Dequeue ( tracy : : moodycamel : : ConsumerToken & token ) ;
2019-08-14 21:06:13 +00:00
DequeueStatus DequeueContextSwitches ( tracy : : moodycamel : : ConsumerToken & token , int64_t & timeStop ) ;
2018-04-01 18:04:35 +00:00
DequeueStatus DequeueSerial ( ) ;
2021-10-09 13:16:36 +00:00
ThreadCtxStatus ThreadCtxCheck ( uint32_t threadId ) ;
2017-11-11 13:16:37 +00:00
bool CommitData ( ) ;
2020-02-23 13:44:19 +00:00
tracy_force_inline bool AppendData ( const void * data , size_t len )
{
const auto ret = NeedDataSize ( len ) ;
AppendDataUnsafe ( data , len ) ;
return ret ;
}
tracy_force_inline bool NeedDataSize ( size_t len )
{
assert ( len < = TargetFrameSize ) ;
bool ret = true ;
2020-11-19 15:36:01 +00:00
if ( m_bufferOffset - m_bufferStart + ( int ) len > TargetFrameSize )
2020-02-23 13:44:19 +00:00
{
ret = CommitData ( ) ;
}
return ret ;
}
2017-10-18 16:48:51 +00:00
2018-06-23 00:16:58 +00:00
tracy_force_inline void AppendDataUnsafe ( const void * data , size_t len )
{
memcpy ( m_buffer + m_bufferOffset , data , len ) ;
m_bufferOffset + = int ( len ) ;
}
2017-09-14 17:07:56 +00:00
bool SendData ( const char * data , size_t len ) ;
2019-06-06 22:22:00 +00:00
void SendLongString ( uint64_t ptr , const char * str , size_t len , QueueType type ) ;
2017-09-26 17:00:25 +00:00
void SendSourceLocation ( uint64_t ptr ) ;
2018-06-19 17:00:57 +00:00
void SendSourceLocationPayload ( uint64_t ptr ) ;
2018-06-19 17:09:43 +00:00
void SendCallstackPayload ( uint64_t ptr ) ;
2020-02-22 13:05:01 +00:00
void SendCallstackPayload64 ( uint64_t ptr ) ;
2019-02-28 19:30:07 +00:00
void SendCallstackAlloc ( uint64_t ptr ) ;
2021-10-22 20:25:09 +00:00
void QueueCallstackFrame ( uint64_t ptr ) ;
void QueueSymbolQuery ( uint64_t symbol ) ;
void QueueExternalName ( uint64_t ptr ) ;
2021-11-25 21:27:35 +00:00
void QueueKernelCode ( uint64_t symbol , uint32_t size ) ;
2022-10-13 17:00:22 +00:00
void QueueSourceCodeQuery ( uint32_t id ) ;
2017-09-21 23:54:04 +00:00
bool HandleServerQuery ( ) ;
2019-08-01 21:14:09 +00:00
void HandleDisconnect ( ) ;
2019-11-25 22:59:48 +00:00
void HandleParameter ( uint64_t payload ) ;
2020-03-25 19:04:55 +00:00
void HandleSymbolCodeQuery ( uint64_t symbol , uint32_t size ) ;
2022-10-13 17:00:22 +00:00
void HandleSourceCodeQuery ( char * data , char * image , uint32_t id ) ;
2017-09-14 17:07:56 +00:00
2021-02-07 19:53:20 +00:00
void AckServerQuery ( ) ;
2021-11-25 21:44:56 +00:00
void AckSymbolCodeNotAvailable ( ) ;
2021-02-07 19:53:20 +00:00
2017-09-23 19:33:05 +00:00
void CalibrateTimer ( ) ;
2017-09-24 14:02:09 +00:00
void CalibrateDelay ( ) ;
2019-11-29 17:29:09 +00:00
void ReportTopology ( ) ;
2017-09-23 19:33:05 +00:00
2021-01-15 19:49:39 +00:00
static tracy_force_inline void SendCallstackSerial ( void * ptr )
2018-06-20 21:30:19 +00:00
{
# ifdef TRACY_HAS_CALLSTACK
2019-02-19 17:38:08 +00:00
auto item = GetProfiler ( ) . m_serialQueue . prepare_next ( ) ;
2021-01-15 19:49:39 +00:00
MemWrite ( & item - > hdr . type , QueueType : : CallstackSerial ) ;
2020-07-26 12:15:16 +00:00
MemWrite ( & item - > callstackFat . ptr , ( uint64_t ) ptr ) ;
2019-02-19 17:38:08 +00:00
GetProfiler ( ) . m_serialQueue . commit_next ( ) ;
2021-11-04 15:24:58 +00:00
# else
static_cast < void > ( ptr ) ; // unused
2018-06-20 21:30:19 +00:00
# endif
}
2021-10-07 22:42:52 +00:00
static tracy_force_inline void SendMemAlloc ( QueueType type , const uint32_t thread , const void * ptr , size_t size )
2018-06-20 21:29:44 +00:00
{
2020-09-22 16:22:34 +00:00
assert ( type = = QueueType : : MemAlloc | | type = = QueueType : : MemAllocCallstack | | type = = QueueType : : MemAllocNamed | | type = = QueueType : : MemAllocCallstackNamed ) ;
2018-06-20 21:29:44 +00:00
2019-02-19 17:38:08 +00:00
auto item = GetProfiler ( ) . m_serialQueue . prepare_next ( ) ;
2018-06-20 21:29:44 +00:00
MemWrite ( & item - > hdr . type , type ) ;
MemWrite ( & item - > memAlloc . time , GetTime ( ) ) ;
MemWrite ( & item - > memAlloc . thread , thread ) ;
MemWrite ( & item - > memAlloc . ptr , ( uint64_t ) ptr ) ;
2018-08-01 12:07:30 +00:00
if ( compile_time_condition < sizeof ( size ) = = 4 > : : value )
2018-06-20 21:29:44 +00:00
{
memcpy ( & item - > memAlloc . size , & size , 4 ) ;
memset ( & item - > memAlloc . size + 4 , 0 , 2 ) ;
}
else
{
assert ( sizeof ( size ) = = 8 ) ;
2020-04-13 11:45:21 +00:00
memcpy ( & item - > memAlloc . size , & size , 4 ) ;
memcpy ( ( ( char * ) & item - > memAlloc . size ) + 4 , ( ( char * ) & size ) + 4 , 2 ) ;
2018-06-20 21:29:44 +00:00
}
2019-02-19 17:38:08 +00:00
GetProfiler ( ) . m_serialQueue . commit_next ( ) ;
2018-06-20 21:29:44 +00:00
}
2021-10-07 22:42:52 +00:00
static tracy_force_inline void SendMemFree ( QueueType type , const uint32_t thread , const void * ptr )
2018-06-20 21:29:44 +00:00
{
2020-09-22 16:22:34 +00:00
assert ( type = = QueueType : : MemFree | | type = = QueueType : : MemFreeCallstack | | type = = QueueType : : MemFreeNamed | | type = = QueueType : : MemFreeCallstackNamed ) ;
2018-06-20 21:29:44 +00:00
2019-02-19 17:38:08 +00:00
auto item = GetProfiler ( ) . m_serialQueue . prepare_next ( ) ;
2018-06-20 21:29:44 +00:00
MemWrite ( & item - > hdr . type , type ) ;
MemWrite ( & item - > memFree . time , GetTime ( ) ) ;
MemWrite ( & item - > memFree . thread , thread ) ;
MemWrite ( & item - > memFree . ptr , ( uint64_t ) ptr ) ;
2019-02-19 17:38:08 +00:00
GetProfiler ( ) . m_serialQueue . commit_next ( ) ;
2018-06-20 21:29:44 +00:00
}
2020-09-22 16:22:34 +00:00
static tracy_force_inline void SendMemName ( const char * name )
{
assert ( name ) ;
auto item = GetProfiler ( ) . m_serialQueue . prepare_next ( ) ;
MemWrite ( & item - > hdr . type , QueueType : : MemNamePayload ) ;
MemWrite ( & item - > memName . name , ( uint64_t ) name ) ;
GetProfiler ( ) . m_serialQueue . commit_next ( ) ;
}
2021-10-07 21:28:40 +00:00
# if defined _WIN32 && defined TRACY_TIMER_QPC
2020-04-07 20:01:31 +00:00
static int64_t GetTimeQpc ( ) ;
# endif
2017-09-23 19:33:05 +00:00
double m_timerMul ;
2017-09-29 16:29:39 +00:00
uint64_t m_resolution ;
2017-09-24 14:02:09 +00:00
uint64_t m_delay ;
2017-10-16 23:07:54 +00:00
std : : atomic < int64_t > m_timeBegin ;
2021-10-07 22:42:52 +00:00
uint32_t m_mainThread ;
2021-01-31 16:42:44 +00:00
uint64_t m_epoch , m_exectime ;
2017-09-10 15:43:56 +00:00
std : : atomic < bool > m_shutdown ;
2018-08-20 19:49:23 +00:00
std : : atomic < bool > m_shutdownManual ;
2018-08-19 23:02:27 +00:00
std : : atomic < bool > m_shutdownFinished ;
2017-10-18 17:49:17 +00:00
Socket * m_sock ;
2019-06-17 00:25:09 +00:00
UdpBroadcast * m_broadcast ;
2018-07-13 21:55:40 +00:00
bool m_noExit ;
2020-03-08 15:14:36 +00:00
uint32_t m_userPort ;
2019-01-14 21:23:24 +00:00
std : : atomic < uint32_t > m_zoneId ;
2020-02-25 22:08:52 +00:00
int64_t m_samplingPeriod ;
2017-09-17 11:10:42 +00:00
2021-10-07 22:42:52 +00:00
uint32_t m_threadCtx ;
2019-10-23 22:04:31 +00:00
int64_t m_refTimeThread ;
int64_t m_refTimeSerial ;
2019-10-25 17:13:11 +00:00
int64_t m_refTimeCtx ;
2019-10-25 17:52:01 +00:00
int64_t m_refTimeGpu ;
2019-08-02 18:18:08 +00:00
2019-05-01 10:57:42 +00:00
void * m_stream ; // LZ4_stream_t*
2017-09-17 11:10:42 +00:00
char * m_buffer ;
int m_bufferOffset ;
2017-11-11 13:16:37 +00:00
int m_bufferStart ;
2017-11-02 11:56:13 +00:00
2017-11-02 16:37:10 +00:00
char * m_lz4Buf ;
2018-04-01 17:53:05 +00:00
2018-04-14 13:46:11 +00:00
FastVector < QueueItem > m_serialQueue , m_serialDequeue ;
2018-07-13 22:39:01 +00:00
TracyMutex m_serialLock ;
2018-07-10 19:50:00 +00:00
2021-04-29 18:55:16 +00:00
# ifndef TRACY_NO_FRAME_IMAGE
2021-10-20 21:18:03 +00:00
FastVector < FrameImageQueueItem > m_fiQueue , m_fiDequeue ;
TracyMutex m_fiLock ;
2021-04-29 18:55:16 +00:00
# endif
2019-06-26 20:50:56 +00:00
2021-11-14 17:50:59 +00:00
SPSCQueue < SymbolQueueItem > m_symbolQueue ;
2021-10-22 20:22:27 +00:00
2019-06-26 21:18:30 +00:00
std : : atomic < uint64_t > m_frameCount ;
2018-07-10 19:50:00 +00:00
std : : atomic < bool > m_isConnected ;
2020-07-16 09:22:06 +00:00
# ifdef TRACY_ON_DEMAND
2019-06-09 15:15:47 +00:00
std : : atomic < uint64_t > m_connectionId ;
2018-07-11 10:14:28 +00:00
2018-07-13 22:39:01 +00:00
TracyMutex m_deferredLock ;
2018-07-11 10:14:28 +00:00
FastVector < QueueItem > m_deferredQueue ;
2018-07-10 19:50:00 +00:00
# endif
2019-02-21 20:59:02 +00:00
# ifdef TRACY_HAS_SYSTIME
void ProcessSysTime ( ) ;
SysTime m_sysTime ;
uint64_t m_sysTimeLast = 0 ;
# else
void ProcessSysTime ( ) { }
# endif
2019-11-25 22:59:48 +00:00
2023-03-09 21:31:31 +00:00
# ifdef TRACY_HAS_SYSPOWER
SysPower m_sysPower ;
# endif
2019-11-25 22:59:48 +00:00
ParameterCallback m_paramCallback ;
2022-08-25 22:46:01 +00:00
void * m_paramCallbackData ;
2022-08-17 13:36:54 +00:00
SourceContentsCallback m_sourceCallback ;
void * m_sourceCallbackData ;
2021-02-03 23:03:25 +00:00
2022-05-01 12:30:18 +00:00
char * m_queryImage ;
2021-02-03 23:03:25 +00:00
char * m_queryData ;
char * m_queryDataPtr ;
2021-07-25 09:40:22 +00:00
2021-10-07 21:28:40 +00:00
# if defined _WIN32
2021-07-25 09:48:27 +00:00
void * m_exceptionHandler ;
# endif
2021-07-25 09:40:22 +00:00
# ifdef __linux__
struct {
struct sigaction pwr , ill , fpe , segv , pipe , bus , abrt ;
} m_prevSignal ;
2024-05-26 18:48:55 +00:00
KCore * m_kcore ;
2021-07-25 09:40:22 +00:00
# endif
2021-07-25 09:46:20 +00:00
bool m_crashHandlerInstalled ;
2023-03-30 19:51:00 +00:00
const char * m_programName ;
TracyMutex m_programNameLock ;
2017-09-10 15:43:56 +00:00
} ;
2020-05-10 13:32:39 +00:00
}
2017-09-10 15:43:56 +00:00
# endif