This repository has been archived on 2024-06-13. You can view files and clone it, but cannot push or open issues or pull requests.
2020-08-04 13:13:01 -04:00

165 lines
7.3 KiB
C++

//========= 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