Example Browser: add option (keypress 'p') to dump json timing profile trace, that you can open using Chrome about://tracing
Make btQuickprof thread safe Add option in btQuickprof to override custom timing profile (btSetCustomEnterProfileZoneFunc, btSetCustomLeaveProfileZoneFunc) remove b3Printf in a user/physics thread (those added added, while drawing the GUI running in the main thread)
This commit is contained in:
@@ -44,7 +44,7 @@ public:
|
||||
|
||||
|
||||
CProfileIterator* profIter;
|
||||
|
||||
|
||||
class MyMenuItems* m_menuItems;
|
||||
MyProfileWindow ( Gwen::Controls::Base* pParent)
|
||||
: Gwen::Controls::WindowControl( pParent ),
|
||||
@@ -192,7 +192,8 @@ public:
|
||||
|
||||
|
||||
// Gwen::Controls::TreeNode* curParent = m_node;
|
||||
|
||||
|
||||
|
||||
double accumulated_time = dumpRecursive(profileIterator,m_node);
|
||||
|
||||
const char* name = profileIterator->Get_Current_Parent_Name();
|
||||
@@ -278,7 +279,7 @@ MyProfileWindow* setupProfileWindow(GwenInternalData* data)
|
||||
//profWindow->SetHidden(true);
|
||||
|
||||
profWindow->m_menuItems = menuItems;
|
||||
//profWindow->profIter = CProfileManager::Get_Iterator();
|
||||
profWindow->profIter = CProfileManager::Get_Iterator();
|
||||
data->m_viewMenu->GetMenu()->AddItem( L"Profiler", menuItems,(Gwen::Event::Handler::Function)&MyMenuItems::MenuItemSelect);
|
||||
|
||||
menuItems->m_profWindow = profWindow;
|
||||
@@ -296,6 +297,11 @@ void processProfileData( MyProfileWindow* profWindow, bool idle)
|
||||
}
|
||||
}
|
||||
|
||||
bool isProfileWindowVisible(MyProfileWindow* window)
|
||||
{
|
||||
return !window->Hidden();
|
||||
}
|
||||
|
||||
void profileWindowSetVisible(MyProfileWindow* window, bool visible)
|
||||
{
|
||||
window->SetHidden(!visible);
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
class MyProfileWindow* setupProfileWindow(struct GwenInternalData* data);
|
||||
void processProfileData(MyProfileWindow* window, bool idle);
|
||||
void profileWindowSetVisible(MyProfileWindow* window, bool visible);
|
||||
bool isProfileWindowVisible(MyProfileWindow* window);
|
||||
|
||||
void destroyProfileWindow(MyProfileWindow* window);
|
||||
|
||||
#endif//GWEN_PROFILE_WINDOW_H
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#endif //_WIN32
|
||||
#endif//__APPLE__
|
||||
#include "../ThirdPartyLibs/Gwen/Renderers/OpenGL_DebugFont.h"
|
||||
|
||||
#include "LinearMath/btThreads.h"
|
||||
#include "Bullet3Common/b3Vector3.h"
|
||||
#include "assert.h"
|
||||
#include <stdio.h>
|
||||
@@ -25,7 +25,9 @@
|
||||
#include "GwenGUISupport/gwenUserInterface.h"
|
||||
#include "../Utils/b3Clock.h"
|
||||
#include "GwenGUISupport/GwenParameterInterface.h"
|
||||
#ifndef BT_NO_PROFILE
|
||||
#include "GwenGUISupport/GwenProfileWindow.h"
|
||||
#endif
|
||||
#include "GwenGUISupport/GwenTextureWindow.h"
|
||||
#include "GwenGUISupport/GraphingTexture.h"
|
||||
#include "../CommonInterfaces/Common2dCanvasInterface.h"
|
||||
@@ -68,7 +70,9 @@ struct OpenGLExampleBrowserInternalData
|
||||
{
|
||||
Gwen::Renderer::Base* m_gwenRenderer;
|
||||
CommonGraphicsApp* m_app;
|
||||
// MyProfileWindow* m_profWindow;
|
||||
#ifndef BT_NO_PROFILE
|
||||
MyProfileWindow* m_profWindow;
|
||||
#endif //BT_NO_PROFILE
|
||||
btAlignedObjectArray<Gwen::Controls::TreeNode*> m_nodes;
|
||||
GwenUserInterface* m_gui;
|
||||
GL3TexLoader* m_myTexLoader;
|
||||
@@ -93,7 +97,9 @@ static CommonWindowInterface* s_window = 0;
|
||||
static CommonParameterInterface* s_parameterInterface=0;
|
||||
static CommonRenderInterface* s_instancingRenderer=0;
|
||||
static OpenGLGuiHelper* s_guiHelper=0;
|
||||
//static MyProfileWindow* s_profWindow =0;
|
||||
#ifndef BT_NO_PROFILE
|
||||
static MyProfileWindow* s_profWindow =0;
|
||||
#endif //BT_NO_PROFILE
|
||||
static SharedMemoryInterface* sSharedMem = 0;
|
||||
|
||||
#define DEMO_SELECTION_COMBOBOX 13
|
||||
@@ -144,6 +150,140 @@ int gGpuArraySizeZ=45;
|
||||
|
||||
|
||||
|
||||
struct btTiming
|
||||
{
|
||||
const char* m_name;
|
||||
int m_threadId;
|
||||
unsigned long long int m_usStartTime;
|
||||
unsigned long long int m_usEndTime;
|
||||
};
|
||||
|
||||
FILE* gTimingFile = 0;
|
||||
#include <inttypes.h>
|
||||
#define BT_TIMING_CAPACITY 65536
|
||||
static bool m_firstTiming = true;
|
||||
|
||||
|
||||
struct btTimings
|
||||
{
|
||||
btTimings()
|
||||
:m_numTimings(0),
|
||||
m_activeBuffer(0)
|
||||
{
|
||||
|
||||
}
|
||||
void flush()
|
||||
{
|
||||
for (int i=0;i<m_numTimings;i++)
|
||||
{
|
||||
const char* name = m_timings[m_activeBuffer][i].m_name;
|
||||
int threadId = m_timings[m_activeBuffer][i].m_threadId;
|
||||
unsigned long long int startTime = m_timings[m_activeBuffer][i].m_usStartTime;
|
||||
unsigned long long int endTime = m_timings[m_activeBuffer][i].m_usEndTime;
|
||||
|
||||
if (!m_firstTiming)
|
||||
{
|
||||
fprintf(gTimingFile,",\n");
|
||||
}
|
||||
|
||||
m_firstTiming = false;
|
||||
|
||||
unsigned long long int startTimeDiv1000 = startTime/1000;
|
||||
unsigned long long int endTimeDiv1000 = endTime/1000;
|
||||
|
||||
fprintf(gTimingFile,"{\"cat\":\"timing\",\"pid\":1,\"tid\":%d,\"ts\":%" PRIu64 " ,\"ph\":\"B\",\"name\":\"%s\",\"args\":{}},\n",
|
||||
threadId, startTimeDiv1000,name);
|
||||
fprintf(gTimingFile,"{\"cat\":\"timing\",\"pid\":1,\"tid\":%d,\"ts\":%" PRIu64 " ,\"ph\":\"E\",\"name\":\"%s\",\"args\":{}}",
|
||||
threadId, endTimeDiv1000,name);
|
||||
|
||||
}
|
||||
m_numTimings = 0;
|
||||
|
||||
}
|
||||
|
||||
void addTiming(const char* name, int threadId, unsigned long long int startTime, unsigned long long int endTime)
|
||||
{
|
||||
if (m_numTimings>=BT_TIMING_CAPACITY)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int slot = m_numTimings++;
|
||||
|
||||
m_timings[m_activeBuffer][slot].m_name = name;
|
||||
m_timings[m_activeBuffer][slot].m_threadId = threadId;
|
||||
m_timings[m_activeBuffer][slot].m_usStartTime = startTime;
|
||||
m_timings[m_activeBuffer][slot].m_usEndTime = endTime;
|
||||
}
|
||||
|
||||
|
||||
int m_numTimings;
|
||||
int m_activeBuffer;
|
||||
btTiming m_timings[2][BT_TIMING_CAPACITY];
|
||||
};
|
||||
|
||||
btTimings gTimings[BT_MAX_THREAD_COUNT];
|
||||
|
||||
btClock clk;
|
||||
|
||||
#define MAX_NESTING 1024
|
||||
|
||||
bool gProfileDisabled = true;
|
||||
int gStackDepths[BT_MAX_THREAD_COUNT] = {0};
|
||||
const char* gFuncNames[BT_MAX_THREAD_COUNT][MAX_NESTING];
|
||||
unsigned long long int gStartTimes[BT_MAX_THREAD_COUNT][MAX_NESTING];
|
||||
|
||||
void MyDummyEnterProfileZoneFunc(const char* msg)
|
||||
{
|
||||
}
|
||||
|
||||
void MyDummyLeaveProfileZoneFunc()
|
||||
{
|
||||
}
|
||||
|
||||
void MyEnterProfileZoneFunc(const char* msg)
|
||||
{
|
||||
if (gProfileDisabled)
|
||||
return;
|
||||
int threadId = btGetCurrentThreadIndex();
|
||||
|
||||
if (gStackDepths[threadId]>=MAX_NESTING)
|
||||
{
|
||||
btAssert(0);
|
||||
return;
|
||||
}
|
||||
gFuncNames[threadId][gStackDepths[threadId]] = msg;
|
||||
gStartTimes[threadId][gStackDepths[threadId]] = clk.getTimeNanoseconds();
|
||||
if (gStartTimes[threadId][gStackDepths[threadId]]<=gStartTimes[threadId][gStackDepths[threadId]-1])
|
||||
{
|
||||
gStartTimes[threadId][gStackDepths[threadId]]=1+gStartTimes[threadId][gStackDepths[threadId]-1];
|
||||
}
|
||||
gStackDepths[threadId]++;
|
||||
}
|
||||
void MyLeaveProfileZoneFunc()
|
||||
{
|
||||
if (gProfileDisabled)
|
||||
return;
|
||||
|
||||
int threadId = btGetCurrentThreadIndex();
|
||||
|
||||
if (gStackDepths[threadId]<=0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gStackDepths[threadId]--;
|
||||
|
||||
const char* name = gFuncNames[threadId][gStackDepths[threadId]];
|
||||
unsigned long long int startTime = gStartTimes[threadId][gStackDepths[threadId]];
|
||||
|
||||
unsigned long long int endTime = clk.getTimeNanoseconds();
|
||||
gTimings[threadId].addTiming(name,threadId,startTime,endTime);
|
||||
}
|
||||
|
||||
|
||||
void deleteDemo()
|
||||
{
|
||||
if (sCurrentDemo)
|
||||
@@ -154,6 +294,7 @@ void deleteDemo()
|
||||
sCurrentDemo=0;
|
||||
delete s_guiHelper;
|
||||
s_guiHelper = 0;
|
||||
// CProfileManager::CleanupMemory();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,6 +378,46 @@ void MyKeyboardCallback(int key, int state)
|
||||
singleStepSimulation = true;
|
||||
}
|
||||
|
||||
if (key=='p')
|
||||
{
|
||||
if (state)
|
||||
{
|
||||
m_firstTiming = true;
|
||||
gProfileDisabled = false;//true;
|
||||
b3SetCustomEnterProfileZoneFunc(MyEnterProfileZoneFunc);
|
||||
b3SetCustomLeaveProfileZoneFunc(MyLeaveProfileZoneFunc);
|
||||
|
||||
//also for Bullet 2.x API
|
||||
btSetCustomEnterProfileZoneFunc(MyEnterProfileZoneFunc);
|
||||
btSetCustomLeaveProfileZoneFunc(MyLeaveProfileZoneFunc);
|
||||
} else
|
||||
{
|
||||
|
||||
b3SetCustomEnterProfileZoneFunc(MyDummyEnterProfileZoneFunc);
|
||||
b3SetCustomLeaveProfileZoneFunc(MyDummyLeaveProfileZoneFunc);
|
||||
//also for Bullet 2.x API
|
||||
btSetCustomEnterProfileZoneFunc(MyDummyEnterProfileZoneFunc);
|
||||
btSetCustomLeaveProfileZoneFunc(MyDummyLeaveProfileZoneFunc);
|
||||
char fileName[1024];
|
||||
static int fileCounter = 0;
|
||||
sprintf(fileName,"d:/timings_%d.json",fileCounter++);
|
||||
gTimingFile = fopen(fileName,"w");
|
||||
fprintf(gTimingFile,"{\"traceEvents\":[\n");
|
||||
//dump the content to file
|
||||
for (int i=0;i<BT_MAX_THREAD_COUNT;i++)
|
||||
{
|
||||
if (gTimings[i].m_numTimings)
|
||||
{
|
||||
printf("Writing %d timings for thread %d\n", gTimings[i].m_numTimings, i);
|
||||
gTimings[i].flush();
|
||||
}
|
||||
}
|
||||
fprintf(gTimingFile,"\n],\n\"displayTimeUnit\": \"ns\"}");
|
||||
fclose(gTimingFile);
|
||||
gTimingFile = 0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NO_OPENGL3
|
||||
if (key=='s' && state)
|
||||
@@ -333,15 +514,7 @@ void OpenGLExampleBrowser::registerFileImporter(const char* extension, CommonExa
|
||||
void openFileDemo(const char* filename)
|
||||
{
|
||||
|
||||
if (sCurrentDemo)
|
||||
{
|
||||
sCurrentDemo->exitPhysics();
|
||||
s_instancingRenderer->removeAllInstances();
|
||||
delete sCurrentDemo;
|
||||
sCurrentDemo=0;
|
||||
delete s_guiHelper;
|
||||
s_guiHelper = 0;
|
||||
}
|
||||
deleteDemo();
|
||||
|
||||
s_guiHelper= new OpenGLGuiHelper(s_app, sUseOpenGL2);
|
||||
s_parameterInterface->removeAllParameters();
|
||||
@@ -387,6 +560,7 @@ void selectDemo(int demoIndex)
|
||||
demoIndex = 0;
|
||||
}
|
||||
deleteDemo();
|
||||
|
||||
|
||||
CommonExampleInterface::CreateFunc* func = gAllExamples->getExampleCreateFunc(demoIndex);
|
||||
if (func)
|
||||
@@ -775,6 +949,8 @@ OpenGLExampleBrowser::~OpenGLExampleBrowser()
|
||||
gAllExamples = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include "EmptyExample.h"
|
||||
|
||||
bool OpenGLExampleBrowser::init(int argc, char* argv[])
|
||||
@@ -886,6 +1062,7 @@ bool OpenGLExampleBrowser::init(int argc, char* argv[])
|
||||
b3SetCustomPrintfFunc(MyGuiPrintf);
|
||||
b3SetCustomErrorMessageFunc(MyStatusBarError);
|
||||
|
||||
|
||||
|
||||
assert(glGetError()==GL_NO_ERROR);
|
||||
|
||||
@@ -940,10 +1117,11 @@ bool OpenGLExampleBrowser::init(int argc, char* argv[])
|
||||
|
||||
//gui->getInternalData()->pRenderer->setTextureLoader(myTexLoader);
|
||||
|
||||
|
||||
// s_profWindow= setupProfileWindow(gui2->getInternalData());
|
||||
//m_internalData->m_profWindow = s_profWindow;
|
||||
// profileWindowSetVisible(s_profWindow,false);
|
||||
#ifndef BT_NO_PROFILE
|
||||
s_profWindow= setupProfileWindow(gui2->getInternalData());
|
||||
m_internalData->m_profWindow = s_profWindow;
|
||||
profileWindowSetVisible(s_profWindow,false);
|
||||
#endif //BT_NO_PROFILE
|
||||
gui2->setFocus();
|
||||
|
||||
s_parameterInterface = s_app->m_parameterInterface = new GwenParameterInterface(gui2->getInternalData());
|
||||
@@ -1073,7 +1251,6 @@ bool OpenGLExampleBrowser::init(int argc, char* argv[])
|
||||
}
|
||||
|
||||
|
||||
|
||||
CommonExampleInterface* OpenGLExampleBrowser::getCurrentExample()
|
||||
{
|
||||
btAssert(sCurrentDemo);
|
||||
@@ -1087,6 +1264,8 @@ bool OpenGLExampleBrowser::requestedExit()
|
||||
|
||||
void OpenGLExampleBrowser::update(float deltaTime)
|
||||
{
|
||||
gProfileDisabled = false;
|
||||
|
||||
B3_PROFILE("OpenGLExampleBrowser::update");
|
||||
assert(glGetError()==GL_NO_ERROR);
|
||||
s_instancingRenderer->init();
|
||||
@@ -1136,7 +1315,7 @@ void OpenGLExampleBrowser::update(float deltaTime)
|
||||
{
|
||||
if (!pauseSimulation || singleStepSimulation)
|
||||
{
|
||||
singleStepSimulation = false;
|
||||
|
||||
//printf("---------------------------------------------------\n");
|
||||
//printf("Framecount = %d\n",frameCount);
|
||||
B3_PROFILE("sCurrentDemo->stepSimulation");
|
||||
@@ -1167,7 +1346,8 @@ void OpenGLExampleBrowser::update(float deltaTime)
|
||||
}
|
||||
BT_PROFILE("Render Scene");
|
||||
sCurrentDemo->renderScene();
|
||||
} else
|
||||
}
|
||||
//else
|
||||
{
|
||||
B3_PROFILE("physicsDebugDraw");
|
||||
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
|
||||
@@ -1198,9 +1378,18 @@ void OpenGLExampleBrowser::update(float deltaTime)
|
||||
if (renderGui)
|
||||
{
|
||||
B3_PROFILE("renderGui");
|
||||
// if (!pauseSimulation)
|
||||
// processProfileData(s_profWindow,false);
|
||||
#ifndef BT_NO_PROFILE
|
||||
|
||||
if (!pauseSimulation || singleStepSimulation)
|
||||
{
|
||||
if (isProfileWindowVisible(s_profWindow))
|
||||
{
|
||||
processProfileData(s_profWindow,false);
|
||||
}
|
||||
}
|
||||
#endif //#ifndef BT_NO_PROFILE
|
||||
|
||||
|
||||
if (sUseOpenGL2)
|
||||
{
|
||||
|
||||
@@ -1219,7 +1408,7 @@ void OpenGLExampleBrowser::update(float deltaTime)
|
||||
|
||||
}
|
||||
|
||||
|
||||
singleStepSimulation = false;
|
||||
|
||||
|
||||
toggle=1-toggle;
|
||||
|
||||
Reference in New Issue
Block a user