Make the fps cap a per-view property

And have ui.fpsCap set only GameView's fps cap. This is the closest we'll be getting to the fps cap being true to its name (i.e. actually controlling frames per second, rather than ticks per second) with this iteration of the user interface. Also disable SRT if the sim is paused. Together, these changes fix some old problems such as non-sim user interfaces burning CPU for no reason when the fps cap is removed.
This commit is contained in:
Tamás Bálint Misius
2025-01-22 15:04:20 +01:00
parent 6576872074
commit c32166efdc
14 changed files with 152 additions and 63 deletions

View File

@@ -8,7 +8,11 @@ struct FpsLimitExplicit
{
float value;
};
using FpsLimit = std::variant<FpsLimitNone, FpsLimitExplicit>;
using SimFpsLimit = std::variant<FpsLimitNone, FpsLimitExplicit>;
struct FpsLimitFollowDraw
{
};
using FpsLimit = std::variant<FpsLimitNone, FpsLimitExplicit, FpsLimitFollowDraw>;
struct DrawLimitDisplay
{

View File

@@ -477,6 +477,7 @@ void EngineProcess()
EventProcess(event);
}
std::optional<uint64_t> delay;
{
auto nowNs = uint64_t(SDL_GetTicks()) * UINT64_C(1'000'000);
auto effectiveDrawLimit = engine.GetEffectiveDrawCap();
@@ -485,10 +486,6 @@ void EngineProcess()
engine.Tick();
engine.Draw();
drawSchedule.SetNow(nowNs);
if (effectiveDrawLimit)
{
drawSchedule.Arm(float(*effectiveDrawLimit));
}
SDLSetScreen();
blit(engine.g->Data());
}
@@ -496,14 +493,24 @@ void EngineProcess()
{
engine.SimTick();
}
}
if (effectiveDrawLimit)
{
delay = drawSchedule.Arm(float(*effectiveDrawLimit)) / UINT64_C(1'000'000);
}
}
auto fpsLimit = ui::Engine::Ref().GetFpsLimit();
if (!std::holds_alternative<FpsLimitFollowDraw>(fpsLimit))
{
delay.reset();
auto nowNs = uint64_t(SDL_GetTicks()) * UINT64_C(1'000'000);
tickSchedule.SetNow(nowNs);
if (auto *fpsLimitExplicit = std::get_if<FpsLimitExplicit>(&fpsLimit))
{
SDL_Delay(tickSchedule.Arm(fpsLimitExplicit->value) / UINT64_C(1'000'000));
delay = tickSchedule.Arm(fpsLimitExplicit->value) / UINT64_C(1'000'000);
}
}
if (delay.has_value())
{
SDL_Delay(std::max(*delay, UINT64_C(1)));
}
}

View File

@@ -970,6 +970,11 @@ void GameController::SetZoomPosition(ui::Point position)
gameModel->SetZoomWindowPosition(zoomWindowPosition);
}
bool GameController::GetPaused() const
{
return gameModel->GetPaused();
}
void GameController::SetPaused(bool pauseState)
{
gameModel->SetPaused(pauseState);
@@ -1730,7 +1735,7 @@ void GameController::AfterSimDraw()
bool GameController::ThreadedRenderingAllowed()
{
return gameModel->GetThreadedRendering() && !commandInterface->HaveSimGraphicsEventHandlers();
return gameModel->GetThreadedRendering() && !GetPaused() && !commandInterface->HaveSimGraphicsEventHandlers();
}
void GameController::SetToolIndex(ByteString identifier, std::optional<int> index)

View File

@@ -117,6 +117,7 @@ public:
void CopyRegion(ui::Point point1, ui::Point point2);
void CutRegion(ui::Point point1, ui::Point point2);
void Update();
bool GetPaused() const;
void SetPaused(bool pauseState);
void SetPaused();
void SetDecoration(bool decorationState);

View File

@@ -1018,7 +1018,7 @@ void GameModel::SetPaused(bool pauseState)
notifyPausedChanged();
}
bool GameModel::GetPaused()
bool GameModel::GetPaused() const
{
return sim->sys_pause?true:false;
}

View File

@@ -237,7 +237,7 @@ public:
void AddObserver(GameView * observer);
void SetPaused(bool pauseState);
bool GetPaused();
bool GetPaused() const;
void SetDecoration(bool decorationState);
bool GetDecoration();
void SetAHeatEnable(bool aHeat);

View File

