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

问题描述 投票:0回答:1

我想编写一个游戏循环并测量渲染所花费的时间。在循环结束时,我希望线程休眠一段时间,以免耗尽 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 帧。我真的不确定为什么会这样。如果我根本不使用 Sleep 方法,我每秒会获得超过 4600 帧。所以这不是性能问题。有没有人以前遇到过这个或知道如何解决它?

c++ winapi game-loop
1个回答
0
投票

Sleep功能分辨率有限:

系统时钟以恒定速率“滴答”。如果 dwMilliseconds 小于系统时钟的分辨率,线程可能会休眠少于指定的时间长度。如果 dwMilliseconds 大于一个滴答声但小于两个滴答声,则等待可以在一到两个滴答声之间的任何时间,依此类推。要提高睡眠间隔的准确性,请调用

timeGetDevCaps
函数来确定支持的最小计时器分辨率,并调用
timeBeginPeriod
函数将计时器分辨率设置为最小值。调用
timeBeginPeriod
时要小心,因为频繁调用会显着影响系统时钟、系统电源使用和调度程序。

我建议使用 SetWaitableTimerSleepEx 函数。

© www.soinside.com 2019 - 2024. All rights reserved.