Функция отрисовки графического процессора OpenGL 4.0?

В описании OpenGL 4.0 из Википедии и других источников я читал об этой функции:

Рисование данных, сгенерированных OpenGL или внешними API, такими как OpenCL, без вмешательства ЦП.

К чему это относится?

Изменить:

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

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


person Garet Claborn    schedule 18.02.2011    source источник


Ответы (3)


Я полагаю, что вы можете иметь в виду функцию GL_ARB_draw_indirect, которая позволяет OpenGL получать параметры DrawArrays или DrawElements из объекта буфера графического процессора, которые могут быть заполнены OpenGL или OpenCL.

Если не ошибаюсь, он входит в ядро ​​OpenGL 4.

person rotoglup    schedule 19.02.2011
comment
Пока я вижу, что это используется только в отношениях, когда сетевой сервер обрабатывает некоторый рендеринг для клиентского компьютера. - person Garet Claborn; 23.02.2011
comment
@ Гарет - я не уверен, что понимаю, что ты имеешь в виду. Это использование, которое вы предвидите, или фактические примеры использования, которые вы нашли? - person rotoglup; 23.02.2011
comment
Это просто примеры использования draw_indirect, которые я нашел в гугле. Я не видел очень подробного описания этой функции. - person Garet Claborn; 23.02.2011
comment
@garet - мне было бы любопытно посмотреть, что ты нашел; Я еще не видел конкретного использования. Эта функция может принести пользу таким алгоритмам, как отсечение графического процессора, например, см. rastergrid.com/blog/2010/10/ и некоторые другие сообщения в этом блоге - person rotoglup; 23.02.2011
comment
ну, я не могу найти те же два примера, которые я нашел ранее.. только расплывчатая ссылка на них в VirtualGL Я немного узнал о draw_indirect для directx, который должен быть похожим, а также на g-truc.net похоже, это должна быть функция, которую я предполагаю. Довольно скудная информация. - person Garet Claborn; 24.02.2011

Я не понял, как именно OpenGL 4.0 заставляет эту функцию работать, поскольку, насколько я понял, она существовала и раньше. Я не уверен, что это отвечает на ваш вопрос, но я все равно расскажу, что я знаю об этом предмете.

Это относится к ситуации, когда какая-то другая библиотека, отличная от OpenGL, например OpenCL или CUDA, создает некоторые данные непосредственно в памяти графической карты, а затем OpenGL продолжает работу с того места, где осталась другая библиотека, и использует эти данные как

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

В подобной ситуации рекомендуется постоянно хранить данные на видеокарте и не копировать их, особенно не копировать их через ЦП, потому что шина PCIe очень медленная по сравнению с шиной памяти видеокарты. видеокарта.

Вот пример кода для работы с CUDA и OpenGL для VBO и PBO:

// in the beginning
glGenBuffers(&id, 1);

// for every frame
cudaGLRegisterBufferObject(id);
CUdeviceptr ptr;
cudaGLMapBufferObject(&ptr, id);
// <launch kernel here>
cudaGLUnmapBufferObject(id);
// <now use the buffer "id" with OpenGL>
cudaGLUnregisterBufferObject(id);

А вот как вы можете загрузить данные в текстуру:

glBindBuffer(GL_PIXEL_UNPACK_BUFFER, id);
glBindTexture(GL_TEXTURE_2D, your_tex_id);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, 0);

Также обратите внимание, что если вы используете какой-то более необычный формат вместо GL_RGBA, он может работать медленнее, потому что он должен преобразовывать все значения.

Я не знаю OpenCL, но идея та же. Отличаются только имена функций.

Другой способ сделать то же самое называется закрепленной памятью хоста. В этом подходе вы сопоставляете некоторый диапазон адресов памяти ЦП с памятью видеокарты.

person kynnysmatto    schedule 18.02.2011
comment
Что ж, я уже использовал VBO и тому подобное для получения/сохранения данных в графической памяти, но вам все еще нужно выдавать DrawArrays() или DrawElements() или что-то подобное из ЦП. В спецификации 4.0 и во многих других местах говорится о некоторых новых функциях, может быть, это просто геометрические шейдеры ... Не уверен, но я думаю, что VBO существуют с версии 1.4 или около того. OpenCL Interop очень похож, просто обработайте сопоставление после инициализации. - person Garet Claborn; 19.02.2011

Чтобы понять, что это за функция, вы должны понять, как все работало раньше.

До 4.0 OpenCL мог заполнять объекты буфера OpenGL данными. Действительно, обычные команды OpenGL могут заполнять буферные объекты OpenGL данными, либо с обратной связью преобразования, либо путем рендеринга в текстуру буфера< /а>. Эти данные могут быть данными вершин, которые будут использоваться для рендеринга.

Только ЦП может инициировать визуализацию данных вершин (путем вызова одной из glDraw* функций. Тем не менее, здесь нет необходимости в явной синхронизации (за исключением того, что требуется для взаимодействия OpenCL/OpenGL).В частности, центральному процессору не нужно читать данные, записанные операциями графического процессора.

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

Проблема в том, что OpenCL сам решил, сколько писать. Но ЦП теперь нуждается в этом числе, чтобы использовать одну из glDraw функций. Если OpenCL записал 22 000 вершин, то процессору нужно передать 22 000 в glDrawArrays.

Что делает ARB_draw_indirect (основная функция GL 4.0), так это позволяет GPU процесс для записи значений в буферный объект, которые представляют параметры, которые вы передали бы функции glDraw*. Единственный параметр, не охваченный этим, — это примитивный тип.

Обратите внимание, что ЦП по-прежнему контролирует, когда происходит рендеринг. ЦП по-прежнему решает, из каких буферов извлекать данные вершин. Таким образом, OpenCL может написать несколько из этих glDraw* команд, но до тех пор, пока процессор не вызовет glDrawElementsIndirect для одной из них на самом деле ничего не отображается.

Итак, что вы можете сделать, так это запустить процесс OpenCL, который запишет некоторые данные в существующие буферные объекты. Затем вы привязываете эти буферы, используя обычную настройку вершин, как с VAO. Процесс OpenCL запишет соответствующие данные команды рендеринга в другие объекты буфера, которые вы привяжете как непрямые буферы. А затем вы используете glDraw*Indirect для рендеринга этих команд.

ЦП никогда не должен считывать данные с графического процессора.

person Nicol Bolas    schedule 17.03.2012