2017-09-10 15:43:56 +00:00
# ifndef __TRACYPROFILER_HPP__
# define __TRACYPROFILER_HPP__
# include <atomic>
2017-09-25 22:42:09 +00:00
# include <chrono>
2017-09-10 18:08:42 +00:00
# include <stdint.h>
2017-10-14 15:20:37 +00:00
# include <string.h>
2017-09-10 15:43:56 +00:00
2017-10-03 12:19:32 +00:00
# include "concurrentqueue.h"
2017-09-17 11:10:42 +00:00
# include "../common/tracy_lz4.hpp"
2017-09-13 20:56:08 +00:00
# include "../common/TracyQueue.hpp"
2017-10-18 17:08:19 +00:00
# include "../common/TracyAlloc.hpp"
2017-09-10 18:09:14 +00:00
2017-09-25 22:42:09 +00:00
# if defined _MSC_VER || defined __CYGWIN__
# include <intrin.h>
# endif
2017-10-30 15:23:23 +00:00
# if defined _MSC_VER || defined __CYGWIN__ || ( ( defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64 ) && !defined __ANDROID__ )
2017-10-03 13:35:43 +00:00
# define TRACY_RDTSCP_SUPPORTED
# endif
2017-09-10 15:43:56 +00:00
namespace tracy
{
2017-09-14 17:07:56 +00:00
class Socket ;
2017-09-26 00:28:14 +00:00
struct SourceLocation
{
const char * function ;
const char * file ;
uint32_t line ;
2017-09-26 16:54:48 +00:00
uint32_t color ;
2017-09-26 00:28:14 +00:00
} ;
2017-10-10 23:44:35 +00:00
struct ProducerWrapper
{
moodycamel : : ConcurrentQueue < QueueItem > : : ExplicitProducer * ptr ;
} ;
extern thread_local ProducerWrapper s_token ;
2017-10-03 12:19:32 +00:00
2017-10-03 12:50:55 +00:00
using Magic = moodycamel : : ConcurrentQueueDefaultTraits : : index_t ;
2017-09-10 15:43:56 +00:00
class Profiler
{
public :
Profiler ( ) ;
~ Profiler ( ) ;
2017-10-03 13:35:43 +00:00
# ifdef TRACY_RDTSCP_SUPPORTED
2017-10-10 21:21:30 +00:00
static tracy_force_inline int64_t tracy_rdtscp ( uint32_t & cpu )
2017-09-25 22:42:09 +00:00
{
# if defined _MSC_VER || defined __CYGWIN__
2017-10-10 21:21:30 +00:00
const auto t = int64_t ( __rdtscp ( & cpu ) ) ;
2017-10-01 17:11:01 +00:00
return t ;
2017-10-03 13:27:07 +00:00
# elif defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64
2017-10-29 12:15:43 +00:00
uint32_t eax , edx ;
2017-10-10 21:21:30 +00:00
asm volatile ( " rdtscp " : " =a " ( eax ) , " =d " ( edx ) , " =c " ( cpu ) : : ) ;
2017-10-29 12:15:43 +00:00
return ( uint64_t ( edx ) < < 32 ) + uint64_t ( eax ) ;
2017-10-03 13:35:43 +00:00
# endif
}
# endif
2017-10-29 15:12:16 +00:00
# ifdef TRACY_RDTSCP_SUPPORTED
static tracy_force_inline int64_t tracy_rdtscp ( )
{
# if defined _MSC_VER || defined __CYGWIN__
static unsigned int dontcare ;
const auto t = int64_t ( __rdtscp ( & dontcare ) ) ;
return t ;
# elif defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64
uint32_t eax , edx ;
2017-10-29 15:20:07 +00:00
asm volatile ( " rdtscp " : " =a " ( eax ) , " =d " ( edx ) : : " %ecx " ) ;
2017-10-29 15:12:16 +00:00
return ( uint64_t ( edx ) < < 32 ) + uint64_t ( eax ) ;
# endif
}
# endif
2017-10-10 21:21:30 +00:00
static tracy_force_inline int64_t GetTime ( uint32_t & cpu )
2017-10-03 13:35:43 +00:00
{
# ifdef TRACY_RDTSCP_SUPPORTED
return tracy_rdtscp ( cpu ) ;
2017-09-25 22:42:09 +00:00
# else
2017-10-10 21:21:30 +00:00
cpu = 0xFFFFFFFF ;
2017-09-25 22:42:09 +00:00
return std : : chrono : : duration_cast < std : : chrono : : nanoseconds > ( std : : chrono : : high_resolution_clock : : now ( ) . time_since_epoch ( ) ) . count ( ) ;
# endif
}
2017-09-10 18:08:42 +00:00
2017-10-29 15:12:16 +00:00
static tracy_force_inline int64_t GetTime ( )
{
# ifdef TRACY_RDTSCP_SUPPORTED
return tracy_rdtscp ( ) ;
# else
return std : : chrono : : duration_cast < std : : chrono : : nanoseconds > ( std : : chrono : : high_resolution_clock : : now ( ) . time_since_epoch ( ) ) . count ( ) ;
# endif
}
2017-10-03 13:10:25 +00:00
static tracy_force_inline void FrameMark ( )
2017-10-03 12:19:32 +00:00
{
2017-10-03 12:50:55 +00:00
Magic magic ;
2017-10-10 23:44:35 +00:00
auto & token = s_token . ptr ;
2017-10-10 23:27:22 +00:00
auto & tail = token - > get_tail_index ( ) ;
2017-10-10 23:04:21 +00:00
auto item = token - > enqueue_begin < moodycamel : : CanAlloc > ( magic ) ;
2017-10-03 12:19:32 +00:00
item - > hdr . type = QueueType : : FrameMarkMsg ;
2017-10-29 15:12:16 +00:00
item - > frameMark . time = GetTime ( ) ;
2017-10-10 23:27:22 +00:00
tail . store ( magic + 1 , std : : memory_order_release ) ;
2017-10-03 12:19:32 +00:00
}
2017-09-10 18:09:14 +00:00
2017-10-13 00:21:29 +00:00
static tracy_force_inline void PlotData ( const char * name , int64_t val )
{
Magic magic ;
auto & token = s_token . ptr ;
auto & tail = token - > get_tail_index ( ) ;
auto item = token - > enqueue_begin < moodycamel : : CanAlloc > ( magic ) ;
item - > hdr . type = QueueType : : PlotData ;
item - > plotData . name = ( uint64_t ) name ;
2017-10-29 15:12:16 +00:00
item - > plotData . time = GetTime ( ) ;
2017-10-13 00:21:29 +00:00
item - > plotData . type = PlotDataType : : Int ;
item - > plotData . data . i = val ;
tail . store ( magic + 1 , std : : memory_order_release ) ;
}
static tracy_force_inline void PlotData ( const char * name , float val )
{
Magic magic ;
auto & token = s_token . ptr ;
auto & tail = token - > get_tail_index ( ) ;
auto item = token - > enqueue_begin < moodycamel : : CanAlloc > ( magic ) ;
item - > hdr . type = QueueType : : PlotData ;
item - > plotData . name = ( uint64_t ) name ;
2017-10-29 15:12:16 +00:00
item - > plotData . time = GetTime ( ) ;
2017-10-13 00:21:29 +00:00
item - > plotData . type = PlotDataType : : Float ;
item - > plotData . data . f = val ;
tail . store ( magic + 1 , std : : memory_order_release ) ;
}
2017-10-13 00:07:03 +00:00
static tracy_force_inline void PlotData ( const char * name , double val )
{
Magic magic ;
auto & token = s_token . ptr ;
auto & tail = token - > get_tail_index ( ) ;
auto item = token - > enqueue_begin < moodycamel : : CanAlloc > ( magic ) ;
item - > hdr . type = QueueType : : PlotData ;
item - > plotData . name = ( uint64_t ) name ;
2017-10-29 15:12:16 +00:00
item - > plotData . time = GetTime ( ) ;
2017-10-13 00:21:29 +00:00
item - > plotData . type = PlotDataType : : Double ;
item - > plotData . data . d = val ;
2017-10-13 00:07:03 +00:00
tail . store ( magic + 1 , std : : memory_order_release ) ;
}
2017-10-14 11:23:13 +00:00
static tracy_force_inline void Message ( const char * txt , size_t size )
{
Magic magic ;
2017-10-20 16:28:25 +00:00
auto & token = s_token . ptr ;
2017-10-14 15:15:18 +00:00
auto ptr = ( char * ) tracy_malloc ( size + 1 ) ;
2017-10-14 11:23:13 +00:00
memcpy ( ptr , txt , size ) ;
ptr [ size ] = ' \0 ' ;
auto & tail = token - > get_tail_index ( ) ;
auto item = token - > enqueue_begin < moodycamel : : CanAlloc > ( magic ) ;
item - > hdr . type = QueueType : : Message ;
2017-10-29 15:12:16 +00:00
item - > message . time = GetTime ( ) ;
2017-10-14 11:23:13 +00:00
item - > message . thread = GetThreadHandle ( ) ;
item - > message . text = ( uint64_t ) ptr ;
tail . store ( magic + 1 , std : : memory_order_release ) ;
}
2017-10-15 11:06:49 +00:00
static tracy_force_inline void Message ( const char * txt )
{
Magic magic ;
auto & token = s_token . ptr ;
auto & tail = token - > get_tail_index ( ) ;
auto item = token - > enqueue_begin < moodycamel : : CanAlloc > ( magic ) ;
item - > hdr . type = QueueType : : MessageLiteral ;
2017-10-29 15:12:16 +00:00
item - > message . time = GetTime ( ) ;
2017-10-15 11:06:49 +00:00
item - > message . thread = GetThreadHandle ( ) ;
item - > message . text = ( uint64_t ) txt ;
tail . store ( magic + 1 , std : : memory_order_release ) ;
}
2017-09-14 17:23:50 +00:00
static bool ShouldExit ( ) ;
2017-09-10 15:43:56 +00:00
private :
2017-10-18 16:48:51 +00:00
enum DequeueStatus { Success , ConnectionLost , QueueEmpty } ;
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 ( ) ;
2017-10-18 16:48:51 +00:00
DequeueStatus Dequeue ( moodycamel : : ConsumerToken & token ) ;
2017-09-14 17:07:56 +00:00
bool SendData ( const char * data , size_t len ) ;
2017-09-21 23:54:04 +00:00
bool SendString ( uint64_t ptr , const char * str , QueueType type ) ;
2017-09-26 17:00:25 +00:00
void SendSourceLocation ( uint64_t ptr ) ;
2017-11-05 15:46:00 +00:00
bool SendSourceLocationPayload ( uint64_t ptr ) ;
2017-09-21 23:54:04 +00:00
bool HandleServerQuery ( ) ;
2017-09-14 17:07:56 +00:00
2017-09-23 19:33:05 +00:00
void CalibrateTimer ( ) ;
2017-09-24 14:02:09 +00:00
void CalibrateDelay ( ) ;
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 ;
2017-09-22 23:37:07 +00:00
uint64_t m_mainThread ;
2017-10-03 22:34:05 +00:00
uint64_t m_epoch ;
2017-09-10 15:43:56 +00:00
std : : atomic < bool > m_shutdown ;
2017-10-18 17:49:17 +00:00
Socket * m_sock ;
2017-09-17 11:10:42 +00:00
LZ4_stream_t * m_stream ;
char * m_buffer ;
int m_bufferOffset ;
2017-11-02 11:56:13 +00:00
QueueItem * m_itemBuf ;
2017-11-02 16:37:10 +00:00
char * m_lz4Buf ;
2017-09-10 15:43:56 +00:00
} ;
} ;
# endif