Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1440 lines
37 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Real-Time Hierarchical Profiling
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #ifndef VPROF_H
  8. #define VPROF_H
  9. #include "tier0/dbg.h"
  10. #include "tier0/fasttimer.h"
  11. #include "tier0/l2cache.h"
  12. #include "tier0/threadtools.h"
  13. #include "tier0/vprof_telemetry.h"
  14. // VProf is enabled by default in all configurations -except- X360 Retail.
  15. #if !( defined( _X360 ) && defined( _CERT ) )
  16. #define VPROF_ENABLED
  17. #endif
  18. #if defined(_X360) && defined(VPROF_ENABLED)
  19. #include "tier0/pmc360.h"
  20. #ifndef USE_PIX
  21. #define VPROF_UNDO_PIX
  22. #undef _PIX_H_
  23. #undef PIXBeginNamedEvent
  24. #undef PIXEndNamedEvent
  25. #undef PIXSetMarker
  26. #undef PIXNameThread
  27. #define USE_PIX
  28. #include <pix.h>
  29. #undef USE_PIX
  30. #else
  31. #include <pix.h>
  32. #endif
  33. #endif
  34. #ifdef _MSC_VER
  35. #pragma warning(push)
  36. #pragma warning(disable:4251)
  37. #endif
  38. // enable this to get detailed nodes beneath budget
  39. // #define VPROF_LEVEL 1
  40. // enable this to use pix (360 only)
  41. // #define VPROF_PIX 1
  42. #if defined(VPROF_PIX)
  43. #pragma comment( lib, "Xapilibi" )
  44. #endif
  45. //-----------------------------------------------------------------------------
  46. //
  47. // Profiling instrumentation macros
  48. //
  49. #define MAXCOUNTERS 256
  50. #ifdef VPROF_ENABLED
  51. #define VPROF_VTUNE_GROUP
  52. #define VPROF( name ) VPROF_(name, 1, VPROF_BUDGETGROUP_OTHER_UNACCOUNTED, false, 0)
  53. #define VPROF_ASSERT_ACCOUNTED( name ) VPROF_(name, 1, VPROF_BUDGETGROUP_OTHER_UNACCOUNTED, true, 0)
  54. #define VPROF_( name, detail, group, bAssertAccounted, budgetFlags ) VPROF_##detail(name,group, bAssertAccounted, budgetFlags)
  55. #define VPROF_BUDGET( name, group ) VPROF_BUDGET_FLAGS(name, group, BUDGETFLAG_OTHER)
  56. #define VPROF_BUDGET_FLAGS( name, group, flags ) VPROF_(name, 0, group, false, flags)
  57. #define VPROF_SCOPE_BEGIN( tag ) do { VPROF( tag )
  58. #define VPROF_SCOPE_END() } while (0)
  59. #define VPROF_ONLY( expression ) expression
  60. #define VPROF_ENTER_SCOPE( name ) g_VProfCurrentProfile.EnterScope( name, 1, VPROF_BUDGETGROUP_OTHER_UNACCOUNTED, false, 0 )
  61. #define VPROF_EXIT_SCOPE() g_VProfCurrentProfile.ExitScope()
  62. #define VPROF_BUDGET_GROUP_ID_UNACCOUNTED 0
  63. // Budgetgroup flags. These are used with VPROF_BUDGET_FLAGS.
  64. // These control which budget panels the groups show up in.
  65. // If a budget group uses VPROF_BUDGET, it gets the default
  66. // which is BUDGETFLAG_OTHER.
  67. #define BUDGETFLAG_CLIENT (1<<0) // Shows up in the client panel.
  68. #define BUDGETFLAG_SERVER (1<<1) // Shows up in the server panel.
  69. #define BUDGETFLAG_OTHER (1<<2) // Unclassified (the client shows these but the dedicated server doesn't).
  70. #define BUDGETFLAG_HIDDEN (1<<15)
  71. #define BUDGETFLAG_ALL 0xFFFF
  72. // NOTE: You can use strings instead of these defines. . they are defined here and added
  73. // in vprof.cpp so that they are always in the same order.
  74. #define VPROF_BUDGETGROUP_OTHER_UNACCOUNTED _T("Unaccounted")
  75. #define VPROF_BUDGETGROUP_WORLD_RENDERING _T("World Rendering")
  76. #define VPROF_BUDGETGROUP_DISPLACEMENT_RENDERING _T("Displacement_Rendering")
  77. #define VPROF_BUDGETGROUP_GAME _T("Game")
  78. #define VPROF_BUDGETGROUP_NPCS _T("NPCs")
  79. #define VPROF_BUDGETGROUP_SERVER_ANIM _T("Server Animation")
  80. #define VPROF_BUDGETGROUP_PHYSICS _T("Physics")
  81. #define VPROF_BUDGETGROUP_STATICPROP_RENDERING _T("Static_Prop_Rendering")
  82. #define VPROF_BUDGETGROUP_MODEL_RENDERING _T("Other_Model_Rendering")
  83. #define VPROF_BUDGETGROUP_MODEL_FAST_PATH_RENDERING _T("Fast Path Model Rendering")
  84. #define VPROF_BUDGETGROUP_BRUSHMODEL_RENDERING _T("Brush_Model_Rendering")
  85. #define VPROF_BUDGETGROUP_SHADOW_RENDERING _T("Shadow_Rendering")
  86. #define VPROF_BUDGETGROUP_DETAILPROP_RENDERING _T("Detail_Prop_Rendering")
  87. #define VPROF_BUDGETGROUP_PARTICLE_RENDERING _T("Particle/Effect_Rendering")
  88. #define VPROF_BUDGETGROUP_ROPES _T("Ropes")
  89. #define VPROF_BUDGETGROUP_DLIGHT_RENDERING _T("Dynamic_Light_Rendering")
  90. #define VPROF_BUDGETGROUP_OTHER_NETWORKING _T("Networking")
  91. #define VPROF_BUDGETGROUP_CLIENT_ANIMATION _T("Client_Animation")
  92. #define VPROF_BUDGETGROUP_OTHER_SOUND _T("Sound")
  93. #define VPROF_BUDGETGROUP_OTHER_VGUI _T("VGUI")
  94. #define VPROF_BUDGETGROUP_OTHER_FILESYSTEM _T("FileSystem")
  95. #define VPROF_BUDGETGROUP_PREDICTION _T("Prediction")
  96. #define VPROF_BUDGETGROUP_INTERPOLATION _T("Interpolation")
  97. #define VPROF_BUDGETGROUP_SWAP_BUFFERS _T("Swap_Buffers")
  98. #define VPROF_BUDGETGROUP_PLAYER _T("Player")
  99. #define VPROF_BUDGETGROUP_OCCLUSION _T("Occlusion")
  100. #define VPROF_BUDGETGROUP_OVERLAYS _T("Overlays")
  101. #define VPROF_BUDGETGROUP_TOOLS _T("Tools")
  102. #define VPROF_BUDGETGROUP_LIGHTCACHE _T("Light_Cache")
  103. #define VPROF_BUDGETGROUP_DISP_HULLTRACES _T("Displacement_Hull_Traces")
  104. #define VPROF_BUDGETGROUP_TEXTURE_CACHE _T("Texture_Cache")
  105. #define VPROF_BUDGETGROUP_REPLAY _T("Replay")
  106. #define VPROF_BUDGETGROUP_PARTICLE_SIMULATION _T("Particle Simulation")
  107. #define VPROF_BUDGETGROUP_SHADOW_DEPTH_TEXTURING _T("Flashlight Shadows")
  108. #define VPROF_BUDGETGROUP_CLIENT_SIM _T("Client Simulation") // think functions, tempents, etc.
  109. #define VPROF_BUDGETGROUP_STEAM _T("Steam")
  110. #define VPROF_BUDGETGROUP_CVAR_FIND _T("Cvar_Find")
  111. #define VPROF_BUDGETGROUP_CLIENTLEAFSYSTEM _T("ClientLeafSystem")
  112. #define VPROF_BUDGETGROUP_JOBS_COROUTINES _T("Jobs/Coroutines")
  113. #define VPROF_BUDGETGROUP_SLEEPING _T("Sleeping")
  114. #define VPROF_BUDGETGROUP_THREADINGMAIN _T("ThreadingMain")
  115. #define VPROF_BUDGETGROUP_HTMLSURFACE _T("HTMLSurface")
  116. #define VPROF_BUDGETGROUP_VGUI VPROF_BUDGETGROUP_HTMLSURFACE
  117. #define VPROF_BUDGETGROUP_TENFOOT VPROF_BUDGETGROUP_HTMLSURFACE
  118. #define VPROF_BUDGETGROUP_STEAMUI VPROF_BUDGETGROUP_HTMLSURFACE
  119. #define VPROF_BUDGETGROUP_ATTRIBUTES _T("Attributes")
  120. #define VPROF_BUDGETGROUP_FINDATTRIBUTE _T("FindAttribute")
  121. #define VPROF_BUDGETGROUP_FINDATTRIBUTEUNSAFE _T("FindAttributeUnsafe")
  122. #ifdef _X360
  123. // update flags
  124. #define VPROF_UPDATE_BUDGET 0x01 // send budget data every frame
  125. #define VPROF_UPDATE_TEXTURE_GLOBAL 0x02 // send global texture data every frame
  126. #define VPROF_UPDATE_TEXTURE_PERFRAME 0x04 // send perframe texture data every frame
  127. #endif
  128. //-------------------------------------
  129. #ifndef VPROF_LEVEL
  130. #define VPROF_LEVEL 0
  131. #endif
  132. //these macros exist to create VProf_<line number> variables. This is important because it avoids /analyze warnings about variable aliasing when VPROF's are nested within each other, and allows
  133. //for multiple VPROF's to exist within the same scope. Three macros must be used to force the __LINE__ to be resolved prior to the token concatenation, but just ignore the _INTERNAL macros and use
  134. //the VPROF_VAR_NAME
  135. #define VPROF_VAR_NAME_INTERNAL_CAT(a, b) a##b
  136. #define VPROF_VAR_NAME_INTERNAL( a, b ) VPROF_VAR_NAME_INTERNAL_CAT( a, b )
  137. #define VPROF_VAR_NAME( a ) VPROF_VAR_NAME_INTERNAL( a, __LINE__ )
  138. #define VPROF_0(name,group,assertAccounted,budgetFlags) tmZone( TELEMETRY_LEVEL2, TMZF_NONE, "(%s)%s", group, name ); CVProfScope VPROF_VAR_NAME( VProf_ )(name, 0, group, assertAccounted, budgetFlags);
  139. #if VPROF_LEVEL > 0
  140. #define VPROF_1(name,group,assertAccounted,budgetFlags) tmZone( TELEMETRY_LEVEL3, TMZF_NONE, "(%s)%s", group, name ); CVProfScope VPROF_VAR_NAME( VProf_ )(name, 1, group, assertAccounted, budgetFlags);
  141. #else
  142. #define VPROF_1(name,group,assertAccounted,budgetFlags) ((void)0)
  143. #endif
  144. #if VPROF_LEVEL > 1
  145. #define VPROF_2(name,group,assertAccounted,budgetFlags) CVProfScope VPROF_VAR_NAME( VProf_ )(name, 2, group, assertAccounted, budgetFlags);
  146. #else
  147. #define VPROF_2(name,group,assertAccounted,budgetFlags) ((void)0)
  148. #endif
  149. #if VPROF_LEVEL > 2
  150. #define VPROF_3(name,group,assertAccounted,budgetFlags) CVProfScope VPROF_VAR_NAME( VProf_ )(name, 3, group, assertAccounted, budgetFlags);
  151. #else
  152. #define VPROF_3(name,group,assertAccounted,budgetFlags) ((void)0)
  153. #endif
  154. #if VPROF_LEVEL > 3
  155. #define VPROF_4(name,group,assertAccounted,budgetFlags) CVProfScope VPROF_VAR_NAME( VProf_ )(name, 4, group, assertAccounted, budgetFlags);
  156. #else
  157. #define VPROF_4(name,group,assertAccounted,budgetFlags) ((void)0)
  158. #endif
  159. //-------------------------------------
  160. #ifdef _MSC_VER
  161. #define VProfCode( code ) \
  162. if ( 0 ) \
  163. ; \
  164. else \
  165. { \
  166. VPROF( __FUNCTION__ ": " #code ); \
  167. code; \
  168. }
  169. #else
  170. #define VProfCode( code ) \
  171. if ( 0 ) \
  172. ; \
  173. else \
  174. { \
  175. VPROF( #code ); \
  176. code; \
  177. }
  178. #endif
  179. //-------------------------------------
  180. #define VPROF_INCREMENT_COUNTER(name,amount) do { static CVProfCounter _counter( name ); _counter.Increment( amount ); } while( 0 )
  181. #define VPROF_INCREMENT_GROUP_COUNTER(name,group,amount) do { static CVProfCounter _counter( name, group ); _counter.Increment( amount ); } while( 0 )
  182. #else
  183. #define VPROF( name ) ((void)0)
  184. #define VPROF_ASSERT_ACCOUNTED( name ) ((void)0)
  185. #define VPROF_( name, detail, group, bAssertAccounted, budgetFlags ) ((void)0)
  186. #define VPROF_BUDGET( name, group ) ((void)0)
  187. #define VPROF_BUDGET_FLAGS( name, group, flags ) ((void)0)
  188. #define VPROF_SCOPE_BEGIN( tag ) do {
  189. #define VPROF_SCOPE_END() } while (0)
  190. #define VPROF_ONLY( expression ) ((void)0)
  191. #define VPROF_ENTER_SCOPE( name )
  192. #define VPROF_EXIT_SCOPE()
  193. #define VPROF_INCREMENT_COUNTER(name,amount) ((void)0)
  194. #define VPROF_INCREMENT_GROUP_COUNTER(name,group,amount) ((void)0)
  195. #define VPROF_TEST_SPIKE( msec ) ((void)0)
  196. #define VProfCode( code ) code
  197. #endif
  198. //-----------------------------------------------------------------------------
  199. #ifdef VPROF_ENABLED
  200. //-----------------------------------------------------------------------------
  201. //
  202. // A node in the call graph hierarchy
  203. //
  204. class DBG_CLASS CVProfNode
  205. {
  206. friend class CVProfRecorder;
  207. friend class CVProfile;
  208. public:
  209. CVProfNode( const tchar * pszName, int detailLevel, CVProfNode *pParent, const tchar *pBudgetGroupName, int budgetFlags );
  210. ~CVProfNode();
  211. CVProfNode *GetSubNode( const tchar *pszName, int detailLevel, const tchar *pBudgetGroupName, int budgetFlags );
  212. CVProfNode *GetSubNode( const tchar *pszName, int detailLevel, const tchar *pBudgetGroupName );
  213. CVProfNode *GetParent();
  214. CVProfNode *GetSibling();
  215. CVProfNode *GetPrevSibling();
  216. CVProfNode *GetChild();
  217. void MarkFrame();
  218. void ResetPeak();
  219. void Pause();
  220. void Resume();
  221. void Reset();
  222. void EnterScope();
  223. bool ExitScope();
  224. const tchar *GetName();
  225. int GetBudgetGroupID()
  226. {
  227. return m_BudgetGroupID;
  228. }
  229. // Only used by the record/playback stuff.
  230. void SetBudgetGroupID( int id )
  231. {
  232. m_BudgetGroupID = id;
  233. }
  234. int GetCurCalls();
  235. double GetCurTime();
  236. int GetPrevCalls();
  237. double GetPrevTime();
  238. int GetTotalCalls();
  239. double GetTotalTime();
  240. double GetPeakTime();
  241. double GetCurTimeLessChildren();
  242. double GetPrevTimeLessChildren();
  243. double GetTotalTimeLessChildren();
  244. int GetPrevL2CacheMissLessChildren();
  245. int GetPrevLoadHitStoreLessChildren();
  246. void ClearPrevTime();
  247. int GetL2CacheMisses();
  248. // Not used in the common case...
  249. void SetCurFrameTime( unsigned long milliseconds );
  250. void SetClientData( int iClientData ) { m_iClientData = iClientData; }
  251. int GetClientData() const { return m_iClientData; }
  252. #ifdef DBGFLAG_VALIDATE
  253. void Validate( CValidator &validator, tchar *pchName ); // Validate our internal structures
  254. #endif // DBGFLAG_VALIDATE
  255. // Used by vprof record/playback.
  256. private:
  257. void SetUniqueNodeID( int id )
  258. {
  259. m_iUniqueNodeID = id;
  260. }
  261. int GetUniqueNodeID() const
  262. {
  263. return m_iUniqueNodeID;
  264. }
  265. static int s_iCurrentUniqueNodeID;
  266. private:
  267. const tchar *m_pszName;
  268. CFastTimer m_Timer;
  269. // L2 Cache data.
  270. int m_iPrevL2CacheMiss;
  271. int m_iCurL2CacheMiss;
  272. int m_iTotalL2CacheMiss;
  273. #ifndef _X360
  274. // L2 Cache data.
  275. CL2Cache m_L2Cache;
  276. #else // 360:
  277. unsigned int m_iBitFlags; // see enum below for settings
  278. CPMCData m_PMCData;
  279. int m_iPrevLoadHitStores;
  280. int m_iCurLoadHitStores;
  281. int m_iTotalLoadHitStores;
  282. public:
  283. enum FlagBits
  284. {
  285. kRecordL2 = 0x01,
  286. kCPUTrace = 0x02, ///< cause a PIX trace inside this node.
  287. };
  288. // call w/ true to enable L2 and LHS recording; false to turn it off
  289. inline void EnableL2andLHS(bool enable)
  290. {
  291. if (enable)
  292. m_iBitFlags |= kRecordL2;
  293. else
  294. m_iBitFlags &= (~kRecordL2);
  295. }
  296. inline bool IsL2andLHSEnabled( void )
  297. {
  298. return (m_iBitFlags & kRecordL2) != 0;
  299. }
  300. int GetLoadHitStores();
  301. private:
  302. #endif
  303. int m_nRecursions;
  304. unsigned m_nCurFrameCalls;
  305. CCycleCount m_CurFrameTime;
  306. unsigned m_nPrevFrameCalls;
  307. CCycleCount m_PrevFrameTime;
  308. unsigned m_nTotalCalls;
  309. CCycleCount m_TotalTime;
  310. CCycleCount m_PeakTime;
  311. CVProfNode *m_pParent;
  312. CVProfNode *m_pChild;
  313. CVProfNode *m_pSibling;
  314. int m_BudgetGroupID;
  315. int m_iClientData;
  316. int m_iUniqueNodeID;
  317. };
  318. //-----------------------------------------------------------------------------
  319. //
  320. // Coordinator and root node of the profile hierarchy tree
  321. //
  322. enum VProfReportType_t
  323. {
  324. VPRT_SUMMARY = ( 1 << 0 ),
  325. VPRT_HIERARCHY = ( 1 << 1 ),
  326. VPRT_HIERARCHY_TIME_PER_FRAME_AND_COUNT_ONLY = ( 1 << 2 ),
  327. VPRT_LIST_BY_TIME = ( 1 << 3 ),
  328. VPRT_LIST_BY_TIME_LESS_CHILDREN = ( 1 << 4 ),
  329. VPRT_LIST_BY_AVG_TIME = ( 1 << 5 ),
  330. VPRT_LIST_BY_AVG_TIME_LESS_CHILDREN = ( 1 << 6 ),
  331. VPRT_LIST_BY_PEAK_TIME = ( 1 << 7 ),
  332. VPRT_LIST_BY_PEAK_OVER_AVERAGE = ( 1 << 8 ),
  333. VPRT_LIST_TOP_ITEMS_ONLY = ( 1 << 9 ),
  334. VPRT_FULL = (0xffffffff & ~(VPRT_HIERARCHY_TIME_PER_FRAME_AND_COUNT_ONLY|VPRT_LIST_TOP_ITEMS_ONLY)),
  335. };
  336. enum CounterGroup_t
  337. {
  338. COUNTER_GROUP_DEFAULT=0,
  339. COUNTER_GROUP_NO_RESET, // The engine doesn't reset these counters. Usually, they are used
  340. // like global variables that can be accessed across modules.
  341. COUNTER_GROUP_TEXTURE_GLOBAL, // Global texture usage counters (totals for what is currently in memory).
  342. COUNTER_GROUP_TEXTURE_PER_FRAME, // Per-frame texture usage counters.
  343. COUNTER_GROUP_TELEMETRY,
  344. };
  345. class DBG_CLASS CVProfile
  346. {
  347. public:
  348. CVProfile();
  349. ~CVProfile();
  350. void Term();
  351. //
  352. // Runtime operations
  353. //
  354. void Start();
  355. void Stop();
  356. void SetTargetThreadId( unsigned id ) { m_TargetThreadId = id; }
  357. unsigned GetTargetThreadId() { return m_TargetThreadId; }
  358. bool InTargetThread() { return ( m_TargetThreadId == ThreadGetCurrentId() ); }
  359. #ifdef _X360
  360. enum VXConsoleReportMode_t
  361. {
  362. VXCONSOLE_REPORT_TIME = 0,
  363. VXCONSOLE_REPORT_L2CACHE_MISSES,
  364. VXCONSOLE_REPORT_LOAD_HIT_STORE,
  365. VXCONSOLE_REPORT_COUNT,
  366. };
  367. void VXProfileStart();
  368. void VXProfileUpdate();
  369. void VXEnableUpdateMode( int event, bool bEnable );
  370. void VXSendNodes( void );
  371. void PMCDisableAllNodes(CVProfNode *pStartNode = NULL); ///< turn off l2 and lhs recording for everywhere
  372. bool PMCEnableL2Upon(const tchar *pszNodeName, bool bRecursive = false); ///< enable l2 and lhs recording for one given node
  373. bool PMCDisableL2Upon(const tchar *pszNodeName, bool bRecursive = false); ///< enable l2 and lhs recording for one given node
  374. void DumpEnabledPMCNodes( void );
  375. void VXConsoleReportMode( VXConsoleReportMode_t mode );
  376. void VXConsoleReportScale( VXConsoleReportMode_t mode, float flScale );
  377. // the CPU trace mode is actually a small state machine; it can be off, primed for
  378. // single capture, primed for everything-in-a-frame capture, or currently in everything-in-a-frame
  379. // capture.
  380. enum CPUTraceState
  381. {
  382. kDisabled,
  383. kFirstHitNode, // record from the first time we hit the node until that node ends
  384. kAllNodesInFrame_WaitingForMark, // we're going to record all the times a node is hit in a frame, but are waiting for the frame to start
  385. kAllNodesInFrame_Recording, // we're recording all hits on a node this frame.
  386. // Same as above, but going to record for > 1 frame
  387. kAllNodesInFrame_WaitingForMarkMultiFrame, // we're going to record all the times a node is hit in a frame, but are waiting for the frame to start
  388. kAllNodesInFrame_RecordingMultiFrame,
  389. };
  390. // Global switch to turn CPU tracing on or off at all. The idea is you set up a node first,
  391. // then trigger tracing by throwing this to true. It'll reset back to false after the trace
  392. // happens.
  393. inline CPUTraceState GetCPUTraceMode();
  394. inline void SetCPUTraceEnabled( CPUTraceState enabled, bool bTraceCompleteEvent = false, int nNumFrames = -1 );
  395. inline void IncrementMultiTraceIndex(); // tick up the counter that gets appended to the multi-per-frame traces
  396. inline unsigned int GetMultiTraceIndex(); // return the counter
  397. void CPUTraceDisableAllNodes( CVProfNode *pStartNode = NULL ); // disable the cpu trace flag wherever it may be
  398. CVProfNode *CPUTraceEnableForNode( const tchar *pszNodeName ); // enable cpu trace on this node only, disabling it wherever else it may be on.
  399. CVProfNode *CPUTraceGetEnabledNode( CVProfNode *pStartNode = NULL ); // return the node enabled for CPU tracing, or NULL.
  400. const char *GetCPUTraceFilename(); // get the filename the trace should write into.
  401. const char *SetCPUTraceFilename( const char *filename ); // set the filename the trace should write into. (don't specify the extension; I'll do that.)
  402. inline bool TraceCompleteEvent( void );
  403. #ifdef _X360
  404. void LatchMultiFrame( int64 cycles );
  405. void SpewWorstMultiFrame();
  406. #endif
  407. #endif
  408. void EnterScope( const tchar *pszName, int detailLevel, const tchar *pBudgetGroupName, bool bAssertAccounted );
  409. void EnterScope( const tchar *pszName, int detailLevel, const tchar *pBudgetGroupName, bool bAssertAccounted, int budgetFlags );
  410. void ExitScope();
  411. void MarkFrame();
  412. void ResetPeaks();
  413. void Pause();
  414. void Resume();
  415. void Reset();
  416. bool IsEnabled() const;
  417. int GetDetailLevel() const;
  418. bool AtRoot() const;
  419. //
  420. // Queries
  421. //
  422. #ifdef VPROF_VTUNE_GROUP
  423. # define MAX_GROUP_STACK_DEPTH 1024
  424. void EnableVTuneGroup( const tchar *pGroupName )
  425. {
  426. m_nVTuneGroupID = BudgetGroupNameToBudgetGroupID( pGroupName );
  427. m_bVTuneGroupEnabled = true;
  428. }
  429. void DisableVTuneGroup( void )
  430. {
  431. m_bVTuneGroupEnabled = false;
  432. }
  433. inline void PushGroup( int nGroupID );
  434. inline void PopGroup( void );
  435. #endif
  436. int NumFramesSampled() { return m_nFrames; }
  437. double GetPeakFrameTime();
  438. double GetTotalTimeSampled();
  439. double GetTimeLastFrame();
  440. CVProfNode *GetRoot();
  441. CVProfNode *FindNode( CVProfNode *pStartNode, const tchar *pszNode );
  442. CVProfNode *GetCurrentNode();
  443. typedef void ( __cdecl *StreamOut_t )( const char* pszFormat, ... );
  444. // Set the output function used for all vprof reports. Call this with NULL
  445. // to set it to the default output function.
  446. void SetOutputStream( StreamOut_t outputStream );
  447. void OutputReport( int type = VPRT_FULL, const tchar *pszStartNode = NULL, int budgetGroupID = -1 );
  448. const tchar *GetBudgetGroupName( int budgetGroupID );
  449. int GetBudgetGroupFlags( int budgetGroupID ) const; // Returns a combination of BUDGETFLAG_ defines.
  450. int GetNumBudgetGroups( void );
  451. void GetBudgetGroupColor( int budgetGroupID, int &r, int &g, int &b, int &a );
  452. int BudgetGroupNameToBudgetGroupID( const tchar *pBudgetGroupName );
  453. int BudgetGroupNameToBudgetGroupID( const tchar *pBudgetGroupName, int budgetFlagsToORIn );
  454. void RegisterNumBudgetGroupsChangedCallBack( void (*pCallBack)(void) );
  455. int BudgetGroupNameToBudgetGroupIDNoCreate( const tchar *pBudgetGroupName ) { return FindBudgetGroupName( pBudgetGroupName ); }
  456. void HideBudgetGroup( int budgetGroupID, bool bHide = true );
  457. void HideBudgetGroup( const char *pszName, bool bHide = true ) { HideBudgetGroup( BudgetGroupNameToBudgetGroupID( pszName), bHide ); }
  458. int *FindOrCreateCounter( const tchar *pName, CounterGroup_t eCounterGroup=COUNTER_GROUP_DEFAULT );
  459. void ResetCounters( CounterGroup_t eCounterGroup );
  460. int GetNumCounters( void ) const;
  461. const tchar *GetCounterName( int index ) const;
  462. int GetCounterValue( int index ) const;
  463. const tchar *GetCounterNameAndValue( int index, int &val ) const;
  464. CounterGroup_t GetCounterGroup( int index ) const;
  465. // Performance monitoring events.
  466. void PMEInitialized( bool bInit ) { m_bPMEInit = bInit; }
  467. void PMEEnable( bool bEnable ) { m_bPMEEnabled = bEnable; }
  468. #ifndef _X360
  469. bool UsePME( void ) { return ( m_bPMEInit && m_bPMEEnabled ); }
  470. #else
  471. bool UsePME( void ) { return ( CPMCData::IsInitialized() && m_bPMEEnabled ); }
  472. #endif
  473. #ifdef DBGFLAG_VALIDATE
  474. void Validate( CValidator &validator, tchar *pchName ); // Validate our internal structures
  475. #endif // DBGFLAG_VALIDATE
  476. protected:
  477. void FreeNodes_R( CVProfNode *pNode );
  478. #ifdef VPROF_VTUNE_GROUP
  479. bool VTuneGroupEnabled()
  480. {
  481. return m_bVTuneGroupEnabled;
  482. }
  483. int VTuneGroupID()
  484. {
  485. return m_nVTuneGroupID;
  486. }
  487. #endif
  488. void SumTimes( const tchar *pszStartNode, int budgetGroupID );
  489. void SumTimes( CVProfNode *pNode, int budgetGroupID );
  490. void DumpNodes( CVProfNode *pNode, int indent, bool bAverageAndCountOnly );
  491. int FindBudgetGroupName( const tchar *pBudgetGroupName );
  492. int AddBudgetGroupName( const tchar *pBudgetGroupName, int budgetFlags );
  493. #ifdef VPROF_VTUNE_GROUP
  494. bool m_bVTuneGroupEnabled;
  495. int m_nVTuneGroupID;
  496. int m_GroupIDStack[MAX_GROUP_STACK_DEPTH];
  497. int m_GroupIDStackDepth;
  498. #endif
  499. int m_enabled;
  500. bool m_fAtRoot; // tracked for efficiency of the "not profiling" case
  501. CVProfNode *m_pCurNode;
  502. CVProfNode m_Root;
  503. int m_nFrames;
  504. int m_ProfileDetailLevel;
  505. int m_pausedEnabledDepth;
  506. class CBudgetGroup
  507. {
  508. public:
  509. tchar *m_pName;
  510. int m_BudgetFlags;
  511. };
  512. CBudgetGroup *m_pBudgetGroups;
  513. int m_nBudgetGroupNamesAllocated;
  514. int m_nBudgetGroupNames;
  515. void (*m_pNumBudgetGroupsChangedCallBack)(void);
  516. // Performance monitoring events.
  517. bool m_bPMEInit;
  518. bool m_bPMEEnabled;
  519. int m_Counters[MAXCOUNTERS];
  520. char m_CounterGroups[MAXCOUNTERS]; // (These are CounterGroup_t's).
  521. tchar *m_CounterNames[MAXCOUNTERS];
  522. int m_NumCounters;
  523. #ifdef _X360
  524. int m_UpdateMode;
  525. CPUTraceState m_iCPUTraceEnabled;
  526. int m_nFramesRemaining;
  527. int m_nFrameCount;
  528. int64 m_WorstCycles;
  529. char m_WorstTraceFilename[128];
  530. char m_CPUTraceFilename[128];
  531. unsigned int m_iSuccessiveTraceIndex;
  532. VXConsoleReportMode_t m_ReportMode;
  533. float m_pReportScale[VXCONSOLE_REPORT_COUNT];
  534. bool m_bTraceCompleteEvent;
  535. #endif
  536. unsigned m_TargetThreadId;
  537. StreamOut_t m_pOutputStream;
  538. };
  539. //-------------------------------------
  540. DBG_INTERFACE CVProfile g_VProfCurrentProfile;
  541. //-----------------------------------------------------------------------------
  542. DBG_INTERFACE bool g_VProfSignalSpike;
  543. class CVProfSpikeDetector
  544. {
  545. public:
  546. CVProfSpikeDetector( float spike ) :
  547. m_timeLast( GetTimeLast() )
  548. {
  549. m_spike = spike;
  550. m_Timer.Start();
  551. }
  552. ~CVProfSpikeDetector()
  553. {
  554. m_Timer.End();
  555. if ( Plat_FloatTime() - m_timeLast > 2.0 )
  556. {
  557. m_timeLast = Plat_FloatTime();
  558. if ( m_Timer.GetDuration().GetMillisecondsF() > m_spike )
  559. {
  560. g_VProfSignalSpike = true;
  561. }
  562. }
  563. }
  564. private:
  565. static float &GetTimeLast() { static float timeLast = 0; return timeLast; }
  566. CFastTimer m_Timer;
  567. float m_spike;
  568. float &m_timeLast;
  569. };
  570. // Macro to signal a local spike. Meant as temporary instrumentation, do not leave in code
  571. #define VPROF_TEST_SPIKE( msec ) CVProfSpikeDetector UNIQUE_ID( msec )
  572. //-----------------------------------------------------------------------------
  573. #ifdef VPROF_VTUNE_GROUP
  574. inline void CVProfile::PushGroup( int nGroupID )
  575. {
  576. // There is always at least one item on the stack since we force
  577. // the first element to be VPROF_BUDGETGROUP_OTHER_UNACCOUNTED.
  578. Assert( m_GroupIDStackDepth > 0 );
  579. Assert( m_GroupIDStackDepth < MAX_GROUP_STACK_DEPTH );
  580. m_GroupIDStack[m_GroupIDStackDepth] = nGroupID;
  581. m_GroupIDStackDepth++;
  582. if( m_GroupIDStack[m_GroupIDStackDepth-2] != nGroupID &&
  583. VTuneGroupEnabled() &&
  584. nGroupID == VTuneGroupID() )
  585. {
  586. vtune( true );
  587. }
  588. }
  589. #endif // VPROF_VTUNE_GROUP
  590. #ifdef VPROF_VTUNE_GROUP
  591. inline void CVProfile::PopGroup( void )
  592. {
  593. m_GroupIDStackDepth--;
  594. // There is always at least one item on the stack since we force
  595. // the first element to be VPROF_BUDGETGROUP_OTHER_UNACCOUNTED.
  596. Assert( m_GroupIDStackDepth > 0 );
  597. if( m_GroupIDStack[m_GroupIDStackDepth] != m_GroupIDStack[m_GroupIDStackDepth+1] &&
  598. VTuneGroupEnabled() &&
  599. m_GroupIDStack[m_GroupIDStackDepth+1] == VTuneGroupID() )
  600. {
  601. vtune( false );
  602. }
  603. }
  604. #endif // VPROF_VTUNE_GROUP
  605. //-----------------------------------------------------------------------------
  606. class CVProfScope
  607. {
  608. public:
  609. CVProfScope( const tchar * pszName, int detailLevel, const tchar *pBudgetGroupName, bool bAssertAccounted, int budgetFlags );
  610. ~CVProfScope();
  611. private:
  612. bool m_bEnabled;
  613. };
  614. //-----------------------------------------------------------------------------
  615. //
  616. // CVProfNode, inline methods
  617. //
  618. inline CVProfNode::CVProfNode( const tchar * pszName, int detailLevel, CVProfNode *pParent, const tchar *pBudgetGroupName, int budgetFlags )
  619. : m_pszName( pszName ),
  620. m_nCurFrameCalls( 0 ),
  621. m_nPrevFrameCalls( 0 ),
  622. m_nRecursions( 0 ),
  623. m_pParent( pParent ),
  624. m_pChild( NULL ),
  625. m_pSibling( NULL ),
  626. m_iClientData( -1 )
  627. #ifdef _X360
  628. , m_iBitFlags( 0 )
  629. #endif
  630. {
  631. m_iUniqueNodeID = s_iCurrentUniqueNodeID++;
  632. if ( m_iUniqueNodeID > 0 )
  633. {
  634. m_BudgetGroupID = g_VProfCurrentProfile.BudgetGroupNameToBudgetGroupID( pBudgetGroupName, budgetFlags );
  635. }
  636. else
  637. {
  638. m_BudgetGroupID = 0; // "m_Root" can't call BudgetGroupNameToBudgetGroupID because g_VProfCurrentProfile not yet initialized
  639. }
  640. Reset();
  641. if( m_pParent && ( m_BudgetGroupID == VPROF_BUDGET_GROUP_ID_UNACCOUNTED ) )
  642. {
  643. m_BudgetGroupID = m_pParent->GetBudgetGroupID();
  644. }
  645. }
  646. //-------------------------------------
  647. inline CVProfNode *CVProfNode::GetParent()
  648. {
  649. Assert( m_pParent );
  650. return m_pParent;
  651. }
  652. //-------------------------------------
  653. inline CVProfNode *CVProfNode::GetSibling()
  654. {
  655. return m_pSibling;
  656. }
  657. //-------------------------------------
  658. // Hacky way to the previous sibling, only used from vprof panel at the moment,
  659. // so it didn't seem like it was worth the memory waste to add the reverse
  660. // link per node.
  661. inline CVProfNode *CVProfNode::GetPrevSibling()
  662. {
  663. CVProfNode* p = GetParent();
  664. if(!p)
  665. return NULL;
  666. CVProfNode* s;
  667. for( s = p->GetChild();
  668. s && ( s->GetSibling() != this );
  669. s = s->GetSibling() )
  670. ;
  671. return s;
  672. }
  673. //-------------------------------------
  674. inline CVProfNode *CVProfNode::GetChild()
  675. {
  676. return m_pChild;
  677. }
  678. //-------------------------------------
  679. inline const tchar *CVProfNode::GetName()
  680. {
  681. Assert( m_pszName );
  682. return m_pszName;
  683. }
  684. //-------------------------------------
  685. inline int CVProfNode::GetTotalCalls()
  686. {
  687. return m_nTotalCalls;
  688. }
  689. //-------------------------------------
  690. inline double CVProfNode::GetTotalTime()
  691. {
  692. return m_TotalTime.GetMillisecondsF();
  693. }
  694. //-------------------------------------
  695. inline int CVProfNode::GetCurCalls()
  696. {
  697. return m_nCurFrameCalls;
  698. }
  699. //-------------------------------------
  700. inline double CVProfNode::GetCurTime()
  701. {
  702. return m_CurFrameTime.GetMillisecondsF();
  703. }
  704. //-------------------------------------
  705. inline int CVProfNode::GetPrevCalls()
  706. {
  707. return m_nPrevFrameCalls;
  708. }
  709. //-------------------------------------
  710. inline double CVProfNode::GetPrevTime()
  711. {
  712. return m_PrevFrameTime.GetMillisecondsF();
  713. }
  714. //-------------------------------------
  715. inline double CVProfNode::GetPeakTime()
  716. {
  717. return m_PeakTime.GetMillisecondsF();
  718. }
  719. //-------------------------------------
  720. inline double CVProfNode::GetTotalTimeLessChildren()
  721. {
  722. double result = GetTotalTime();
  723. CVProfNode *pChild = GetChild();
  724. while ( pChild )
  725. {
  726. result -= pChild->GetTotalTime();
  727. pChild = pChild->GetSibling();
  728. }
  729. return result;
  730. }
  731. //-------------------------------------
  732. inline double CVProfNode::GetCurTimeLessChildren()
  733. {
  734. double result = GetCurTime();
  735. CVProfNode *pChild = GetChild();
  736. while ( pChild )
  737. {
  738. result -= pChild->GetCurTime();
  739. pChild = pChild->GetSibling();
  740. }
  741. return result;
  742. }
  743. inline double CVProfNode::GetPrevTimeLessChildren()
  744. {
  745. double result = GetPrevTime();
  746. CVProfNode *pChild = GetChild();
  747. while ( pChild )
  748. {
  749. result -= pChild->GetPrevTime();
  750. pChild = pChild->GetSibling();
  751. }
  752. return result;
  753. }
  754. //-----------------------------------------------------------------------------
  755. inline int CVProfNode::GetPrevL2CacheMissLessChildren()
  756. {
  757. int result = m_iPrevL2CacheMiss;
  758. CVProfNode *pChild = GetChild();
  759. while ( pChild )
  760. {
  761. result -= pChild->m_iPrevL2CacheMiss;
  762. pChild = pChild->GetSibling();
  763. }
  764. return result;
  765. }
  766. //-----------------------------------------------------------------------------
  767. inline int CVProfNode::GetPrevLoadHitStoreLessChildren()
  768. {
  769. #ifndef _X360
  770. return 0;
  771. #else
  772. int result = m_iPrevLoadHitStores;
  773. CVProfNode *pChild = GetChild();
  774. while ( pChild )
  775. {
  776. result -= pChild->m_iPrevLoadHitStores;
  777. pChild = pChild->GetSibling();
  778. }
  779. return result;
  780. #endif
  781. }
  782. //-----------------------------------------------------------------------------
  783. inline void CVProfNode::ClearPrevTime()
  784. {
  785. m_PrevFrameTime.Init();
  786. }
  787. //-----------------------------------------------------------------------------
  788. inline int CVProfNode::GetL2CacheMisses( void )
  789. {
  790. #ifndef _X360
  791. return m_L2Cache.GetL2CacheMisses();
  792. #else
  793. return m_iTotalL2CacheMiss;
  794. #endif
  795. }
  796. #ifdef _X360
  797. inline int CVProfNode::GetLoadHitStores( void )
  798. {
  799. return m_iTotalLoadHitStores;
  800. }
  801. #endif
  802. //-----------------------------------------------------------------------------
  803. //
  804. // CVProfile, inline methods
  805. //
  806. //-------------------------------------
  807. inline bool CVProfile::IsEnabled() const
  808. {
  809. return ( m_enabled != 0 );
  810. }
  811. //-------------------------------------
  812. inline int CVProfile::GetDetailLevel() const
  813. {
  814. return m_ProfileDetailLevel;
  815. }
  816. //-------------------------------------
  817. inline bool CVProfile::AtRoot() const
  818. {
  819. return m_fAtRoot;
  820. }
  821. //-------------------------------------
  822. inline void CVProfile::Start()
  823. {
  824. if ( ++m_enabled == 1 )
  825. {
  826. m_Root.EnterScope();
  827. #ifdef _X360
  828. VXProfileStart();
  829. CPMCData::InitializeOnceProgramWide();
  830. #endif
  831. }
  832. }
  833. //-------------------------------------
  834. inline void CVProfile::Stop()
  835. {
  836. if ( --m_enabled == 0 )
  837. m_Root.ExitScope();
  838. }
  839. //-------------------------------------
  840. inline void CVProfile::EnterScope( const tchar *pszName, int detailLevel, const tchar *pBudgetGroupName, bool bAssertAccounted, int budgetFlags )
  841. {
  842. if ( ( m_enabled != 0 || !m_fAtRoot ) && InTargetThread() ) // if became disabled, need to unwind back to root before stopping
  843. {
  844. // Only account for vprof stuff on the primary thread.
  845. //if( !Plat_IsPrimaryThread() )
  846. // return;
  847. if ( pszName != m_pCurNode->GetName() )
  848. {
  849. m_pCurNode = m_pCurNode->GetSubNode( pszName, detailLevel, pBudgetGroupName, budgetFlags );
  850. }
  851. m_pBudgetGroups[m_pCurNode->GetBudgetGroupID()].m_BudgetFlags |= budgetFlags;
  852. #if defined( _DEBUG ) && !defined( _X360 )
  853. // 360 doesn't want this to allow tier0 debug/release .def files to match
  854. if ( bAssertAccounted )
  855. {
  856. // FIXME
  857. AssertOnce( m_pCurNode->GetBudgetGroupID() != 0 );
  858. }
  859. #endif
  860. m_pCurNode->EnterScope();
  861. m_fAtRoot = false;
  862. }
  863. #if defined(_X360) && defined(VPROF_PIX)
  864. if ( m_pCurNode->GetBudgetGroupID() != VPROF_BUDGET_GROUP_ID_UNACCOUNTED )
  865. PIXBeginNamedEvent( 0, pszName );
  866. #endif
  867. }
  868. inline void CVProfile::EnterScope( const tchar *pszName, int detailLevel, const tchar *pBudgetGroupName, bool bAssertAccounted )
  869. {
  870. EnterScope( pszName, detailLevel, pBudgetGroupName, bAssertAccounted, BUDGETFLAG_OTHER );
  871. }
  872. //-------------------------------------
  873. inline void CVProfile::ExitScope()
  874. {
  875. #if defined(_X360) && defined(VPROF_PIX)
  876. #ifdef PIXBeginNamedEvent
  877. #error
  878. #endif
  879. if ( m_pCurNode->GetBudgetGroupID() != VPROF_BUDGET_GROUP_ID_UNACCOUNTED )
  880. PIXEndNamedEvent();
  881. #endif
  882. if ( ( !m_fAtRoot || m_enabled != 0 ) && InTargetThread() )
  883. {
  884. // Only account for vprof stuff on the primary thread.
  885. //if( !Plat_IsPrimaryThread() )
  886. // return;
  887. // ExitScope will indicate whether we should back up to our parent (we may
  888. // be profiling a recursive function)
  889. if (m_pCurNode->ExitScope())
  890. {
  891. m_pCurNode = m_pCurNode->GetParent();
  892. }
  893. m_fAtRoot = ( m_pCurNode == &m_Root );
  894. }
  895. }
  896. //-------------------------------------
  897. inline void CVProfile::Pause()
  898. {
  899. m_pausedEnabledDepth = m_enabled;
  900. m_enabled = 0;
  901. if ( !AtRoot() )
  902. m_Root.Pause();
  903. }
  904. //-------------------------------------
  905. inline void CVProfile::Resume()
  906. {
  907. m_enabled = m_pausedEnabledDepth;
  908. if ( !AtRoot() )
  909. m_Root.Resume();
  910. }
  911. //-------------------------------------
  912. inline void CVProfile::Reset()
  913. {
  914. m_Root.Reset();
  915. m_nFrames = 0;
  916. }
  917. //-------------------------------------
  918. inline void CVProfile::ResetPeaks()
  919. {
  920. m_Root.ResetPeak();
  921. }
  922. //-------------------------------------
  923. inline void CVProfile::MarkFrame()
  924. {
  925. if ( m_enabled )
  926. {
  927. ++m_nFrames;
  928. m_Root.ExitScope();
  929. m_Root.MarkFrame();
  930. m_Root.EnterScope();
  931. #ifdef _X360
  932. // update the CPU trace state machine if enabled
  933. switch ( GetCPUTraceMode() )
  934. {
  935. case kAllNodesInFrame_WaitingForMark:
  936. // mark! Start recording a zillion traces.
  937. m_iCPUTraceEnabled = kAllNodesInFrame_Recording;
  938. break;
  939. case kAllNodesInFrame_WaitingForMarkMultiFrame:
  940. m_iCPUTraceEnabled = kAllNodesInFrame_RecordingMultiFrame;
  941. break;
  942. case kAllNodesInFrame_Recording:
  943. // end of frame. stop recording if no more frames needed
  944. m_iCPUTraceEnabled = kDisabled;
  945. Msg("Frame ended. Recording no more CPU traces\n");
  946. break;
  947. case kAllNodesInFrame_RecordingMultiFrame:
  948. // end of frame. stop recording if no more frames needed
  949. if ( --m_nFramesRemaining == 0 )
  950. {
  951. m_iCPUTraceEnabled = kDisabled;
  952. Msg("Frames ended. Recording no more CPU traces\n");
  953. SpewWorstMultiFrame();
  954. }
  955. ++m_nFrameCount;
  956. break;
  957. default:
  958. // no default
  959. break;
  960. }
  961. #endif
  962. }
  963. }
  964. //-------------------------------------
  965. inline double CVProfile::GetTotalTimeSampled()
  966. {
  967. return m_Root.GetTotalTime();
  968. }
  969. //-------------------------------------
  970. inline double CVProfile::GetPeakFrameTime()
  971. {
  972. return m_Root.GetPeakTime();
  973. }
  974. //-------------------------------------
  975. inline double CVProfile::GetTimeLastFrame()
  976. {
  977. return m_Root.GetCurTime();
  978. }
  979. //-------------------------------------
  980. inline CVProfNode *CVProfile::GetRoot()
  981. {
  982. return &m_Root;
  983. }
  984. //-------------------------------------
  985. inline CVProfNode *CVProfile::GetCurrentNode()
  986. {
  987. return m_pCurNode;
  988. }
  989. inline const tchar *CVProfile::GetBudgetGroupName( int budgetGroupID )
  990. {
  991. Assert( budgetGroupID >= 0 && budgetGroupID < m_nBudgetGroupNames );
  992. return m_pBudgetGroups[budgetGroupID].m_pName;
  993. }
  994. inline int CVProfile::GetBudgetGroupFlags( int budgetGroupID ) const
  995. {
  996. Assert( budgetGroupID >= 0 && budgetGroupID < m_nBudgetGroupNames );
  997. return m_pBudgetGroups[budgetGroupID].m_BudgetFlags;
  998. }
  999. #ifdef _X360
  1000. inline CVProfile::CPUTraceState CVProfile::GetCPUTraceMode()
  1001. {
  1002. return m_iCPUTraceEnabled;
  1003. }
  1004. inline void CVProfile::SetCPUTraceEnabled( CPUTraceState enabled, bool bTraceCompleteEvent /*=true*/, int nNumFrames /*= -1*/ )
  1005. {
  1006. m_iCPUTraceEnabled = enabled;
  1007. m_bTraceCompleteEvent = bTraceCompleteEvent;
  1008. if ( nNumFrames != -1 )
  1009. {
  1010. m_nFramesRemaining = nNumFrames;
  1011. m_nFrameCount = 0;
  1012. m_WorstCycles = 0;
  1013. m_WorstTraceFilename[ 0 ] = 0;
  1014. }
  1015. }
  1016. inline void CVProfile::IncrementMultiTraceIndex()
  1017. {
  1018. ++m_iSuccessiveTraceIndex;
  1019. }
  1020. inline unsigned int CVProfile::GetMultiTraceIndex()
  1021. {
  1022. return m_iSuccessiveTraceIndex;
  1023. }
  1024. #endif
  1025. //-----------------------------------------------------------------------------
  1026. inline CVProfScope::CVProfScope( const tchar * pszName, int detailLevel, const tchar *pBudgetGroupName, bool bAssertAccounted, int budgetFlags )
  1027. : m_bEnabled( g_VProfCurrentProfile.IsEnabled() )
  1028. {
  1029. if ( m_bEnabled )
  1030. {
  1031. g_VProfCurrentProfile.EnterScope( pszName, detailLevel, pBudgetGroupName, bAssertAccounted, budgetFlags );
  1032. }
  1033. }
  1034. //-------------------------------------
  1035. inline CVProfScope::~CVProfScope()
  1036. {
  1037. if ( m_bEnabled )
  1038. {
  1039. g_VProfCurrentProfile.ExitScope();
  1040. }
  1041. }
  1042. class CVProfCounter
  1043. {
  1044. public:
  1045. CVProfCounter( const tchar *pName, CounterGroup_t group=COUNTER_GROUP_DEFAULT )
  1046. {
  1047. m_pCounter = g_VProfCurrentProfile.FindOrCreateCounter( pName, group );
  1048. Assert( m_pCounter );
  1049. }
  1050. ~CVProfCounter()
  1051. {
  1052. }
  1053. void Increment( int val )
  1054. {
  1055. Assert( m_pCounter );
  1056. *m_pCounter += val;
  1057. }
  1058. private:
  1059. int *m_pCounter;
  1060. };
  1061. #endif
  1062. #ifdef _X360
  1063. #include "xbox/xbox_console.h"
  1064. #include "tracerecording.h"
  1065. #include "tier1/fmtstr.h"
  1066. #pragma comment( lib, "tracerecording.lib" )
  1067. #pragma comment( lib, "xbdm.lib" )
  1068. class CPIXRecorder
  1069. {
  1070. public:
  1071. CPIXRecorder() : m_bActive( false ) {}
  1072. ~CPIXRecorder() { Stop(); }
  1073. void Start( const char *pszFilename = "capture" )
  1074. {
  1075. if ( !m_bActive )
  1076. {
  1077. if ( !XTraceStartRecording( CFmtStr( "e:\\%s.pix2", pszFilename ) ) )
  1078. {
  1079. Msg( "XTraceStartRecording failed, error code %d\n", GetLastError() );
  1080. }
  1081. else
  1082. {
  1083. m_bActive = true;
  1084. }
  1085. }
  1086. }
  1087. void Stop()
  1088. {
  1089. if ( m_bActive )
  1090. {
  1091. m_bActive = false;
  1092. if ( XTraceStopRecording() )
  1093. {
  1094. Msg( "CPU trace finished.\n" );
  1095. // signal VXConsole that trace is completed
  1096. XBX_rTraceComplete();
  1097. }
  1098. }
  1099. }
  1100. private:
  1101. bool m_bActive;
  1102. };
  1103. #define VPROF_BEGIN_PIX_BLOCK( convar ) \
  1104. { \
  1105. bool bRunPix = 0; \
  1106. static CFastTimer PIXTimer; \
  1107. extern ConVar convar; \
  1108. ConVar &PIXConvar = convar; \
  1109. CPIXRecorder PIXRecorder; \
  1110. { \
  1111. PIXLabel: \
  1112. if ( bRunPix ) \
  1113. { \
  1114. PIXRecorder.Start(); \
  1115. } \
  1116. else \
  1117. { \
  1118. if ( PIXConvar.GetBool() ) \
  1119. { \
  1120. PIXTimer.Start(); \
  1121. } \
  1122. } \
  1123. {
  1124. #define VPROF_END_PIX_BLOCK() \
  1125. } \
  1126. \
  1127. if ( !bRunPix ) \
  1128. { \
  1129. if ( PIXConvar.GetBool() ) \
  1130. { \
  1131. PIXTimer.End(); \
  1132. if ( PIXTimer.GetDuration().GetMillisecondsF() > PIXConvar.GetFloat() ) \
  1133. { \
  1134. PIXConvar.SetValue( 0 ); \
  1135. bRunPix = true; \
  1136. goto PIXLabel; \
  1137. } \
  1138. } \
  1139. } \
  1140. else \
  1141. { \
  1142. PIXRecorder.Stop(); \
  1143. } \
  1144. } \
  1145. }
  1146. #else
  1147. #define VPROF_BEGIN_PIX_BLOCK( PIXConvar ) {
  1148. #define VPROF_END_PIX_BLOCK() }
  1149. #endif
  1150. #ifdef VPROF_UNDO_PIX
  1151. #undef USE_PIX
  1152. #undef _PIX_H_
  1153. #undef PIXBeginNamedEvent
  1154. #undef PIXEndNamedEvent
  1155. #undef PIXSetMarker
  1156. #undef PIXNameThread
  1157. #include <pix.h>
  1158. #endif
  1159. #ifdef _MSC_VER
  1160. #pragma warning(pop)
  1161. #endif
  1162. #endif
  1163. //=============================================================================