Counter Strike : Global Offensive Source Code
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.

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