Skip to content

Instantly share code, notes, and snippets.

@m4saka
Last active June 12, 2023 01:13
Show Gist options
  • Save m4saka/227b88b19567439574f181278214decc to your computer and use it in GitHub Desktop.
Save m4saka/227b88b19567439574f181278214decc to your computer and use it in GitHub Desktop.
FrameRateLimit addon for OpenSiv3D 0.6.x
// License: CC0 1.0
# include <Siv3D.hpp>
class FrameRateLimit : public IAddon
{
private:
static constexpr std::chrono::steady_clock::duration kMaxDrift = 10ms;
int32 m_targetFPS;
std::chrono::time_point<std::chrono::steady_clock> m_sleepUntil;
public:
explicit FrameRateLimit(int32 targetFPS)
: m_targetFPS(targetFPS)
, m_sleepUntil(std::chrono::steady_clock::now() - kMaxDrift)
{
}
virtual void postPresent() override
{
// Determine the end time of sleep until the next frame
m_sleepUntil += std::chrono::duration_cast<std::chrono::steady_clock::duration>(1s) / m_targetFPS;
// Set a lower limit so that m_sleepUntil does not go back in time from the current time if the target frame rate is not reached
// (Because even if you sleep until the exact current time, there might be a long wait time depending on the environment,
// so as a countermeasure, we are setting the time subtracted by kMaxDrift as the lower limit)
const auto sleepUntilLowerLimit = std::chrono::steady_clock::now() - kMaxDrift;
if (m_sleepUntil < sleepUntilLowerLimit)
{
m_sleepUntil = sleepUntilLowerLimit;
}
// Execute sleep
std::this_thread::sleep_until(m_sleepUntil);
}
void setTargetFPS(int32 targetFPS)
{
m_targetFPS = targetFPS;
}
};
void Main()
{
// Set frame rate
constexpr int32 kTargetFPS = 300;
Addon::Register(U"FrameRateLimit", std::make_unique<FrameRateLimit>(kTargetFPS));
// Disable VSync
Graphics::SetVSyncEnabled(false);
const Font font{ FontMethod::MSDF, 48, Typeface::Bold };
while (System::Update())
{
// Show frame rate
font(U"{}fps"_fmt(Profiler::FPS())).draw();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment