OpenGL 4.0 GPU Draw Возможность? - PullRequest
2 голосов
/ 19 февраля 2011

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

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

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

Редактировать :

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

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

Ответы [ 3 ]

3 голосов
/ 19 февраля 2011

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

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

2 голосов
/ 19 февраля 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, но идея та же.Различаются только имена функций.

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

0 голосов
/ 17 марта 2012

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

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

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

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

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

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

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

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

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

...