Я пытаюсь создать образец приложения, используя glew и glfw. Основной цикл прост и выглядит так:
while (running) {
someUsefullMathHere();
renderer->render(timeDelta);
glfwSwapBuffers(window);
glfwPollEvents();
running = running & (!glfwWindowShouldClose(window));
}
Проблема в том, что из-за vsync текущий поток спит в течение некоторого времени выполнения glfwSwapBuffers (частота кадров ограничена 60 кадрами в секунду). Я ищу способ использовать это время для последовательного выполнения метода someUsefullMath. В идеале код должен выглядеть примерно так:
while (running) {
while (!timeToRenderAndSwap()) {
someUsefullMathHere();
}
renderer->render(timeDelta);
glfwSwapBuffers(window);
glfwPollEvents();
running = running & (!glfwWindowShouldClose(window));
}
Есть ли способ для этого?
Решение проблемы
Современные реализации GL обычно не блокируются на SwapBuffers
, даже если VSync включен. Они будут ставить в очередь команды GL на несколько кадров вперед и блокировать только SwapBuffers
после того, как будет достигнуто ограничение на количество кадров в очереди, зависящее от реализации (кстати, в драйвере nvidia для Windows есть явная настройка для этого). В немодифицированном цикле рендеринга, который вы набросали, это приводит к тому, что обычно первые две-пять итераций цикла не блокируются, а все последующие — блокируются.
С достаточно современным GL вы можете использовать объекты синхронизации, чтобы улучшить ситуацию. В псевдокоде это может выглядеть так:
GLsync fence=NULL;
while (running) {
if (fence) {
while (glClientWaitSync(fence, GL_SYNC_FLUSH_COMMANDS_BIT, 0)==GL_TIMEOUT_EXPIRED) {
someUsefullMathHere();
}
glDeleteSync(fence);
fence=NULL;
}
renderer->render(timeDelta);
glfwSwapBuffers(window);
fence=glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
glfwPollEvents();
running = running & (!glfwWindowShouldClose(window));
}
if (fence) {
glDeleteSync(fence);
}
Это использует тот факт, что SwapBuffers
не будет немедленно блокироваться, а будет использоваться все время, пока обмен буфера не будет фактически выполнен для полезной математики, которую вы хотите сделать.
Это также имеет побочный эффект ограничения задержки до одного кадра, что может быть хорошо или плохо, в зависимости от вашего сценария. Но, в принципе, вы также можете чередовать несколько объектов синхронизации ограждения и ждать предпоследней замены буфера вместо последнего и так далее.
Комментариев нет:
Отправить комментарий