OpenGL несинхронизированная / неблокирующая карта - PullRequest
7 голосов
/ 06 августа 2011

Я только что нашел следующую спецификацию OpenGL для ARB_map_buffer_range.

Мне интересно, возможно ли выполнять неблокирующие вызовы карты с помощью этого расширения?

В настоящее время в моем приложении я рендеринг в FBO, который я затем сопоставить с буфером PBO хоста.

glMapBuffer(target_, GL_READ_ONLY);  

Однако проблема в том, что при передаче данных он блокирует поток рендеринга.

Я мог бы уменьшить эту проблему путем конвейерного рендеринга, но задержка - большая проблема в моем приложении.

Мой вопрос заключается в том, могу ли я использовать map_buffer_range с MAP_UNSYNCHRONIZED_BIT и ждать завершения операции карты в другом потоке, или отложить операцию карты в том же потоке, пока поток рендеринга отображает следующий кадр.

, например

thread 1:

map();
render_next_frame();

thread 2:

wait_for_map

или

thread 1:

map();
while(!is_map_ready())
   do_some_rendering_for_next_frame();

В чем я не уверен, так это в том, как я знаю, когда операция сопоставления готова, в спецификации упоминаются только «другие методы синхронизации для обеспечения правильной работы».

Есть идеи?

Ответы [ 2 ]

7 голосов
/ 07 августа 2011

Если вы сопоставите буфер с GL_MAP_UNSYNCHRONIZED_BIT, драйвер не будет ждать, пока OpenGL завершит работу с этой памятью, прежде чем отобразить его для вас. Таким образом, вы получите более или менее немедленный доступ к нему.

Проблема в том, что это не означает, что вы можете просто читать / записывать эту память волей-неволей. Если OpenGL читает или записывает данные в этот буфер, и вы меняете его ... добро пожаловать в неопределенное поведение . Который может включать сбой.

Поэтому, чтобы фактически использовать несинхронизированное отображение, вы должны синхронизировать свое поведение с доступом OpenGL к этому буферу. Это будет включать использование объектов ARB_sync (или NV_fence, если вы используете только NVIDIA и недавно не обновляли свои драйверы).

При этом, если вы используете объект ограждения для синхронизации доступа к буферу, то вам действительно не нужен GL_MAP_UNSYNCHRONIZED_BIT вообще. Как только вы закончите ограждение или обнаружите, что он завершен, вы можете нормально отобразить буфер, и он должен завершиться немедленно (если только не выполняется какая-либо другая операция чтения / записи).

В общем, несинхронизированный доступ лучше всего использовать, когда вам нужен детальный доступ для записи в буфер. В этом случае хорошее использование объектов синхронизации даст вам то, что вам действительно нужно (возможность определить, когда операция карты завершена).


Приложение. Вышеуказанное устарело (в зависимости от вашего оборудования). Благодаря OpenGL 4.4 / ARB_buffer_storage теперь вы можете не только отображать несинхронизированные, вы можете хранить буфер, отображенный , на неопределенный срок. Да, вы можете иметь буфер, отображенный , пока он находится в использовать.

Это делается путем создания неизменяемого хранилища и предоставления этому хранилищу (среди прочего) GL_MAP_PERSISTENT_BIT. Тогда вы glMapBufferRange, также предоставив тот же бит.

Теперь технически это ничего не меняет. Вам все еще нужно синхронизировать свои действия с OpenGL. Если вы записываете материал в область буфера, вам нужно либо выдать барьер , либо , чтобы очистить эту область буфера явно . И если вы читаете, вам все равно нужно использовать объект синхронизации забора , чтобы убедиться, что данные на самом деле там перед их чтением (и если вы не используете GL_MAP_COHERENT_BIT тоже, перед чтением вам нужно будет поставить барьер).

6 голосов
/ 06 августа 2011

Как правило, невозможно создать «неблокирующую карту», ​​но вы можете отобразить без блокировки.

Причина, по которой не может быть «неблокирующей карты», заключается в том, что в момент возврата вызова функции, вы можете получить доступ к данным, поэтому водитель должен убедиться, что он там, положительно.Если данные не были переданы, что еще может сделать драйвер, кроме как заблокировать.
Потоки не делают это лучше и, возможно, ухудшают его (добавляя проблемы синхронизации и совместного использования контекста).Потоки не могут волшебным образом устранить необходимость переноса данных.

И это приводит к тому, как не блокировать отображение: отображать только тогда, когда вы уверены, что передача завершена.Один из безопасных способов сделать это - отобразить буфер после переключения буферов, или после glFinish, или после ожидания объекта запроса / забора.Использование забора является предпочтительным способом, если вы не можете дождаться замены буферов.Забор не остановит конвейер, но сообщит вам, выполнен ли ваш перенос (glFinish может или не может, но , вероятно, остановится).Чтение после замены буферов также на 100% безопасно, но может быть неприемлемо, если вам нужны данные в одном кадре (хотя отлично работает для снимков экрана или для расчета гистограммы для отображения тонов).

Менее безопасный способэто вставить «некоторые другие вещи» и надеяться, что в это время передача завершена.

В отношении нижеследующего комментария:
Этот ответ не неверен.Невозможно сделать что-то лучше, чем получить доступ к данным после того, как они станут доступны (это должно быть очевидно).Это означает, что вы должны синхронизировать / блокировать, так или иначе, выбора нет.
Хотя, с очень педантичной точки зрения, вы, конечно, можете использовать GL_MAP_UNSYNCHRONIZED_BIT, чтобы получитьнеблокирующая операция сопоставления, это совершенно не имеет значения, поскольку она не будет работать, если вы явно не воспроизведете неявную синхронизацию, как описано выше.Картография, к которой вы не можете получить безопасный доступ, бесполезна.

Отображение и доступ к буферу, в который OpenGL передает данные без синхронизации / блокировки (неявно или явно), означает «неопределенное поведение», что является лишь более приятной формулировкой для «возможно, результаты мусора, возможно, сбой».
Если, с другой стороны, вы явно синхронизируете (скажем, с забором, как описано выше), то не имеет значения, используете ли вы флаг несинхронизированного, так как в любом случае не требуется никакой неявной синхронизации.

...