Используя инстансинг для всего?


16

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

Изменить: скажем, мы создаем игру FPS. У большинства объектов есть только один экземпляр: нож, пистолет, пулемет, здание и радиовышка. Но есть также несколько объектов с несколькими экземплярами: деревья (например, 3 вида деревьев с сотнями экземпляров), трава и т. Д. Я имею в виду: вместо того, чтобы визуализировать объекты с одним экземпляром «традиционным» способом и деревья и трава, используя инстансинг, мы рендерим их все, используя инстансинг Таким образом, наша радиомачта имеет только один экземпляр (чью информацию мы храним в буфере данных экземпляра), и мы визуализируем эту башню, используя какой-то DrawInstanced()вызов с равным количеством экземпляров 1. То же самое со всеми другими объектами (конечно, деревья и трава имеют несколько экземпляров).

Поэтому мой вопрос: плохая идея нарисовать один экземпляр объекта с использованием инстансинга? Есть ли у экземпляра слишком много накладных расходов (с точки зрения памяти и производительности) или это каким-то образом нежелательно для рендеринга объектов с одним экземпляром?

Ответы:


19

Под D3D9 с XPDM вы почти наверняка захотите использовать экземпляр везде, где это возможно. Затраты на прорисовку настолько высоки, что это имеет смысл. В этом сценарии точка пересечения может составлять всего 2 или 3 экземпляра.

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

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

Даже если у вас есть только одна сетка (например, модель оружия в FPS), есть случаи, когда инстансинг полезен. Допустим, вы выполняете многопроходное накопление света в прямом рендерере и с помощью z-prepass. Вместо дополнительного прохода для каждого источника света вы создаете данные источников света для каждого экземпляра и рисуете их экземпляры.

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

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


Причины, которые вы привели, - те самые, которые заставили меня задать этот вопрос. Спасибо.
NPS

12

(В моей системе это нигде не проверялось). В GL создание единственного меша (рисование с count = 1) имеет некоторые неприятные накладные расходы, но я не знаю, откуда это взялось. Я настоятельно рекомендую не делать этого.

Я проверил это в практическом приложении пару месяцев назад. Я кодировал некоторые глобальные алгоритмы освещения в сцене Crytek Sponza, которая состоит примерно из 350 или около того ячеек (точно не помню), из которых пара делит несколько примеров. В начале я сделал это так, как вы предлагаете, просто скопируйте все и нарисуйте остальное с количеством экземпляров 1, поскольку это немного упростило код рендеринга.

Позже, когда я оптимизировал рендерер, просто переключившись с создания экземпляров объектов count = 1 и отправив их обычным способом, я сэкономил около 3,5 миллисекунд на кадр на i7 3770k (и GTX 770). Переключение ячеек с несколькими экземплярами на выполнение их традиционным способом сэкономило мне еще 0,5 мс. В целом приложение выросло с ~ 120 FPS до ~ 230 FPS.

Эти цифры, конечно, всегда зависят от того, где узкие места в вашем приложении, и последние 0,5 мс могут фактически стать замедлением в приложении, где вы сильно привязаны к вызову. Но в остальном, по моему опыту, у инстансинга есть некоторые неприятные накладные расходы, если вы не рисуете много вещей одновременно.


Интересно, но было бы неплохо увидеть данные и для драйверов AMD и Intel, в противном случае вам действительно следует сказать «На моей системе» вместо «В GL». С другой стороны, даже если это не проблема с другими реализациями, тот факт, что это может быть в некоторых случаях, является достаточной причиной, чтобы избежать создания экземпляров, если вы не используете его.
bcrist

2

Вы можете быть уверены, что рисование одного экземпляра объекта обходится дороже, чем обычное рисование одного объекта. Для создания экземпляров GPU готовит большое количество объектов, и эта подготовка будет отличаться, чем для одного объекта. Однако насколько велика эта разница в производительности, можно узнать только экспериментально, и она очень сильно зависит от вашей фактической настройки рендеринга. Единственный способ узнать наверняка - это проверить его самостоятельно. Сложно провести сравнительный анализ одного колла, вот несколько идей о том, как вы могли бы продолжить.


2

Прошло 4 года ... и я думаю, что можно с уверенностью сказать, что это прекрасно, когда вы отправляете вызовы "экземпляра" с 1. Как вы могли заметить, оба новых API DX12 и Vk имеют количество экземпляров, которое может быть от 0 до NUM_INSTANCES . Также обратите внимание, что нет DrawIndexed (...) .

РЕДАКТИРОВАТЬ

В качестве предостережения, вышеприведенное, вероятно, подходит для этих современных API, возможно, использование чего-то старого, такого как Gl <3.3, или, возможно, DX11 потребует некоторого профилирования, как упоминали другие пользователи.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.