我想编写一个游戏循环并测量渲染所花费的时间。在循环结束时,我希望线程休眠一段时间,以免耗尽 CPU。目前我想每秒运行 60 次循环。
这是我想出的最小例子:
#include <iostream>
#include <Windows.h>
class Clock {
public:
Clock() : m_Start(), m_Elapsed(0) {}
double AbsoluteTime() {
LARGE_INTEGER current_time;
QueryPerformanceCounter(¤t_time);
LARGE_INTEGER frequency;
QueryPerformanceFrequency(&frequency);
return static_cast<double>(current_time.QuadPart) / frequency.QuadPart;
}
void Start() {
m_Start = AbsoluteTime();
}
double GetElapsed() {
double current_time = AbsoluteTime();
m_Elapsed = current_time - m_Start;
return m_Elapsed;
}
private:
double m_Start;
double m_Elapsed;
};
int main() {
Clock clock;
Clock fpsClock;
int frameCount = 0;
while (true) {
clock.Start();
// Do some rendering stuff....
double elapsed = clock.GetElapsed();
double delay = (1.0 / 60.0) - elapsed;
if (delay > 0) {
Sleep(static_cast<DWORD>(delay * 1000));
}
frameCount++;
if (fpsClock.GetElapsed() > 1.0) {
std::cout << "FPS: " << frameCount << std::endl;
fpsClock.Start();
frameCount = 0;
}
}
return 0;
}
然而,当执行这段代码时,我得到的是每秒打印 33 帧。我真的不确定为什么会这样。如果我根本不使用 Sleep 方法,我每秒会获得超过 4600 帧。所以这不是性能问题。有没有人以前遇到过这个或知道如何解决它?
Sleep功能分辨率有限:
系统时钟以恒定速率“滴答”。如果 dwMilliseconds 小于系统时钟的分辨率,线程可能会休眠少于指定的时间长度。如果 dwMilliseconds 大于一个滴答声但小于两个滴答声,则等待可以在一到两个滴答声之间的任何时间,依此类推。要提高睡眠间隔的准确性,请调用
函数来确定支持的最小计时器分辨率,并调用timeGetDevCaps
函数将计时器分辨率设置为最小值。调用timeBeginPeriod
时要小心,因为频繁调用会显着影响系统时钟、系统电源使用和调度程序。timeBeginPeriod
我建议使用 SetWaitableTimer 和 SleepEx 函数。