Merge pull request 'FPS limiter' (#116) from fps_limiter into master

Reviewed-on: https://git.madvoxel.net/OpenVulkano/OpenVulkano/pulls/116
Reviewed-by: Georg Hagen <georg.hagen@madvoxel.com>
This commit is contained in:
Oleksii_Hyzha
2024-08-28 15:10:30 +02:00
5 changed files with 71 additions and 5 deletions

View File

@@ -9,6 +9,7 @@
#include <cstdint>
#include <algorithm>
#include <array>
#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<int32_t> OnFpsCapChanged;
private:
EngineConfiguration();

View File

@@ -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);
}

View File

@@ -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))
{

View File

@@ -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,14 @@ namespace OpenVulkano
renderer = std::unique_ptr<IRenderer>(PlatformProducer::CreateRenderManager(renderApi));
app->SetGraphicsAppManager(this);
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)
@@ -57,11 +67,41 @@ namespace OpenVulkano
renderer = std::unique_ptr<IRenderer>(PlatformProducer::CreateRenderManager(renderApi));
app->SetGraphicsAppManager(this);
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::microseconds(0);
}
else
{
cappedFrameTime = std::chrono::microseconds(1'000'000 / newFpsCap);
}
}
void GraphicsAppManager::OnCappedFPS(const auto& frameStartTime)
{
auto frameEndTime = frameStartTime + cappedFrameTime;
while (clock::now() < frameEndTime)
{
std::this_thread::yield();
}
}
GraphicsAppManager::~GraphicsAppManager() noexcept
{
if (windowTitleFormat.empty()) return;
engineConfig->OnFpsCapChanged -= EventHandler(this, &GraphicsAppManager::UpdateCappedFpsInfo);
ShutDown();
}
@@ -139,9 +179,14 @@ namespace OpenVulkano
}
else
{
Input::InputManager::GetInstance()->Tick();
auto start = clock::now();
inputManager->Tick();
app->Tick();
if (CURRENT_FRAME.needsRedraw) renderer->Tick();
if (cappedFrameTime.count())
{
OnCappedFPS(start);
}
frameTimer.Tick();
UpdateFps();
CURRENT_FRAME.frameId = frameCount;

View File

@@ -18,6 +18,11 @@
namespace OpenVulkano
{
class IPlatform;
namespace Input
{
class InputManager;
}
class EngineConfiguration;
/**
* \brief A simple GraphicsAppManager. It can only handle one window.
@@ -33,9 +38,15 @@ namespace OpenVulkano
bool paused = false, running = false;
float fpsTimer = 0, avgFps = 0, avgFrameTime = 0;
uint64_t frameCount = 0, lastFrameCount = 0;
std::chrono::microseconds cappedFrameTime = std::chrono::microseconds(0);
Timer frameTimer;
std::string windowTitleFormat;
Input::InputManager* inputManager;
EngineConfiguration* engineConfig;
private:
void OnCappedFPS(const auto& frameStartTime);
void UpdateCappedFpsInfo(int32_t newFpsCap);
public:
explicit GraphicsAppManager(IGraphicsApp* app, RenderAPI::RenderApi renderApi = RenderAPI::Vulkan);