Скільки часу потрібно, щоб OpenGL фактично оновив екран?


9

У мене є простий тестовий додаток OpenGL в C, який малює різні речі у відповідь на введення ключа. (Mesa 8.0.4, спробували з Mesa-EGL та GLFW, Ubuntu 12.04LTS на ПК із NVIDIA GTX650). Малюнки досить прості / швидкі (обертовий тип трикутника). Мій тестовий код свідомо не обмежує рамку, він виглядає приблизно так:

while (true)
{
    draw();
    swap_buffers();
}

Я придумував це дуже ретельно, і вважаю, що час від одного eglSwapBuffers()(або того glfwSwapBuffersж самого) дзвінка до наступного становить ~ 16,6 мілісекунд. Час після дзвінка до eglSwapBuffers()безпосередньо перед наступним дзвінком лише трохи менший, ніж те, що малюється дуже просто. Час, який потребує виклик буферів своп, становить менше 1 мс.

Однак час, коли додаток змінює те, що він малює, у відповідь на натискання клавіші на зміну, яка фактично відображається на екрані, становить> 150 мс (приблизно 8-9 кадрів). Це вимірюється за допомогою камери на екрані та клавіатурі в 60 кадрів в секунду.

Тому питання:

  1. Де розміщені розіграші між закликом до заміни буферів і фактичним відображенням на екрані? Чому затримка? Напевно, схоже, що додаток малює багато кадрів попереду екрана.

  2. Що може зробити програма OpenGL для негайного малювання на екрані? (тобто: не буферизація, просто блокуйте, поки малюнок не завершиться; мені не потрібна висока пропускна здатність, мені потрібна низька затримка)

  3. Що може зробити програма, щоб зробити вищезазначене негайне розіграш якнайшвидше?

  4. Як програма може знати, що саме зараз є на екрані? (Або скільки часу / скільки кадрів становить поточна затримка буферизації?)


Чи можете ви відокремити час, який потрібна клавіатурі, щоб сповістити вашу програму, і час, необхідний для її фактичного відображення?
ThorinII

@ThorinII: Справедливий пункт. Я, ймовірно, можу налаштувати щось хакі, використовуючи світлодіод на паралельному порту тощо, щоб отримати вказівку, коли програма насправді отримує клавішу. І все-таки це просто fgetc (stdin), наскільки повільним це може бути? : /
Олексій І

У мене було враження, що glFlush використовується для негайного розмивання всіх команд.
Programmdude

1
@AlexI перевірити це gamedev.stackexchange.com/questions/66543/… може допомогти вам
concept3d

1
@ concept3d: Так, в основному відповіли, просто подумав, що вам сподобається додаткова представниця :) Мабуть, мені доведеться почекати день, щоб нагородити це.
Олексій І

Відповіді:


6

Будь-яка функція API малювання, викликана з процесора, буде передана в буфер командного кільця GPU, який буде виконаний пізніше GPU. Це означає, що функції OpenGL - це в основному неблокуючі функції. Тож процесор і GPU працюватимуть паралельно.

Найголовніше, що потрібно відзначити, це те, що ваша програма може бути пов'язана з процесором або графічним процесором. як тільки ви зателефонуєте на glFinish, процесор повинен зачекати GPU, щоб виконати свої команди малювання, якщо GPU займає більше часу і може / викликає зупинку процесора, то ваші програми пов'язані з графічним процесором. Якщо GPU закінчує нанесення команд, і процесор забирає занадто багато часу, щоб glFinish, то ваша програма пов'язана з процесором.

І зауважте, що різниця між glFlushі glFinish.

glFlush: вказує на те, що всі команди, які раніше були надіслані в GL, повинні виконуватись за обмежений час.

glFinish: примушує всі попередні команди GL виконувати. Завершення не повертається до тих пір, поки всі ефекти з раніше виданих команд на стан клієнта та сервера GL та фреймбуфер не будуть повністю реалізовані. "

glXSwapBuffers виконує неявну glFlush перед поверненням. Наступні команди OpenGL можуть бути видані негайно після виклику glXSwapBuffers, але вони не виконуються до завершення обміну буферами.

Фактичний час кадру буде, швидше за все, визначатися тим, кому з двох процесорів / GPU потрібно більше часу для завершення роботи.


Це дуже корисно. Деякі можливі виправлення: opengl.org/sdk/docs/man2/xhtml/glXSwapBuffers.xml "glXSwapBuffers виконує неявний glFlush перед поверненням", здається, це насправді не робить glFinish, тому буфер команд може мати досить багато в ньому, коли повертаються буфери swap.
Олексій І

