C++ 如何设置精确的帧率限制?
C++ How to make precise frame rate limit?
我正在尝试使用C++创建游戏,我想为 fps 创建限制,但我总是得到比我想要的更多或更少的 fps。当我查看具有 fps 限制的游戏时,它总是精确的帧速率。已尝试使用Sleep() std::this_thread::sleep_for(sleep_until)
.例如,Sleep(0.01-deltaTime)
获得 100 fps,但最终得到 +-90fps。 当任何睡眠不精确时,这些游戏如何如此精确地处理 fps? 我知道我可以使用无限循环来检查时间是否过去,但它正在使用 CPU 的全部功能,但我想在没有 VSync 的情况下通过此限制降低 CPU 使用率。
您可以在开始时记录时间点,为其添加固定持续时间并休眠,直到计算的时间点出现在每个循环的结束(或开始(处。例:
#include <chrono>
#include <iostream>
#include <ratio>
#include <thread>
template<std::intmax_t FPS>
class frame_rater {
public:
frame_rater() : // initialize the object keeping the pace
time_between_frames{1}, // std::ratio<1, FPS> seconds
tp{std::chrono::steady_clock::now()}
{}
void sleep() {
// add to time point
tp += time_between_frames;
// and sleep until that time point
std::this_thread::sleep_until(tp);
}
private:
// a duration with a length of 1/FPS seconds
std::chrono::duration<double, std::ratio<1, FPS>> time_between_frames;
// the time point we'll add to in every loop
std::chrono::time_point<std::chrono::steady_clock, decltype(time_between_frames)> tp;
};
// this should print ~10 times per second pretty accurately
int main() {
frame_rater<10> fr; // 10 FPS
while(true) {
std::cout << "Hello worldn";
fr.sleep(); // let it sleep any time remaining
}
}
是的,睡眠通常是不准确的。这就是为什么你的睡眠时间少于完成帧所需的实际时间。例如,如果还需要 5 毫秒才能完成帧,则睡眠 4 毫秒。睡眠后,只需对帧的其余部分进行旋转锁定即可。类似的东西
float TimeRemaining = NextFrameTime - GetCurrentTime();
Sleep(ConvertToMilliseconds(TimeRemaining) - 1);
while (GetCurrentTime() < NextFrameTime) {};
编辑:如另一个答案所述,应该调用timeBeginPeriod((以提高Sleep((的准确性。另外,根据我所读到的内容,当您的进程退出时,如果您在此之前没有退出,Windows将自动调用timeEndPeriod((。
接受的答案听起来真的很糟糕。它不会准确,它会烧毁 CPU!
Thread.Sleep 不准确,因为您必须告诉它是准确的(默认情况下大约 15 毫秒准确 - 这意味着如果你告诉它睡眠 1 毫秒,它可以睡眠 15 毫秒(。
您可以使用Win32 API调用timeBeginPeriod和timeEndPeriod函数来执行此操作。
查看 MSDN 以获取更多详细信息 -> https://learn.microsoft.com/en-us/windows/win32/api/timeapi/nf-timeapi-timebeginperiod
(我会评论接受的答案,但仍然没有 50 的声誉(
在实现任何基于调度程序睡眠的等待时要非常小心。
大多数操作系统计划程序具有更高的延迟周转时间,等待时间没有明确定义的间隔或信号,无法将线程恢复到准备运行状态。
睡眠本身并不是不准确的,你只是在处理问题时完全错了。如果您可以访问 DXGI 的可等待交换链之类的内容,则可以同步到 DWM 的当前队列并获得真正可靠的低延迟计时。
您无需忙于等待即可获得准确的计时,可等待计时器将为您提供一个同步对象来重新安排线程。
无论您做什么,都不要在生产代码中使用当前接受的答案。这里有一个你想要避免的边缘情况,其中睡眠 (0( 不会将 CPU 时间让给更高优先级的线程。我见过很多游戏开发者尝试睡眠(0(,它会给你带来重大问题。
使用计时器。
某些操作系统可以提供特殊功能。例如,对于Windows,您可以使用SetTimer 并处理其WM_TIMER
消息。
然后计算计时器的频率。 100 fps 表示计时器必须每 0.01 秒触发一个事件。
在此计时器事件的事件处理程序中,您可以进行渲染。
如果渲染速度慢于所需频率,请使用 syncro 标志 OpenGL sync,如果之前的渲染未完成,则丢弃计时器事件。
您可以将const fps 变量设置为所需的帧速率,然后如果上次更新后的经过时间等于或大于 1/desired_fps,则可以更新游戏。 这可能会起作用。 例:
const /*or constexpr*/ int fps{60};
// then at update loop.
while(running)
{
// update the game timer.
timer->update();
// check for any events.
if(timer->ElapsedTime() >= 1 / fps)
{
// do your updates and THEN renderer.
}
}
- 如何提高 OpenCV 实时检测器应用程序的帧率?
- C++ 如何设置精确的帧率限制?
- 提高Basler相机的帧率
- 低帧率,仅使用地图和小地图绘制 (SFML)
- OpenCV视频阅读慢帧率
- C++SDL帧率脉冲
- OpenGL帧率:与窗口大小的连接
- 在openCV中编写可变帧率视频
- 快板5线程影响帧率
- OpenCV VideoWriter帧率问题
- 如何找到视频的帧率使用c++ opencv 2.4.10
- 控制帧率
- 我如何获得和改变OGRE应用程序的帧率?
- OpenCV慢相机帧率
- 数学:无论帧率如何,都能平稳地减速
- 如何改变libav解码帧率
- 发行控制游戏帧率的c++
- OpenCV -从播放显著提高帧率
- OpenCV:低帧率的限制是什么?
- 将帧率提高到30 fps,并从AVT GigE相机获得bayerr8