Идеальная реализация V-sync для облегченной игры OpenGL: нужен один кусочек информации - PullRequest
0 голосов
/ 04 февраля 2011

В игре, которую программирует наша интернет-команда, мы предполагаем, что у всех из нашей аудитории будет ПУТЬ в полной скорости в игре.

Таким образом, для экономии видеопамяти и, как мы надеемся, даем немного больше времени простоя графической карте, использование V-sync без двойной буферизации было бы нашим лучшим вариантом. Итак, в OpenGL нам нужно знать, как это сделать.

Насколько я понимаю, V-синхронизация - это когда видеокарта ставится на паузу после завершения рендеринга одного кадра, пока этот кадр не будет отправлен на устройство отображения. Двойная буферизация не приостанавливает операции рендеринга (или, может быть, делает это, или, может быть, это зависит от реализации; не уверен), потому что вместо этого он рисует во второй буфер перед копированием в кадровый буфер, так что монитор получает полный кадр или нет новый кадр вообще (в частности, последнее сохраненное изображение в кадровом буфере). Ну, нам не нужна эта функция, если видеокарта просто пишет в фрейм-буфер ТОЛЬКО тогда, когда это необходимо.

Это довольно медленная онлайн-игра (но ОЧЕНЬ креативная ^ _ ^). Там очень мало действий в реальном времени. Следовательно, чрезвычайно точный пользовательский ввод не является необходимостью; он может быть записан из ОС как единое целое в любое время перед рендерингом кадра.

Итак, чтобы сделать именно это, мне нужно иметь возможность получить сообщение «Кадр завершил отправку на монитор» из OpenGL. Является ли это возможным? Если нет, то какая лучшая альтернатива?

Игра в данный момент программируется для Windows, но для Linux она должна была быть сделана через несколько месяцев.

Ответы [ 2 ]

9 голосов
/ 04 февраля 2011

Вы страдаете от неправильного представления о том, что делает V-Sync.В видео ОЗУ есть часть, которая постоянно отправляется на дисплей с постоянной частотой, частота обновления кадров.Таким образом, сразу после отправки полного кадра отправляется следующий кадр через очень короткое время.Но время между отправкой кадров намного короче, чем время, необходимое для отправки полного кадра.

Что происходит без V-Sync, так это то, что операции с содержимым буфера кадра становятся видимыми, например, если кадрзаполнен попеременно красным и зеленым, и нет V-Sync, вы увидите красные и зеленые полосы на мониторе.Чтобы избежать этого, V-Sync меняет указатель, используемый драйвером дисплея для доступа к буферу кадров сразу после отправки полного кадра.

Что приводит нас к тому, что делает двойной буфер.Без двойной буферизации мало что пригодится для V-Sync.Действие, запускаемое V-Sync, должно происходить очень и очень быстро.Таким образом, это сводится к замене указателя или к очень быстрой операции блиттинга (возможно, просто путем установки атрибутов CoW для MMU графического процессора).

Без двойной буферизации и без V-Sync эффект заключается в том, что можно увидеть процессв котором изображение передается по частям в кадровый буфер.Конечно, если рендеринг происходит быстрее, чем период кадра, это приводит к тому, что сверху вниз вы увидите только малонаселенное изображение с большим и большим количеством контента, видимого в нижней части, и где-то между ними оно достигнет нижнего края экрана,валяется наверх.Линия пересечения будет двигаться.

TL; DR: Просто используйте двойную буферизацию и включите V-Sync для замены буфера.Не бойтесь потребления памяти.Сегодня все графические процессоры имеют более чем достаточно оперативной памяти, чтобы легко обеспечить память для цветовых плоскостей с двойной буферизацией.Просто подсчитайте: 1920x1200 * RGB = 6 МБ, даже самые маленькие графические процессоры на сегодняшний день обеспечивают по крайней мере 128 МБ ОЗУ.Мобильные устройства, скажем, iPad 1024 * 768 * RGB = 2 МБ против 32 МБ для графики.Интерфейс iPad в любом случае имеет двойной буфер.

0 голосов
/ 04 февраля 2011

Вы можете использовать wglGetProcAddress, чтобы получить адрес wglSwapIntervalEXT, а затем вызвать wglSwapIntervalEXT(1);, чтобы синхронизировать обновления с вертикальной синхронизацией.Когда вы делаете это, вы не получаете сообщение при вертикальной синхронизации - вместо этого glFlush просто не возвращается, пока не произошла вертикальная обратная трассировка, и экран не был обновлен.Итак, у вас есть обработчик WM_PAINT, который выглядит примерно так:

BeginPaint
wglMakeCurrent
do drawing
glFlush
EndPaint

glFlush необходим в любом случае, чтобы гарантировать, что сделанный вами чертеж будет отправлен на экран.

...