2024-12-25 21:44:33 +00:00
|
|
|
#include "PerformanceWindow.h"
|
|
|
|
#include "imgui.h"
|
2025-01-04 00:32:39 +00:00
|
|
|
#include <algorithm> // for std::max
|
|
|
|
#include <float.h> // for FLT_MAX
|
2024-12-26 04:00:13 +00:00
|
|
|
#include "Engine/ThemeManager.h"
|
2025-01-01 07:36:53 +00:00
|
|
|
#include "Engine/ScopedTimer.h"
|
2024-12-25 23:01:05 +00:00
|
|
|
|
2024-12-27 18:19:20 +00:00
|
|
|
extern int LoadedAssets;
|
2024-12-27 01:34:34 +00:00
|
|
|
extern int g_GPU_Triangles_drawn_to_screen;
|
2025-01-03 23:14:25 +00:00
|
|
|
extern int g_GPU_Draw_Calls;
|
|
|
|
|
2025-01-01 07:36:53 +00:00
|
|
|
const char *polygonModeOptions[] = {"Fill", "Wireframe", "Points"};
|
2025-01-04 00:32:39 +00:00
|
|
|
static int polygonMode = 0;
|
2024-12-27 06:09:43 +00:00
|
|
|
|
2024-12-25 23:01:05 +00:00
|
|
|
// Initialize static members
|
|
|
|
int PerformanceWindow::m_OpenGLCallCount = 0;
|
2024-12-26 04:00:13 +00:00
|
|
|
int PerformanceWindow::m_TriangleCount = 0;
|
2024-12-25 23:01:05 +00:00
|
|
|
|
|
|
|
// We'll store up to 60 data points for each stat.
|
2025-01-04 00:32:39 +00:00
|
|
|
static float s_FpsHistory[60] = {0.0f};
|
|
|
|
static float s_MsHistory[60] = {0.0f};
|
|
|
|
static float s_CallsHistory[60] = {0.0f};
|
2024-12-25 23:01:05 +00:00
|
|
|
static float s_TriangleHistory[60] = {0.0f};
|
|
|
|
|
2024-12-25 23:52:19 +00:00
|
|
|
// Current dynamic max scale for FPS and ms
|
|
|
|
static float s_FpsScale = 120.0f; // default starting scale for FPS
|
2025-01-04 00:32:39 +00:00
|
|
|
static float s_MsScale = 25.0f; // default starting scale for ms
|
2024-12-25 23:52:19 +00:00
|
|
|
|
2025-01-04 00:32:39 +00:00
|
|
|
// Push new value into history, shifting old values left
|
|
|
|
static void PushValueToHistory(float* historyArray, int historySize, float newValue)
|
2024-12-25 23:01:05 +00:00
|
|
|
{
|
|
|
|
for (int i = 0; i < historySize - 1; i++)
|
2025-01-04 00:32:39 +00:00
|
|
|
{
|
2024-12-25 23:01:05 +00:00
|
|
|
historyArray[i] = historyArray[i + 1];
|
2025-01-04 00:32:39 +00:00
|
|
|
}
|
2024-12-25 23:01:05 +00:00
|
|
|
historyArray[historySize - 1] = newValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We'll track when we last pushed data to our history.
|
|
|
|
static double s_LastPushTime = 0.0;
|
2024-12-25 23:52:19 +00:00
|
|
|
// We'll also track when we last updated the scale
|
|
|
|
static double s_LastScaleUpdate = 0.0;
|
|
|
|
|
2024-12-25 23:01:05 +00:00
|
|
|
void PerformanceWindow::UpdatePerformanceStats(int newCallCount, int newTriangleCount)
|
|
|
|
{
|
|
|
|
m_OpenGLCallCount = newCallCount;
|
2025-01-04 00:32:39 +00:00
|
|
|
m_TriangleCount = newTriangleCount;
|
2024-12-27 01:34:34 +00:00
|
|
|
|
2025-01-04 00:32:39 +00:00
|
|
|
// Reset GPU counters each frame, or each time you show
|
2024-12-27 01:34:34 +00:00
|
|
|
g_GPU_Triangles_drawn_to_screen = 0;
|
2025-01-03 23:14:25 +00:00
|
|
|
g_GPU_Draw_Calls = 0;
|
2024-12-25 23:01:05 +00:00
|
|
|
}
|
2024-12-25 21:44:33 +00:00
|
|
|
|
|
|
|
void PerformanceWindow::Show(float fps, float ms)
|
|
|
|
{
|
2025-01-01 07:36:53 +00:00
|
|
|
SCOPE_TIMER("PerformanceWindow::Show");
|
|
|
|
|
2024-12-25 23:52:19 +00:00
|
|
|
// 1) Get current time from ImGui's internal clock
|
2024-12-26 04:00:13 +00:00
|
|
|
double currentTime = ImGui::GetTime();
|
2024-12-25 23:52:19 +00:00
|
|
|
|
2025-01-04 00:32:39 +00:00
|
|
|
// 2) If at least 0.05s has passed, push new data (~20 times a second)
|
2024-12-25 23:01:05 +00:00
|
|
|
if ((currentTime - s_LastPushTime) >= 0.05)
|
|
|
|
{
|
|
|
|
s_LastPushTime = currentTime;
|
|
|
|
|
|
|
|
// Push new values into our history arrays
|
2024-12-26 04:00:13 +00:00
|
|
|
PushValueToHistory(s_FpsHistory, 60, fps);
|
|
|
|
PushValueToHistory(s_MsHistory, 60, ms);
|
|
|
|
PushValueToHistory(s_CallsHistory, 60, (float)m_OpenGLCallCount);
|
2024-12-25 23:01:05 +00:00
|
|
|
PushValueToHistory(s_TriangleHistory, 60, (float)m_TriangleCount);
|
|
|
|
}
|
|
|
|
|
2025-01-04 00:32:39 +00:00
|
|
|
// We'll calculate a fallback max for calls
|
|
|
|
static float callsMax = 300.0f;
|
|
|
|
|
|
|
|
// 3) Every 1 second, recalculate the max scale for FPS, ms, and calls
|
2024-12-25 23:52:19 +00:00
|
|
|
if ((currentTime - s_LastScaleUpdate) >= 1.0)
|
|
|
|
{
|
|
|
|
s_LastScaleUpdate = currentTime;
|
|
|
|
|
2025-01-04 00:32:39 +00:00
|
|
|
// Recompute s_FpsScale
|
2024-12-25 23:52:19 +00:00
|
|
|
float maxFps = 0.0f;
|
|
|
|
for (int i = 0; i < 60; i++)
|
2025-01-04 00:32:39 +00:00
|
|
|
maxFps = std::max(maxFps, s_FpsHistory[i]);
|
|
|
|
maxFps = std::max(1.0f, maxFps * 1.15f); // add ~15% headroom
|
2024-12-25 23:52:19 +00:00
|
|
|
s_FpsScale = maxFps;
|
|
|
|
|
2025-01-04 00:32:39 +00:00
|
|
|
// Recompute s_MsScale
|
2024-12-25 23:52:19 +00:00
|
|
|
float maxMs = 0.0f;
|
|
|
|
for (int i = 0; i < 60; i++)
|
2025-01-04 00:32:39 +00:00
|
|
|
maxMs = std::max(maxMs, s_MsHistory[i]);
|
|
|
|
maxMs = std::max(1.0f, maxMs * 1.15f);
|
2024-12-25 23:52:19 +00:00
|
|
|
s_MsScale = maxMs;
|
2025-01-04 00:32:39 +00:00
|
|
|
|
|
|
|
// Recompute callsMax
|
|
|
|
float localMax = 0.0f;
|
|
|
|
for (int i = 0; i < 60; i++)
|
|
|
|
localMax = std::max(localMax, s_CallsHistory[i]);
|
|
|
|
if (localMax > 0.0f)
|
|
|
|
callsMax = localMax * 1.2f; // 20% headroom
|
|
|
|
else
|
|
|
|
callsMax = 300.0f; // default
|
2024-12-25 23:52:19 +00:00
|
|
|
}
|
|
|
|
|
2024-12-25 23:01:05 +00:00
|
|
|
// Optional style adjustments
|
|
|
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(10, 10));
|
2025-01-04 00:32:39 +00:00
|
|
|
|
|
|
|
// Optionally make the window auto-resize or set constraints:
|
|
|
|
// ImGui::SetNextWindowSizeConstraints(ImVec2(350, 300), ImVec2(FLT_MAX, FLT_MAX));
|
|
|
|
// ImGui::Begin("Performance##performance", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
|
|
|
|
|
2024-12-29 02:50:39 +00:00
|
|
|
ImGui::Begin("Performance##performance");
|
2024-12-25 23:01:05 +00:00
|
|
|
|
2025-01-04 00:32:39 +00:00
|
|
|
// A color-coded main header
|
2024-12-25 23:01:05 +00:00
|
|
|
ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.2f, 1.0f), "Performance Stats");
|
|
|
|
ImGui::Separator();
|
2025-01-04 00:32:39 +00:00
|
|
|
ImGui::Spacing();
|
2024-12-25 23:01:05 +00:00
|
|
|
|
2025-01-04 00:32:39 +00:00
|
|
|
// Show current FPS / ms in color
|
|
|
|
{
|
|
|
|
// Line 1: FPS (green) + MS (teal)
|
|
|
|
ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.4f, 1.0f), "FPS: %.1f", fps);
|
|
|
|
ImGui::SameLine();
|
|
|
|
ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.8f, 1.0f), "| ms: %.3f", ms);
|
|
|
|
}
|
2024-12-25 23:01:05 +00:00
|
|
|
|
2025-01-04 00:32:39 +00:00
|
|
|
// Collapsible header for the performance graphs
|
|
|
|
if (ImGui::CollapsingHeader("Performance Graphs", ImGuiTreeNodeFlags_DefaultOpen))
|
|
|
|
{
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
|
|
|
// --------- FPS & MS side by side ----------
|
|
|
|
ImGui::BeginGroup(); // left group
|
|
|
|
{
|
|
|
|
ImGui::Text("FPS");
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_PlotLines, IM_COL32(0, 255, 0, 255)); // green
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_PlotLinesHovered, IM_COL32(255, 0, 0, 255)); // red on hover
|
|
|
|
|
|
|
|
ImGui::PlotLines("##FPS", // hidden label
|
|
|
|
s_FpsHistory, IM_ARRAYSIZE(s_FpsHistory),
|
|
|
|
0, // offset
|
|
|
|
nullptr, // overlay
|
|
|
|
0.0f,
|
|
|
|
s_FpsScale,
|
|
|
|
ImVec2(150, 60));
|
|
|
|
|
|
|
|
if (ImGui::IsItemHovered())
|
|
|
|
{
|
|
|
|
ImGui::BeginTooltip();
|
|
|
|
ImGui::Text("Frames per second over time");
|
|
|
|
ImGui::EndTooltip();
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::PopStyleColor(2);
|
|
|
|
}
|
|
|
|
ImGui::EndGroup();
|
|
|
|
|
|
|
|
ImGui::SameLine();
|
2024-12-25 23:01:05 +00:00
|
|
|
|
2025-01-04 00:32:39 +00:00
|
|
|
ImGui::BeginGroup(); // right group
|
|
|
|
{
|
|
|
|
ImGui::Text("ms/frame");
|
|
|
|
ImGui::PlotHistogram("##ms/frame",
|
|
|
|
s_MsHistory,
|
|
|
|
IM_ARRAYSIZE(s_MsHistory),
|
|
|
|
0,
|
|
|
|
nullptr,
|
|
|
|
0.0f,
|
|
|
|
s_MsScale,
|
|
|
|
ImVec2(150, 60));
|
|
|
|
|
|
|
|
if (ImGui::IsItemHovered())
|
|
|
|
{
|
|
|
|
ImGui::BeginTooltip();
|
|
|
|
ImGui::Text("Frame time in milliseconds");
|
|
|
|
ImGui::EndTooltip();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ImGui::EndGroup();
|
|
|
|
|
|
|
|
ImGui::Spacing();
|
|
|
|
ImGui::Separator();
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
|
|
|
// --------- OpenGL Calls & Indices -----------
|
|
|
|
// 1) GL Calls
|
|
|
|
ImGui::Text("OpenGL Calls: %d", m_OpenGLCallCount);
|
|
|
|
|
|
|
|
ImGui::PlotLines("##GL Calls",
|
|
|
|
s_CallsHistory,
|
|
|
|
IM_ARRAYSIZE(s_CallsHistory),
|
|
|
|
0, // offset
|
|
|
|
nullptr, // overlay text
|
2024-12-26 04:00:13 +00:00
|
|
|
0.0f,
|
2025-01-04 00:32:39 +00:00
|
|
|
callsMax,
|
|
|
|
ImVec2(-1, 50)); // auto-fill width, fixed height=50
|
2024-12-25 23:01:05 +00:00
|
|
|
|
2025-01-04 00:32:39 +00:00
|
|
|
if (ImGui::IsItemHovered())
|
|
|
|
{
|
|
|
|
ImGui::BeginTooltip();
|
|
|
|
ImGui::Text("Number of GL draw calls per frame");
|
|
|
|
ImGui::EndTooltip();
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
|
|
|
// 2) Indices
|
|
|
|
ImGui::Text("Indices: %d", m_TriangleCount);
|
|
|
|
|
|
|
|
// For Indices, we use a histogram. We could also do dynamic range like callsMax.
|
|
|
|
float indexHistMax = std::max(1.0f, (float)m_TriangleCount * 2.5f);
|
2024-12-25 23:35:38 +00:00
|
|
|
|
2025-01-04 00:32:39 +00:00
|
|
|
ImGui::PlotHistogram("##Indices",
|
|
|
|
s_TriangleHistory,
|
|
|
|
IM_ARRAYSIZE(s_TriangleHistory),
|
|
|
|
0,
|
|
|
|
nullptr,
|
|
|
|
0.0f,
|
|
|
|
indexHistMax,
|
|
|
|
ImVec2(-1, 50)); // auto-size width, height=50
|
2024-12-25 23:35:38 +00:00
|
|
|
|
2025-01-04 00:32:39 +00:00
|
|
|
if (ImGui::IsItemHovered())
|
|
|
|
{
|
|
|
|
ImGui::BeginTooltip();
|
|
|
|
ImGui::Text("Number of indices being rendered per frame");
|
|
|
|
ImGui::EndTooltip();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::Spacing();
|
2024-12-26 04:00:13 +00:00
|
|
|
ImGui::Separator();
|
2025-01-04 00:32:39 +00:00
|
|
|
ImGui::Spacing();
|
|
|
|
|
|
|
|
// -------------- Asset Count --------------
|
|
|
|
{
|
|
|
|
ImGui::Text("Loaded Assets: ");
|
|
|
|
ImGui::SameLine();
|
|
|
|
ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.4f, 1.0f), "%d", LoadedAssets);
|
|
|
|
}
|
2024-12-26 04:00:13 +00:00
|
|
|
|
2025-01-04 00:32:39 +00:00
|
|
|
ImGui::Spacing();
|
|
|
|
ImGui::Separator();
|
|
|
|
ImGui::Spacing();
|
2024-12-26 04:00:13 +00:00
|
|
|
|
2025-01-04 00:32:39 +00:00
|
|
|
// -------------- Theme Combo Box --------------
|
2024-12-26 04:00:13 +00:00
|
|
|
{
|
2025-01-04 00:32:39 +00:00
|
|
|
const char* options[] = {"Bootstrap", "Duck Red", "Windark", "Deep Dark", "Tesseract Black"};
|
|
|
|
static int current_option = -1;
|
|
|
|
const char* preview_value = (current_option >= 0 && current_option < IM_ARRAYSIZE(options))
|
|
|
|
? options[current_option]
|
|
|
|
: "Select an option";
|
|
|
|
|
|
|
|
ImGui::Text("Theme: ");
|
|
|
|
ImGui::SameLine();
|
|
|
|
if (ImGui::BeginCombo("##ThemeCombo", preview_value))
|
2024-12-26 04:00:13 +00:00
|
|
|
{
|
2025-01-04 00:32:39 +00:00
|
|
|
for (int n = 0; n < IM_ARRAYSIZE(options); n++)
|
2024-12-26 04:00:13 +00:00
|
|
|
{
|
2025-01-04 00:32:39 +00:00
|
|
|
bool is_selected = (current_option == n);
|
|
|
|
if (ImGui::Selectable(options[n], is_selected))
|
|
|
|
{
|
|
|
|
current_option = n;
|
|
|
|
// Switch theme
|
|
|
|
ThemeManager_ChangeTheme(n);
|
|
|
|
}
|
|
|
|
if (is_selected)
|
|
|
|
ImGui::SetItemDefaultFocus();
|
2024-12-26 04:00:13 +00:00
|
|
|
}
|
2025-01-04 00:32:39 +00:00
|
|
|
ImGui::EndCombo();
|
2024-12-26 04:00:13 +00:00
|
|
|
}
|
|
|
|
}
|
2025-01-04 00:32:39 +00:00
|
|
|
|
|
|
|
ImGui::Spacing();
|
|
|
|
|
|
|
|
// -------------- Polygon Mode Combo Box --------------
|
2024-12-27 06:09:43 +00:00
|
|
|
{
|
2025-01-04 00:32:39 +00:00
|
|
|
ImGui::Text("Polygon Mode: ");
|
|
|
|
ImGui::SameLine();
|
|
|
|
if (ImGui::Combo("##PolygonMode", &polygonMode, polygonModeOptions, IM_ARRAYSIZE(polygonModeOptions)))
|
2024-12-27 06:09:43 +00:00
|
|
|
{
|
2025-01-04 00:32:39 +00:00
|
|
|
switch (polygonMode)
|
|
|
|
{
|
|
|
|
case 0: // Fill
|
|
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
|
|
break;
|
|
|
|
case 1: // Wireframe
|
|
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
|
|
|
break;
|
|
|
|
case 2: // Points
|
|
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
|
|
break;
|
|
|
|
}
|
2024-12-27 06:09:43 +00:00
|
|
|
}
|
|
|
|
}
|
2024-12-26 04:00:13 +00:00
|
|
|
|
2025-01-04 00:32:39 +00:00
|
|
|
ImGui::End(); // End of "Performance##performance"
|
2024-12-26 04:00:13 +00:00
|
|
|
|
2025-01-04 00:32:39 +00:00
|
|
|
// Pop the style var
|
2024-12-25 23:01:05 +00:00
|
|
|
ImGui::PopStyleVar();
|
2024-12-25 21:44:33 +00:00
|
|
|
}
|