00001 00002 /*************************************************************************************************** 00003 ** 00004 ** Real-Time Hierarchical Profiling for Game Programming Gems 3 00005 ** 00006 ** by Greg Hjelstrom & Byon Garrabrant 00007 ** 00008 ***************************************************************************************************/ 00009 00010 // Credits: The Clock class was inspired by the Timer classes in 00011 // Ogre (www.ogre3d.org). 00012 00013 00014 00015 #ifndef BT_QUICK_PROF_H 00016 #define BT_QUICK_PROF_H 00017 00018 //To disable built-in profiling, please comment out next line 00019 //#define BT_NO_PROFILE 1 00020 #ifndef BT_NO_PROFILE 00021 #include <stdio.h>//@todo remove this, backwards compatibility 00022 #include "btScalar.h" 00023 #include "btAlignedAllocator.h" 00024 #include <new> 00025 00026 00027 00028 00029 00030 #define USE_BT_CLOCK 1 00031 00032 #ifdef USE_BT_CLOCK 00033 00035 class btClock 00036 { 00037 public: 00038 btClock(); 00039 00040 btClock(const btClock& other); 00041 btClock& operator=(const btClock& other); 00042 00043 ~btClock(); 00044 00046 void reset(); 00047 00050 unsigned long int getTimeMilliseconds(); 00051 00054 unsigned long int getTimeMicroseconds(); 00055 private: 00056 struct btClockData* m_data; 00057 }; 00058 00059 #endif //USE_BT_CLOCK 00060 00061 00062 00063 00065 class CProfileNode { 00066 00067 public: 00068 CProfileNode( const char * name, CProfileNode * parent ); 00069 ~CProfileNode( void ); 00070 00071 CProfileNode * Get_Sub_Node( const char * name ); 00072 00073 CProfileNode * Get_Parent( void ) { return Parent; } 00074 CProfileNode * Get_Sibling( void ) { return Sibling; } 00075 CProfileNode * Get_Child( void ) { return Child; } 00076 00077 void CleanupMemory(); 00078 void Reset( void ); 00079 void Call( void ); 00080 bool Return( void ); 00081 00082 const char * Get_Name( void ) { return Name; } 00083 int Get_Total_Calls( void ) { return TotalCalls; } 00084 float Get_Total_Time( void ) { return TotalTime; } 00085 void* GetUserPointer() const {return m_userPtr;} 00086 void SetUserPointer(void* ptr) { m_userPtr = ptr;} 00087 protected: 00088 00089 const char * Name; 00090 int TotalCalls; 00091 float TotalTime; 00092 unsigned long int StartTime; 00093 int RecursionCounter; 00094 00095 CProfileNode * Parent; 00096 CProfileNode * Child; 00097 CProfileNode * Sibling; 00098 void* m_userPtr; 00099 }; 00100 00102 class CProfileIterator 00103 { 00104 public: 00105 // Access all the children of the current parent 00106 void First(void); 00107 void Next(void); 00108 bool Is_Done(void); 00109 bool Is_Root(void) { return (CurrentParent->Get_Parent() == 0); } 00110 00111 void Enter_Child( int index ); // Make the given child the new parent 00112 void Enter_Largest_Child( void ); // Make the largest child the new parent 00113 void Enter_Parent( void ); // Make the current parent's parent the new parent 00114 00115 // Access the current child 00116 const char * Get_Current_Name( void ) { return CurrentChild->Get_Name(); } 00117 int Get_Current_Total_Calls( void ) { return CurrentChild->Get_Total_Calls(); } 00118 float Get_Current_Total_Time( void ) { return CurrentChild->Get_Total_Time(); } 00119 00120 void* Get_Current_UserPointer( void ) { return CurrentChild->GetUserPointer(); } 00121 void Set_Current_UserPointer(void* ptr) {CurrentChild->SetUserPointer(ptr);} 00122 // Access the current parent 00123 const char * Get_Current_Parent_Name( void ) { return CurrentParent->Get_Name(); } 00124 int Get_Current_Parent_Total_Calls( void ) { return CurrentParent->Get_Total_Calls(); } 00125 float Get_Current_Parent_Total_Time( void ) { return CurrentParent->Get_Total_Time(); } 00126 00127 00128 00129 protected: 00130 00131 CProfileNode * CurrentParent; 00132 CProfileNode * CurrentChild; 00133 00134 00135 CProfileIterator( CProfileNode * start ); 00136 friend class CProfileManager; 00137 }; 00138 00139 00141 class CProfileManager { 00142 public: 00143 static void Start_Profile( const char * name ); 00144 static void Stop_Profile( void ); 00145 00146 static void CleanupMemory(void) 00147 { 00148 Root.CleanupMemory(); 00149 } 00150 00151 static void Reset( void ); 00152 static void Increment_Frame_Counter( void ); 00153 static int Get_Frame_Count_Since_Reset( void ) { return FrameCounter; } 00154 static float Get_Time_Since_Reset( void ); 00155 00156 static CProfileIterator * Get_Iterator( void ) 00157 { 00158 00159 return new CProfileIterator( &Root ); 00160 } 00161 static void Release_Iterator( CProfileIterator * iterator ) { delete ( iterator); } 00162 00163 static void dumpRecursive(CProfileIterator* profileIterator, int spacing); 00164 00165 static void dumpAll(); 00166 00167 private: 00168 static CProfileNode Root; 00169 static CProfileNode * CurrentNode; 00170 static int FrameCounter; 00171 static unsigned long int ResetTime; 00172 }; 00173 00174 00177 class CProfileSample { 00178 public: 00179 CProfileSample( const char * name ) 00180 { 00181 CProfileManager::Start_Profile( name ); 00182 } 00183 00184 ~CProfileSample( void ) 00185 { 00186 CProfileManager::Stop_Profile(); 00187 } 00188 }; 00189 00190 00191 #define BT_PROFILE( name ) CProfileSample __profile( name ) 00192 00193 #else 00194 00195 #define BT_PROFILE( name ) 00196 00197 #endif //#ifndef BT_NO_PROFILE 00198 00199 00200 00201 #endif //BT_QUICK_PROF_H 00202 00203