//========= Copyright Valve Corporation, All rights reserved. ============// // // ETW (Event Tracing for Windows) profiling helpers. // This allows easy insertion of Generic Event markers into ETW/xperf tracing // which then aids in analyzing the traces and finding performance problems. // The usage patterns are to use ETWBegin and ETWEnd (typically through the // convenience class CETWScope) to bracket time-consuming operations. In addition // ETWFrameMark marks the beginning of each frame, and ETWMark can be used to // mark other notable events. More event types and providers can be added as needed. // When recording xperf profiles add Valve-Main+Valve-FrameRate to the list of // user-mode providers and be sure to register the providers with this sequence // of commands: // xcopy /y game\bin\tier0.dll %temp% // wevtutil um src\tier0\ValveETWProvider.man // wevtutil im src\tier0\ValveETWProvider.man // //=============================================================================== #ifndef ETWPROF_H #define ETWPROF_H #if defined( COMPILER_MSVC ) #pragma once #endif #include "tier0/platform.h" #ifdef IS_WINDOWS_PC // ETW support should be compiled in for all Windows PC platforms. It isn't // supported on Windows XP but that is determined at run-time. #define ETW_MARKS_ENABLED #endif #ifdef ETW_MARKS_ENABLED // Insert a single event to mark a point in an ETW trace. The return value is a 64-bit // time stamp. PLATFORM_INTERFACE int64 ETWMark( const char *pMessage ); // Optionally do full printf formatting of the mark string. This will be more expensive, // but only when tracing is enabled. PLATFORM_INTERFACE void ETWMarkPrintf( PRINTF_FORMAT_STRING const char *pMessage, ... ) FMTFUNCTION( 1, 2 ); // Optionally specify one to four floats. They will show up in separate columns in // summary tables to allow sorting and easier transfer to spreadsheets. PLATFORM_INTERFACE void ETWMark1F( const char *pMessage, float data1 ); PLATFORM_INTERFACE void ETWMark2F( const char *pMessage, float data1, float data2 ); PLATFORM_INTERFACE void ETWMark3F( const char *pMessage, float data1, float data2, float data3 ); PLATFORM_INTERFACE void ETWMark4F( const char *pMessage, float data1, float data2, float data3, float data4 ); // Optionally specify one to four ints. They will show up in separate columns in // summary tables to allow sorting and easier transfer to spreadsheets. PLATFORM_INTERFACE void ETWMark1I( const char *pMessage, int data1 ); PLATFORM_INTERFACE void ETWMark2I( const char *pMessage, int data1, int data2 ); PLATFORM_INTERFACE void ETWMark3I( const char *pMessage, int data1, int data2, int data3 ); PLATFORM_INTERFACE void ETWMark4I( const char *pMessage, int data1, int data2, int data3, int data4 ); // Optionally specify one to two strings. They will show up in separate columns in // summary tables to allow sorting and easier transfer to spreadsheets. PLATFORM_INTERFACE void ETWMark1S( const char *pMessage, const char* data1 ); PLATFORM_INTERFACE void ETWMark2S( const char *pMessage, const char* data1, const char* data2 ); // Insert a begin event to mark the start of some work. The return value is a 64-bit // time stamp which should be passed to the corresponding ETWEnd function. PLATFORM_INTERFACE int64 ETWBegin( const char *pMessage ); // Insert a paired end event to mark the end of some work. PLATFORM_INTERFACE int64 ETWEnd( const char *pMessage, int64 nStartTime ); // Mark the start of the next render frame. bIsServerProcess must be passed // in consistently for a particular process. PLATFORM_INTERFACE void ETWRenderFrameMark( bool bIsServerProcess ); // Mark the start of the next simulation frame. bIsServerProcess must be passed // in consistently for a particular process. PLATFORM_INTERFACE void ETWSimFrameMark( bool bIsServerProcess ); // Return the frame number recorded in the ETW trace -- useful for synchronizing // other profile information to the ETW trace. PLATFORM_INTERFACE int ETWGetRenderFrameNumber(); PLATFORM_INTERFACE void ETWMouseDown( int nWhichButton, int nX, int nY ); PLATFORM_INTERFACE void ETWMouseUp( int nWhichButton, int nX, int nY ); PLATFORM_INTERFACE void ETWMouseMove( int nX, int nY ); PLATFORM_INTERFACE void ETWMouseWheel( int nWheelDelta, int nX, int nY ); PLATFORM_INTERFACE void ETWKeyDown( int nScanCode, int nVirtualCode, const char *pChar ); PLATFORM_INTERFACE void ETWSendPacket( const char *pTo, int nWireSize, int nOutSequenceNR, int nOutSequenceNrAck ); PLATFORM_INTERFACE void ETWThrottled(); PLATFORM_INTERFACE void ETWReadPacket( const char *pFrom, int nWireSize, int nInSequenceNR, int nOutSequenceNRAck ); // This class calls the ETW Begin and End functions in order to insert a // pair of events to bracket some work. class CETWScope { public: CETWScope( const char *pMessage ) : m_pMessage( pMessage ) { m_nStartTime = ETWBegin( pMessage ); } ~CETWScope() { ETWEnd( m_pMessage, m_nStartTime ); } private: // Private and unimplemented to disable copying. CETWScope( const CETWScope& rhs ); CETWScope& operator=( const CETWScope& rhs ); const char* m_pMessage; int64 m_nStartTime; }; #else inline int64 ETWMark( const char* ) { return 0; } inline void ETWMarkPrintf( const char *, ... ) { return; } inline void ETWMark1F( const char *, float ) { } inline void ETWMark2F( const char *, float , float ) { } inline void ETWMark3F( const char *, float , float , float ) { } inline void ETWMark4F( const char *, float , float , float , float ) { } inline void ETWMark1I( const char *, int ) { } inline void ETWMark2I( const char *, int , int ) { } inline void ETWMark3I( const char *, int , int , int ) { } inline void ETWMark4I( const char *, int , int , int , int ) { } // Optionally specify one to two strings. They will show up in separate columns in // summary tables to allow sorting and easier transfer to spreadsheets. inline void ETWMark1S( const char *, const char* ) { } inline void ETWMark2S( const char *, const char* , const char* ) { } inline int64 ETWBegin( const char* ) { return 0; } inline int64 ETWEnd( const char*, int64 ) { return 0; } inline void ETWRenderFrameMark( bool ) {} inline void ETWSimFrameMark( bool ) {} inline int ETWGetRenderFrameNumber() { return 0; } inline void ETWMouseDown( int nWhichButton, int nX, int nY ) {} inline void ETWMouseUp( int nWhichButton, int nX, int nY ) {} inline void ETWMouseMove( int nX, int nY ) {} inline void ETWMouseWheel( int nWheelDelta, int nX, int nY ) {} inline void ETWKeyDown( int nScanCode, int nVirtualCode, const char *pChar ) {} inline void ETWSendPacket( const char *pTo, int nWireSize, int nOutSequenceNR, int nOutSequenceNrAck ) {} inline void ETWThrottled() {} inline void ETWReadPacket( const char *pFrom, int nWireSize, int nInSequenceNR, int nOutSequenceNRAck ) {} // This class calls the ETW Begin and End functions in order to insert a // pair of events to bracket some work. class CETWScope { public: CETWScope( const char* ) { } private: // Private and unimplemented to disable copying. CETWScope( const CETWScope& rhs ); CETWScope& operator=( const CETWScope& rhs ); }; #endif #endif // ETWPROF_H