[我试图在CPP中为Windows创建一个简单的图形程序(我的机器上装有Windows 10,并且我正在努力锁定帧速率。
这是我的问题的简单说明:
inline LARGE_INTEGER
get_wall_clock()
{
LARGE_INTEGER result;
QueryPerformanceCounter(&result);
return result;
}
static LARGE_INTEGER frequency;
inline float
get_seconds_elapsed(LARGE_INTEGER begin, LARGE_INTEGER end)
{
return (float)(end.QuadPart - begin.QuadPart) / (float)frequency.QuadPart;
}
int main()
{
bool can_sleep = (timeBeginPeriod(1) == TIMERR_NOERROR);
QueryPerformanceFrequency(&frequency);
int target_HZ = 60;
float target_seconds_per_frame = 1.0f / (float)target_HZ;
LARGE_INTEGER last_counter = get_wall_clock();
while(true)
{
do_something();
LARGE_INTEGER end_frame = get_wall_clock();
float seconds_of_work = get_seconds_elapsed(last_counter, end_frame);
float seconds_of_frame = seconds_of_work;
if(seconds_of_work < target_seconds_per_frame)
{
if(can_sleep)
{
int ms_to_sleep = (int)(1000.0f * (target_seconds_per_frame - seconds_of_work));
if(ms_to_sleep)
{
Sleep(ms_to_sleep);
}
}
float frame_duration = get_seconds_elapsed(last_counter, get_wall_clock());
Assert(frame_duration < target_seconds_per_frame);
while(seconds_of_frame < target_seconds_per_frame)
seconds_of_frame = get_seconds_elapsed(last_counter, get_wall_clock());
}
last_counter = get_wall_clock();
}
timeEndPeriod(1);
}
我的问题是断言:
Assert(frame_duration < target_seconds_per_frame);
几乎总是在开火。
[我试图对睡眠的毫秒数进行一些调整,甚至调整了睡眠时间,使其只能睡眠所需的90%的毫秒-但这似乎没有帮助。
但是真正的奇怪之处是以下...当我尝试通过以下方法测量Sleep函数实际睡眠的时间时:
LARGE_INTEGER sleep_start = get_wall_clock();
Sleep(ms_to_sleep);
float seconds_slept = get_seconds_elapsed(sleep_start, get_wall_clock());
我发现有时它会睡[[waaayyy超过要求的毫秒数。看到相差10到20毫秒的情况并不少见(我有一次ms_to_sleep
为12,实际上它睡了30毫秒以上)。
ms_to_sleep
的地板可以覆盖...还有其他方法可以可靠地等待帧结束(不仅仅是循环)?
预先感谢你们...
有什么明显的地方我想念吗?
坦白说,是的。您没有阅读手册。从docs:
经过睡眠间隔后,线程准备运行。如果指定0毫秒,则线程将放弃其时间片的其余部分,但保持就绪状态。请注意,不能保证就绪线程可以立即运行。因此,线程可能要等到睡眠间隔过后的一段时间才能运行。有关更多信息,请参阅安排优先级。
Sleep
不能完全按照您要求的时间睡觉。