@@ -768,6 +768,7 @@ void GameView::NotifyUserChanged(GameModel * sender)
void GameView::NotifyPausedChanged(GameModel * sender)
{
pauseButton->SetToggleState(sender->GetPaused());
ApplySimFpsLimit();
}
void GameView::NotifyToolTipChanged(GameModel * sender)
@@ -2542,7 +2543,12 @@ void GameView::OnDraw()
{
//FPS and some version info
StringBuilder fpsInfo;
fpsInfo << Format::Precision(2) << "FPS: " << ui::Engine::Ref().GetFps();
auto fps = 0.f;
if (!c->GetPaused())
{
fps = ui::Engine::Ref().GetFps();
}
fpsInfo << Format::Precision(2) << "FPS: " << fps;
if (showDebug)
{
@@ -2563,14 +2569,13 @@ void GameView::OnDraw()
{
fpsInfo << "\nSimulation";
fpsInfo << "\n FPS cap: ";
auto fpsLimit = ui::Engine::Ref().GetFpsLimit();
if (std::holds_alternative<FpsLimitNone>(fpsLimit))
if (std::holds_alternative<FpsLimitNone>(simFpsLimit))
{
fpsInfo << "none";
}
else
{
fpsInfo << std::get<FpsLimitExplicit>(fpsLimit).value;
fpsInfo << std::get<FpsLimitExplicit>(simFpsLimit).value;
}
}
if (c->GetDebugFlags() & DEBUG_RENHUD)
@@ -2811,3 +2816,25 @@ void GameView::WaitForRendererThread()
return !rendererThreadOwnsRenderer;
});
}
void GameView::ApplySimFpsLimit()
{
if (c->GetPaused())
{
SetFpsLimit(FpsLimitFollowDraw{});
}
else if (std::holds_alternative<FpsLimitNone>(simFpsLimit))
{
SetFpsLimit(FpsLimitNone{});
}
else
{
SetFpsLimit(std::get<FpsLimitExplicit>(simFpsLimit));
}
}
void GameView::SetSimFpsLimit(SimFpsLimit newSimFpsLimit)
{
simFpsLimit = newSimFpsLimit;
ApplySimFpsLimit();
}

View File

@@ -175,6 +175,9 @@ private:
int foundParticles = 0;
const RendererFrame *rendererFrame = nullptr;
SimFpsLimit simFpsLimit = FpsLimitExplicit{ 60.f };
void ApplySimFpsLimit();
public:
GameView();
~GameView();
@@ -278,4 +281,10 @@ public:
void RenderSimulation(const RenderableSimulation &sim, bool handleEvents);
void AfterSimDraw(const RenderableSimulation &sim);
void SetSimFpsLimit(SimFpsLimit newSimFpsLimit);
SimFpsLimit GetSimFpsLimit() const
{
return simFpsLimit;
}
};

View File

@@ -24,7 +24,6 @@ Engine::Engine():
mousexp_(0),
mouseyp_(0)
{
SetFpsLimit(FpsLimitExplicit{ 60.0f });
}
Engine::~Engine()
@@ -38,19 +37,9 @@ Engine::~Engine()
}
}
void Engine::SetFpsLimit(FpsLimit newFpsLimit)
void Engine::ApplyFpsLimit()
{
fpsLimit = newFpsLimit;
::SetFpsLimit(fpsLimit);
// Populate dt with whatever that makes any sort of sense.
if (auto *explicitFpsLimit = std::get_if<FpsLimitExplicit>(&fpsLimit))
{
SetFps(explicitFpsLimit->value);
}
else
{
SetFps(1);
}
::SetFpsLimit(GetFpsLimit());
}
void Engine::Begin()
@@ -110,7 +99,7 @@ void Engine::ShowWindow(Window * window)
state_->DoBlur();
state_ = window;
ApplyFpsLimit();
}
void Engine::CloseWindowAndEverythingAbove(Window *window)
@@ -153,11 +142,13 @@ int Engine::CloseWindow()
mouseyp_ = mousey_;
}
ignoreEvents = true;
ApplyFpsLimit();
return 0;
}
else
{
state_ = nullptr;
ApplyFpsLimit();
return 1;
}
}
@@ -179,7 +170,7 @@ void Engine::Tick()
{
if(state_ != nullptr)
{
state_->DoTick(dt);
state_->DoTick();
state_->DoSimTick();
}
@@ -241,19 +232,6 @@ void Engine::Draw()
FrameIndex %= 7200;
}
void Engine::SetFps(float fps)
{
this->fps = fps;
if (std::holds_alternative<FpsLimitExplicit>(fpsLimit))
{
this->dt = 60/fps;
}
else
{
this->dt = 1.0f;
}
}
void Engine::onKeyPress(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt)
{
if (state_ && !ignoreEvents)
@@ -396,3 +374,29 @@ std::optional<int> Engine::GetEffectiveDrawCap() const
}
return effectiveDrawCap;
}
void Engine::SetFps(float newFps)
{
if (state_)
{
return state_->SetFps(newFps);
}
}
float Engine::GetFps() const
{
if (state_)
{
return state_->GetFps();
}
return 1;
}
FpsLimit Engine::GetFpsLimit() const
{
if (state_)
{
return state_->GetFpsLimit();
}
return FpsLimitNone{};
}

