Оптимальный способ рисования сцен друг над другом

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

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

  • Есть ли лучшая стратегия для этого? (например, запуск нового прохода рендеринга для каждой сцены.)
  • Я нашел vkCmdClearAttachments, но не уверен, что ему нужна синхронизация с предыдущей и следующей командами или нет?

person Hossein Noroozpour    schedule 27.09.2018    source источник
comment
Я не уверен, что ему нужна синхронизация с предыдущей и следующей командами или нет? Первое правило Vulkan: если он обращается к памяти, к которой обращается кто-то другой (если оба доступа не читаются), это всегда нуждается в синхронизации. Очевидно, что во многих случаях это неправда, но это всегда хорошее предположение по умолчанию.   -  person Nicol Bolas    schedule 28.09.2018


Ответы (1)


«Оптимальный» способ сделать это, будь то в Vulkan или OpenGL, - разделить буфер глубины на две области: по одной для каждой сцены. Вы используете преобразование области просмотра для разделения буфера глубины. Одна сцена получит диапазон [0,5, 1], а следующая - диапазон [0, 0,5]. glDepthRange - это то, что вы использовали бы для установки этого в OpenGL, а поля min/maxDepth в VkViewport обрабатывают аналогичное преобразование в Vulkan.

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

person Nicol Bolas    schedule 28.09.2018
comment
Почему vkCmdClearAttachments обязательно будет плохим в плиточном рендерере? Предполагая, что вложение не сохраняется между проходами рендеринга, драйвер должен иметь всю информацию, необходимую для свертывания до операции «очистить эту плитку» и сохранить вложение как целое виртуальным. - person Jherico; 28.09.2018
comment
@Jherico: Потому что, если вы очистите буфер глубины, это означает, что вы должны фактически выполнить все операции с фрагментами для предыдущего материала. Это означает, что вам нужно растрировать все в тайле по порядку. Этого не делают некоторые TBR. И даже те, кто это делает, иногда оптимизируют это, по сути выполняя предварительный проход глубины, затем возвращаясь и выполняя определенные шейдеры фрагментов для тех фрагментов, которые действительно видны. - person Nicol Bolas; 28.09.2018
comment
Разделение по глубине - это нехорошо, потому что я теряю точность, появляется z-борьба и усложняет дизайн моего кода, поэтому я прихожу к такому выводу, чтобы начать новый проход рендеринга для каждой сцены. - person Hossein Noroozpour; 28.09.2018
comment
@NicolBolas не стал бы использовать набор отложенных вложений временного буфера глубины, который позволил бы вам выполнить то же самое без явного четкого разделения по глубине или нового прохода рендеринга? Вы просто перебираете насадки глубины для каждой «секционированной» сцены. - person Jherico; 28.09.2018