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.

1510 lines
39 KiB

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