View File

@@ -60,8 +60,8 @@ namespace ui
void SimTick();
void Draw();
void SetFps(float fps);
inline float GetFps() { return fps; }
void SetFps(float newFps);
float GetFps() const;
inline int GetMouseButton() { return mouseb_; }
inline int GetMouseX() { return mousex_; }
@@ -75,11 +75,7 @@ namespace ui
//inline State* GetState() { return state_; }
inline Window* GetWindow() { return state_; }
void SetFpsLimit(FpsLimit newFpsLimit);
FpsLimit GetFpsLimit() const
{
return fpsLimit;
}
FpsLimit GetFpsLimit() const;
DrawLimit drawingFrequencyLimit;
Graphics * g;
@@ -89,13 +85,11 @@ namespace ui
unsigned int FrameIndex;
private:
FpsLimit fpsLimit;
bool textInput = false;
int lastTextEditingStart = INT_MAX;
float dt;
float fps;
void ApplyFpsLimit();
std::deque<Window*> windows;
std::stack<Point> mousePositions;
//Window* statequeued_;

View File

@@ -26,6 +26,7 @@ Window::Window(Point _position, Point _size):
destruct(false),
stop(false)
{
SetFps(1);
}
Window::~Window()
@@ -228,7 +229,7 @@ void Window::DoDraw()
}
}
void Window::DoTick(float dt)
void Window::DoTick()
{
if (debugMode)
return;
@@ -610,3 +611,29 @@ void Window::Halt()
halt = true;
}
void Window::SetFps(float newFps)
{
fps = newFps;
if (std::holds_alternative<FpsLimitExplicit>(fpsLimit))
{
dt = 60/fps;
}
else
{
dt = 1.0f;
}
}
void Window::SetFpsLimit(FpsLimit newFpsLimit)
{
fpsLimit = newFpsLimit;
// Populate dt with whatever that makes any sort of sense.
if (auto *explicitFpsLimit = std::get_if<FpsLimitExplicit>(&fpsLimit))
{
SetFps(explicitFpsLimit->value);
}
else
{
SetFps(1);
}
}

View File

@@ -1,6 +1,7 @@
#pragma once
#include "common/String.h"
#include "gui/interface/Point.h"
#include "FpsLimit.h"
#include <vector>
class Graphics;
@@ -54,7 +55,7 @@ namespace ui
virtual void DoInitialized();
virtual void DoExit();
virtual void DoTick(float dt);
virtual void DoTick();
virtual void DoSimTick();
virtual void DoDraw();
virtual void DoFocus();
@@ -85,6 +86,16 @@ namespace ui
void MakeActiveWindow();
void CloseActiveWindow();
Graphics * GetGraphics();
void SetFps(float newFps);
float GetFps() const
{
return fps;
}
void SetFpsLimit(FpsLimit newFpsLimit);
FpsLimit GetFpsLimit() const
{
return fpsLimit;
}
protected:
ui::Button * okayButton;
@@ -122,5 +133,8 @@ namespace ui
bool destruct;
bool stop;
float dt;
float fps;
FpsLimit fpsLimit = FpsLimitFollowDraw{};
};
}

View File

@@ -197,10 +197,11 @@ static int debug(lua_State *L)
static int fpsCap(lua_State *L)
{
auto *lsi = GetLSI();
int acount = lua_gettop(L);
if (acount == 0)
{
auto fpsLimit = ui::Engine::Ref().GetFpsLimit();
auto fpsLimit = lsi->window->GetSimFpsLimit();
if (std::holds_alternative<FpsLimitNone>(fpsLimit))
{
lua_pushnumber(L, 2);
@@ -218,10 +219,10 @@ static int fpsCap(lua_State *L)
}
if (fpscap == 2)
{
ui::Engine::Ref().SetFpsLimit(FpsLimitNone{});
lsi->window->SetSimFpsLimit(FpsLimitNone{});
return 0;
}
ui::Engine::Ref().SetFpsLimit(FpsLimitExplicit{ fpscap });
lsi->window->SetSimFpsLimit(FpsLimitExplicit{ fpscap });
return 0;
}

View File

@@ -14,11 +14,7 @@ namespace http
class Request;
}
namespace ui
{
class Window;
}
class GameView;
class Graphics;
class Renderer;
class Simulation;
@@ -82,7 +78,7 @@ public:
GameModel *gameModel;
GameController *gameController;
ui::Window *window;
GameView *window;
Simulation *sim;
Graphics *g;