From 97bc667e0b2e4b39d92fa4235a557f2b8ad8b2cf Mon Sep 17 00:00:00 2001 From: ohyzha Date: Fri, 23 Aug 2024 17:04:37 +0300 Subject: [PATCH 1/4] fix out of bounds exceptions --- openVulkanoCpp/Base/Version.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openVulkanoCpp/Base/Version.cpp b/openVulkanoCpp/Base/Version.cpp index c2c6547..f9f39cc 100644 --- a/openVulkanoCpp/Base/Version.cpp +++ b/openVulkanoCpp/Base/Version.cpp @@ -34,7 +34,7 @@ namespace OpenVulkano offset++; ReadTagComponents(tagComponents, versionStr, offset); } - if (versionStr.size() - 3 > offset && versionStr[offset] == ' ' && versionStr[offset + 1] == '(' && versionStr.back() == ')') + if (versionStr.size() > 3 && versionStr.size() - 3 > offset && versionStr[offset] == ' ' && versionStr[offset + 1] == '(' && versionStr.back() == ')') { ReadVersionComponents(appleBuildComponents, versionStr, offset); if (versionStr[offset] != ')') appleBuildComponents.clear(); @@ -69,7 +69,7 @@ namespace OpenVulkano size_t blockStart = offset; while (versionStr.size() > offset && versionStr[offset] != '-' && versionStr[offset] != ' ' && versionStr[offset] != '\0') offset++; tags.emplace_back(versionStr.data() + blockStart, offset - blockStart); - if (versionStr[offset] == ' ' || versionStr[offset] == '\0') break; + if (offset >= versionStr.size() || versionStr[offset] == ' ' || versionStr[offset] == '\0') break; offset++; } while (versionStr.size() > offset); } From f002ea2ecaf77b8283f1b71648db3a6572134640 Mon Sep 17 00:00:00 2001 From: ohyzha Date: Fri, 23 Aug 2024 17:05:06 +0300 Subject: [PATCH 2/4] implement fps limiter --- openVulkanoCpp/Base/EngineConfiguration.hpp | 2 +- .../Controller/FreeCamCameraController.cpp | 2 +- openVulkanoCpp/Host/GraphicsAppManager.cpp | 29 ++++++++++++++++++- openVulkanoCpp/Host/GraphicsAppManager.hpp | 11 ++++++- 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/openVulkanoCpp/Base/EngineConfiguration.hpp b/openVulkanoCpp/Base/EngineConfiguration.hpp index 27f299f..347fec7 100644 --- a/openVulkanoCpp/Base/EngineConfiguration.hpp +++ b/openVulkanoCpp/Base/EngineConfiguration.hpp @@ -48,7 +48,7 @@ namespace OpenVulkano bool m_preferFramebufferFormatSRGB = true; bool m_lazyRendering = false; bool m_vSync = false; - int32_t m_fpsCap = -1; // -1 = no fps cap. 0 = fps cap if vsync, no cap otherwise. > 0 = set fps cap + int32_t m_fpsCap = 500; // -1 = no fps cap. 0 = fps cap if vsync, no cap otherwise. > 0 = set fps cap #ifdef __APPLE__ uint32_t m_preferredImageCount = 3; #else diff --git a/openVulkanoCpp/Controller/FreeCamCameraController.cpp b/openVulkanoCpp/Controller/FreeCamCameraController.cpp index 71da9cc..8f94d3e 100644 --- a/openVulkanoCpp/Controller/FreeCamCameraController.cpp +++ b/openVulkanoCpp/Controller/FreeCamCameraController.cpp @@ -32,7 +32,7 @@ namespace OpenVulkano vec = Math::Utils::normalize(vec); } - float timeScale = 5 * CURRENT_FRAME.frameTime; //TODO + float timeScale = 3 * CURRENT_FRAME.frameTime; //TODO vec = vec * timeScale * 3.0f; // scale vector if (input->GetButton(m_actionBoost)) { diff --git a/openVulkanoCpp/Host/GraphicsAppManager.cpp b/openVulkanoCpp/Host/GraphicsAppManager.cpp index f9cd1bb..6d29b66 100644 --- a/openVulkanoCpp/Host/GraphicsAppManager.cpp +++ b/openVulkanoCpp/Host/GraphicsAppManager.cpp @@ -19,6 +19,8 @@ namespace OpenVulkano { + using clock = std::chrono::steady_clock; + GraphicsAppManager::GraphicsAppManager(OpenVulkano::IGraphicsApp* app, RenderAPI::RenderApi renderApi) : app(app), renderApi(renderApi) { @@ -37,6 +39,8 @@ namespace OpenVulkano renderer = std::unique_ptr(PlatformProducer::CreateRenderManager(renderApi)); app->SetGraphicsAppManager(this); window->SetWindowHandler(this); + inputManager = Input::InputManager::GetInstance(); + engineConfig = EngineConfiguration::GetEngineConfiguration(); } GraphicsAppManager::GraphicsAppManager(IGraphicsApp* app, IWindow* window, RenderAPI::RenderApi renderApi) @@ -57,6 +61,24 @@ namespace OpenVulkano renderer = std::unique_ptr(PlatformProducer::CreateRenderManager(renderApi)); app->SetGraphicsAppManager(this); window->SetWindowHandler(this); + inputManager = OpenVulkano::Input::InputManager::GetInstance(); + engineConfig = OpenVulkano::EngineConfiguration::GetEngineConfiguration(); + } + + void GraphicsAppManager::OnCappedFPS(const auto& frameStartTime) + { + int32_t fpsCap = engineConfig->GetFpsCap(); + fpsCapRemainder += 1000 % fpsCap; + auto frameTime = std::chrono::milliseconds(1000 / fpsCap); + if (fpsCapRemainder >= fpsCap) + { + frameTime += std::chrono::milliseconds(1); + fpsCapRemainder -= fpsCap; + } + while (clock::now() < frameStartTime + frameTime) + { + std::this_thread::yield(); + } } GraphicsAppManager::~GraphicsAppManager() noexcept @@ -139,9 +161,14 @@ namespace OpenVulkano } else { - Input::InputManager::GetInstance()->Tick(); + auto start = clock::now(); + inputManager->Tick(); app->Tick(); if (CURRENT_FRAME.needsRedraw) renderer->Tick(); + if (engineConfig->GetFpsCap() > 0 && !engineConfig->GetVSync()) + { + OnCappedFPS(start); + } frameTimer.Tick(); UpdateFps(); CURRENT_FRAME.frameId = frameCount; diff --git a/openVulkanoCpp/Host/GraphicsAppManager.hpp b/openVulkanoCpp/Host/GraphicsAppManager.hpp index 5d4b627..d264e1b 100644 --- a/openVulkanoCpp/Host/GraphicsAppManager.hpp +++ b/openVulkanoCpp/Host/GraphicsAppManager.hpp @@ -18,6 +18,11 @@ namespace OpenVulkano { class IPlatform; + namespace Input + { + class InputManager; + } + class EngineConfiguration; /** * \brief A simple GraphicsAppManager. It can only handle one window. @@ -32,10 +37,14 @@ namespace OpenVulkano RenderAPI::RenderApi renderApi; bool paused = false, running = false; float fpsTimer = 0, avgFps = 0, avgFrameTime = 0; - uint64_t frameCount = 0, lastFrameCount = 0; + uint64_t frameCount = 0, lastFrameCount = 0, fpsCapRemainder = 0; Timer frameTimer; std::string windowTitleFormat; + Input::InputManager* inputManager; + EngineConfiguration* engineConfig; + private: + void OnCappedFPS(const auto& frameStartTime); public: explicit GraphicsAppManager(IGraphicsApp* app, RenderAPI::RenderApi renderApi = RenderAPI::Vulkan); From 32ffd21076bfd0704e3eff0eef3b8bba97e31638 Mon Sep 17 00:00:00 2001 From: ohyzha Date: Sun, 25 Aug 2024 16:21:31 +0300 Subject: [PATCH 3/4] main loop improvements --- openVulkanoCpp/Base/EngineConfiguration.hpp | 14 +++++++-- openVulkanoCpp/Host/GraphicsAppManager.cpp | 34 ++++++++++++++++++--- openVulkanoCpp/Host/GraphicsAppManager.hpp | 2 ++ 3 files changed, 44 insertions(+), 6 deletions(-) diff --git a/openVulkanoCpp/Base/EngineConfiguration.hpp b/openVulkanoCpp/Base/EngineConfiguration.hpp index 347fec7..61ef440 100644 --- a/openVulkanoCpp/Base/EngineConfiguration.hpp +++ b/openVulkanoCpp/Base/EngineConfiguration.hpp @@ -9,6 +9,7 @@ #include #include #include +#include "Base/Event.hpp" #undef max namespace OpenVulkano @@ -34,10 +35,19 @@ namespace OpenVulkano void SetVSync(bool vSync) { m_vSync = vSync; } [[nodiscard]] int32_t GetFpsCap() const { return m_fpsCap; } - void SetFpsCap(int32_t fpsCap) { m_fpsCap = fpsCap; } + void SetFpsCap(int32_t fpsCap) + { + if (m_fpsCap != fpsCap) + { + m_fpsCap = fpsCap; + OnFpsCapChanged(fpsCap); + } + } [[nodiscard]] uint32_t GetPrefferedSwapChainImageCount() const { return m_preferredImageCount; } void SetPrefferedSwapChainImageCount(uint32_t preferredImageCount) { m_preferredImageCount = preferredImageCount; } + public: + Event OnFpsCapChanged; private: EngineConfiguration(); @@ -48,7 +58,7 @@ namespace OpenVulkano bool m_preferFramebufferFormatSRGB = true; bool m_lazyRendering = false; bool m_vSync = false; - int32_t m_fpsCap = 500; // -1 = no fps cap. 0 = fps cap if vsync, no cap otherwise. > 0 = set fps cap + int32_t m_fpsCap = -1; // -1 = no fps cap. 0 = fps cap if vsync, no cap otherwise. > 0 = set fps cap #ifdef __APPLE__ uint32_t m_preferredImageCount = 3; #else diff --git a/openVulkanoCpp/Host/GraphicsAppManager.cpp b/openVulkanoCpp/Host/GraphicsAppManager.cpp index 6d29b66..9377b56 100644 --- a/openVulkanoCpp/Host/GraphicsAppManager.cpp +++ b/openVulkanoCpp/Host/GraphicsAppManager.cpp @@ -41,6 +41,12 @@ namespace OpenVulkano window->SetWindowHandler(this); inputManager = Input::InputManager::GetInstance(); engineConfig = EngineConfiguration::GetEngineConfiguration(); + engineConfig->OnFpsCapChanged += EventHandler(this, &GraphicsAppManager::UpdateCappedFpsInfo); + // set initial values + if (engineConfig->GetFpsCap() > 0) + { + UpdateCappedFpsInfo(engineConfig->GetFpsCap()); + } } GraphicsAppManager::GraphicsAppManager(IGraphicsApp* app, IWindow* window, RenderAPI::RenderApi renderApi) @@ -63,19 +69,38 @@ namespace OpenVulkano window->SetWindowHandler(this); inputManager = OpenVulkano::Input::InputManager::GetInstance(); engineConfig = OpenVulkano::EngineConfiguration::GetEngineConfiguration(); + engineConfig->OnFpsCapChanged += EventHandler(this, &GraphicsAppManager::UpdateCappedFpsInfo); + // set initial values + if (engineConfig->GetFpsCap() > 0) + { + UpdateCappedFpsInfo(engineConfig->GetFpsCap()); + } + } + + void GraphicsAppManager::UpdateCappedFpsInfo(int32_t newFpsCap) + { + if (newFpsCap < 0) + { + cappedFrameTime = std::chrono::milliseconds(0); + } + else + { + cappedFrameTime = std::chrono::milliseconds(1000 / newFpsCap); + } } void GraphicsAppManager::OnCappedFPS(const auto& frameStartTime) { int32_t fpsCap = engineConfig->GetFpsCap(); fpsCapRemainder += 1000 % fpsCap; - auto frameTime = std::chrono::milliseconds(1000 / fpsCap); + auto expectedFrameTime = cappedFrameTime; if (fpsCapRemainder >= fpsCap) { - frameTime += std::chrono::milliseconds(1); + expectedFrameTime += std::chrono::milliseconds(1); fpsCapRemainder -= fpsCap; } - while (clock::now() < frameStartTime + frameTime) + auto frameEndTime = frameStartTime + expectedFrameTime; + while (clock::now() < frameEndTime) { std::this_thread::yield(); } @@ -84,6 +109,7 @@ namespace OpenVulkano GraphicsAppManager::~GraphicsAppManager() noexcept { if (windowTitleFormat.empty()) return; + engineConfig->OnFpsCapChanged -= EventHandler(this, &GraphicsAppManager::UpdateCappedFpsInfo); ShutDown(); } @@ -165,7 +191,7 @@ namespace OpenVulkano inputManager->Tick(); app->Tick(); if (CURRENT_FRAME.needsRedraw) renderer->Tick(); - if (engineConfig->GetFpsCap() > 0 && !engineConfig->GetVSync()) + if (cappedFrameTime.count()) { OnCappedFPS(start); } diff --git a/openVulkanoCpp/Host/GraphicsAppManager.hpp b/openVulkanoCpp/Host/GraphicsAppManager.hpp index d264e1b..d28490b 100644 --- a/openVulkanoCpp/Host/GraphicsAppManager.hpp +++ b/openVulkanoCpp/Host/GraphicsAppManager.hpp @@ -38,6 +38,7 @@ namespace OpenVulkano bool paused = false, running = false; float fpsTimer = 0, avgFps = 0, avgFrameTime = 0; uint64_t frameCount = 0, lastFrameCount = 0, fpsCapRemainder = 0; + std::chrono::milliseconds cappedFrameTime = std::chrono::milliseconds(0); Timer frameTimer; std::string windowTitleFormat; Input::InputManager* inputManager; @@ -45,6 +46,7 @@ namespace OpenVulkano private: void OnCappedFPS(const auto& frameStartTime); + void UpdateCappedFpsInfo(int32_t newFpsCap); public: explicit GraphicsAppManager(IGraphicsApp* app, RenderAPI::RenderApi renderApi = RenderAPI::Vulkan); From 0fe28f4759c23e55fe2a5f40f513120907abff4b Mon Sep 17 00:00:00 2001 From: ohyzha Date: Tue, 27 Aug 2024 09:26:10 +0300 Subject: [PATCH 4/4] switch to microseconds --- openVulkanoCpp/Host/GraphicsAppManager.cpp | 14 +++----------- openVulkanoCpp/Host/GraphicsAppManager.hpp | 4 ++-- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/openVulkanoCpp/Host/GraphicsAppManager.cpp b/openVulkanoCpp/Host/GraphicsAppManager.cpp index 9377b56..e880467 100644 --- a/openVulkanoCpp/Host/GraphicsAppManager.cpp +++ b/openVulkanoCpp/Host/GraphicsAppManager.cpp @@ -81,25 +81,17 @@ namespace OpenVulkano { if (newFpsCap < 0) { - cappedFrameTime = std::chrono::milliseconds(0); + cappedFrameTime = std::chrono::microseconds(0); } else { - cappedFrameTime = std::chrono::milliseconds(1000 / newFpsCap); + cappedFrameTime = std::chrono::microseconds(1'000'000 / newFpsCap); } } void GraphicsAppManager::OnCappedFPS(const auto& frameStartTime) { - int32_t fpsCap = engineConfig->GetFpsCap(); - fpsCapRemainder += 1000 % fpsCap; - auto expectedFrameTime = cappedFrameTime; - if (fpsCapRemainder >= fpsCap) - { - expectedFrameTime += std::chrono::milliseconds(1); - fpsCapRemainder -= fpsCap; - } - auto frameEndTime = frameStartTime + expectedFrameTime; + auto frameEndTime = frameStartTime + cappedFrameTime; while (clock::now() < frameEndTime) { std::this_thread::yield(); diff --git a/openVulkanoCpp/Host/GraphicsAppManager.hpp b/openVulkanoCpp/Host/GraphicsAppManager.hpp index d28490b..d48704a 100644 --- a/openVulkanoCpp/Host/GraphicsAppManager.hpp +++ b/openVulkanoCpp/Host/GraphicsAppManager.hpp @@ -37,8 +37,8 @@ namespace OpenVulkano RenderAPI::RenderApi renderApi; bool paused = false, running = false; float fpsTimer = 0, avgFps = 0, avgFrameTime = 0; - uint64_t frameCount = 0, lastFrameCount = 0, fpsCapRemainder = 0; - std::chrono::milliseconds cappedFrameTime = std::chrono::milliseconds(0); + uint64_t frameCount = 0, lastFrameCount = 0; + std::chrono::microseconds cappedFrameTime = std::chrono::microseconds(0); Timer frameTimer; std::string windowTitleFormat; Input::InputManager* inputManager;