2017-08-01 12:30:58 +00:00
|
|
|
|
|
|
|
/***************************************************************************************************
|
|
|
|
**
|
|
|
|
** Real-Time Hierarchical Profiling for Game Programming Gems 3
|
|
|
|
**
|
|
|
|
** by Greg Hjelstrom & Byon Garrabrant
|
|
|
|
**
|
|
|
|
***************************************************************************************************/
|
|
|
|
|
2019-01-03 13:26:51 +00:00
|
|
|
// Credits: The Clock class was inspired by the Timer classes in
|
2017-08-01 12:30:58 +00:00
|
|
|
// Ogre (www.ogre3d.org).
|
|
|
|
|
|
|
|
#ifndef BT_QUICK_PROF_H
|
|
|
|
#define BT_QUICK_PROF_H
|
|
|
|
|
|
|
|
#include "btScalar.h"
|
|
|
|
#define USE_BT_CLOCK 1
|
|
|
|
|
|
|
|
#ifdef USE_BT_CLOCK
|
|
|
|
|
|
|
|
///The btClock is a portable basic clock that measures accurate time in seconds, use for profiling.
|
|
|
|
class btClock
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
btClock();
|
|
|
|
|
|
|
|
btClock(const btClock& other);
|
|
|
|
btClock& operator=(const btClock& other);
|
|
|
|
|
|
|
|
~btClock();
|
|
|
|
|
|
|
|
/// Resets the initial reference time.
|
|
|
|
void reset();
|
|
|
|
|
2019-01-03 13:26:51 +00:00
|
|
|
/// Returns the time in ms since the last call to reset or since
|
2017-08-01 12:30:58 +00:00
|
|
|
/// the btClock was created.
|
|
|
|
unsigned long long int getTimeMilliseconds();
|
|
|
|
|
2019-01-03 13:26:51 +00:00
|
|
|
/// Returns the time in us since the last call to reset or since
|
2017-08-01 12:30:58 +00:00
|
|
|
/// the Clock was created.
|
|
|
|
unsigned long long int getTimeMicroseconds();
|
2019-01-03 13:26:51 +00:00
|
|
|
|
2017-08-01 12:30:58 +00:00
|
|
|
unsigned long long int getTimeNanoseconds();
|
|
|
|
|
2019-01-03 13:26:51 +00:00
|
|
|
/// Returns the time in s since the last call to reset or since
|
2017-08-01 12:30:58 +00:00
|
|
|
/// the Clock was created.
|
|
|
|
btScalar getTimeSeconds();
|
2019-01-03 13:26:51 +00:00
|
|
|
|
2017-08-01 12:30:58 +00:00
|
|
|
private:
|
|
|
|
struct btClockData* m_data;
|
|
|
|
};
|
|
|
|
|
2019-01-03 13:26:51 +00:00
|
|
|
#endif //USE_BT_CLOCK
|
2017-08-01 12:30:58 +00:00
|
|
|
|
2019-01-03 13:26:51 +00:00
|
|
|
typedef void(btEnterProfileZoneFunc)(const char* msg);
|
|
|
|
typedef void(btLeaveProfileZoneFunc)();
|
2017-08-01 12:30:58 +00:00
|
|
|
|
|
|
|
btEnterProfileZoneFunc* btGetCurrentEnterProfileZoneFunc();
|
|
|
|
btLeaveProfileZoneFunc* btGetCurrentLeaveProfileZoneFunc();
|
|
|
|
|
|
|
|
void btSetCustomEnterProfileZoneFunc(btEnterProfileZoneFunc* enterFunc);
|
|
|
|
void btSetCustomLeaveProfileZoneFunc(btLeaveProfileZoneFunc* leaveFunc);
|
|
|
|
|
2019-01-03 13:26:51 +00:00
|
|
|
#ifndef BT_ENABLE_PROFILE
|
|
|
|
#define BT_NO_PROFILE 1
|
|
|
|
#endif //BT_NO_PROFILE
|
2017-08-01 12:30:58 +00:00
|
|
|
|
2018-09-07 14:11:04 +00:00
|
|
|
const unsigned int BT_QUICKPROF_MAX_THREAD_COUNT = 64;
|
|
|
|
|
2019-01-03 13:26:51 +00:00
|
|
|
//btQuickprofGetCurrentThreadIndex will return -1 if thread index cannot be determined,
|
2017-08-01 12:30:58 +00:00
|
|
|
//otherwise returns thread index in range [0..maxThreads]
|
|
|
|
unsigned int btQuickprofGetCurrentThreadIndex2();
|
|
|
|
|
2019-01-03 13:26:51 +00:00
|
|
|
#ifndef BT_NO_PROFILE
|
2017-08-01 12:30:58 +00:00
|
|
|
|
|
|
|
|
2019-01-03 13:26:51 +00:00
|
|
|
#include <stdio.h> //@todo remove this, backwards compatibility
|
2017-08-01 12:30:58 +00:00
|
|
|
|
2019-01-03 13:26:51 +00:00
|
|
|
#include "btAlignedAllocator.h"
|
|
|
|
#include <new>
|
2017-08-01 12:30:58 +00:00
|
|
|
|
|
|
|
///A node in the Profile Hierarchy Tree
|
2019-01-03 13:26:51 +00:00
|
|
|
class CProfileNode
|
|
|
|
{
|
2017-08-01 12:30:58 +00:00
|
|
|
public:
|
2019-01-03 13:26:51 +00:00
|
|
|
CProfileNode(const char* name, CProfileNode* parent);
|
|
|
|
~CProfileNode(void);
|
2017-08-01 12:30:58 +00:00
|
|
|
|
2019-01-03 13:26:51 +00:00
|
|
|
CProfileNode* Get_Sub_Node(const char* name);
|
2017-08-01 12:30:58 +00:00
|
|
|
|
2019-01-03 13:26:51 +00:00
|
|
|
CProfileNode* Get_Parent(void) { return Parent; }
|
|
|
|
CProfileNode* Get_Sibling(void) { return Sibling; }
|
|
|
|
CProfileNode* Get_Child(void) { return Child; }
|
2017-08-01 12:30:58 +00:00
|
|
|
|
2019-01-03 13:26:51 +00:00
|
|
|
void CleanupMemory();
|
|
|
|
void Reset(void);
|
|
|
|
void Call(void);
|
|
|
|
bool Return(void);
|
2017-08-01 12:30:58 +00:00
|
|
|
|
2019-01-03 13:26:51 +00:00
|
|
|
const char* Get_Name(void) { return Name; }
|
|
|
|
int Get_Total_Calls(void) { return TotalCalls; }
|
|
|
|
float Get_Total_Time(void) { return TotalTime; }
|
|
|
|
void* GetUserPointer() const { return m_userPtr; }
|
|
|
|
void SetUserPointer(void* ptr) { m_userPtr = ptr; }
|
2017-08-01 12:30:58 +00:00
|
|
|
|
2019-01-03 13:26:51 +00:00
|
|
|
protected:
|
|
|
|
const char* Name;
|
|
|
|
int TotalCalls;
|
|
|
|
float TotalTime;
|
|
|
|
unsigned long int StartTime;
|
|
|
|
int RecursionCounter;
|
|
|
|
|
|
|
|
CProfileNode* Parent;
|
|
|
|
CProfileNode* Child;
|
|
|
|
CProfileNode* Sibling;
|
|
|
|
void* m_userPtr;
|
2017-08-01 12:30:58 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
///An iterator to navigate through the tree
|
|
|
|
class CProfileIterator
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
// Access all the children of the current parent
|
2019-01-03 13:26:51 +00:00
|
|
|
void First(void);
|
|
|
|
void Next(void);
|
|
|
|
bool Is_Done(void);
|
|
|
|
bool Is_Root(void) { return (CurrentParent->Get_Parent() == 0); }
|
2017-08-01 12:30:58 +00:00
|
|
|
|
2019-01-03 13:26:51 +00:00
|
|
|
void Enter_Child(int index); // Make the given child the new parent
|
|
|
|
void Enter_Largest_Child(void); // Make the largest child the new parent
|
|
|
|
void Enter_Parent(void); // Make the current parent's parent the new parent
|
2017-08-01 12:30:58 +00:00
|
|
|
|
|
|
|
// Access the current child
|
2019-01-03 13:26:51 +00:00
|
|
|
const char* Get_Current_Name(void) { return CurrentChild->Get_Name(); }
|
|
|
|
int Get_Current_Total_Calls(void) { return CurrentChild->Get_Total_Calls(); }
|
|
|
|
float Get_Current_Total_Time(void) { return CurrentChild->Get_Total_Time(); }
|
2017-08-01 12:30:58 +00:00
|
|
|
|
2019-01-03 13:26:51 +00:00
|
|
|
void* Get_Current_UserPointer(void) { return CurrentChild->GetUserPointer(); }
|
|
|
|
void Set_Current_UserPointer(void* ptr) { CurrentChild->SetUserPointer(ptr); }
|
2017-08-01 12:30:58 +00:00
|
|
|
// Access the current parent
|
2019-01-03 13:26:51 +00:00
|
|
|
const char* Get_Current_Parent_Name(void) { return CurrentParent->Get_Name(); }
|
|
|
|
int Get_Current_Parent_Total_Calls(void) { return CurrentParent->Get_Total_Calls(); }
|
|
|
|
float Get_Current_Parent_Total_Time(void) { return CurrentParent->Get_Total_Time(); }
|
2017-08-01 12:30:58 +00:00
|
|
|
|
|
|
|
protected:
|
2019-01-03 13:26:51 +00:00
|
|
|
CProfileNode* CurrentParent;
|
|
|
|
CProfileNode* CurrentChild;
|
2017-08-01 12:30:58 +00:00
|
|
|
|
2019-01-03 13:26:51 +00:00
|
|
|
CProfileIterator(CProfileNode* start);
|
|
|
|
friend class CProfileManager;
|
2017-08-01 12:30:58 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
///The Manager for the Profile system
|
2019-01-03 13:26:51 +00:00
|
|
|
class CProfileManager
|
|
|
|
{
|
2017-08-01 12:30:58 +00:00
|
|
|
public:
|
2019-01-03 13:26:51 +00:00
|
|
|
static void Start_Profile(const char* name);
|
|
|
|
static void Stop_Profile(void);
|
2017-08-01 12:30:58 +00:00
|
|
|
|
2019-01-03 13:26:51 +00:00
|
|
|
static void CleanupMemory(void);
|
|
|
|
// {
|
|
|
|
// Root.CleanupMemory();
|
|
|
|
// }
|
2017-08-01 12:30:58 +00:00
|
|
|
|
2019-01-03 13:26:51 +00:00
|
|
|
static void Reset(void);
|
|
|
|
static void Increment_Frame_Counter(void);
|
|
|
|
static int Get_Frame_Count_Since_Reset(void) { return FrameCounter; }
|
|
|
|
static float Get_Time_Since_Reset(void);
|
2017-08-01 12:30:58 +00:00
|
|
|
|
2019-01-03 13:26:51 +00:00
|
|
|
static CProfileIterator* Get_Iterator(void);
|
|
|
|
// {
|
|
|
|
//
|
|
|
|
// return new CProfileIterator( &Root );
|
|
|
|
// }
|
|
|
|
static void Release_Iterator(CProfileIterator* iterator) { delete (iterator); }
|
2017-08-01 12:30:58 +00:00
|
|
|
|
2019-01-03 13:26:51 +00:00
|
|
|
static void dumpRecursive(CProfileIterator* profileIterator, int spacing);
|
2017-08-01 12:30:58 +00:00
|
|
|
|
2019-01-03 13:26:51 +00:00
|
|
|
static void dumpAll();
|
2017-08-01 12:30:58 +00:00
|
|
|
|
|
|
|
private:
|
2019-01-03 13:26:51 +00:00
|
|
|
static int FrameCounter;
|
|
|
|
static unsigned long int ResetTime;
|
2017-08-01 12:30:58 +00:00
|
|
|
};
|
|
|
|
|
2019-01-03 13:26:51 +00:00
|
|
|
#endif //#ifndef BT_NO_PROFILE
|
2017-08-01 12:30:58 +00:00
|
|
|
|
|
|
|
///ProfileSampleClass is a simple way to profile a function's scope
|
|
|
|
///Use the BT_PROFILE macro at the start of scope to time
|
2019-01-03 13:26:51 +00:00
|
|
|
class CProfileSample
|
|
|
|
{
|
2017-08-01 12:30:58 +00:00
|
|
|
public:
|
2019-01-03 13:26:51 +00:00
|
|
|
CProfileSample(const char* name);
|
2017-08-01 12:30:58 +00:00
|
|
|
|
2019-01-03 13:26:51 +00:00
|
|
|
~CProfileSample(void);
|
2017-08-01 12:30:58 +00:00
|
|
|
};
|
|
|
|
|
2019-01-03 13:26:51 +00:00
|
|
|
#define BT_PROFILE(name) CProfileSample __profile(name)
|
2017-08-01 12:30:58 +00:00
|
|
|
|
2019-01-03 13:26:51 +00:00
|
|
|
#endif //BT_QUICK_PROF_H
|