我正在尝试用C++创建一个游戏,我想为fps创建限制,但我总是得到比我想要的更多或更少的fps。当我看到有fps限制的游戏时,它总是精确的帧速率。尝试使用Sleep() std::this_thread::sleep_for(sleep_until)
。例如Sleep(0.01-deltaTime)
得到100 fps,但最终得到+-90fps。当任何睡眠都不精确时,这些游戏如何如此精确地处理fps?我知道我可以使用无限循环,它只检查时间是否已过,但它使用了CPU的全部功率,但我希望在不使用VSync的情况下通过此限制降低CPU使用率。
6条答案
按热度按时间trnvg8h31#
是的,睡眠通常是不准确的。这就是为什么你睡眠的时间比完成一帧所需的实际时间要短。例如,如果你需要5毫秒来完成一帧,那么睡眠4毫秒。睡眠后,只需对帧的其余部分进行旋转锁定。类似于
编辑:正如在另一个答案中所述,应该调用timeBeginPeriod()来提高Sleep()的准确性。此外,根据我所读到的,如果您在进程退出之前没有调用timeEndPeriod(),Windows将在进程退出时自动调用它。
rur96b6h2#
您可以在开始时记录时间点,添加一个固定的持续时间,然后休眠,直到计算出的时间点出现在每个循环的结束(或开始)。
lawou6xi3#
被接受的答案听起来真的很糟糕。它不会准确,而且会烧掉CPU!
Thread.Sleep是不准确的,因为你必须告诉它是准确的(默认情况下大约是15 ms准确-意味着如果你告诉它休眠1 ms,它可以休眠15 ms)。
您可以通过Win32 API调用timeBeginPeriod和timeEndPeriod函数来完成此操作。
有关详细信息,请查看MSDN-〉https://learn.microsoft.com/en-us/windows/win32/api/timeapi/nf-timeapi-timebeginperiod
(我会对已接受的答案进行评论,但仍没有50点声望)
nhn9ugyo4#
在实现任何基于调度程序休眠的等待时,请务必小心。
大多数操作系统调度程序都有较高的等待时间,没有明确定义的时间间隔或信号来使线程返回到准备运行状态。
睡眠本身并不是不准确的,你只是在错误地处理问题。如果你可以访问像DXGI的Waitable Swapchain这样的东西,你就可以同步到DWM的当前队列,并获得真正可靠的低延迟定时。
你不需要忙等待来获得准确的计时,一个可等待的计时器会给予你一个同步对象来重新安排你的线程。
无论你做什么,都不要在产品代码中使用当前接受的答案。这里有一个你要避免的边缘情况,即Sleep(0)不会为更高优先级的线程提供CPU时间。我见过很多游戏开发人员尝试Sleep(0),它会给你带来很大的问题。
7kqas0il5#
使用计时器。
某些操作系统可以提供特殊功能。例如,对于Windows,您可以使用SetTimer并处理其
WM_TIMER
消息。然后计算计时器的频率。100 fps表示计时器必须每0.01秒触发一个事件。
您可以在这个计时器事件的事件行程常式中进行呈现。
如果渲染比所需频率慢,则使用同步标志OpenGL sync,并且如果之前的渲染未完成,则丢弃定时器事件。
drnojrws6#
您可以将const fps变量设置为所需的帧速率,然后如果自上次更新以来的经过时间等于或大于1 / desired_fps,您就可以更新游戏。这可能会起作用。示例: