Add a statistical profiler. Also applied a bugfix b3Profiler.
- This is a compact hierarchical profiler which also stores node statistics - Might need to use a hash-table to lookup statistic for node because each frame trees are build
This commit is contained in:
parent
ff535f9f7b
commit
1ef6d46d33
@ -104,9 +104,13 @@ static void Run()
|
||||
while (glfwWindowShouldClose(g_window) == 0)
|
||||
{
|
||||
g_profiler->Begin();
|
||||
|
||||
g_profilerSt->Begin();
|
||||
|
||||
g_profiler->BeginScope("Frame");
|
||||
|
||||
|
||||
g_profilerSt->BeginScope("Frame");
|
||||
|
||||
g_view->BeginInterface();
|
||||
|
||||
if (g_model->IsPaused())
|
||||
@ -122,6 +126,8 @@ static void Run()
|
||||
|
||||
g_model->Update();
|
||||
|
||||
g_profilerSt->EndScope();
|
||||
|
||||
g_profiler->EndScope();
|
||||
|
||||
if (g_settings->drawProfileTree)
|
||||
@ -129,20 +135,13 @@ static void Run()
|
||||
g_view->InterfaceProfileTree();
|
||||
}
|
||||
|
||||
g_profilerRecorder->BuildRecords();
|
||||
|
||||
if (g_settings->drawProfile)
|
||||
if (g_settings->drawProfileTreeStats)
|
||||
{
|
||||
b3StackArray<ProfilerRecord*, 256> records;
|
||||
g_profilerRecorder->BuildSortedRecords(records);
|
||||
|
||||
for (u32 i = 0; i < records.Count(); ++i)
|
||||
{
|
||||
ProfilerRecord* r = records[i];
|
||||
g_draw->DrawString(b3Color_white, "%s %.4f (min = %.4f) (max = %.4f) (calls = %d) [ms]", r->name, r->elapsed, r->minElapsed, r->maxElapsed, r->callCount);
|
||||
}
|
||||
g_view->InterfaceProfileTreeStats();
|
||||
}
|
||||
|
||||
g_profilerSt->End();
|
||||
|
||||
g_profiler->End();
|
||||
|
||||
g_view->EndInterface();
|
||||
|
@ -26,7 +26,7 @@ Model::Model()
|
||||
g_draw = &m_draw;
|
||||
g_camera = &m_camera;
|
||||
g_profiler = &m_profiler;
|
||||
g_profilerRecorder = &m_profilerRecorder;
|
||||
g_profilerSt = &m_profilerSt;
|
||||
|
||||
#if (PROFILE_JSON == 1)
|
||||
g_profilerListener = &m_jsonListener;
|
||||
@ -56,7 +56,7 @@ Model::~Model()
|
||||
g_draw = nullptr;
|
||||
g_camera = nullptr;
|
||||
g_profiler = nullptr;
|
||||
g_profilerRecorder = nullptr;
|
||||
g_profilerSt = nullptr;
|
||||
|
||||
#if (PROFILE_JSON == 1)
|
||||
g_profilerListener = nullptr;
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
#include <testbed/framework/draw.h>
|
||||
#include <testbed/framework/profiler.h>
|
||||
#include <testbed/framework/profiler_recorder.h>
|
||||
#include <testbed/framework/profiler_st.h>
|
||||
|
||||
// Set to 1 to write profile events into a .json file. Set to 0 otherwise.
|
||||
#define PROFILE_JSON 0
|
||||
@ -71,7 +71,7 @@ private:
|
||||
Draw m_draw;
|
||||
Camera m_camera;
|
||||
Profiler m_profiler;
|
||||
ProfilerRecorder m_profilerRecorder;
|
||||
ProfilerSt m_profilerSt;
|
||||
|
||||
#if (PROFILE_JSON == 1)
|
||||
JsonProfiler m_jsonListener;
|
||||
|
@ -127,12 +127,13 @@ void Profiler::End()
|
||||
listener->BeginEvents();
|
||||
}
|
||||
|
||||
RecurseEvents(m_root);
|
||||
|
||||
RecurseDestroyNode(m_root);
|
||||
m_root = nullptr;
|
||||
if (m_root)
|
||||
{
|
||||
RecurseEvents(m_root);
|
||||
|
||||
assert(m_root == nullptr);
|
||||
RecurseDestroyNode(m_root);
|
||||
m_root = nullptr;
|
||||
}
|
||||
|
||||
if (listener)
|
||||
{
|
||||
|
@ -62,8 +62,6 @@ public:
|
||||
// Get the root profiler node.
|
||||
ProfilerNode* GetRoot() { return m_root; }
|
||||
private:
|
||||
friend class ProfilerRecorder;
|
||||
|
||||
ProfilerNode* CreateNode();
|
||||
void DestroyNode(ProfilerNode* node);
|
||||
|
||||
|
@ -1,120 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include <testbed/framework/profiler_recorder.h>
|
||||
#include <testbed/framework/profiler.h>
|
||||
|
||||
ProfilerRecorder* g_profilerRecorder = nullptr;
|
||||
|
||||
ProfilerRecord* ProfilerRecorder::FindRecord(const char* name)
|
||||
{
|
||||
for (u32 i = 0; i < m_records.Count(); ++i)
|
||||
{
|
||||
ProfilerRecord& r = m_records[i];
|
||||
if (r.name == name)
|
||||
{
|
||||
return &r;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ProfilerRecorder::RecurseBuildRecords(ProfilerNode* node)
|
||||
{
|
||||
ProfilerRecord* fr = FindRecord(node->name);
|
||||
if (fr)
|
||||
{
|
||||
float64 elapsedTime = node->t1 - node->t0;
|
||||
|
||||
fr->elapsed += elapsedTime;
|
||||
fr->minElapsed = b3Min(fr->minElapsed, elapsedTime);
|
||||
fr->maxElapsed = b3Max(fr->maxElapsed, elapsedTime);
|
||||
++fr->callCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
float64 elapsedTime = node->t1 - node->t0;
|
||||
|
||||
ProfilerRecord r;
|
||||
r.name = node->name;
|
||||
r.elapsed = elapsedTime;
|
||||
r.minElapsed = elapsedTime;
|
||||
r.maxElapsed = elapsedTime;
|
||||
r.callCount = 1;
|
||||
|
||||
m_records.PushBack(r);
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < node->children.Count(); ++i)
|
||||
{
|
||||
RecurseBuildRecords(node->children[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void ProfilerRecorder::BuildRecords()
|
||||
{
|
||||
for (u32 i = 0; i < m_records.Count(); ++i)
|
||||
{
|
||||
m_records[i].elapsed = 0.0;
|
||||
m_records[i].callCount = 0;
|
||||
}
|
||||
|
||||
RecurseBuildRecords(g_profiler->m_root);
|
||||
}
|
||||
|
||||
static ProfilerRecord* FindSortedRecord(b3Array<ProfilerRecord*>& records, const char* name)
|
||||
{
|
||||
for (u32 i = 0; i < records.Count(); ++i)
|
||||
{
|
||||
ProfilerRecord* r = records[i];
|
||||
if (r->name == name)
|
||||
{
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ProfilerRecorder::RecurseBuildSortedRecords(ProfilerNode* node, b3Array<ProfilerRecord*>& output)
|
||||
{
|
||||
ProfilerRecord* fsr = FindSortedRecord(output, node->name);
|
||||
|
||||
if (fsr == nullptr)
|
||||
{
|
||||
ProfilerRecord* fr = FindRecord(node->name);
|
||||
|
||||
assert(fr != nullptr);
|
||||
|
||||
// Push back the first ocurrence of call in calling order
|
||||
output.PushBack(fr);
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < node->children.Count(); ++i)
|
||||
{
|
||||
RecurseBuildSortedRecords(node->children[i], output);
|
||||
}
|
||||
}
|
||||
|
||||
void ProfilerRecorder::BuildSortedRecords(b3Array<ProfilerRecord*>& output)
|
||||
{
|
||||
assert(output.Count() == 0);
|
||||
|
||||
output.Reserve(m_records.Count());
|
||||
|
||||
RecurseBuildSortedRecords(g_profiler->m_root, output);
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef PROFILER_RECORDER_H
|
||||
#define PROFILER_RECORDER_H
|
||||
|
||||
#include <bounce/common/math/math.h>
|
||||
#include <bounce/common/template/array.h>
|
||||
|
||||
struct ProfilerNode;
|
||||
|
||||
// A persistent profiler record
|
||||
struct ProfilerRecord
|
||||
{
|
||||
const char* name;
|
||||
float64 elapsed;
|
||||
float64 minElapsed;
|
||||
float64 maxElapsed;
|
||||
u32 callCount;
|
||||
};
|
||||
|
||||
// This class maintains persistent profiler records
|
||||
class ProfilerRecorder
|
||||
{
|
||||
public:
|
||||
void BuildRecords();
|
||||
|
||||
void BuildSortedRecords(b3Array<ProfilerRecord*>& output);
|
||||
|
||||
const b3Array<ProfilerRecord>& GetRecords() const { return m_records; }
|
||||
private:
|
||||
void RecurseBuildRecords(ProfilerNode* node);
|
||||
|
||||
void RecurseBuildSortedRecords(ProfilerNode* node, b3Array<ProfilerRecord*>& output);
|
||||
|
||||
ProfilerRecord* FindRecord(const char* name);
|
||||
|
||||
b3StackArray<ProfilerRecord, 256> m_records; // persistent profiler records
|
||||
};
|
||||
|
||||
extern ProfilerRecorder* g_profilerRecorder;
|
||||
|
||||
#endif
|
199
examples/testbed/framework/profiler_st.cpp
Normal file
199
examples/testbed/framework/profiler_st.cpp
Normal file
@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include <testbed/framework/profiler_st.h>
|
||||
|
||||
ProfilerSt* g_profilerSt = nullptr;
|
||||
|
||||
ProfilerSt::ProfilerSt() : m_pool(sizeof(ProfilerStNode))
|
||||
{
|
||||
m_root = nullptr;
|
||||
m_top = nullptr;
|
||||
}
|
||||
|
||||
ProfilerSt::~ProfilerSt()
|
||||
{
|
||||
if (m_root)
|
||||
{
|
||||
RecurseDestroyNode(m_root);
|
||||
}
|
||||
}
|
||||
|
||||
ProfilerStNodeStat* ProfilerSt::FindStat(const char* name)
|
||||
{
|
||||
for (u32 i = 0; i < m_stats.Count(); ++i)
|
||||
{
|
||||
if (m_stats[i].name == name)
|
||||
{
|
||||
return &m_stats[i];
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ProfilerStNodeStat* ProfilerSt::CreateStat()
|
||||
{
|
||||
m_stats.PushBack(ProfilerStNodeStat());
|
||||
return &m_stats.Back();
|
||||
}
|
||||
|
||||
ProfilerStNode* ProfilerSt::CreateNode()
|
||||
{
|
||||
void* block = m_pool.Allocate();
|
||||
return new (block) ProfilerStNode();
|
||||
}
|
||||
|
||||
void ProfilerSt::DestroyNode(ProfilerStNode* node)
|
||||
{
|
||||
node->~ProfilerStNode();
|
||||
m_pool.Free(node);
|
||||
}
|
||||
|
||||
void ProfilerSt::RecurseDestroyNode(ProfilerStNode* node)
|
||||
{
|
||||
for (u32 i = 0; i < node->children.Count(); ++i)
|
||||
{
|
||||
return RecurseDestroyNode(node->children[i]);
|
||||
}
|
||||
|
||||
DestroyNode(node);
|
||||
}
|
||||
|
||||
static ProfilerStNode* RecurseFindNode(ProfilerStNode* node, const char* name)
|
||||
{
|
||||
if (node->name == name)
|
||||
{
|
||||
return node;
|
||||
}
|
||||
|
||||
ProfilerStNode* result = nullptr;
|
||||
for (u32 i = 0; result == nullptr && i < node->children.Count(); ++i)
|
||||
{
|
||||
result = RecurseFindNode(node->children[i], name);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ProfilerStNode* ProfilerSt::FindNode(const char* name)
|
||||
{
|
||||
if (m_top)
|
||||
{
|
||||
return RecurseFindNode(m_top, name);
|
||||
}
|
||||
|
||||
if (m_root)
|
||||
{
|
||||
return RecurseFindNode(m_root, name);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ProfilerSt::BeginScope(const char* name)
|
||||
{
|
||||
ProfilerStNode* fn = FindNode(name);
|
||||
|
||||
if (fn)
|
||||
{
|
||||
m_time.Update();
|
||||
fn->t0 = m_time.GetCurrentMilis();
|
||||
++fn->callCount;
|
||||
m_top = fn;
|
||||
return;
|
||||
}
|
||||
|
||||
m_time.Update();
|
||||
|
||||
ProfilerStNode* n = CreateNode();
|
||||
n->name = name;
|
||||
n->t0 = m_time.GetCurrentMilis();
|
||||
n->elapsed = 0.0f;
|
||||
n->callCount = 1;
|
||||
n->parent = m_top;
|
||||
n->stat = nullptr;
|
||||
|
||||
if (m_root == nullptr)
|
||||
{
|
||||
m_root = n;
|
||||
m_top = n;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_top)
|
||||
{
|
||||
m_top->children.PushBack(n);
|
||||
}
|
||||
|
||||
m_top = n;
|
||||
}
|
||||
|
||||
void ProfilerSt::EndScope()
|
||||
{
|
||||
assert(m_top != nullptr);
|
||||
|
||||
m_time.Update();
|
||||
|
||||
m_top->t1 = m_time.GetCurrentMilis();
|
||||
|
||||
float64 elapsedTime = m_top->t1 - m_top->t0;
|
||||
|
||||
m_top->elapsed += elapsedTime;
|
||||
|
||||
ProfilerStNodeStat* stat = FindStat(m_top->name);
|
||||
|
||||
if (stat == nullptr)
|
||||
{
|
||||
stat = CreateStat();
|
||||
stat->name = m_top->name;
|
||||
stat->minElapsed = elapsedTime;
|
||||
stat->maxElapsed = elapsedTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
stat->minElapsed = b3Min(stat->minElapsed, elapsedTime);
|
||||
stat->maxElapsed = b3Max(stat->maxElapsed, elapsedTime);
|
||||
}
|
||||
|
||||
if (m_top->stat == nullptr)
|
||||
{
|
||||
m_top->stat = stat;
|
||||
}
|
||||
|
||||
assert(m_top->stat == stat);
|
||||
|
||||
m_top = m_top->parent;
|
||||
}
|
||||
|
||||
void ProfilerSt::Begin()
|
||||
{
|
||||
assert(m_top == nullptr);
|
||||
}
|
||||
|
||||
void ProfilerSt::End()
|
||||
{
|
||||
assert(m_top == nullptr);
|
||||
|
||||
if (m_root)
|
||||
{
|
||||
RecurseDestroyNode(m_root);
|
||||
m_root = nullptr;
|
||||
}
|
||||
}
|
94
examples/testbed/framework/profiler_st.h
Normal file
94
examples/testbed/framework/profiler_st.h
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef PROFILER_ST_H
|
||||
#define PROFILER_ST_H
|
||||
|
||||
#include <bounce/common/math/math.h>
|
||||
#include <bounce/common/memory/block_pool.h>
|
||||
#include <bounce/common/template/array.h>
|
||||
#include <bounce/common/time.h>
|
||||
|
||||
// Profiler tree node statistics
|
||||
struct ProfilerStNodeStat
|
||||
{
|
||||
const char* name;
|
||||
float64 minElapsed;
|
||||
float64 maxElapsed;
|
||||
};
|
||||
|
||||
// A profiler tree node
|
||||
struct ProfilerStNode
|
||||
{
|
||||
const char* name;
|
||||
float64 t0;
|
||||
float64 t1;
|
||||
|
||||
float64 elapsed;
|
||||
u32 callCount;
|
||||
|
||||
ProfilerStNode* parent;
|
||||
b3StackArray<ProfilerStNode*, 32> children;
|
||||
|
||||
ProfilerStNodeStat* stat;
|
||||
};
|
||||
|
||||
// A profiler tree
|
||||
class ProfilerSt
|
||||
{
|
||||
public:
|
||||
ProfilerSt();
|
||||
|
||||
~ProfilerSt();
|
||||
|
||||
// Must be called before profiling.
|
||||
void Begin();
|
||||
|
||||
// Must be called after profiling.
|
||||
void End();
|
||||
|
||||
// Begin a new scope.
|
||||
void BeginScope(const char* name);
|
||||
|
||||
// End the top scope.
|
||||
void EndScope();
|
||||
|
||||
ProfilerStNode* GetRoot() { return m_root; }
|
||||
private:
|
||||
ProfilerStNode* CreateNode();
|
||||
void DestroyNode(ProfilerStNode* node);
|
||||
|
||||
void RecurseDestroyNode(ProfilerStNode* node);
|
||||
|
||||
ProfilerStNode* FindNode(const char* name);
|
||||
|
||||
ProfilerStNodeStat* CreateStat();
|
||||
|
||||
ProfilerStNodeStat* FindStat(const char* name);
|
||||
|
||||
b3BlockPool m_pool; // pool of nodes
|
||||
b3Time m_time; // timer
|
||||
ProfilerStNode* m_root; // tree root node
|
||||
ProfilerStNode* m_top; // top node
|
||||
|
||||
b3StackArray<ProfilerStNodeStat, 256> m_stats; // node statistics
|
||||
};
|
||||
|
||||
extern ProfilerSt* g_profilerSt;
|
||||
|
||||
#endif
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include <testbed/framework/test.h>
|
||||
#include <testbed/framework/profiler.h>
|
||||
#include <testbed/framework/profiler_st.h>
|
||||
|
||||
extern u32 b3_allocCalls, b3_maxAllocCalls;
|
||||
extern u32 b3_convexCalls, b3_convexCacheHits;
|
||||
@ -27,11 +28,13 @@ extern bool b3_convexCache;
|
||||
void b3BeginProfileScope(const char* name)
|
||||
{
|
||||
g_profiler->BeginScope(name);
|
||||
g_profilerSt->BeginScope(name);
|
||||
}
|
||||
|
||||
void b3EndProfileScope()
|
||||
{
|
||||
g_profiler->EndScope();
|
||||
g_profilerSt->EndScope();
|
||||
}
|
||||
|
||||
Test::Test() :
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <testbed/framework/view_model.h>
|
||||
#include <testbed/framework/test.h>
|
||||
#include <testbed/framework/profiler.h>
|
||||
#include <testbed/framework/profiler_st.h>
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
#if defined (U_OPENGL_2)
|
||||
@ -218,8 +219,8 @@ void View::Interface()
|
||||
|
||||
if (ImGui::BeginMenu("View"))
|
||||
{
|
||||
ImGui::MenuItem("Profile", "", &settings.drawProfile);
|
||||
ImGui::MenuItem("Profile Tree", "", &settings.drawProfileTree);
|
||||
ImGui::MenuItem("Profile Tree Statistics", "", &settings.drawProfileTreeStats);
|
||||
ImGui::MenuItem("Statistics", "", &settings.drawStats);
|
||||
|
||||
ImGui::Separator();
|
||||
@ -435,7 +436,7 @@ void View::InterfaceProfileTree()
|
||||
ImGui::SetNextWindowPos(ImVec2(0.0f, wp.y + ws.y));
|
||||
ImGui::SetNextWindowSize(ImVec2(g_camera->m_width - 250.0f, 0.0f));
|
||||
|
||||
ImGui::Begin("##ProfileTree", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysAutoResize);
|
||||
ImGui::Begin("Profile Tree", NULL, ImGuiWindowFlags_AlwaysAutoResize);
|
||||
|
||||
ProfilerNode* root = g_profiler->GetRoot();
|
||||
if (root)
|
||||
@ -449,6 +450,64 @@ void View::InterfaceProfileTree()
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
|
||||
static void TreeNode(ProfilerStNode* node, u32& index)
|
||||
{
|
||||
ImGui::PushID(index);
|
||||
++index;
|
||||
|
||||
if (ImGui::TreeNode(node->name))
|
||||
{
|
||||
ImGui::Text("%.4f (min = %.4f) (max = %.4f) (calls = %d) [ms]", node->elapsed, node->stat->minElapsed, node->stat->maxElapsed, node->callCount);
|
||||
|
||||
for (u32 i = 0; i < node->children.Count(); ++i)
|
||||
{
|
||||
TreeNode(node->children[i], index);
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
void View::InterfaceProfileTreeStats()
|
||||
{
|
||||
ImGui::Begin("Overlay", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar);
|
||||
ImVec2 wp = ImGui::GetWindowPos();
|
||||
ImVec2 ws = ImGui::GetWindowSize();
|
||||
ImGui::End();
|
||||
|
||||
wp.y = wp.y + ws.y;
|
||||
|
||||
if (g_settings->drawProfileTree)
|
||||
{
|
||||
ImGui::Begin("Profile Tree", NULL, ImGuiWindowFlags_AlwaysAutoResize);
|
||||
ImVec2 ptwp = ImGui::GetWindowPos();
|
||||
ImVec2 ptws = ImGui::GetWindowSize();
|
||||
ImGui::End();
|
||||
|
||||
wp.y = ptwp.y + ptws.y;
|
||||
}
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
||||
|
||||
ImGui::SetNextWindowBgAlpha(0.0f);
|
||||
ImGui::SetNextWindowPos(ImVec2(0.0f, wp.y));
|
||||
ImGui::SetNextWindowSize(ImVec2(g_camera->m_width - 250.0f, 0.0f));
|
||||
|
||||
ImGui::Begin("Profile Tree Statistics", NULL, ImGuiWindowFlags_AlwaysAutoResize);
|
||||
|
||||
ProfilerStNode* root = g_profilerSt->GetRoot();
|
||||
if (root)
|
||||
{
|
||||
u32 index = 0;
|
||||
TreeNode(root, index);
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
|
||||
void View::EndInterface()
|
||||
{
|
||||
ImGui::PopStyleVar();
|
||||
|
@ -42,6 +42,7 @@ public:
|
||||
void BeginInterface();
|
||||
void Interface();
|
||||
void InterfaceProfileTree();
|
||||
void InterfaceProfileTreeStats();
|
||||
void EndInterface();
|
||||
private:
|
||||
friend class ViewModel;
|
||||
|
@ -32,8 +32,8 @@ struct Settings
|
||||
drawLines = true;
|
||||
drawTriangles = true;
|
||||
drawGrid = true;
|
||||
drawProfile = false;
|
||||
drawProfileTree = false;
|
||||
drawProfileTreeStats = false;
|
||||
drawStats = false;
|
||||
}
|
||||
|
||||
@ -43,8 +43,8 @@ struct Settings
|
||||
bool drawLines;
|
||||
bool drawTriangles;
|
||||
bool drawGrid;
|
||||
bool drawProfile;
|
||||
bool drawProfileTree;
|
||||
bool drawProfileTreeStats;
|
||||
bool drawStats;
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user