Skip to content

Commit

Permalink
fix: 优化帧率限制精度
Browse files Browse the repository at this point in the history
  • Loading branch information
Blinue committed Dec 30, 2024
1 parent 1ec028b commit 505ab9d
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 23 deletions.
2 changes: 1 addition & 1 deletion src/Magpie.Core/Logger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ void Logger::_Log(spdlog::level::level_enum logLevel, std::string_view msg, cons
assert(!msg.empty());

if (logLevel >= spdlog::level::warn && IsDebuggerPresent()) {
// 警告或更高等级的日志也记录到调试器(VS 中的输出窗口)
// 警告或更高等级的日志也记录到调试器
if (msg.back() == '\n') {
OutputDebugString(StrHelper::Concat(L"[LOG] ", StrHelper::UTF8ToUTF16(msg)).c_str());
} else {
Expand Down
31 changes: 10 additions & 21 deletions src/Magpie.Core/StepTimer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,42 +24,25 @@ void StepTimer::Initialize(float minFrameRate, std::optional<float> maxFrameRate
}

StepTimerStatus StepTimer::WaitForNextFrame(bool waitMsgForNewFrame) noexcept {
const time_point<steady_clock> now = steady_clock::now();
_frameStartTime = steady_clock::now();

if (_lastFrameTime == time_point<steady_clock>{}) {
// 等待第一帧,无需更新 FPS
if (waitMsgForNewFrame) {
WaitMessage();
}

if (_isNewFrame) {
_isNewFrame = false;
_lastFrameTime = now;
}

return StepTimerStatus::WaitForNewFrame;
}

if (_isNewFrame) {
_isNewFrame = false;

if (_HasMinInterval()) {
// 总是以最小帧间隔计算上一帧的时间点。因为最大帧间隔是最小帧间隔的整数倍,
// 帧间隔可以保持稳定。
_lastFrameTime = now - (now - _lastFrameTime) % _minInterval;
} else {
_lastFrameTime = now;
}
}

const nanoseconds delta = now - _lastFrameTime;
const nanoseconds delta = _frameStartTime - _lastFrameTime;

if (delta >= _maxInterval) {
return StepTimerStatus::ForceNewFrame;
}

// 没有新帧也应更新 FPS。作为性能优化,强制帧无需更新,因为 PrepareForNewFrame 必定会执行
_UpdateFPS(now);
_UpdateFPS(_frameStartTime);

if (delta < _minInterval) {
_WaitForMsgAndTimer(_minInterval - delta);
Expand All @@ -79,7 +62,13 @@ StepTimerStatus StepTimer::WaitForNextFrame(bool waitMsgForNewFrame) noexcept {
}

void StepTimer::PrepareForNewFrame() noexcept {
_isNewFrame = true;
if (_HasMinInterval()) {
// 总是以最小帧间隔计算上一帧的时间点。因为最大帧间隔是最小帧间隔的整数倍,
// 帧间隔可以保持稳定。
_lastFrameTime = _frameStartTime - (_frameStartTime - _lastFrameTime) % _minInterval;
} else {
_lastFrameTime = _frameStartTime;
}

++_framesThisSecond;
++_frameCount;
Expand Down
2 changes: 1 addition & 1 deletion src/Magpie.Core/StepTimer.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class StepTimer {
std::atomic<uint32_t> _framesPerSecond = 0;
uint32_t _framesThisSecond = 0;

bool _isNewFrame = false;
std::chrono::time_point<std::chrono::steady_clock> _frameStartTime;
};

}

0 comments on commit 505ab9d

Please sign in to comment.