diff --git a/include/Engine/Common.h b/include/Engine/Common.h index 7d6f520d..8038b8af 100644 --- a/include/Engine/Common.h +++ b/include/Engine/Common.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "Core/Util/Logging.h" #include "Core/Util/IfDebug.h" \ No newline at end of file diff --git a/include/Engine/Editor/EditorStats.h b/include/Engine/Editor/EditorStats.h new file mode 100644 index 00000000..5dfa5378 --- /dev/null +++ b/include/Engine/Editor/EditorStats.h @@ -0,0 +1,29 @@ +#include +#include +#include +#include "../Common.h" +#include "../GLM.h" +#include "../OpenGL.h" + +class EditorStats +{ +public: + EditorStats(); + void Draw(double dt); + +private: + // FPS graph + const unsigned int m_SampleSize = 100; + unsigned int m_FrameCount = 0; + std::vector m_FrameTimes; + double m_TimeAccumulator = 0.0; + double m_AveragedSamplesPerSecond = 10.0; + const unsigned int m_AveragedSampleSize = 100; + unsigned int m_CurrentAveragedSampleIndex = 0; + std::vector m_AveragedSamples; + void drawFPSGraph(double dt); + + void drawRAMUsage(double dt); + + void drawVRAMStats(double dt); +}; diff --git a/include/Engine/Editor/EditorSystem.h b/include/Engine/Editor/EditorSystem.h index 7b908872..ae3502c3 100644 --- a/include/Engine/Editor/EditorSystem.h +++ b/include/Engine/Editor/EditorSystem.h @@ -9,6 +9,7 @@ #include "../Core/EntityFilePreprocessor.h" #include "../Core/EntityFileParser.h" #include "EditorGUI.h" +#include "EditorStats.h" class EditorSystem : public ImpureSystem { @@ -28,6 +29,7 @@ private: EntityWrapper m_Camera = EntityWrapper::Invalid; DebugCameraInputController* m_DebugCameraInputController; EditorGUI* m_EditorGUI; + EditorStats* m_EditorStats; void OnEntitySelected(EntityWrapper entity); }; \ No newline at end of file diff --git a/src/Engine/Editor/EditorStats.cpp b/src/Engine/Editor/EditorStats.cpp new file mode 100644 index 00000000..a626c442 --- /dev/null +++ b/src/Engine/Editor/EditorStats.cpp @@ -0,0 +1,115 @@ +#include "Editor/EditorStats.h" +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#include +#include +#endif +#include + +EditorStats::EditorStats() +{ + m_AveragedSamples.push_back(0.0); + m_CurrentAveragedSampleIndex = 1; +} + +void EditorStats::Draw(double dt) +{ + if (ImGui::Begin("Stats")) { + drawFPSGraph(dt); + drawRAMUsage(dt); + drawVRAMStats(dt); + } + ImGui::End(); +} + +void EditorStats::drawFPSGraph(double dt) +{ + if (m_FrameCount < m_SampleSize) { + m_FrameTimes.push_back(dt); + } else { + m_FrameTimes[m_FrameCount % m_SampleSize] = dt; + } + m_FrameCount++; + + double average = 0.0; + double max = 0.0; + for (double t : m_FrameTimes) { + average += t; + max = std::max(max, t); + } + average /= m_FrameTimes.size(); + + m_TimeAccumulator += dt; + if (m_TimeAccumulator >= 1.0/m_AveragedSamplesPerSecond) { + if (m_CurrentAveragedSampleIndex < m_AveragedSampleSize) { + m_AveragedSamples.push_back(1.0/average); + } else { + m_AveragedSamples[m_CurrentAveragedSampleIndex % m_AveragedSampleSize] = 1.0/average; + } + m_CurrentAveragedSampleIndex++; + m_TimeAccumulator = 0.0; + } + + float maxFPS = 0.f; + ImVector values; + int values_offset = m_CurrentAveragedSampleIndex % m_AveragedSampleSize; + for (double d : m_AveragedSamples) { + values.push_back(static_cast(d)); + maxFPS = std::max(maxFPS, static_cast(d)); + } + std::stringstream header; + header << std::round(1.0/average) << " FPS (" << std::setprecision(5) << average << " ms)"; + ImGui::PlotLines("##FPSGraph", values.Data, values.Size, values_offset, header.str().c_str(), 0.f, maxFPS + maxFPS/5.f, ImVec2(0, 100)); +} + +void EditorStats::drawRAMUsage(double dt) +{ +#ifdef WIN32 + PROCESS_MEMORY_COUNTERS_EX ppm; + GetProcessMemoryInfo(GetCurrentProcess(), (PPROCESS_MEMORY_COUNTERS)&ppm, sizeof(ppm)); + float megabytes = ppm.WorkingSetSize / (float)std::pow(1024, 2); + ImGui::Text("Memory: ~%f MiB", megabytes); +#endif +} + +void EditorStats::drawVRAMStats(double dt) +{ + //const unsigned int GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX = 0x9049; + //const unsigned int GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX = 0x9048; + //glm::ivec4 total; + //glGetIntegerv(GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, glm::value_ptr(total)); + //if (glGetError() == GL_NO_ERROR) { + // glm::ivec4 available; + // glGetIntegerv(GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, glm::value_ptr(available)); + // float megabytes = (total.x - available.x) / 1024.f; // NVidia returns in KiB + // ImGui::Text("VRAM: %f", megabytes); + //} + + //GLuint uNoOfGPUs = wglGetGPUIDsAMD(0, 0); + //if (!GLERROR("")) { + // GLuint* uGPUIDs = new GLuint[uNoOfGPUs]; + // wglGetGPUIDsAMD(uNoOfGPUs, uGPUIDs); + // GLuint uTotalMemoryInMB = 0; + // wglGetGPUInfoAMD(uGPUIDs[0], + // WGL_GPU_RAM_AMD, + // GL_UNSIGNED_INT, + // sizeof(GLuint), + // &uTotalMemoryInMB); + // GLint nCurAvailMemoryInKB[4]; + // glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, + // &nCurAvailMemoryInKB[0]); + // float usedTexture = (nCurAvailMemoryInKB[0] / 1024.f); + // glGetIntegerv(GL_VBO_FREE_MEMORY_ATI, + // &nCurAvailMemoryInKB[0]); + // float usedVBO = (nCurAvailMemoryInKB[0] / 1024.f); + // glGetIntegerv(GL_RENDERBUFFER_FREE_MEMORY_ATI, + // &nCurAvailMemoryInKB[0]); + // float usedFB = (nCurAvailMemoryInKB[0] / 1024.f); + // ImGui::Text("VRAM: %f MiB ", (float)uTotalMemoryInMB - usedTexture - usedVBO - usedFB); + // ImGui::Text(" Texture: %f MiB", usedTexture); + // ImGui::Text(" VBO: %f MiB", usedVBO); + // ImGui::Text(" Framebuffer: %f MiB", usedFB); + // delete[] uGPUIDs; + //} +} diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index 2d0a4b55..0a96ab9b 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -27,6 +27,8 @@ EditorSystem::EditorSystem(EventBroker* eventBroker, IRenderer* renderer, Render m_EditorGUI = new EditorGUI(m_EventBroker); m_EditorGUI->SetEntitySelectedCallback(std::bind(&EditorSystem::OnEntitySelected, this, std::placeholders::_1)); + m_EditorStats = new EditorStats(); + Events::SetCamera e; e.CameraEntity = m_Camera; m_EventBroker->Publish(e); @@ -34,6 +36,7 @@ EditorSystem::EditorSystem(EventBroker* eventBroker, IRenderer* renderer, Render EditorSystem::~EditorSystem() { + delete m_EditorStats; delete m_EditorGUI; delete m_DebugCameraInputController; delete m_EditorWorldSystemPipeline; @@ -45,6 +48,7 @@ void EditorSystem::Update(World* world, double dt) m_EditorWorldSystemPipeline->Update(m_EditorWorld, dt); m_EditorGUI->Draw(world); + m_EditorStats->Draw(dt); m_DebugCameraInputController->Update(dt); m_Camera["Transform"]["Position"] = m_DebugCameraInputController->Position();