我有一个简单的循环
LARGE_INTEGER ticks_per_second;
::QueryPerformanceFrequency(&ticks_per_second);
MSG msg = { 0 };
while (true)
{
if (msg.message == WM_QUIT)
exit(0);
if (::PeekMessageW(&msg, NULL, 0U, 0U, PM_REMOVE))
{
::TranslateMessage(&msg);
::DispatchMessageW(&msg);
continue;
}
static double last_time_s = 0;
LARGE_INTEGER cur_time_li;
::QueryPerformanceCounter(&cur_time_li);
double cur_time_s = (double)cur_time_li.QuadPart / (double)ticks_per_second.QuadPart;
double diff_s = cur_time_s - last_time_s;
double rate_s = 1 / 30.0f;
uint32_t slept_ms = 0;
if (diff_s < rate_s)
{
slept_ms = (uint32_t)((rate_s - diff_s) * 1000.0);
::Sleep(slept_ms);
}
update();
::printf("updated %f %u\n", diff_s, slept_ms);
last_time_s = cur_time_s;
}
并且希望 update() 每秒被调用 30 次,但不要更频繁 使用这段代码会出错,在控制台中我得到如下内容:
updated 0.031747 1
updated 0.001997 31
updated 0.031912 1
updated 0.001931 31
updated 0.031442 1
updated 0.002084 31
这似乎仅对于第一次更新是正确的,第二次调用太快,我不明白为什么 我知道 update、PeekMessageW 等也浪费时间,但即使我创建一个 while (true) 循环并注释 update() ,它仍然打印类似的结果 我使用 DirectX 11 并关闭垂直同步进行渲染(在更新函数内渲染):
g_pSwapChain->Present(0, 0);
如何修复代码以使 update() 稳定地在一秒钟内调用 30 次?
最佳答案
我不认为转换为双倍是个好主意。我会运行这样的东西:
static LARGE_INTEGER last_time_s = { 0 };
::QueryPerformanceCounter(&cur_time_li);
time_diff_microsec.QuadPart = cur_time_li.QuadPart - last_time_s.QuadPart;
// To avoid precision lost, convert to seconds *before* dividing by ticks-per-second.
time_diff_microsec.QuadPart *= 1000000;
time_diff_microsec.QuadPart /= ticks_per_second.QuadPart;
double rate_s = 1 / 30.0f;
uint32_t slept_ms = 0;
if (time_diff_microsec.QuadPart >= rate_s)// if (diff_s < rate_s)
{
// slept_ms = (uint32_t)(rate_s - time_diff_microsec.LowPart);// *1000.0);
// ::Sleep(slept_ms);
//}
//update();
::printf("updated %lld %u\n", time_diff_microsec.QuadPart, slept_ms);
}
last_time_s.QuadPart = time_diff_microsec.QuadPart/ 1000000;
}
只是简单的“草图”。但尚未验证计算是否正确。
关于c++ - 在 Windows 中限制帧速率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59336323/