From 41edc4e45fffb14a674ac999f62ada96685a7936 Mon Sep 17 00:00:00 2001 From: Vladyslav Baranovskyi Date: Tue, 11 Jun 2024 14:02:08 +0300 Subject: [PATCH 01/14] Added PrettyBytes function to Utils class --- openVulkanoCpp/Base/Utils.cpp | 42 +++++++++++++++++++++++++++++++++++ openVulkanoCpp/Base/Utils.hpp | 1 + 2 files changed, 43 insertions(+) diff --git a/openVulkanoCpp/Base/Utils.cpp b/openVulkanoCpp/Base/Utils.cpp index 95c2ca7..57533e3 100644 --- a/openVulkanoCpp/Base/Utils.cpp +++ b/openVulkanoCpp/Base/Utils.cpp @@ -74,4 +74,46 @@ namespace OpenVulkano file.close(); return data; } + + std::string Utils::PrettyBytes(uint64_t bytes) + { + static const uint64_t TERABYTES = 1024ULL*1024*1024*1024; + static const uint64_t GIGABYTES = 1024ULL*1024*1024; + static const uint64_t MEGABYTES = 1024*1024; + static const uint64_t KILOBYTES = 1024; + + int TB, GB, MB, KB; + TB = bytes / TERABYTES; + bytes -= TB * TERABYTES; + GB = bytes / GIGABYTES; + bytes -= GB * GIGABYTES; + MB = bytes / MEGABYTES; + bytes -= MB * MEGABYTES; + KB = bytes / KILOBYTES; + bytes -= KB * KILOBYTES; + + std::string result; + if(TB) + { + result = std::to_string(TB) + " TB"; + } + else if(GB) + { + result = std::to_string(GB) + " GB"; + } + else if(MB) + { + result = std::to_string(MB) + " MB"; + } + else if(KB) + { + result = std::to_string(KB) + " KB"; + } + else + { + result = std::to_string(bytes) + " B"; + } + + return result; + } } diff --git a/openVulkanoCpp/Base/Utils.hpp b/openVulkanoCpp/Base/Utils.hpp index 34fc5dc..0f6c499 100644 --- a/openVulkanoCpp/Base/Utils.hpp +++ b/openVulkanoCpp/Base/Utils.hpp @@ -138,5 +138,6 @@ namespace OpenVulkano } static Array ReadFile(const std::string& filePath, bool emptyOnMissing = false); + static std::string PrettyBytes(uint64_t bytes); }; } From ecb7b99f27302188d853f09058bb94530697ada3 Mon Sep 17 00:00:00 2001 From: Vladyslav Baranovskyi Date: Tue, 11 Jun 2024 14:03:13 +0300 Subject: [PATCH 02/14] Added PreformanceOverlayUiElement class --- .../Scene/UI/PerformanceOverlayUiElement.cpp | 101 ++++++++++++++++++ .../Scene/UI/PerformanceOverlayUiElement.hpp | 31 ++++++ 2 files changed, 132 insertions(+) create mode 100644 openVulkanoCpp/Scene/UI/PerformanceOverlayUiElement.cpp create mode 100644 openVulkanoCpp/Scene/UI/PerformanceOverlayUiElement.hpp diff --git a/openVulkanoCpp/Scene/UI/PerformanceOverlayUiElement.cpp b/openVulkanoCpp/Scene/UI/PerformanceOverlayUiElement.cpp new file mode 100644 index 0000000..67da856 --- /dev/null +++ b/openVulkanoCpp/Scene/UI/PerformanceOverlayUiElement.cpp @@ -0,0 +1,101 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include "Scene/Ui/PerformanceOverlayUiElement.hpp" +#include "Base/FrameMetadata.hpp" +#include "Base/Utils.hpp" +#include "Host/SystemInfo.hpp" +#include "Math/ByteSize.hpp" + +#include + +namespace OpenVulkano::Scene::UI +{ + namespace + { + float FloatValuesGetter(void *data, int index) + { + auto queue = reinterpret_cast *>(data); + return (*queue)[index]; + } + + float FPSValuesGetter(void *data, int index) + { + auto queue = reinterpret_cast *>(data); + float value = (*queue)[index]; + if(value != 0) + return 1 / value; + else + return 0; + } + + float RamValuesGetter(void *data, int index) + { + auto queue = reinterpret_cast *>(data); + float used = (*queue)[index]; + float max = SystemInfo::GetAppRamMax(); + float percentage = used / max * 100; + return percentage; + } + } + + void PerformanceOverlayUiElement::UpdateQueues() + { + m_frameTimes.push_back(static_cast(CURRENT_FRAME.frameTime)); + while(m_frameTimes.size() > m_frameCount) + m_frameTimes.pop_front(); + + m_ramUsed.push_back(static_cast(SystemInfo::GetAppRamUsed())); + while(m_ramUsed.size() > m_ramUsageCount) + m_ramUsed.pop_front(); + } + + void PerformanceOverlayUiElement::Init() + { + } + + void PerformanceOverlayUiElement::BeginDraw() + { + bool alwaysShow = true; + ImGui::Begin("Debug Info", &alwaysShow); + } + + void PerformanceOverlayUiElement::Draw() + { + UpdateQueues(); + + ImVec2 availableSize = ImGui::GetContentRegionAvail(); + availableSize.y *= 1/3.; + if(ImGui::CollapsingHeader("Frame Times/FPS")) + { + ImGui::Text("Last Frame Time: %f s", m_frameTimes.back()); + ImGui::SliderInt("Window Size", &m_frameCount, 10, 1000); + ImGui::PlotLines("", &FloatValuesGetter, &m_frameTimes, (int)m_frameTimes.size(), 0, nullptr, FLT_MAX, FLT_MAX, availableSize); + + ImGui::Text("Last FPS: %f", 1 / m_frameTimes.back()); + ImGui::PlotLines("", &FPSValuesGetter, &m_frameTimes, (int)m_frameTimes.size(), 0, nullptr, FLT_MAX, FLT_MAX, availableSize); + } + + if(ImGui::CollapsingHeader("RAM Usage")) + { + // NOTE(vb) used and max return unexpected values - used is bigger than max... Is it intended to do so? + std::string used = Utils::PrettyBytes(SystemInfo::GetAppRamUsed()); + std::string max = Utils::PrettyBytes(SystemInfo::GetAppRamMax()); + std::string avail = Utils::PrettyBytes(SystemInfo::GetAppRamAvailable()); + ImGui::Text("RAM: %s / %s, Free: %s", used.c_str(), max.c_str(), avail.c_str()); + + ImGui::SliderInt("Window Size", &m_ramUsageCount, 10, 1000); + float scaleMin = 0.01; + float scaleMax = 100; + ImGui::PlotLines("", &RamValuesGetter, &m_ramUsed, (int)m_ramUsed.size(), 0, nullptr, scaleMin, scaleMax, availableSize); + } + } + + void PerformanceOverlayUiElement::EndDraw() + { + ImGui::End(); + } +} \ No newline at end of file diff --git a/openVulkanoCpp/Scene/UI/PerformanceOverlayUiElement.hpp b/openVulkanoCpp/Scene/UI/PerformanceOverlayUiElement.hpp new file mode 100644 index 0000000..4af33e5 --- /dev/null +++ b/openVulkanoCpp/Scene/UI/PerformanceOverlayUiElement.hpp @@ -0,0 +1,31 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include "Scene/Ui/Ui.hpp" + +#include + +namespace OpenVulkano::Scene::UI +{ + class PerformanceOverlayUiElement : public Ui + { + int m_frameCount = 200; + std::deque m_frameTimes; + + int m_ramUsageCount = 200; + std::deque m_ramUsed; + + void UpdateQueues(); + + protected: + void Init() override; + void BeginDraw() override; + void Draw() override; + void EndDraw() override; + }; +} From 14aba25ef776613a3ee21900751633dd4db5f5d7 Mon Sep 17 00:00:00 2001 From: Vladyslav Baranovskyi Date: Tue, 11 Jun 2024 14:03:37 +0300 Subject: [PATCH 03/14] Using PerformanceOverlayUiElement in example apps --- examples/ExampleApps/CubesExampleApp.cpp | 4 ++++ examples/ExampleApps/MovingCubeApp.cpp | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/examples/ExampleApps/CubesExampleApp.cpp b/examples/ExampleApps/CubesExampleApp.cpp index bb1b615..175bb99 100644 --- a/examples/ExampleApps/CubesExampleApp.cpp +++ b/examples/ExampleApps/CubesExampleApp.cpp @@ -11,6 +11,7 @@ #include "Scene/Material.hpp" #include "Scene/Vertex.hpp" #include "Scene/SimpleDrawable.hpp" +#include "Scene/UI/PerformanceOverlayUiElement.hpp" #include "Input/InputManager.hpp" #include "Host/GraphicsAppManager.hpp" #include "Math/Math.hpp" @@ -40,6 +41,7 @@ namespace OpenVulkano std::vector drawablesPool; std::vector nodesPool; Vector3f_SIMD position = {0, 0, -10}; + OpenVulkano::Scene::UI::PerformanceOverlayUiElement m_ui; public: void Init() override @@ -78,6 +80,8 @@ namespace OpenVulkano camController.Init(&cam); camController.SetDefaultKeybindings(); + + GetGraphicsAppManager()->GetRenderer()->SetActiveUi(&m_ui); } void Tick() override diff --git a/examples/ExampleApps/MovingCubeApp.cpp b/examples/ExampleApps/MovingCubeApp.cpp index 472583e..2c9eb6e 100644 --- a/examples/ExampleApps/MovingCubeApp.cpp +++ b/examples/ExampleApps/MovingCubeApp.cpp @@ -15,6 +15,7 @@ #include "Scene/Camera.hpp" #include "Scene/SimpleAnimationController.hpp" #include "Scene/SequenceAnimationController.hpp" +#include "Scene/UI/PerformanceOverlayUiElement.hpp" #include "Input/InputManager.hpp" #include "Host/GraphicsAppManager.hpp" #include "Base/EngineConfiguration.hpp" @@ -46,6 +47,8 @@ namespace OpenVulkano SceneElement m_whiteBox; SceneElement m_redBox; + Scene::UI::PerformanceOverlayUiElement m_ui; + void CreateSceneElement(SceneElement *dest, const Math::Vector4f &color, float scale) { dest->m_geometry.InitCube(scale, scale, scale, color); @@ -95,6 +98,8 @@ namespace OpenVulkano m_sequenceAnimationController.AddAnimationStep(Math::PoseF(Math::Utils::normalize(Math::QuaternionF(3, 2, 1, 1)), Math::Vector3f_SIMD(1, 1, -1)), 3); m_sequenceAnimationController.AddAnimationStep(Math::PoseF(Math::Utils::normalize(Math::QuaternionF(0, 0, 1, 1)), Math::Vector3f_SIMD(0, 1, 0)), 1); m_sequenceAnimationController.SetAnimationPoseResetTime(10); + + GetGraphicsAppManager()->GetRenderer()->SetActiveUi(&m_ui); } void OnSimpleAnimationCompleted(Scene::SimpleAnimationController *anim) From 8be512e1624bb92796d380678d8745058a56212b Mon Sep 17 00:00:00 2001 From: Vladyslav Baranovskyi Date: Tue, 11 Jun 2024 18:43:13 +0300 Subject: [PATCH 04/14] Added SimpleUi class that inherits from Ui --- openVulkanoCpp/Scene/UI/UI.hpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/openVulkanoCpp/Scene/UI/UI.hpp b/openVulkanoCpp/Scene/UI/UI.hpp index 09e8560..b09d64f 100644 --- a/openVulkanoCpp/Scene/UI/UI.hpp +++ b/openVulkanoCpp/Scene/UI/UI.hpp @@ -50,4 +50,15 @@ namespace OpenVulkano::Scene::UI void Draw() override {} }; + + class SimpleUi : public Ui + { + public: + void Init() override {} + + void AddElement(const std::shared_ptr& element) + { + children.push_back(element); + } + }; } From 91a44eaee08f949ee953eef167722889df2aa084 Mon Sep 17 00:00:00 2001 From: Vladyslav Baranovskyi Date: Tue, 11 Jun 2024 18:43:29 +0300 Subject: [PATCH 05/14] Removed PrettyBytes function --- openVulkanoCpp/Base/Utils.cpp | 42 ----------------------------------- openVulkanoCpp/Base/Utils.hpp | 1 - 2 files changed, 43 deletions(-) diff --git a/openVulkanoCpp/Base/Utils.cpp b/openVulkanoCpp/Base/Utils.cpp index 57533e3..95c2ca7 100644 --- a/openVulkanoCpp/Base/Utils.cpp +++ b/openVulkanoCpp/Base/Utils.cpp @@ -74,46 +74,4 @@ namespace OpenVulkano file.close(); return data; } - - std::string Utils::PrettyBytes(uint64_t bytes) - { - static const uint64_t TERABYTES = 1024ULL*1024*1024*1024; - static const uint64_t GIGABYTES = 1024ULL*1024*1024; - static const uint64_t MEGABYTES = 1024*1024; - static const uint64_t KILOBYTES = 1024; - - int TB, GB, MB, KB; - TB = bytes / TERABYTES; - bytes -= TB * TERABYTES; - GB = bytes / GIGABYTES; - bytes -= GB * GIGABYTES; - MB = bytes / MEGABYTES; - bytes -= MB * MEGABYTES; - KB = bytes / KILOBYTES; - bytes -= KB * KILOBYTES; - - std::string result; - if(TB) - { - result = std::to_string(TB) + " TB"; - } - else if(GB) - { - result = std::to_string(GB) + " GB"; - } - else if(MB) - { - result = std::to_string(MB) + " MB"; - } - else if(KB) - { - result = std::to_string(KB) + " KB"; - } - else - { - result = std::to_string(bytes) + " B"; - } - - return result; - } } diff --git a/openVulkanoCpp/Base/Utils.hpp b/openVulkanoCpp/Base/Utils.hpp index 0f6c499..34fc5dc 100644 --- a/openVulkanoCpp/Base/Utils.hpp +++ b/openVulkanoCpp/Base/Utils.hpp @@ -138,6 +138,5 @@ namespace OpenVulkano } static Array ReadFile(const std::string& filePath, bool emptyOnMissing = false); - static std::string PrettyBytes(uint64_t bytes); }; } From 91b9da6aa66cde23111e109b9f845f1047b4c9af Mon Sep 17 00:00:00 2001 From: Vladyslav Baranovskyi Date: Tue, 11 Jun 2024 18:43:49 +0300 Subject: [PATCH 06/14] Fixed bug in TextFmt() on windows --- openVulkanoCpp/Scene/UI/ImGuiExtensions/ImGuiTextFmt.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openVulkanoCpp/Scene/UI/ImGuiExtensions/ImGuiTextFmt.hpp b/openVulkanoCpp/Scene/UI/ImGuiExtensions/ImGuiTextFmt.hpp index a209ae8..b628ef4 100644 --- a/openVulkanoCpp/Scene/UI/ImGuiExtensions/ImGuiTextFmt.hpp +++ b/openVulkanoCpp/Scene/UI/ImGuiExtensions/ImGuiTextFmt.hpp @@ -22,6 +22,6 @@ namespace ImGui template IMGUI_API void TextFmt(T&& fmt, const Args &... args) { std::string str = fmt::format(std::forward(fmt), args...); - ImGui::TextUnformatted(&*str.begin(), &*str.end()); + ImGui::TextUnformatted(str.data(), str.data() + str.size()); } } \ No newline at end of file From 938495ab81a4bc6e9a894151aa4a56dc98eb68bd Mon Sep 17 00:00:00 2001 From: Vladyslav Baranovskyi Date: Tue, 11 Jun 2024 18:44:51 +0300 Subject: [PATCH 07/14] Fixed issue where on windows GetAppRamMax() returned less values than GetAppRamAvailable() --- openVulkanoCpp/Host/Windows/SystemInfo.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/openVulkanoCpp/Host/Windows/SystemInfo.cpp b/openVulkanoCpp/Host/Windows/SystemInfo.cpp index 49a5c70..6457544 100644 --- a/openVulkanoCpp/Host/Windows/SystemInfo.cpp +++ b/openVulkanoCpp/Host/Windows/SystemInfo.cpp @@ -48,13 +48,25 @@ namespace OpenVulkano { switch(type) { - case APP_MEM_TYPE::VM_MAX: return counters.PeakWorkingSetSize; + case APP_MEM_TYPE::VM_MAX: return counters.PeakPagefileUsage; case APP_MEM_TYPE::USED: return counters.PrivateUsage; } } Logger::PERF->error("Failed to get process memory info"); return 0; } + + size_t GetCommitLimit() + { + MEMORYSTATUSEX status; + status.dwLength = sizeof(status); + if(GlobalMemoryStatusEx(&status)) + { + return status.ullTotalPageFile; + } + Logger::PERF->error("Failed to get system commit limit"); + return 0; + } } size_t SystemInfo::GetSystemRam() @@ -69,12 +81,12 @@ namespace OpenVulkano size_t SystemInfo::GetAppRamMax() { - return std::min(GetSystemRam(), GetAppVirtualMemoryMax()); + return std::min(GetSystemRam(), GetCommitLimit()); } size_t SystemInfo::GetAppRamAvailable() { - return std::min(GetSystemRamAvailable(), GetAppVirtualMemoryMax() - GetAppRamUsed()); + return std::min(GetSystemRamAvailable(), GetCommitLimit() - GetAppRamUsed()); } size_t SystemInfo::GetAppRamUsed() From f6299b054fb45737d39f58f3d6ab4c6a84e81454 Mon Sep 17 00:00:00 2001 From: Vladyslav Baranovskyi Date: Tue, 11 Jun 2024 18:45:47 +0300 Subject: [PATCH 08/14] Renamed file from PerformanceOverlayUiElement to PerformanceInfo --- ...erlayUiElement.cpp => PerformanceInfo.cpp} | 45 +++++-------------- ...erlayUiElement.hpp => PerformanceInfo.hpp} | 5 +-- 2 files changed, 14 insertions(+), 36 deletions(-) rename openVulkanoCpp/Scene/UI/{PerformanceOverlayUiElement.cpp => PerformanceInfo.cpp} (51%) rename openVulkanoCpp/Scene/UI/{PerformanceOverlayUiElement.hpp => PerformanceInfo.hpp} (84%) diff --git a/openVulkanoCpp/Scene/UI/PerformanceOverlayUiElement.cpp b/openVulkanoCpp/Scene/UI/PerformanceInfo.cpp similarity index 51% rename from openVulkanoCpp/Scene/UI/PerformanceOverlayUiElement.cpp rename to openVulkanoCpp/Scene/UI/PerformanceInfo.cpp index 67da856..3ef15aa 100644 --- a/openVulkanoCpp/Scene/UI/PerformanceOverlayUiElement.cpp +++ b/openVulkanoCpp/Scene/UI/PerformanceInfo.cpp @@ -4,11 +4,12 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -#include "Scene/Ui/PerformanceOverlayUiElement.hpp" +#include "PerformanceInfo.hpp" #include "Base/FrameMetadata.hpp" #include "Base/Utils.hpp" #include "Host/SystemInfo.hpp" #include "Math/ByteSize.hpp" +#include "ImGuiExtensions/ImGuiTextFmt.hpp" #include @@ -22,16 +23,6 @@ namespace OpenVulkano::Scene::UI return (*queue)[index]; } - float FPSValuesGetter(void *data, int index) - { - auto queue = reinterpret_cast *>(data); - float value = (*queue)[index]; - if(value != 0) - return 1 / value; - else - return 0; - } - float RamValuesGetter(void *data, int index) { auto queue = reinterpret_cast *>(data); @@ -42,7 +33,7 @@ namespace OpenVulkano::Scene::UI } } - void PerformanceOverlayUiElement::UpdateQueues() + void PerformanceInfo::UpdateQueues() { m_frameTimes.push_back(static_cast(CURRENT_FRAME.frameTime)); while(m_frameTimes.size() > m_frameCount) @@ -53,48 +44,36 @@ namespace OpenVulkano::Scene::UI m_ramUsed.pop_front(); } - void PerformanceOverlayUiElement::Init() - { - } - - void PerformanceOverlayUiElement::BeginDraw() + void PerformanceInfo::BeginDraw() { bool alwaysShow = true; ImGui::Begin("Debug Info", &alwaysShow); } - void PerformanceOverlayUiElement::Draw() + void PerformanceInfo::Draw() { UpdateQueues(); ImVec2 availableSize = ImGui::GetContentRegionAvail(); availableSize.y *= 1/3.; - if(ImGui::CollapsingHeader("Frame Times/FPS")) - { - ImGui::Text("Last Frame Time: %f s", m_frameTimes.back()); - ImGui::SliderInt("Window Size", &m_frameCount, 10, 1000); - ImGui::PlotLines("", &FloatValuesGetter, &m_frameTimes, (int)m_frameTimes.size(), 0, nullptr, FLT_MAX, FLT_MAX, availableSize); - ImGui::Text("Last FPS: %f", 1 / m_frameTimes.back()); - ImGui::PlotLines("", &FPSValuesGetter, &m_frameTimes, (int)m_frameTimes.size(), 0, nullptr, FLT_MAX, FLT_MAX, availableSize); - } + ImGui::Text("Last Frame Time: %f s", m_frameTimes.back()); + ImGui::Text("Last FPS: %f", 1 / m_frameTimes.back()); + ImGui::SliderInt("Window Size", &m_frameCount, 10, 1000); + ImGui::PlotLines("", &FloatValuesGetter, &m_frameTimes, (int)m_frameTimes.size(), 0, nullptr, FLT_MAX, FLT_MAX, availableSize); if(ImGui::CollapsingHeader("RAM Usage")) { - // NOTE(vb) used and max return unexpected values - used is bigger than max... Is it intended to do so? - std::string used = Utils::PrettyBytes(SystemInfo::GetAppRamUsed()); - std::string max = Utils::PrettyBytes(SystemInfo::GetAppRamMax()); - std::string avail = Utils::PrettyBytes(SystemInfo::GetAppRamAvailable()); - ImGui::Text("RAM: %s / %s, Free: %s", used.c_str(), max.c_str(), avail.c_str()); + ImGui::TextFmt("RAM: {} / {}, Free: {}", ByteSize(m_ramUsed.back()), ByteSize(SystemInfo::GetAppRamMax()), ByteSize(SystemInfo::GetAppRamAvailable())); - ImGui::SliderInt("Window Size", &m_ramUsageCount, 10, 1000); + ImGui::SliderInt("Window Size ", &m_ramUsageCount, 10, 1000); float scaleMin = 0.01; float scaleMax = 100; ImGui::PlotLines("", &RamValuesGetter, &m_ramUsed, (int)m_ramUsed.size(), 0, nullptr, scaleMin, scaleMax, availableSize); } } - void PerformanceOverlayUiElement::EndDraw() + void PerformanceInfo::EndDraw() { ImGui::End(); } diff --git a/openVulkanoCpp/Scene/UI/PerformanceOverlayUiElement.hpp b/openVulkanoCpp/Scene/UI/PerformanceInfo.hpp similarity index 84% rename from openVulkanoCpp/Scene/UI/PerformanceOverlayUiElement.hpp rename to openVulkanoCpp/Scene/UI/PerformanceInfo.hpp index 4af33e5..2a5bf0a 100644 --- a/openVulkanoCpp/Scene/UI/PerformanceOverlayUiElement.hpp +++ b/openVulkanoCpp/Scene/UI/PerformanceInfo.hpp @@ -6,13 +6,13 @@ #pragma once -#include "Scene/Ui/Ui.hpp" +#include "Ui.hpp" #include namespace OpenVulkano::Scene::UI { - class PerformanceOverlayUiElement : public Ui + class PerformanceInfo : public UiElement { int m_frameCount = 200; std::deque m_frameTimes; @@ -23,7 +23,6 @@ namespace OpenVulkano::Scene::UI void UpdateQueues(); protected: - void Init() override; void BeginDraw() override; void Draw() override; void EndDraw() override; From efd271e56022f9070bf64bfbd39c958dcbf040e4 Mon Sep 17 00:00:00 2001 From: Vladyslav Baranovskyi Date: Tue, 11 Jun 2024 18:46:15 +0300 Subject: [PATCH 09/14] Using Scene::Ui::PerformanceInfo properly --- examples/ExampleApps/CubesExampleApp.cpp | 8 ++++++-- examples/ExampleApps/MovingCubeApp.cpp | 7 +++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/examples/ExampleApps/CubesExampleApp.cpp b/examples/ExampleApps/CubesExampleApp.cpp index 175bb99..2ef7aba 100644 --- a/examples/ExampleApps/CubesExampleApp.cpp +++ b/examples/ExampleApps/CubesExampleApp.cpp @@ -11,7 +11,7 @@ #include "Scene/Material.hpp" #include "Scene/Vertex.hpp" #include "Scene/SimpleDrawable.hpp" -#include "Scene/UI/PerformanceOverlayUiElement.hpp" +#include "Scene/UI/PerformanceInfo.hpp" #include "Input/InputManager.hpp" #include "Host/GraphicsAppManager.hpp" #include "Math/Math.hpp" @@ -41,7 +41,9 @@ namespace OpenVulkano std::vector drawablesPool; std::vector nodesPool; Vector3f_SIMD position = {0, 0, -10}; - OpenVulkano::Scene::UI::PerformanceOverlayUiElement m_ui; + + OpenVulkano::Scene::UI::SimpleUi m_ui; + std::shared_ptr m_perfInfo; public: void Init() override @@ -81,6 +83,8 @@ namespace OpenVulkano camController.Init(&cam); camController.SetDefaultKeybindings(); + std::shared_ptr m_perfInfo = std::make_shared(); + m_ui.AddElement(m_perfInfo); GetGraphicsAppManager()->GetRenderer()->SetActiveUi(&m_ui); } diff --git a/examples/ExampleApps/MovingCubeApp.cpp b/examples/ExampleApps/MovingCubeApp.cpp index 2c9eb6e..317883d 100644 --- a/examples/ExampleApps/MovingCubeApp.cpp +++ b/examples/ExampleApps/MovingCubeApp.cpp @@ -15,7 +15,7 @@ #include "Scene/Camera.hpp" #include "Scene/SimpleAnimationController.hpp" #include "Scene/SequenceAnimationController.hpp" -#include "Scene/UI/PerformanceOverlayUiElement.hpp" +#include "Scene/UI/PerformanceInfo.hpp" #include "Input/InputManager.hpp" #include "Host/GraphicsAppManager.hpp" #include "Base/EngineConfiguration.hpp" @@ -47,7 +47,8 @@ namespace OpenVulkano SceneElement m_whiteBox; SceneElement m_redBox; - Scene::UI::PerformanceOverlayUiElement m_ui; + Scene::UI::SimpleUi m_ui; + std::shared_ptr m_perfInfo; void CreateSceneElement(SceneElement *dest, const Math::Vector4f &color, float scale) { @@ -99,6 +100,8 @@ namespace OpenVulkano m_sequenceAnimationController.AddAnimationStep(Math::PoseF(Math::Utils::normalize(Math::QuaternionF(0, 0, 1, 1)), Math::Vector3f_SIMD(0, 1, 0)), 1); m_sequenceAnimationController.SetAnimationPoseResetTime(10); + std::shared_ptr m_perfInfo = std::make_shared(); + m_ui.AddElement(m_perfInfo); GetGraphicsAppManager()->GetRenderer()->SetActiveUi(&m_ui); } From 15d0a6a669b55b964d4a5fa03b7a2d43bc91b8c1 Mon Sep 17 00:00:00 2001 From: Vladyslav Baranovskyi Date: Tue, 11 Jun 2024 19:16:20 +0300 Subject: [PATCH 10/14] Fixed imgui window name, including UI.hpp header properly --- openVulkanoCpp/Scene/UI/PerformanceInfo.cpp | 2 +- openVulkanoCpp/Scene/UI/PerformanceInfo.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openVulkanoCpp/Scene/UI/PerformanceInfo.cpp b/openVulkanoCpp/Scene/UI/PerformanceInfo.cpp index 3ef15aa..37d8684 100644 --- a/openVulkanoCpp/Scene/UI/PerformanceInfo.cpp +++ b/openVulkanoCpp/Scene/UI/PerformanceInfo.cpp @@ -47,7 +47,7 @@ namespace OpenVulkano::Scene::UI void PerformanceInfo::BeginDraw() { bool alwaysShow = true; - ImGui::Begin("Debug Info", &alwaysShow); + ImGui::Begin("Performance Info", &alwaysShow); } void PerformanceInfo::Draw() diff --git a/openVulkanoCpp/Scene/UI/PerformanceInfo.hpp b/openVulkanoCpp/Scene/UI/PerformanceInfo.hpp index 2a5bf0a..3336a74 100644 --- a/openVulkanoCpp/Scene/UI/PerformanceInfo.hpp +++ b/openVulkanoCpp/Scene/UI/PerformanceInfo.hpp @@ -6,7 +6,7 @@ #pragma once -#include "Ui.hpp" +#include "UI.hpp" #include From 93d5ea4291efe1de0c707793101077ba1ce77326 Mon Sep 17 00:00:00 2001 From: Vladyslav Baranovskyi Date: Wed, 12 Jun 2024 18:36:55 +0300 Subject: [PATCH 11/14] ImGui::PlotTwoLines() extension, PerformanceInfo improvements --- .../UI/ImGuiExtensions/ImGuiPlotTwoLines.cpp | 142 ++++++++++++++++++ .../UI/ImGuiExtensions/ImGuiPlotTwoLines.hpp | 17 +++ openVulkanoCpp/Scene/UI/PerformanceInfo.cpp | 57 ++++--- openVulkanoCpp/Scene/UI/PerformanceInfo.hpp | 12 +- 4 files changed, 200 insertions(+), 28 deletions(-) create mode 100644 openVulkanoCpp/Scene/UI/ImGuiExtensions/ImGuiPlotTwoLines.cpp create mode 100644 openVulkanoCpp/Scene/UI/ImGuiExtensions/ImGuiPlotTwoLines.hpp diff --git a/openVulkanoCpp/Scene/UI/ImGuiExtensions/ImGuiPlotTwoLines.cpp b/openVulkanoCpp/Scene/UI/ImGuiExtensions/ImGuiPlotTwoLines.cpp new file mode 100644 index 0000000..bec93d1 --- /dev/null +++ b/openVulkanoCpp/Scene/UI/ImGuiExtensions/ImGuiPlotTwoLines.cpp @@ -0,0 +1,142 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include "ImGuiPlotTwoLines.hpp" + +#include +#include + +namespace ImGui +{ + void PlotTwoLines(const char* label, + float (*getter1)(void* data, int idx), void* data1, const char *tooltipPrefix1, + float (*getter2)(void* data, int idx), void* data2, const char *tooltipPrefix2, + int values_count, float scale_min, float scale_max, ImVec2 graph_size) + { + ImGuiContext& g = *ImGui::GetCurrentContext(); + ImGuiWindow* window = ImGui::GetCurrentWindow(); + if (window->SkipItems) + return; + + const ImGuiStyle& style = g.Style; + + ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true); + if (graph_size.x == 0.0f) + graph_size.x = ImGui::CalcItemWidth(); + if (graph_size.y == 0.0f) + graph_size.y = label_size.y + (style.FramePadding.y * 2); + + ImRect frame_bb(window->DC.CursorPos, ImVec2(window->DC.CursorPos.x + graph_size.x, window->DC.CursorPos.y + graph_size.y)); + ImRect inner_bb(ImVec2(frame_bb.Min.x + style.FramePadding.x, frame_bb.Min.y + style.FramePadding.y), ImVec2(frame_bb.Max.x - style.FramePadding.x, frame_bb.Max.y - style.FramePadding.y)); + ImRect total_bb(frame_bb.Min, ImVec2(frame_bb.Max.x + (label_size.x > 0.0f ? (style.ItemInnerSpacing.x + label_size.x) : 0.0f), frame_bb.Max.y)); + + ImGui::ItemSize(total_bb, style.FramePadding.y); + if (!ImGui::ItemAdd(total_bb, 0)) + return; + + // Determine scale from inputs if not specified + if (scale_min == FLT_MAX || scale_max == FLT_MAX) + { + float v1_min = FLT_MAX, v1_max = -FLT_MAX; + for (int i = 0; i < values_count; i++) + { + float v = getter1(data1, i); + if (v != v) // Ignore NaN values + continue; + v1_min = ImMin(v1_min, v); + v1_max = ImMax(v1_max, v); + } + float v2_min = FLT_MAX, v2_max = -FLT_MAX; + for (int i = 0; i < values_count; i++) + { + float v = getter2(data2, i); + if (v != v) // Ignore NaN values + continue; + v2_min = ImMin(v2_min, v); + v2_max = ImMax(v2_max, v); + } + if (scale_min == FLT_MAX) scale_min = ImMin(v1_min, v2_min); + if (scale_max == FLT_MAX) scale_max = ImMax(v1_max, v2_max); + } + + ImGui::RenderFrame(frame_bb.Min, frame_bb.Max, ImGui::GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); + int res_w = ImMin((int)graph_size.x, values_count); // Number of samples + + if (res_w <= 0) + return; + + // Tooltip on hover + int v_hovered = -1; + if (ImGui::IsItemHovered()) + { + const float t = ImClamp((g.IO.MousePos.x - inner_bb.Min.x) / (inner_bb.Max.x - inner_bb.Min.x), 0.0f, 0.9999f); + const int v_idx = (int)(t * values_count); + IM_ASSERT(v_idx >= 0 && v_idx < values_count); + + const float v0 = getter1(data1, v_idx); + const float v1 = getter2(data2, v_idx); + ImGui::SetTooltip("%d: (%s: %8.4g, %s: %8.4g)", v_idx, tooltipPrefix1, v0, tooltipPrefix2, v1); + v_hovered = v_idx; + } + + const float t_step = 1.0f / res_w; + + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + draw_list->PushClipRect(inner_bb.Min, inner_bb.Max, true); + + ImColor col1 = ImColor(255, 100, 100); + ImColor col2 = ImColor(100, 255, 100); + + // Plot first line + for (int n = 0; n < res_w; n++) + { + const float t0 = t_step * (n + 0); + const float t1 = t_step * (n + 1); + const int v_idx0 = (int)(t0 * values_count); + int v_idx1 = (int)(t1 * values_count); + if(v_idx1 >= values_count) + v_idx1 = values_count - 1; + + IM_ASSERT(v_idx0 >= 0 && v_idx0 < values_count); + IM_ASSERT(v_idx1 >= 0 && v_idx1 < values_count); + + const float v0 = getter1(data1, v_idx0); + const float v1 = getter1(data1, v_idx1); + const float x0 = ImLerp(inner_bb.Min.x, inner_bb.Max.x, t0); + const float x1 = ImLerp(inner_bb.Min.x, inner_bb.Max.x, t1); + const float y0 = ImLerp(inner_bb.Max.y, inner_bb.Min.y, (v0 - scale_min) / (scale_max - scale_min)); + const float y1 = ImLerp(inner_bb.Max.y, inner_bb.Min.y, (v1 - scale_min) / (scale_max - scale_min)); + draw_list->AddLine(ImVec2(x0, y0), ImVec2(x1, y1), col1); + } + + // Plot second line + for (int n = 0; n < res_w; n++) + { + const float t0 = t_step * (n + 0); + const float t1 = t_step * (n + 1); + const int v_idx0 = (int)(t0 * values_count); + int v_idx1 = (int)(t1 * values_count); + if(v_idx1 >= values_count) + v_idx1 = values_count - 1; + + IM_ASSERT(v_idx0 >= 0 && v_idx0 < values_count); + IM_ASSERT(v_idx1 >= 0 && v_idx1 < values_count); + + const float v0 = getter2(data2, v_idx0); + const float v1 = getter2(data2, v_idx1); + const float x0 = ImLerp(inner_bb.Min.x, inner_bb.Max.x, t0); + const float x1 = ImLerp(inner_bb.Min.x, inner_bb.Max.x, t1); + const float y0 = ImLerp(inner_bb.Max.y, inner_bb.Min.y, (v0 - scale_min) / (scale_max - scale_min)); + const float y1 = ImLerp(inner_bb.Max.y, inner_bb.Min.y, (v1 - scale_min) / (scale_max - scale_min)); + draw_list->AddLine(ImVec2(x0, y0), ImVec2(x1, y1), col2); + } + + draw_list->PopClipRect(); + + if (label_size.x > 0.0f) + ImGui::RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label); + } +} \ No newline at end of file diff --git a/openVulkanoCpp/Scene/UI/ImGuiExtensions/ImGuiPlotTwoLines.hpp b/openVulkanoCpp/Scene/UI/ImGuiExtensions/ImGuiPlotTwoLines.hpp new file mode 100644 index 0000000..a4bd497 --- /dev/null +++ b/openVulkanoCpp/Scene/UI/ImGuiExtensions/ImGuiPlotTwoLines.hpp @@ -0,0 +1,17 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +namespace ImGui +{ + void PlotTwoLines(const char* label, + float (*getter1)(void* data, int idx), void* data1, const char *tooltipPrefix1, + float (*getter2)(void* data, int idx), void* data2, const char *tooltipPrefix2, + int values_count, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0)); +} \ No newline at end of file diff --git a/openVulkanoCpp/Scene/UI/PerformanceInfo.cpp b/openVulkanoCpp/Scene/UI/PerformanceInfo.cpp index 37d8684..9a28ddf 100644 --- a/openVulkanoCpp/Scene/UI/PerformanceInfo.cpp +++ b/openVulkanoCpp/Scene/UI/PerformanceInfo.cpp @@ -10,17 +10,20 @@ #include "Host/SystemInfo.hpp" #include "Math/ByteSize.hpp" #include "ImGuiExtensions/ImGuiTextFmt.hpp" +#include "ImGuiExtensions/ImGuiPlotTwoLines.hpp" -#include +#include namespace OpenVulkano::Scene::UI { namespace { - float FloatValuesGetter(void *data, int index) + float FrameCollectionValuesGetter(void *data, int index) { - auto queue = reinterpret_cast *>(data); - return (*queue)[index]; + auto frameCollection = reinterpret_cast(data); + float value = frameCollection->m_frameTimes[index]; + float result = value / frameCollection->m_maxValue * 100; + return result; } float RamValuesGetter(void *data, int index) @@ -31,16 +34,25 @@ namespace OpenVulkano::Scene::UI float percentage = used / max * 100; return percentage; } + } void PerformanceInfo::UpdateQueues() { - m_frameTimes.push_back(static_cast(CURRENT_FRAME.frameTime)); - while(m_frameTimes.size() > m_frameCount) - m_frameTimes.pop_front(); + m_frameCollection.m_frameTimes.push_back(static_cast(CURRENT_FRAME.frameTime)); + while(m_frameCollection.m_frameTimes.size() > m_windowSize) + m_frameCollection.m_frameTimes.pop_front(); + + float maxFrameTime = FLT_MIN; + for(auto value : m_frameCollection.m_frameTimes) + { + if(value > maxFrameTime) + maxFrameTime = value; + } + m_frameCollection.m_maxValue = maxFrameTime; m_ramUsed.push_back(static_cast(SystemInfo::GetAppRamUsed())); - while(m_ramUsed.size() > m_ramUsageCount) + while(m_ramUsed.size() > m_windowSize) m_ramUsed.pop_front(); } @@ -53,24 +65,21 @@ namespace OpenVulkano::Scene::UI void PerformanceInfo::Draw() { UpdateQueues(); + assert(m_frameCollection.m_frameTimes.size() == m_ramUsed.size()); + + ImGui::Text("Last Frame Time(wrt max): %f s", m_frameCollection.m_frameTimes.back()); + ImGui::Text("Last FPS: %f", 1 / m_frameCollection.m_frameTimes.back()); + ImGui::SliderInt("Window Size", &m_windowSize, 10, 1000); + ImGui::TextFmt("RAM: {} / {}, Free: {}", ByteSize(m_ramUsed.back()), ByteSize(SystemInfo::GetAppRamMax()), ByteSize(SystemInfo::GetAppRamAvailable())); ImVec2 availableSize = ImGui::GetContentRegionAvail(); - availableSize.y *= 1/3.; - - ImGui::Text("Last Frame Time: %f s", m_frameTimes.back()); - ImGui::Text("Last FPS: %f", 1 / m_frameTimes.back()); - ImGui::SliderInt("Window Size", &m_frameCount, 10, 1000); - ImGui::PlotLines("", &FloatValuesGetter, &m_frameTimes, (int)m_frameTimes.size(), 0, nullptr, FLT_MAX, FLT_MAX, availableSize); - - if(ImGui::CollapsingHeader("RAM Usage")) - { - ImGui::TextFmt("RAM: {} / {}, Free: {}", ByteSize(m_ramUsed.back()), ByteSize(SystemInfo::GetAppRamMax()), ByteSize(SystemInfo::GetAppRamAvailable())); - - ImGui::SliderInt("Window Size ", &m_ramUsageCount, 10, 1000); - float scaleMin = 0.01; - float scaleMax = 100; - ImGui::PlotLines("", &RamValuesGetter, &m_ramUsed, (int)m_ramUsed.size(), 0, nullptr, scaleMin, scaleMax, availableSize); - } + float scaleMin = 0.01; + float scaleMax = 100; + ImGui::PlotTwoLines("", + &FrameCollectionValuesGetter, &m_frameCollection, "Frame Time", + &RamValuesGetter, &m_ramUsed, "RAM", + (int)m_ramUsed.size(), + scaleMin, scaleMax, availableSize); } void PerformanceInfo::EndDraw() diff --git a/openVulkanoCpp/Scene/UI/PerformanceInfo.hpp b/openVulkanoCpp/Scene/UI/PerformanceInfo.hpp index 3336a74..53afdd7 100644 --- a/openVulkanoCpp/Scene/UI/PerformanceInfo.hpp +++ b/openVulkanoCpp/Scene/UI/PerformanceInfo.hpp @@ -12,13 +12,17 @@ namespace OpenVulkano::Scene::UI { + struct FrameTimeCollection + { + std::deque m_frameTimes; + float m_maxValue; + }; + class PerformanceInfo : public UiElement { - int m_frameCount = 200; - std::deque m_frameTimes; - - int m_ramUsageCount = 200; + int m_windowSize = 200; std::deque m_ramUsed; + FrameTimeCollection m_frameCollection; void UpdateQueues(); From bad6c95c3fbf84e0b6a65dfce6225c32c1abc220 Mon Sep 17 00:00:00 2001 From: Vladyslav Baranovskyi Date: Thu, 13 Jun 2024 22:52:58 +0300 Subject: [PATCH 12/14] Completely rewritten PlotTwoLines() algorithm --- .../UI/ImGuiExtensions/ImGuiPlotTwoLines.cpp | 194 ++++++++---------- .../UI/ImGuiExtensions/ImGuiPlotTwoLines.hpp | 3 +- 2 files changed, 85 insertions(+), 112 deletions(-) diff --git a/openVulkanoCpp/Scene/UI/ImGuiExtensions/ImGuiPlotTwoLines.cpp b/openVulkanoCpp/Scene/UI/ImGuiExtensions/ImGuiPlotTwoLines.cpp index bec93d1..5052545 100644 --- a/openVulkanoCpp/Scene/UI/ImGuiExtensions/ImGuiPlotTwoLines.cpp +++ b/openVulkanoCpp/Scene/UI/ImGuiExtensions/ImGuiPlotTwoLines.cpp @@ -11,132 +11,104 @@ namespace ImGui { - void PlotTwoLines(const char* label, - float (*getter1)(void* data, int idx), void* data1, const char *tooltipPrefix1, - float (*getter2)(void* data, int idx), void* data2, const char *tooltipPrefix2, - int values_count, float scale_min, float scale_max, ImVec2 graph_size) - { - ImGuiContext& g = *ImGui::GetCurrentContext(); - ImGuiWindow* window = ImGui::GetCurrentWindow(); - if (window->SkipItems) - return; + namespace + { + void RenderLine(ImDrawList* drawList, float (*getter)(void* data, int idx), void* data, int valuesCount, float scaleMin, float scaleMax, ImRect innerBb, ImColor color, int resW) + { + const float tStep = 1.0f / (float)resW; + const float invScale = (scaleMin == scaleMax) ? 0.0f : (1.0f / (scaleMax - scaleMin)); - const ImGuiStyle& style = g.Style; + float v0 = getter(data, 0); + float t0 = 0.0f; + ImVec2 tp0 = ImVec2(t0, 1.0f - ImSaturate((v0 - scaleMin) * invScale)); - ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true); - if (graph_size.x == 0.0f) - graph_size.x = ImGui::CalcItemWidth(); - if (graph_size.y == 0.0f) - graph_size.y = label_size.y + (style.FramePadding.y * 2); + for (int n = 0; n < resW; n++) + { + const float t1 = t0 + tStep; + const int v1Idx = (int)(t0 * (valuesCount - 1) + 0.5f); + IM_ASSERT(v1Idx >= 0 && v1Idx < valuesCount); + const float v1 = getter(data, ImMin(v1Idx + 1, valuesCount - 1)); + const ImVec2 tp1 = ImVec2( t1, 1.0f - ImSaturate((v1 - scaleMin) * invScale) ); - ImRect frame_bb(window->DC.CursorPos, ImVec2(window->DC.CursorPos.x + graph_size.x, window->DC.CursorPos.y + graph_size.y)); - ImRect inner_bb(ImVec2(frame_bb.Min.x + style.FramePadding.x, frame_bb.Min.y + style.FramePadding.y), ImVec2(frame_bb.Max.x - style.FramePadding.x, frame_bb.Max.y - style.FramePadding.y)); - ImRect total_bb(frame_bb.Min, ImVec2(frame_bb.Max.x + (label_size.x > 0.0f ? (style.ItemInnerSpacing.x + label_size.x) : 0.0f), frame_bb.Max.y)); + ImVec2 pos0 = ImLerp(innerBb.Min, innerBb.Max, tp0); + ImVec2 pos1 = ImLerp(innerBb.Min, innerBb.Max, tp1); - ImGui::ItemSize(total_bb, style.FramePadding.y); - if (!ImGui::ItemAdd(total_bb, 0)) - return; + drawList->AddLine(pos0, pos1, color); - // Determine scale from inputs if not specified - if (scale_min == FLT_MAX || scale_max == FLT_MAX) - { - float v1_min = FLT_MAX, v1_max = -FLT_MAX; - for (int i = 0; i < values_count; i++) - { - float v = getter1(data1, i); - if (v != v) // Ignore NaN values - continue; - v1_min = ImMin(v1_min, v); - v1_max = ImMax(v1_max, v); - } - float v2_min = FLT_MAX, v2_max = -FLT_MAX; - for (int i = 0; i < values_count; i++) - { - float v = getter2(data2, i); - if (v != v) // Ignore NaN values - continue; - v2_min = ImMin(v2_min, v); - v2_max = ImMax(v2_max, v); - } - if (scale_min == FLT_MAX) scale_min = ImMin(v1_min, v2_min); - if (scale_max == FLT_MAX) scale_max = ImMax(v1_max, v2_max); - } + t0 = t1; + tp0 = tp1; + } + } + } - ImGui::RenderFrame(frame_bb.Min, frame_bb.Max, ImGui::GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); - int res_w = ImMin((int)graph_size.x, values_count); // Number of samples + void PlotTwoLines(const char* label, + float (*getter1)(void* data, int idx), void* data1, const char *tooltip1, + float (*getter2)(void* data, int idx), void* data2, const char *tooltip2, + int valuesCount, float scaleMin, float scaleMax, ImVec2 graphSize, ImColor color1, ImColor color2) + { + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return; - if (res_w <= 0) - return; + const ImGuiStyle& style = ImGui::GetCurrentContext()->Style; + const ImGuiID id = window->GetID(label); - // Tooltip on hover - int v_hovered = -1; - if (ImGui::IsItemHovered()) - { - const float t = ImClamp((g.IO.MousePos.x - inner_bb.Min.x) / (inner_bb.Max.x - inner_bb.Min.x), 0.0f, 0.9999f); - const int v_idx = (int)(t * values_count); - IM_ASSERT(v_idx >= 0 && v_idx < values_count); + const ImVec2 labelSize = CalcTextSize(label, NULL, true); + const ImVec2 frameSize = CalcItemSize(graphSize, CalcItemWidth(), labelSize.y + style.FramePadding.y * 2.0f); - const float v0 = getter1(data1, v_idx); - const float v1 = getter2(data2, v_idx); - ImGui::SetTooltip("%d: (%s: %8.4g, %s: %8.4g)", v_idx, tooltipPrefix1, v0, tooltipPrefix2, v1); - v_hovered = v_idx; - } + const ImRect frameBb(window->DC.CursorPos, ImVec2(window->DC.CursorPos.x + frameSize.x, window->DC.CursorPos.y + frameSize.y)); + const ImRect innerBb(ImVec2(frameBb.Min.x + style.FramePadding.x, frameBb.Min.y + style.FramePadding.y), ImVec2(frameBb.Max.x - style.FramePadding.x, frameBb.Max.y - style.FramePadding.y)); + const ImRect totalBb(frameBb.Min, ImVec2(frameBb.Max.x + (labelSize.x > 0.0f ? (style.ItemInnerSpacing.x + labelSize.x) : 0.0f), frameBb.Max.y)); - const float t_step = 1.0f / res_w; + ItemSize(totalBb, style.FramePadding.y); + if (!ItemAdd(totalBb, 0, &frameBb)) + return; + const bool hovered = ItemHoverable(frameBb, id, ImGui::GetCurrentContext()->LastItemData.InFlags); - ImDrawList* draw_list = ImGui::GetWindowDrawList(); - draw_list->PushClipRect(inner_bb.Min, inner_bb.Max, true); + // Determine scale from values if not specified + if(scaleMin == FLT_MAX || scaleMax == FLT_MAX) + { + float vMin = FLT_MAX; + float vMax = -FLT_MAX; + for(int i = 0; i < valuesCount; i++) + { + const float v1 = getter1(data1, i); + const float v2 = getter2(data2, i); + if(v1 != v1 || v2 != v2) // Ignore NaN values + continue; + vMin = ImMin(ImMin(vMin, v1), v2); + vMax = ImMax(ImMax(vMax, v1), v2); + } + if(scaleMin == FLT_MAX) + scaleMin = vMin; + if(scaleMax == FLT_MAX) + scaleMax = vMax; + } - ImColor col1 = ImColor(255, 100, 100); - ImColor col2 = ImColor(100, 255, 100); + RenderFrame(frameBb.Min, frameBb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); - // Plot first line - for (int n = 0; n < res_w; n++) - { - const float t0 = t_step * (n + 0); - const float t1 = t_step * (n + 1); - const int v_idx0 = (int)(t0 * values_count); - int v_idx1 = (int)(t1 * values_count); - if(v_idx1 >= values_count) - v_idx1 = values_count - 1; + if(valuesCount >= 2) + { + int resW = ImMin((int)frameSize.x, valuesCount) - 1; + int itemCount = valuesCount - 1; - IM_ASSERT(v_idx0 >= 0 && v_idx0 < values_count); - IM_ASSERT(v_idx1 >= 0 && v_idx1 < values_count); + // Tooltip on hover + if(hovered && innerBb.Contains(ImGui::GetCurrentContext()->IO.MousePos)) + { + const float t = ImClamp((ImGui::GetCurrentContext()->IO.MousePos.x - innerBb.Min.x) / (innerBb.Max.x - innerBb.Min.x), 0.0f, 0.9999f); + const int vIdx = (int)(t * itemCount); + IM_ASSERT(vIdx >= 0 && vIdx < valuesCount); - const float v0 = getter1(data1, v_idx0); - const float v1 = getter1(data1, v_idx1); - const float x0 = ImLerp(inner_bb.Min.x, inner_bb.Max.x, t0); - const float x1 = ImLerp(inner_bb.Min.x, inner_bb.Max.x, t1); - const float y0 = ImLerp(inner_bb.Max.y, inner_bb.Min.y, (v0 - scale_min) / (scale_max - scale_min)); - const float y1 = ImLerp(inner_bb.Max.y, inner_bb.Min.y, (v1 - scale_min) / (scale_max - scale_min)); - draw_list->AddLine(ImVec2(x0, y0), ImVec2(x1, y1), col1); - } + const float v0 = getter1(data1, vIdx % valuesCount); + const float v1 = getter2(data2, (vIdx + 1) % valuesCount); + SetTooltip("%s: %8.4g\n%s: %8.4g", tooltip1, v0, tooltip2, v1); + } - // Plot second line - for (int n = 0; n < res_w; n++) - { - const float t0 = t_step * (n + 0); - const float t1 = t_step * (n + 1); - const int v_idx0 = (int)(t0 * values_count); - int v_idx1 = (int)(t1 * values_count); - if(v_idx1 >= values_count) - v_idx1 = values_count - 1; + RenderLine(window->DrawList, getter1, data1, valuesCount, scaleMin, scaleMax, innerBb, color1, resW); + RenderLine(window->DrawList, getter2, data2, valuesCount, scaleMin, scaleMax, innerBb, color2, resW); + } - IM_ASSERT(v_idx0 >= 0 && v_idx0 < values_count); - IM_ASSERT(v_idx1 >= 0 && v_idx1 < values_count); - - const float v0 = getter2(data2, v_idx0); - const float v1 = getter2(data2, v_idx1); - const float x0 = ImLerp(inner_bb.Min.x, inner_bb.Max.x, t0); - const float x1 = ImLerp(inner_bb.Min.x, inner_bb.Max.x, t1); - const float y0 = ImLerp(inner_bb.Max.y, inner_bb.Min.y, (v0 - scale_min) / (scale_max - scale_min)); - const float y1 = ImLerp(inner_bb.Max.y, inner_bb.Min.y, (v1 - scale_min) / (scale_max - scale_min)); - draw_list->AddLine(ImVec2(x0, y0), ImVec2(x1, y1), col2); - } - - draw_list->PopClipRect(); - - if (label_size.x > 0.0f) - ImGui::RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label); - } + if(labelSize.x > 0.0f) + RenderText(ImVec2(frameBb.Max.x + style.ItemInnerSpacing.x, innerBb.Min.y), label); + } } \ No newline at end of file diff --git a/openVulkanoCpp/Scene/UI/ImGuiExtensions/ImGuiPlotTwoLines.hpp b/openVulkanoCpp/Scene/UI/ImGuiExtensions/ImGuiPlotTwoLines.hpp index a4bd497..1ad54fe 100644 --- a/openVulkanoCpp/Scene/UI/ImGuiExtensions/ImGuiPlotTwoLines.hpp +++ b/openVulkanoCpp/Scene/UI/ImGuiExtensions/ImGuiPlotTwoLines.hpp @@ -13,5 +13,6 @@ namespace ImGui void PlotTwoLines(const char* label, float (*getter1)(void* data, int idx), void* data1, const char *tooltipPrefix1, float (*getter2)(void* data, int idx), void* data2, const char *tooltipPrefix2, - int values_count, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0)); + int values_count, float scale_min = FLT_MAX, float scale_max = FLT_MAX, + ImVec2 graph_size = ImVec2(0, 0), ImColor color1 = ImColor(255, 100, 100), ImColor color2 = ImColor(100, 255, 100)); } \ No newline at end of file From b5df2edab51a17250c1a1cf2da0ca4c6019cd7b5 Mon Sep 17 00:00:00 2001 From: Vladyslav Baranovskyi Date: Thu, 13 Jun 2024 22:53:38 +0300 Subject: [PATCH 13/14] PerformanceInfo improvements --- openVulkanoCpp/Scene/UI/PerformanceInfo.cpp | 67 +++++++++++---------- openVulkanoCpp/Scene/UI/PerformanceInfo.hpp | 8 +-- 2 files changed, 39 insertions(+), 36 deletions(-) diff --git a/openVulkanoCpp/Scene/UI/PerformanceInfo.cpp b/openVulkanoCpp/Scene/UI/PerformanceInfo.cpp index 9a28ddf..473f605 100644 --- a/openVulkanoCpp/Scene/UI/PerformanceInfo.cpp +++ b/openVulkanoCpp/Scene/UI/PerformanceInfo.cpp @@ -18,42 +18,45 @@ namespace OpenVulkano::Scene::UI { namespace { - float FrameCollectionValuesGetter(void *data, int index) + float FloatCollectionValuesGetter(void *data, int index) { - auto frameCollection = reinterpret_cast(data); - float value = frameCollection->m_frameTimes[index]; - float result = value / frameCollection->m_maxValue * 100; + auto collection = static_cast(data); + float value = collection->m_values[index]; + float result = value / collection->m_maxValue * 100; return result; } - - float RamValuesGetter(void *data, int index) - { - auto queue = reinterpret_cast *>(data); - float used = (*queue)[index]; - float max = SystemInfo::GetAppRamMax(); - float percentage = used / max * 100; - return percentage; - } - } void PerformanceInfo::UpdateQueues() { - m_frameCollection.m_frameTimes.push_back(static_cast(CURRENT_FRAME.frameTime)); - while(m_frameCollection.m_frameTimes.size() > m_windowSize) - m_frameCollection.m_frameTimes.pop_front(); + float newFrameTime = static_cast(CURRENT_FRAME.frameTime); + if(newFrameTime > m_frames.m_maxValue) + m_frames.m_maxValue = newFrameTime; - float maxFrameTime = FLT_MIN; - for(auto value : m_frameCollection.m_frameTimes) + m_frames.m_values.push_back(newFrameTime); + + while(m_frames.m_values.size() > m_windowSize) { - if(value > maxFrameTime) - maxFrameTime = value; + float poppedFrameTime = m_frames.m_values.front(); + m_frames.m_values.pop_front(); + if(m_frames.m_maxValue == poppedFrameTime) + { + m_frames.m_maxValue = FLT_MIN; + for(auto value : m_frames.m_values) + { + if(value > m_frames.m_maxValue) + m_frames.m_maxValue = value; + } + } } - m_frameCollection.m_maxValue = maxFrameTime; - m_ramUsed.push_back(static_cast(SystemInfo::GetAppRamUsed())); - while(m_ramUsed.size() > m_windowSize) - m_ramUsed.pop_front(); + m_ramUsed.m_values.push_back(static_cast(SystemInfo::GetAppRamUsed())); + while(m_ramUsed.m_values.size() > m_windowSize) + m_ramUsed.m_values.pop_front(); + + m_ramUsed.m_maxValue = SystemInfo::GetAppRamMax(); + + assert(m_ramUsed.m_values.size() <= m_windowSize); } void PerformanceInfo::BeginDraw() @@ -65,20 +68,20 @@ namespace OpenVulkano::Scene::UI void PerformanceInfo::Draw() { UpdateQueues(); - assert(m_frameCollection.m_frameTimes.size() == m_ramUsed.size()); + assert(m_frames.m_values.size() == m_ramUsed.m_values.size()); - ImGui::Text("Last Frame Time(wrt max): %f s", m_frameCollection.m_frameTimes.back()); - ImGui::Text("Last FPS: %f", 1 / m_frameCollection.m_frameTimes.back()); + ImGui::Text("Last Frame Time: %f s", m_frames.m_values.back()); + ImGui::Text("Last FPS: %f", 1 / m_frames.m_values.back()); + ImGui::TextFmt("RAM: {} / {}, Free: {}", ByteSize(m_ramUsed.m_values.back()), ByteSize(SystemInfo::GetAppRamMax()), ByteSize(SystemInfo::GetAppRamAvailable())); ImGui::SliderInt("Window Size", &m_windowSize, 10, 1000); - ImGui::TextFmt("RAM: {} / {}, Free: {}", ByteSize(m_ramUsed.back()), ByteSize(SystemInfo::GetAppRamMax()), ByteSize(SystemInfo::GetAppRamAvailable())); ImVec2 availableSize = ImGui::GetContentRegionAvail(); float scaleMin = 0.01; float scaleMax = 100; ImGui::PlotTwoLines("", - &FrameCollectionValuesGetter, &m_frameCollection, "Frame Time", - &RamValuesGetter, &m_ramUsed, "RAM", - (int)m_ramUsed.size(), + &FloatCollectionValuesGetter, &m_frames, "Frame Time(wrt max)", + &FloatCollectionValuesGetter, &m_ramUsed, "RAM", + (int)m_ramUsed.m_values.size(), scaleMin, scaleMax, availableSize); } diff --git a/openVulkanoCpp/Scene/UI/PerformanceInfo.hpp b/openVulkanoCpp/Scene/UI/PerformanceInfo.hpp index 53afdd7..ed3342f 100644 --- a/openVulkanoCpp/Scene/UI/PerformanceInfo.hpp +++ b/openVulkanoCpp/Scene/UI/PerformanceInfo.hpp @@ -12,17 +12,17 @@ namespace OpenVulkano::Scene::UI { - struct FrameTimeCollection + struct FloatCollection { - std::deque m_frameTimes; + std::deque m_values; float m_maxValue; }; class PerformanceInfo : public UiElement { int m_windowSize = 200; - std::deque m_ramUsed; - FrameTimeCollection m_frameCollection; + FloatCollection m_ramUsed; + FloatCollection m_frames; void UpdateQueues(); From 1a51134fddd7d2cb4b5cd227673da5182f2c2310 Mon Sep 17 00:00:00 2001 From: Vladyslav Baranovskyi Date: Fri, 14 Jun 2024 11:41:20 +0300 Subject: [PATCH 14/14] Displaying max frame time --- openVulkanoCpp/Scene/UI/PerformanceInfo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openVulkanoCpp/Scene/UI/PerformanceInfo.cpp b/openVulkanoCpp/Scene/UI/PerformanceInfo.cpp index 473f605..10e1399 100644 --- a/openVulkanoCpp/Scene/UI/PerformanceInfo.cpp +++ b/openVulkanoCpp/Scene/UI/PerformanceInfo.cpp @@ -70,7 +70,7 @@ namespace OpenVulkano::Scene::UI UpdateQueues(); assert(m_frames.m_values.size() == m_ramUsed.m_values.size()); - ImGui::Text("Last Frame Time: %f s", m_frames.m_values.back()); + ImGui::Text("Last Frame Time: %f s, max: %f s", m_frames.m_values.back(), m_frames.m_maxValue); ImGui::Text("Last FPS: %f", 1 / m_frames.m_values.back()); ImGui::TextFmt("RAM: {} / {}, Free: {}", ByteSize(m_ramUsed.m_values.back()), ByteSize(SystemInfo::GetAppRamMax()), ByteSize(SystemInfo::GetAppRamAvailable())); ImGui::SliderInt("Window Size", &m_windowSize, 10, 1000);