【发布时间】:2020-08-22 15:14:49
【问题描述】:
我试图在 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% 的毫秒 - 但它似乎没有帮助。
但真正奇怪的是以下...当我尝试通过以下方法测量睡眠功能实际睡眠的时间时:
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 多毫秒)。
我在这里有什么明显的遗漏吗?
我知道根据文档,睡眠不能保证在请求的时间内睡眠,但我认为 timeBeginPeriod +ms_to_sleep 的地板可以覆盖...
有没有其他方法可以可靠地等待帧结束(除了循环)?
提前谢谢各位...
【问题讨论】:
标签: c++ windows sleep frame-rate msdn