Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add new profiler #410

Merged
merged 1 commit into from
Oct 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Engine/Source/Editor/EditorApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "ImGui/ImGuiContextInstance.h"
#include "ImGui/Localization.h"
#include "ImGui/UILayers/DebugPanel.h"
#include "ImGui/UILayers/Profiler.h"
#include "Log/Log.h"
#include "Math/MeshGenerator.h"
#include "Path/Path.h"
Expand Down Expand Up @@ -177,6 +178,7 @@ void EditorApp::InitEditorUILayers()
m_pEditorImGuiContext->AddDynamicLayer(cd::MoveTemp(pSceneView));

m_pEditorImGuiContext->AddDynamicLayer(std::make_unique<SkeletonView>("SkeletonView"));
m_pEditorImGuiContext->AddDynamicLayer(std::make_unique<engine::Profiler>("Profiler"));
m_pEditorImGuiContext->AddDynamicLayer(std::make_unique<Inspector>("Inspector"));

auto pAssetBrowser = std::make_unique<AssetBrowser>("AssetBrowser");
Expand Down Expand Up @@ -205,10 +207,8 @@ void EditorApp::InitEngineImGuiContext(engine::Language language)

void EditorApp::InitEngineUILayers()
{
//auto pEntityList = std::make_unique<engine::DebugPanel>("DebugPanel");
//pEntityList->SetCameraController(m_pCameraController);
//m_pEngineImGuiContext->AddDynamicLayer(cd::MoveTemp(pEntityList));

//m_pEngineImGuiContext->AddDynamicLayer(std::make_unique<engine::DebugPanel>("DebugPanel"));

auto pImGuizmoView = std::make_unique<editor::ImGuizmoView>("ImGuizmoView");
pImGuizmoView->SetSceneView(m_pSceneView);
m_pEngineImGuiContext->AddDynamicLayer(cd::MoveTemp(pImGuizmoView));
Expand Down
1 change: 1 addition & 0 deletions Engine/Source/Runtime/ImGui/ImGuiContextInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ void ImGuiContextInstance::BeginDockSpace()
ImGui::DockBuilderDockWindow("GameView", dockSpaceLeftLeft);
ImGui::DockBuilderDockWindow("SceneView", dockSpaceLeftRight);
ImGui::DockBuilderDockWindow("SkeletonView", dockSpaceUpRight);
ImGui::DockBuilderDockWindow("Profiler", dockSpaceUpRight);
ImGui::DockBuilderDockWindow("Inspector", dockSpaceUpRight);
ImGui::DockBuilderDockWindow("AssetBrowser", dockSpaceBottomLeft);
ImGui::DockBuilderDockWindow("OutputLog", dockSpaceBottomRight);
Expand Down
22 changes: 0 additions & 22 deletions Engine/Source/Runtime/ImGui/UILayers/DebugPanel.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include "DebugPanel.h"
#include "Display/CameraController.h"
#include "ImGui/IconFont/IconsMaterialDesignIcons.h"

#include <bgfx/bgfx.h>
Expand Down Expand Up @@ -85,27 +84,6 @@ void DebugPanel::Update()

ImGui::Separator();

if (ImGui::Selectable("Front"))
{
if (m_pCameraController)
m_pCameraController->MoveToPosition(cd::Vec3f(-15.40f, 1.75f, 0.16f), cd::Vec3f(49.64f, 88.32f, 48.37f));
}
if (ImGui::Selectable("Left"))
{
if (m_pCameraController)
m_pCameraController->MoveToPosition(cd::Vec3f(-2.40, 1.75f, -1.95f), cd::Vec3f(173.14f, 50.70f, 165.59f));
}
if (ImGui::Selectable("Right"))
{
if (m_pCameraController)
m_pCameraController->MoveToPosition(cd::Vec3f(-4.71, 0.75f, 2.37f), cd::Vec3f(2.36f, 36.19f, 0.77f));
}
if (ImGui::Selectable("Behind"))
{
if (m_pCameraController)
m_pCameraController->MoveToPosition(cd::Vec3f(9.18, 0.75f, -7.05f), cd::Vec3f(-25.74f, 33.71f, -7.92f));
}

ImGui::End();
}

Expand Down
9 changes: 1 addition & 8 deletions Engine/Source/Runtime/ImGui/UILayers/DebugPanel.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
#include "ImGui/ImGuiBaseLayer.h"

#include <memory>
namespace engine
{

class CameraController;

class DebugPanel : public engine::ImGuiBaseLayer
{
public:
Expand All @@ -15,12 +12,8 @@ class DebugPanel : public engine::ImGuiBaseLayer
virtual void Init() override;
virtual void Update() override;

void SetCameraController(std::shared_ptr<engine::CameraController> cameraController) { m_pCameraController = cameraController; }

void ShowProfiler();

private:
std::shared_ptr<engine::CameraController> m_pCameraController;
void ShowProfiler();
};

}
243 changes: 243 additions & 0 deletions Engine/Source/Runtime/ImGui/UILayers/Profiler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
#include "Profiler.h"
#include "ImGui/IconFont/IconsMaterialDesignIcons.h"

#include <bgfx/bgfx.h>
#include <bx/string.h>
#include <bx/timer.h>
#include <bx/math.h>
#include <imgui/imgui.h>

#include <cmath>

namespace
{

bool DrawBar(const char* id, float width, float maxWidth, float height, const ImVec4& color)
{
const ImGuiStyle& style = ImGui::GetStyle();

ImVec4 hoveredColor(color.x * 1.1f, color.y * 1.1f, color.z * 1.1f, color.w * 1.1f);

ImGui::PushStyleColor(ImGuiCol_Button, color);
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, hoveredColor);
ImGui::PushStyleColor(ImGuiCol_ButtonActive, color);
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, style.ItemSpacing.y));

bool itemHovered = false;

ImGui::PushID(id);

ImGui::Button("##Visible", ImVec2(width, height));
itemHovered = itemHovered || ImGui::IsItemHovered();

ImGui::SameLine();
ImGui::InvisibleButton("##Invisible", ImVec2(std::max(1.0f, maxWidth - width), height));
itemHovered = itemHovered || ImGui::IsItemHovered();

ImGui::PopID();

ImGui::PopStyleVar(2);
ImGui::PopStyleColor(3);

return itemHovered;
}

}

namespace engine
{

Profiler::~Profiler()
{
}

void Profiler::Init()
{
}

void Profiler::Update()
{
// top left, transparent background
//ImGui::SetNextWindowPos(padding, ImGuiCond_Always);
ImGui::SetNextWindowBgAlpha(0.5f);
constexpr auto flags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;
ImGui::Begin(GetName(), &m_isEnable, flags);

const float overlayWidth = 150.0f;
const ImVec2 padding = { 5.0f, 5.0f };

float deltaTime = ImGui::GetIO().DeltaTime;
static bool showFPS = true;
static bool showFrameTime = true;
static bool showViewStats = true;
static bool showGPUMemory = true;

// title
ImGui::Text("Stats");
ImGui::TextDisabled("right-click for options");
ImGui::Separator();

// general data
const bgfx::Stats* stats = bgfx::getStats();
const double toCpuMs = 1000.0 / double(stats->cpuTimerFreq);
const double toGpuMs = 1000.0 / double(stats->gpuTimerFreq);

ImGui::Text("Backend: %s", bgfx::getRendererName(bgfx::getRendererType()));
ImGui::Text("Buffer size: %u x %u px", stats->width, stats->height);
ImGui::Text("Triangles: %u", stats->numPrims[bgfx::Topology::TriList]);
ImGui::Text("Draw calls: %u", stats->numDraw);
ImGui::Text("Compute calls: %u", stats->numCompute);

// plots
static constexpr size_t GRAPH_HISTORY = 100;
static float fpsValues[GRAPH_HISTORY] = { 0 };
static float frameTimeValues[GRAPH_HISTORY] = { 0 };
static float gpuMemoryValues[GRAPH_HISTORY] = { 0 };
static size_t offset = 0;

if (showFPS)
{
ImGui::Separator();
ImGui::Text("FPS");
ImGui::PlotLines("",
fpsValues,
IM_ARRAYSIZE(fpsValues),
(int)offset + 1,
nullptr,
0.0f,
200.0f,
ImVec2(overlayWidth, 50));
ImGui::Text("%.0f", fpsValues[offset]);
}

if (showFrameTime)
{
ImGui::Separator();
ImGui::Text("Frame time");
ImGui::PlotLines("",
frameTimeValues,
IM_ARRAYSIZE(frameTimeValues),
(int)offset + 1,
nullptr,
0.0f,
30.0f,
ImVec2(overlayWidth, 50));
ImGui::Text("CPU: %.2f ms", float(stats->cpuTimeEnd - stats->cpuTimeBegin) * toCpuMs);
ImGui::Text("GPU: %.2f ms", float(stats->gpuTimeEnd - stats->gpuTimeBegin) * toGpuMs);
ImGui::Text("Total: %.2f ms", frameTimeValues[offset]);
}

if (showViewStats)
{
ImGui::Separator();
ImGui::Text("View stats");
if (stats->numViews > 0)
{
ImVec4 cpuColor(0.5f, 1.0f, 0.5f, 1.0f);
ImVec4 gpuColor(0.5f, 0.5f, 1.0f, 1.0f);

const float itemHeight = ImGui::GetTextLineHeightWithSpacing();
const float itemHeightWithSpacing = ImGui::GetFrameHeightWithSpacing();
const float scale = 2.0f;

if (ImGui::BeginListBox("##ViewStats", ImVec2(overlayWidth, stats->numViews * itemHeightWithSpacing)))
{
ImGuiListClipper clipper;
clipper.Begin(stats->numViews, itemHeight);

while (clipper.Step())
{
for (int32_t pos = clipper.DisplayStart; pos < clipper.DisplayEnd; ++pos)
{
const bgfx::ViewStats& viewStats = stats->viewStats[pos];
float cpuElapsed = float((viewStats.cpuTimeEnd - viewStats.cpuTimeBegin) * toCpuMs);
float gpuElapsed = float((viewStats.gpuTimeEnd - viewStats.gpuTimeBegin) * toGpuMs);

ImGui::Text("%d", viewStats.view);

const float maxWidth = overlayWidth * 0.35f;
const float cpuWidth = bx::clamp(cpuElapsed * scale, 1.0f, maxWidth);
const float gpuWidth = bx::clamp(gpuElapsed * scale, 1.0f, maxWidth);

ImGui::SameLine(overlayWidth * 0.3f);

if (DrawBar("CPU", cpuWidth, maxWidth, itemHeight, cpuColor))
{
ImGui::SetTooltip("%s -- CPU: %.2f ms", viewStats.name, cpuElapsed);
}

ImGui::SameLine();

if (DrawBar("GPU", gpuWidth, maxWidth, itemHeight, gpuColor))
{
ImGui::SetTooltip("%s -- GPU: %.2f ms", viewStats.name, gpuElapsed);
}
}
}

clipper.End();

ImGui::EndListBox();
}
}
else
{
ImGui::TextWrapped("Profiler disabled");
}
}

if (showGPUMemory)
{
int64_t used = stats->gpuMemoryUsed;
int64_t max = stats->gpuMemoryMax;

ImGui::Separator();
if (used > 0 && max > 0)
{
ImGui::Text("GPU memory");
ImGui::PlotLines("",
gpuMemoryValues,
IM_ARRAYSIZE(gpuMemoryValues),
(int)offset + 1,
nullptr,
0.0f,
float(max),
ImVec2(overlayWidth, 50));
char strUsed[64];
bx::prettify(strUsed, BX_COUNTOF(strUsed), stats->gpuMemoryUsed);
char strMax[64];
bx::prettify(strMax, BX_COUNTOF(strMax), stats->gpuMemoryMax);
ImGui::Text("%s / %s", strUsed, strMax);
}
}

// update after drawing so offset is the current value
static float currentTime = 0.0f;
static float oldTime = 0.0f;
constexpr float GRAPH_FREQUENCY = 0.1f;
currentTime += deltaTime;
if (currentTime - oldTime > GRAPH_FREQUENCY)
{
offset = (offset + 1) % GRAPH_HISTORY;
ImGuiIO& io = ImGui::GetIO();
fpsValues[offset] = 1 / io.DeltaTime;
frameTimeValues[offset] = io.DeltaTime * 1000;
gpuMemoryValues[offset] = float(stats->gpuMemoryUsed) / 1024 / 1024;

oldTime = currentTime;
}

// right click menu
if (ImGui::BeginPopupContextWindow())
{
ImGui::Checkbox("FPS", &showFPS);
ImGui::Checkbox("Frame time", &showFrameTime);
ImGui::Checkbox("View stats", &showViewStats);
ImGui::Checkbox("GPU memory", &showGPUMemory);
ImGui::EndPopup();
}
ImGui::End();
}

}
16 changes: 16 additions & 0 deletions Engine/Source/Runtime/ImGui/UILayers/Profiler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include "ImGui/ImGuiBaseLayer.h"

namespace engine
{

class Profiler : public engine::ImGuiBaseLayer
{
public:
using ImGuiBaseLayer::ImGuiBaseLayer;
virtual ~Profiler();

virtual void Init() override;
virtual void Update() override;
};

}
Loading