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:
Erwin Coumans
2016-12-23 15:20:04 -08:00
parent da7ae53941
commit 4c06fd27b3
12 changed files with 515 additions and 225 deletions

View File

@@ -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);

View File

@@ -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

View File

@@ -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;