2017-02-02 16 views
0

Я создаю модуль, который должен отображать изображения с определенной скоростью (не предварительно определенные, но не очень высокие) - 10 Гц для обмена изображениями).Показать изображение с qt & opengl, точностью времени и проблемами vsync, C++

Из моих исследований я пришел к выводу, что QGLWidget является правильным инструментом для этой задачи после включения vsync с вызовами openGL (семейство SwapInterval).

Тем не менее, я не знаю, как на самом деле реализовать механизм обмена - следует ли использовать таймер? Если я устанавливаю таймер на 333,3 мс (3 Гц), когда частота обновления составляет 60 Гц (16,67 за цикл, таким образом, таймер составляет 20 циклов), и я уверен, что синхронизация будет прекрасной? И если скорость должна быть 9 Гц, мне нужно установить таймер на 100 + 16,67, потому что это лучшее, что я могу получить? И если таймер в порядке, должен ли я просто вызвать paintGL(), когда он отправит мне время ожидания?

Благодаря

ответ

1

я должен использовать таймер?

Да, но не наивным образом. Если вы просто используете таймер для точного определения изображений, ваша частота таймера будет beat против дисплея. V-Sync/refresh generator - программные таймеры работают от другого источника синхронизации, чем выход дисплея.

Это избиение приведет к пропущенным интервалам подкачки, которые будут восприниматься как застревание рамы.

Вместо этого вы должны сделать следующее: Использовать V-синхронизированный буферный своп (SwapBuffers¹) в качестве контрольной точки для запуска высокоточного времени измерение таймер.

Затем визуализируйте рамку для следующего времени презентации в будущем, к которому вы стремитесь; учитывайте, что интервалы кадров входят в гранулярность интервала обновления дисплея - если не используются G-Sync или FreeSync. Используйте glFinish для принудительного завершения процесса рендеринга кадра, затем остановите таймер и определите, сколько времени потребовалось для рендеринга кадра. Если кадр был закончен раньше периода обновления, который вы намеревались добавить (задержка высокого разрешения), которая задерживает вашу программу в течение периода отображения (нацеливается на середину периода), а затем SwapBuffers, который будет ссылкой точка для следующей итерации.


¹: Это будет работать надежно только для карт Nvidia и AMD и их проприетарных драйверов. Драйверы для графических процессоров Intel имеют разные временные характеристики.

+0

Спасибо, но что вы подразумеваете под «V-Synced buffer swap»? Как я могу начать измерять, когда это произойдет? Это что-то, что я могу контролировать или получить? Из того, что я понимаю, буферный обмен называется неявно, а не мной. – JLev

+1

@JLev: Вы используете QGLWidget, который технически является наследием Qt-4, и вы правы, что в Qt-5 с QOpenGLWindow все стало немного сложнее. В любом случае, QGLWidget имеет функцию-член 'QGLWidget :: swapBuffers', которая делает именно то, что подразумевает его название. Однако для фактической синхронизации V-Sync должен быть включен. Это может быть принудительно/запрещено в настройках графического драйвера и поведение, запрошенное во время выполнения, настроенное с помощью расширений '... swap_control' (см. Http://opengl.org/registry search for' swap_control'). – datenwolf

+0

Пытаясь реализовать ваше предложение, мне трудно найти синхронизацию v-sync. Я думаю, может быть, проблема заключается в инициализации первого запуска таймера - если я вызываю swapbuffers только для справки, я получаю «QOpenGLContext :: swapBuffers(), вызываемый с незакрытым окном, поведение не определено». Должен ли я просто сделать что-то пустое и использовать его? – JLev