Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 

README.md

Много объектов

В данном задании вам предстоит оптимизировать отрисовку 3D-моделей в случае когда на сцене много-много одинаковых объектов.

Перед началом

  1. В идеале, скопируйте ваше решение model_bakery в эту папку. Если его у вас нет, скопируйте заготовку-рендерилку из model_bakery. Не забудьте поменять название таргета в CMake.
  2. Поменяйте загружаемую сцену на Avocado, предварительно прогнав её через печку.
  3. Запустите рендерилку. Что с производительностью? Посмотрите в профайлер.

Также наведём немного терминологии.

  • RenderElement — группа треугольников с фиксированным материалом.
  • Модель — набор RenderElement. Например, фонарь.
  • Инстанс модели — пара (модель, матрица трансформации). Обратите внимание, что не возможно отрисовать на экран просто модель, так как мы не знаем где конкретно на сцене мы хотим её нарисовать, отрисовать можно только инстанс модели. Если модель — фонарь, то на сцене конечно же будет далеко не один фонарь, а геометрию фонаря мы хотим хранить ровно один раз.
  • Инстанс RenderElement — пара (RenderElement, матрица трансформации). Если посмотреть на инстанс модели с другой стороны, то он по факту состоит из инстансов RenderElement. Каждый инстанс RenderElement в наивной реализации соответствует ровно одном вызову vkCmdDrawIndexed с корректно выставленными биндингами (параметрами матриала и матрицами трансформации).

Задание

Шаг 1

Поменяйте отрисовку в вашем приложении так, чтобы как можно больше инстансов RenderElement рисовалось за один дроу-колл. Для этого используйте функцию вулкана vkCmdDrawIndexed с параметром instanceCount > 1. При желании можно использовать vkCmdDrawIndexedIndirect и в ручную загружать параметры вызова отрисовки на GPU, тем самым рисуя несколько разных RenderElement за один дроу-колл.

При таком подходе нам придётся заранее загрузить матрицы трансформации каждого инстанса в единый буфер на GPU и читать их в вершинном шейдере по индексу инстанса. Будьте аккуратны: второй шаг задания может повлиять на то, в какой момент вам нужно загружать эти матрицы на GPU. В обратную сторону может повлиять бонусный уровень. Ознакомьтесь с ними перед тем как бежать писать код.

Если вы выполнили бонус в прошлой домашке, то объединить в один дроу-колл отрисовку инстансов RenderElement с разными материалами во всяком случае не получится. Чтобы побороть эту проблему, вам придётся отсортировать инстансы RenderElement по используемому материалу и аналогично отсортировать матрицы трансформации, делать один дроу-колл на каждый материал, а нужный "сдвиг" в массив матриц можно реализовать через параметр firstInstance.

Шаг 2

Добавьте в приложение фрустум куллинг на CPU. Иными словами,

  1. вычислите bounding box для каждого RenderElement;
  2. преобразуйте все вершины bounding box кажого RenderElement матрицами MVP каждого инстанса модели чтобы получить bounding box инстансов RenderElement;
  3. выберите только те инстансы RenderElement, у которых хотя бы одна вершина bounding box попала внутри единичного куба в пространстве экрана;
  4. на отрисовку передавайте только выбранные инстансы RenderElement.

Проверьте через профайлер что отрисовка стала быстрее на GPU когда на экране видно только одну авокадину.

Бонусный уровень

Реализуйте фрустум куллинг на GPU. Для этого загрузите заранее все данные сцены на GPU и напишите компьют-шейдер который будет выполнять действия аналогичные шагу 2 основного задания, составляя на выходе буферы с количеством вызовов отрисовки и самими вызовами отрисовки для vkCmdDrawIndexedIndirectCount.

Вновь не забудьте, что если у вас прикручены материалы, то вам придётся по-отдельности совершать эти действия для каждого материала. В будущем мы решим эту проблему и будем рисовать всю сцену за один дроу-колл vkCmdDrawIndexedIndirectCount, а пока предлагается костылять, либо вообще временно открутить материалы.

Полезные материалы

  1. https://docs.vulkan.org/spec/latest/chapters/drawing.html — справка по разным командам отрисовки
  2. https://vkguide.dev/docs/gpudriven/gpu_driven_engines/ — про GPU-driven rendering в целом (код там устаревший и не работает, но объяснения и ссылки полезные!)