#ifndef VPROF_TELEMETRY_H #define VPROF_TELEMETRY_H #if !defined( MAKE_VPC ) #if !defined( RAD_TELEMETRY_DISABLED ) && ( defined( IS_WINDOWS_PC ) || defined( _LINUX ) ) #endif #ifdef WIN32 #define __PRETTY_FUNCTION__ __FUNCSIG__ #endif #endif enum TelemetryZonePlotSlot_t { TELEMETRY_ZONE_PLOT_SLOT_1, TELEMETRY_ZONE_PLOT_SLOT_2, TELEMETRY_ZONE_PLOT_SLOT_3, TELEMETRY_ZONE_PLOT_SLOT_4, TELEMETRY_ZONE_PLOT_SLOT_5, TELEMETRY_ZONE_PLOT_SLOT_6, TELEMETRY_ZONE_PLOT_SLOT_7, TELEMETRY_ZONE_PLOT_SLOT_8, TELEMETRY_ZONE_PLOT_SLOT_9, TELEMETRY_ZONE_PLOT_SLOT_10, TELEMETRY_ZONE_PLOT_SLOT_11, TELEMETRY_ZONE_PLOT_SLOT_12, TELEMETRY_ZONE_PLOT_SLOT_13, TELEMETRY_ZONE_PLOT_SLOT_14, TELEMETRY_ZONE_PLOT_SLOT_15, TELEMETRY_ZONE_PLOT_SLOT_16, TELEMETRY_ZONE_PLOT_SLOT_MAX }; #if !defined( RAD_TELEMETRY_ENABLED ) #define NTELEMETRY 1 #undef RADCOPYRIGHT inline void TelemetryTick() {} inline void TelemetrySetLevel(unsigned int Level) {} #define TELEMETRY_REQUIRED( tmRequiredCode ) #define TELEMETRY_REQUIRED_REPLACE( tmRequiredCode, replacementCode ) replacementCode #else #include "../../thirdparty/telemetry/include/telemetry.h" #undef RADCOPYRIGHT PLATFORM_INTERFACE void TelemetryTick(); PLATFORM_INTERFACE void TelemetrySetLevel(unsigned int Level); struct TelemetryZonePlotData { const char* m_Name; TmU64 m_CurrFrameTime; }; struct TelemetryData { HTELEMETRY tmContext[32]; float flRDTSCToMilliSeconds; uint32 FrameCount; char ServerAddress[128]; uint32 ZoneFilterVal; int playbacktick; float dotatime; uint32 DemoTickStart; uint32 DemoTickEnd; uint32 Level; TelemetryZonePlotData m_ZonePlot[TELEMETRY_ZONE_PLOT_SLOT_MAX]; }; PLATFORM_INTERFACE TelemetryData g_Telemetry; #define TELEMETRY_REQUIRED( tmRequiredCode ) tmRequiredCode #define TELEMETRY_REQUIRED_REPLACE( tmRequiredCode, replacementCode ) tmRequiredCode #endif #define TELEMETRY_ERROR_BUILD_DISABLED TELEMETRY_REQUIRED_REPLACE( TMERR_DISABLED, 0x0001 ) #define TELEMETRY_ERROR_DISCONNECTED TELEMETRY_REQUIRED_REPLACE( TMCS_DISCONNECTED, 0 ) #define TELEMETRY_LEVEL0 TELEMETRY_REQUIRED_REPLACE( g_Telemetry.tmContext[0], 0 ) #define TELEMETRY_LEVEL1 TELEMETRY_REQUIRED_REPLACE( g_Telemetry.tmContext[1], 0 ) #define TELEMETRY_LEVEL2 TELEMETRY_REQUIRED_REPLACE( g_Telemetry.tmContext[2], 0 ) #define TELEMETRY_LEVEL3 TELEMETRY_REQUIRED_REPLACE( g_Telemetry.tmContext[3], 0 ) #define TELEMETRY_LEVEL4 TELEMETRY_REQUIRED_REPLACE( g_Telemetry.tmContext[4], 0 ) #define TELEMETRY_LEVEL5 TELEMETRY_REQUIRED_REPLACE( g_Telemetry.tmContext[5], 0 ) #define TELEMETRY_LEVEL6 TELEMETRY_REQUIRED_REPLACE( g_Telemetry.tmContext[6], 0 ) #define TM_FAST_TIME() TELEMETRY_REQUIRED_REPLACE( tmFastTime(), 0 ) #define TM_LOAD_TELEMETRY(kUseCheckedDll) TELEMETRY_REQUIRED_REPLACE( tmLoadTelemetry(kUseCheckedDll), 0 ) #define TM_STARTUP() TELEMETRY_REQUIRED_REPLACE( tmStartup(), TELEMETRY_ERROR_BUILD_DISABLED ) #define TM_SHUTDOWN() TELEMETRY_REQUIRED( tmShutdown() ) #define TM_INITIALIZE_CONTEXT( pContext, pArena, kArenaSize ) TELEMETRY_REQUIRED_REPLACE( tmInitializeContext( pContext, pArena, kArenaSize ), TELEMETRY_ERROR_BUILD_DISABLED ) #define TM_ZONE_FILTERED( context, kThreshold, kFlags, kpFormat, ... ) TELEMETRY_REQUIRED( tmZoneFiltered( context, kThreshold, kFlags, kpFormat, ##__VA_ARGS__ ) ) #define TM_ZONE( context, kFlags, kpFormat, ... ) TELEMETRY_REQUIRED( tmZone( context, kFlags, kpFormat, ##__VA_ARGS__ ) ) #define TM_ZONE_DEFAULT( context ) TM_ZONE( context, TMZF_NONE, __FUNCTION__ ) #define TM_ZONE_IDLE( context ) TM_ZONE( context, TMZF_IDLE, __FUNCTION__ ) #define TM_ZONE_STALL( context ) TM_ZONE( context, TMZF_STALL, __FUNCTION__ ) #define TM_CHECK_VERSION( context, major, minor, build, cust ) TELEMETRY_REQUIRED_REPLACE( tmCheckVersion( context, major, minor, build, cust ), TELEMETRY_ERROR_BUILD_DISABLED ) #define TM_LISTEN_IPC( context, name ) TELEMETRY_REQUIRED_REPLACE( tmListenIPC( context, name ), TELEMETRY_ERROR_BUILD_DISABLED ) #define TM_UPDATE_SYMBOL_DATA( context ) TELEMETRY_REQUIRED( tmUpdateSymbolData( context ) ) #define TM_GET_SESSION_NAME( context, dst, kDstSize ) TELEMETRY_REQUIRED_REPLACE( tmGetSessionName( context, dst, kDstSize ), TELEMETRY_ERROR_BUILD_DISABLED ) #define TM_UNWIND_TO_DEBUG_ZONE_LEVEL( context, kLevel ) TELEMETRY_REQUIRED( tmUnwindToDebugZoneLevel( context, kLevel ) ) #define TM_SET_DEBUG_ZONE_LEVEL( context, kLevel ) TELEMETRY_REQUIRED( tmSetDebugZoneLevel( context, kLevel ) ) #define TM_CHECK_DEBUG_ZONE_LEVEL( context, kLevel ) TELEMETRY_REQUIRED( tmCheckDebugZoneLevel( context, kLevel ) ) #define TM_GET_CALL_STACK( context, TmCallStack_Ptr ) TELEMETRY_REQUIRED_REPLACE( tmGetCallStack( context, TmCallStack_Ptr ), 0 ) #define TM_SEND_CALL_STACK( context, TmCallStack_Ptr ) TELEMETRY_REQUIRED_REPLACE( tmSendCallStack( context, TmCallStack_Ptr ), 0 ) #define TM_GET_LAST_ERROR( context ) TELEMETRY_REQUIRED_REPLACE( tmGetLastError( context ), TELEMETRY_ERROR_BUILD_DISABLED ) #define TM_SHUTDOWN_CONTEXT( context ) TELEMETRY_REQUIRED( tmShutdownContext( context ) ) #define TM_GET_ACCUMULATION_START( context ) TELEMETRY_REQUIRED_REPLACE( tmGetAccumulationStart( context ), 0 ) #define TM_GET_LAST_CONTEXT_SWITCH_TIME( context ) TELEMETRY_REQUIRED_REPLACE( tmGetLastContextSwitchTime( context ), 0 ) #define TM_ENTER_ACCUMULATION_ZONE( context, zone_variable ) TELEMETRY_REQUIRED( tmEnterAccumulationZone( context, zone_variable ) ) #define TM_LEAVE_ACCUMULATION_ZONE( context, zone_variable ) TELEMETRY_REQUIRED( tmLeaveAccumulationZone( context, zone_variable ) ) #define TM_GET_FORMAT_CODE( context, pCode, kpFmt ) TELEMETRY_REQUIRED( tmGetFormatCode( context, pCode, kpFmt ) ) #define TM_DYNAMIC_STRING( context, kpString ) TELEMETRY_REQUIRED_REPLACE( tmDynamicString( context, kpString ), NULL ) #define TM_CLEAR_STATIC_STRING( context, kpString ) TELEMETRY_REQUIRED( tmClearStaticString( context, kpString ) ) #define TM_ENABLE( context, kOption, kValue ) TELEMETRY_REQUIRED( tmEnable( context, kOption, kValue ) ) #define TM_IS_ENABLED( context, kOption ) TELEMETRY_REQUIRED_REPLACE( tmIsEnabled( context, kOption ), 0 ) #define TM_SET_PARAMETER( context, kParameter, kpValue ) TELEMETRY_REQUIRED( tmSetParameter( context, kParameter, kpValue ) ) #define TM_OPEN( context, kpAppName, kpBuildInfo, kpServerAddress, kConnection, kServerPort, kFlags, kTimeoutMS ) TELEMETRY_REQUIRED_REPLACE( tmOpen( context, kpAppName, kpBuildInfo, kpServerAddress, kConnection, kServerPort, kFlags, kTimeoutMS ), TELEMETRY_ERROR_BUILD_DISABLED ) #define TM_CLOSE( context ) TELEMETRY_REQUIRED( tmClose( context ) ) #define TM_TICK( context ) TELEMETRY_REQUIRED( tmTick( context ) ) #define TM_FLUSH( context ) TELEMETRY_REQUIRED( tmFlush( context ) ) #define TM_PAUSE( context, kPause ) TELEMETRY_REQUIRED( tmPause( context, kPause ) ) #define TM_IS_PAUSED( context ) TELEMETRY_REQUIRED_REPLACE( tmIsPaused( context ), 0 ) #define TM_GET_CONNECTION_STATUS( context ) TELEMETRY_REQUIRED_REPLACE( tmGetConnectionStatus( context ), TELEMETRY_ERROR_DISCONNECTED ) #define TM_FREE( context, kpPtr ) TELEMETRY_REQUIRED( tmFree( context, kpPtr ) ) #define TM_GET_STAT_I( context, kStat ) TELEMETRY_REQUIRED_REPLACE( tmGetStati( context, kStat ), 0 ) #define TM_LEAVE( context ) TELEMETRY_REQUIRED( tmLeave( context ) ) #define TM_LEAVE_EX( context, kMatchId, kThreadId, kpFilename, kLine ) TELEMETRY_REQUIRED( tmLeaveEx( context, kMatchId, kThreadId, kpFilename, kLine ) ) #define TM_TRY_LOCK( context, kPtr, kpLockName, ... ) TELEMETRY_REQUIRED( tmTryLock( context, kPtr, kpLockName, ##__VA_ARGS__ ) ) #define TM_TRY_LOCK_EX( context, matcher, kThreshold, kpFileName, kLine, kPtr, kpLockName, ... ) TELEMETRY_REQUIRED( tmTryLockEx( context, matcher, kThreshold, kpFileName, kLine, kPtr, kpLockName, ##__VA_ARGS__ ) ) #define TM_END_TRY_LOCK( context, kPtr, kResult ) TELEMETRY_REQUIRED( tmEndTryLock( context, kPtr, kResult ) ) #define TM_END_TRY_LOCK_EX( context, kMatchId, kpFileName, kLine, kPtr, kResult ) TELEMETRY_REQUIRED( tmEndTryLockEx( context, kMatchId, kpFileName, kLine, kPtr, kResult ) ) #define TM_BEGIN_TIME_SPAN( context, kId, kFlags, kpNameFormat, ... ) TELEMETRY_REQUIRED( tmBeginTimeSpan( context, kId, kFlags, kpNameFormat, ##__VA_ARGS__ ) ) #define TM_END_TIME_SPAN( context, kId, kFlags, kpNameFormat, ... ) TELEMETRY_REQUIRED( tmEndTimeSpan( context, kId, kFlags, kpNameFormat, ##__VA_ARGS__ ) ) #define TM_BEGIN_TIME_SPAN_AT( context, kId, kFlags, kTimeStamp, kpNameFormat, ... ) TELEMETRY_REQUIRED( tmBeginTimeSpanAt( context, kId, kFlags, kTimeStamp, kpNameFormat, ##__VA_ARGS__ ) ) #define TM_END_TIME_SPAN_AT( context, kId, kFlags, kTimeStamp, kpNameFormat, ... ) TELEMETRY_REQUIRED( tmEndTimeSpanAt( context, kId, kFlags, kTimeStamp, kpNameFormat, ##__VA_ARGS__ ) ) #define TM_SIGNAL_LOCK_COUNT( context, kPtr, kCount, kpDescription, ... ) TELEMETRY_REQUIRED( tmSignalLockCount( context, kPtr, kCount, kpDescription, ##__VA_ARGS__ ) ) #define TM_SET_LOCK_STATE( context, kPtr, kState, kpDescription, ... ) TELEMETRY_REQUIRED( tmSetLockState( context, kPtr, kState, kpDescription, ##__VA_ARGS__ ) ) #define TM_SET_LOCK_STATE_EX( context, kpFileName, kLine, kPtr, kState, kpDescription, ... ) TELEMETRY_REQUIRED( tmSetLockStateEx( context, kpFileName, kLine, kPtr, kState, kpDescription, ##__VA_ARGS__ ) ) #define TM_SET_LOCK_STATE_MIN_TIME( context, buf, kPtr, kState, kpDescription, ... ) TELEMETRY_REQUIRED( tmSetLockStateMinTime( context, buf, kPtr, kState, kpDescription, ##__VA_ARGS__ ) ) #define TM_SET_LOCK_STATE_MIN_TIME_EX( context, buf, kpFilename, kLine, kPtr, kState, kpDescription, ... ) TELEMETRY_REQUIRED( tmSetLockStateMinTimeEx( context, buf, kpFilename, kLine, kPtr, kState, kpDescription, ##__VA_ARGS__ ) ) #define TM_THREAD_NAME( context, kThreadID, kpNameFormat, ... ) TELEMETRY_REQUIRED( tmThreadName( context, kThreadID, kpNameFormat, ##__VA_ARGS__ ) ) #define TM_LOCK_NAME( context, kPtr, kpNameFormat, ... ) TELEMETRY_REQUIRED( tmLockName( context, kPtr, kpNameFormat, ##__VA_ARGS__ ) ) #define TM_EMIT_ACCUMULATION_ZONE( context, kZoneFlags, pStart, kCount, kTotal, kpZoneFormat, ... ) TELEMETRY_REQUIRED( tmEmitAccumulationZone( context, kZoneFlags, pStart, kCount, kTotal, kpZoneFormat, ##__VA_ARGS__ ) ) #define TM_SET_VARIABLE( context, kpKey, kpValueFormat, ... ) TELEMETRY_REQUIRED( tmSetVariable( context, kpKey, kpValueFormat, ##__VA_ARGS__ ) ) #define TM_SET_TIMELINE_SECTION_NAME( context, kpNameFormat, ... ) TELEMETRY_REQUIRED( tmSetTimelineSectionName( context, kpNameFormat, ##__VA_ARGS__ ) ) #define TM_ENTER( context, kFlags, kpZoneName, ... ) TELEMETRY_REQUIRED( tmEnter( context, kFlags, kpZoneName, ##__VA_ARGS__ ) ) #define TM_ENTER_EX( context, pMatchId, kThreadId, kThreshold, kpFilename, kLine, kFlags, kpZoneName, ... ) TELEMETRY_REQUIRED( tmEnterEx( context, pMatchId, kThreadId, kThreshold, kpFilename, kLine, kFlags, kpZoneName, ##__VA_ARGS__ ) ) #define TM_ALLOC( context, kPtr, kSize, kpDescription, ... ) TELEMETRY_REQUIRED( tmAlloc( context, kPtr, kSize, kpDescription, ##__VA_ARGS__ ) ) #define TM_ALLOC_EX( context, kpFilename, kLineNumber, kPtr, kSize, kpDescription, ... ) TELEMETRY_REQUIRED( tmAllocEx( context, kpFilename, kLineNumber, kPtr, kSize, kpDescription, ##__VA_ARGS__ ) ) #define TM_MESSAGE( context, kFlags, kpFormatString, ... ) TELEMETRY_REQUIRED( tmMessage( context, kFlags, kpFormatString, ##__VA_ARGS__ ) ) #define TM_LOG( context, kpFormatString, ... ) TM_MESSAGE( context, TMMF_SEVERITY_LOG, kpFormatString, ##__VA_ARGS__ ) #define TM_WARNING( context, kpFormatString, ... ) TM_MESSAGE( context, TMMF_SEVERITY_WARNING, kpFormatString, ##__VA_ARGS__ ) #define TM_ERROR( context, kpFormatString, ... ) TM_MESSAGE( context, TMMF_SEVERITY_ERROR, kpFormatString, ##__VA_ARGS__ ) #define TM_PLOT( context, kType, kFlags, kValue, kpNameFormat, ... ) TELEMETRY_REQUIRED( tmPlot( context, kType, kFlags, kValue, kpNameFormat, ##__VA_ARGS__ ) ) #define TM_PLOT_F32( context, kType, kFlags, kValue, kpNameFormat, ... ) TELEMETRY_REQUIRED( tmPlotF32( context, kType, kFlags, kValue, kpNameFormat, ##__VA_ARGS__ ) ) #define TM_PLOT_F64( context, kType, kFlags, kValue, kpNameFormat, ... ) TELEMETRY_REQUIRED( tmPlotF64( context, kType, kFlags, kValue, kpNameFormat, ##__VA_ARGS__ ) ) #define TM_PLOT_I32( context, kType, kFlags, kValue, kpNameFormat, ... ) TELEMETRY_REQUIRED( tmPlotI32( context, kType, kFlags, kValue, kpNameFormat, ##__VA_ARGS__ ) ) #define TM_PLOT_U32( context, kType, kFlags, kValue, kpNameFormat, ... ) TELEMETRY_REQUIRED( tmPlotU32( context, kType, kFlags, kValue, kpNameFormat, ##__VA_ARGS__ ) ) #define TM_PLOT_I64( context, kType, kFlags, kValue, kpNameFormat, ... ) TELEMETRY_REQUIRED( tmPlotI64( context, kType, kFlags, kValue, kpNameFormat, ##__VA_ARGS__ ) ) #define TM_PLOT_U64( context, kType, kFlags, kValue, kpNameFormat, ... ) TELEMETRY_REQUIRED( tmPlotU64( context, kType, kFlags, kValue, kpNameFormat, ##__VA_ARGS__ ) ) #define TM_BLOB( context, kpData, kDataSize, kpPluginIdentifier, kpBlobName, ...) TELEMETRY_REQUIRED( tmBlob( context, kpData, kDataSize, kpPluginIdentifier, kpBlobName, ##__VA_ARGS__ ) ) #define TM_DISJOINT_BLOB( context, kNumPieces, kpData, kDataSizes, kpPluginIdentifier, kpBlobName, ... ) TELEMETRY_REQUIRED( tmDisjointBlob( context, kNumPieces, kpData, kDataSizes, kpPluginIdentifier, kpBlobName, ##__VA_ARGS__ ) ) #if !defined( RAD_TELEMETRY_ENABLED ) class CTelemetryLock { public: CTelemetryLock(void* plocation, const char* description) {} ~CTelemetryLock() {} void Locked() {} void Unlocked() {} }; class CTelemetrySpikeDetector { public: CTelemetrySpikeDetector(const char* msg, unsigned int threshold = 50) {} ~CTelemetrySpikeDetector() { } }; class CTelemetryZonePlotScope { public: CTelemetryZonePlotScope(const char* pName, TelemetryZonePlotSlot_t slot) {} ~CTelemetryZonePlotScope() {} }; #define TelemetrySetLockName( _ctx, _location, _description ) #define TM_ZONE_PLOT( context, name, slot ) #else #define TelemetrySetLockName( _ctx, _location, _description ) \ do \ { \ static bool s_bNameSet = false; \ if( _ctx && !s_bNameSet ) \ { \ tmLockName( _ctx, _location, _description ); \ s_bNameSet = true; \ } \ } while( 0 ) class CTelemetryLock { public: CTelemetryLock(void* plocation, const char* description) { m_plocation = (const char*)plocation; m_description = description; TelemetrySetLockName(TELEMETRY_LEVEL1, m_plocation, m_description); TM_TRY_LOCK(TELEMETRY_LEVEL1, m_plocation, "%s", m_description); } ~CTelemetryLock() { Unlocked(); } void Locked() { TM_END_TRY_LOCK(TELEMETRY_LEVEL1, m_plocation, TMLR_SUCCESS); TM_SET_LOCK_STATE(TELEMETRY_LEVEL1, m_plocation, TMLS_LOCKED, "%s Locked", m_description); } void Unlocked() { if (m_plocation) { TM_SET_LOCK_STATE(TELEMETRY_LEVEL1, m_plocation, TMLS_RELEASED, "%s Released", m_description); m_plocation = NULL; } } public: const char* m_plocation; const char* m_description; }; class CTelemetrySpikeDetector { public: CTelemetrySpikeDetector(const char* msg, float threshold = 5) : m_message(msg), m_threshold(threshold), time0(tmFastTime()) {} ~CTelemetrySpikeDetector() { float time = (tmFastTime() - time0) * g_Telemetry.flRDTSCToMilliSeconds; if (time >= m_threshold) { TM_MESSAGE(TELEMETRY_LEVEL0, TMMF_ICON_NOTE | TMMF_SEVERITY_WARNING, "(dota/spike)%s %.2fms %t", m_message, time, tmSendCallStack(TELEMETRY_LEVEL0, 0)); } } private: TmU64 time0; float m_threshold; const char* m_message; }; #define TM_ZONE_PLOT( context, name, slot ) CTelemetryZonePlotScope _telemetryZonePlot##__LINE__(context, name, slot); class CTelemetryZonePlotScope { public: CTelemetryZonePlotScope(HTELEMETRY context, const char* pName, TelemetryZonePlotSlot_t slot) : m_Context(context), m_SlotData(NULL), m_StartTime(0) { if (slot < TELEMETRY_ZONE_PLOT_SLOT_MAX) { m_SlotData = &g_Telemetry.m_ZonePlot[slot]; m_SlotData->m_Name = pName; m_StartTime = TM_FAST_TIME(); } TM_ENTER(m_Context, TMZF_NONE, "%s", pName); } ~CTelemetryZonePlotScope() { TM_LEAVE(m_Context); if (m_SlotData) { m_SlotData->m_CurrFrameTime += (TM_FAST_TIME() - m_StartTime); } } private: HTELEMETRY m_Context; TelemetryZonePlotData* m_SlotData; TmU64 m_StartTime; }; #endif #endif