c++ 使用WIN32 API将游戏循环同步到所需的每秒滴答数

e5njpo68  于 2023-05-02  发布在  其他
关注(0)|答案(1)|浏览(128)

我想写一个游戏循环并测量渲染所需的时间。在循环结束时,我希望线程睡眠一段时间,以免耗尽CPU。现在我想每秒循环60次。
下面是我想到的最小例子:

#include <iostream>
#include <Windows.h>

class Clock {
public:
    Clock() : m_Start(), m_Elapsed(0) {}

    double AbsoluteTime() {
        LARGE_INTEGER current_time;
        QueryPerformanceCounter(&current_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帧。我真的不知道为什么会发生这种情况。如果我不使用睡眠方法,我得到超过4600帧一秒。所以这不可能是性能问题。有没有人遇到过这种情况,或者知道如何解决?

bttbmeg0

bttbmeg01#

Sleep函数的分辨率有限:
系统时钟以恒定速率“滴答”。如果 dwMilliseconds 小于系统时钟的分辨率,则线程可能会休眠少于指定的时间长度。如果 dwMilliseconds 大于一个刻度但小于两个刻度,则等待时间可以介于一个和两个刻度之间,依此类推。要提高休眠间隔的精度,请调用timeGetDevCaps函数确定支持的最小计时器分辨率,并调用timeBeginPeriod函数将计时器分辨率设置为最小值。调用timeBeginPeriod时要小心,因为频繁的调用会严重影响系统时钟、系统电源使用和调度程序。
我建议使用SetWaitableTimerSleepEx函数。

相关问题