... Крім того, я думаю, що найцікавішим моментом є те, що мій дуже простий тестовий додаток не є ні процесором, ні GPU обмеженим - ні багато роботи тут робити - але щось інше, воно якось закінчується як низьким частотою кадрів (точно таким же, як монітор частота оновлення ??) і висока затримка (через буфер команд, ви насправді добре пояснили цю частину).
Олексій І

@AlexI both low framerate (exactly same as monitor refresh rate??ні, якщо ви прямо не використовуєте VSync.
concept3d

@ Алекси Я також хочу зазначити, що час кадру відрізняється від FPS, використовуйте час кадру для профілю вашої програми, оскільки це лінійно. FPS, з іншого боку, є поганим вимірюванням, яке не є лінійним.
concept3d

Я не використовую явно vsync. Я нічого не роблю, щоб змінити параметри vsync за замовчуванням, я навіть не знаю, де їх змінити в OpenGL. Я просто отримую рівно 60 кадрів в секунду (до відсотка).
Олексій І

4

OpenGL ніколи технічно не оновлює екран.

Існує API віконної системи, який окремо від GL (наприклад, GLX, WGL, CGL, EGL), який робить це. Буферні підкачки за допомогою цих API зазвичай неявно викликають, glFlush (...)але в деяких реалізаціях (наприклад, GDI-растризатор в Windows) він виконує повне glFinish (...):

 

    * Ліворуч проходить шлях МКБ (обладнання) SwapBuffers (...). З правого боку - шлях GDI (програмне забезпечення).

Якщо увімкнено VSYNC та подвійне буферизація, то будь-яка команда, яка модифікувала би задній буфер до того, як відбудеться своп, що очікує, повинен зупинитися до заміни. У черзі команд є обмежена глибина, тому ця застопоріла команда з часом спричинить затор у трафіку. Це може означати, що замість блокуванняSwapBuffers (...) вашій програмі насправді блокується якась непов'язана команда GL, поки VBLANK не обернеться. Насправді це зводиться до кількості зворотних буферів у вашому ланцюзі свопів.

Поки всі задні буфери заповнені готовими кадрами, які ще мають бути переміщені на передню частину, буфери підкачки неявно спричинять блокування. На жаль, немає можливості явно контролювати кількість зворотних буферів, які використовуються більшістю API віконних систем GL (крім 0 однобуферних або 1 двобуферних). Драйвер може безкоштовно використовувати 2 зворотних буфера, якщо він хоче (потрійне буферування), але ви не можете вимагати цього на рівні програми, використовуючи щось на зразок GLX або WGL.


Андон: Хороша інформація, дякую. Я думаю, що я бачу частково подвійне буферизація, але: "спроба змінити задній буфер до того, як відбудеться своп, повинна блокуватися" - чому? це здається, що все може бути надіслано до буфера команд, включаючи своп :)
Олексій І

"явно контролює кількість зворотних буферів, які використовуються більшістю API віконних систем GL (окрім 0 однобуферних або 1 двобуферних)" - як один керуючий один / подвійний буферизований?
Олексій І

@AlexI: Я уточнив мову щодо того, чому команда може призвести до блокування. В інших API існує концепція, відома як візуалізація, яка фактично є глибиною черги команд. Що стосується керування одинарним / подвійним буферизованим, він контролюється піксельним форматом, який ви вибираєте під час створення контексту візуалізації. У WGL ви можете вибрати одно- або двобуферні, але якщо ви виберете подвійний буферизатор, драйвер може насправді створити два зворотні буфери (таким чином подвійне буферизація стає потрійним буферуванням), якщо користувач встановить свій драйвер для цього.
Андон М. Коулман

Ви насправді не хочете виводити занадто багато кадрів попереду, оскільки, хоча це зменшить блокування, воно також збільшує затримку. Найкращий спосіб мінімізувати затримку - це насправді викликати glFinish (...)відразу після заміни буферів. Це очистить чергу команд, але це також означає, що GPU і CPU будуть синхронізовані (що не добре, якщо ви хочете тримати роботу GPU весь час).
Андон М. Коулман

1

Я припускаю, що ви знайомі з цим експериментом ?

По суті, Джон Кармак займався чимось подібним, записуючи на екран і надсилаючи на екран пікселі. Він виявив, що значна частина затримок виходить з екрану. Іншими факторами були затримка введення з клавіатури, відеодрайвери і, звичайно, виконання програми.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.