Подтвердить что ты не робот

Почему призывы привлечь дорого?

если данные текстуры, вершины и шейдера уже находятся на графической карте, вам не нужно отправлять много данных на карту. есть несколько байтов для идентификации данных и предположительно матрицы 4x4 и некоторых других параметров.

Итак, откуда взялись все накладные расходы? выполняются ли какие-либо операции с помощью gpu?

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

4b9b3361

Ответ 1

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

Рисование вызовов не обязательно дорого. В более старых версиях Direct3D многие вызовы требовали переключения контекста, что было дорого, но это не так в новых версиях.

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

Создание однократного вызова с двумя треугольниками дешево, но если вы отправляете слишком мало данных с каждым вызовом, у вас не будет достаточно времени процессора, чтобы представить столько геометрии на GPU, сколько вы могли бы.

Существуют некоторые реальные затраты при выполнении вызовов вызова, для этого требуется настройка состояния состояния (какой набор вершин использовать, какой шейдер использовать и т.д.), а изменения состояния имеют стоимость как на стороне оборудования ( обновление группы регистров) и со стороны водителя (проверка и перевод ваших вызовов, которые устанавливают состояние).

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

Так же, как Джош сказал, призывы рисования также могут вызвать сброс командного буфера, но в моем опыте это обычно происходит, когда вы вызываете SwapBuffers, а не при отправке геометрии. Видеодрайверы обычно стараются сбрасывать столько, сколько они могут уйти (несколько кадров иногда!), Чтобы выжать как можно больше parallelism из GPU.

Вы должны прочитать презентацию nVidia Batch Batch Batch!, она довольно старая, но охватывает именно эту тему.

Ответ 2

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

До тех пор, пока буфер не будет сброшен, графический процессор сможет выполнять некоторую подготовительную работу параллельно с ЦП, если ЦП не делает запрос блокировки (например, отображение данных обратно в ЦП). Но графический процессор не будет - и не может - подготовить все, пока ему не понадобится фактически рисовать. Просто потому, что некоторые данные вершин или текстуры находятся на карте, это не значит, что она организована надлежащим образом и может не быть организована до тех пор, пока не будут установлены макеты вершин или шейдеры привязаны и т.д. Основная часть реальной работы происходит во время команды flush и draw call.

В DirectX SDK есть раздел для точного профилирования производительности D3D, который, хотя и не имеет прямого отношения к вашему вопросу, может дать некоторые подсказки относительно того, что есть и не дорого и (в некоторых случаях) почему.

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

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

Ответ 3

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

Это делается по нескольким причинам:

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

Альтернативный ответ (ы):

  • Буфер, который использует драйвер для хранения команд рендеринга, заполнен, и приложение действительно ждет, пока GPU обработает некоторые из ранних работ. Обычно это будет отображаться как чрезвычайно большие блоки блокировки времени в случайном обратном вызове внутри кадра.
  • Достигнуто количество фреймов, которым разрешен буфер для буфера, и приложение ожидает на GPU обработки одного из них. Обычно это будет отображаться как большой фрагмент блокировки времени в первом вызове рисования внутри кадра или в Present в конце предыдущего кадра.