Почему некоторые команды могут быть записаны только вне прохода рендеринга? - PullRequest
3 голосов
/ 14 мая 2019

Я не знаю, это функция API (я почти уверен, что это не так) или специфика GPU, но почему, например, vkCmdWaitEvents может быть записано внутри и снаружи прохода рендеринга, но vkCmdResetEvent можно записать только снаружи? То же самое относится и к другим командам.

Ответы [ 2 ]

7 голосов
/ 14 мая 2019

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

Напомним, что весь смысл сложности модели прохода рендерингадолжен обслуживать потребности рендереров на основе тайлов (TBR). Когда TBR встречает сложную серию подпроходов, он хочет, чтобы выполнил их следующим образом.

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

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

Итак, допустим, вы хотите установить событиев середине подземного перехода.ОК ... когда это на самом деле происходит?Помните, что команда set-event фактически устанавливает событие после завершения всех предыдущих команд.В TBR, если все идет так, как описано выше, когда он устанавливается?В идеале, вся обработка вершин для всего всего прохода рендеринга должна выполняться перед любой растеризацией, поэтому установка события должна произойти после того, как обработка вершин завершена.И вся обработка растеризации происходит по частям, обрабатывая те примитивы, которые перекрывают эту плитку.Из-за фрагментированного процесса рендеринга трудно узнать, когда была выполнена отдельная команда рендеринга.

Таким образом, единственное место, где может произойти вызов set-event, это ... после всего прохода рендеринга завершено.Это, очевидно, не очень полезно.

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

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

Кроме того, Vulkan спроектирован так, что, если что-то должно быть реализовано крайне неэффективно, то либо невозможно сделать напрямую, либо APIдействительно заставляет это выглядеть действительно неэффективным.vkCmd(Re)SetEvent не может быть эффективно реализовано в рамках прохода рендеринга на оборудовании TBR, поэтому вы не можете сделать это в течение периода.

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


Для других видов команд напомним, что граф зависимостейвсего, что происходит в ходе рендеринга, определяется внутри VkRenderPass.График зависимостей подземного перехода есть.Вы даже не можете выдать нормальный vkCmdPipelineBarrier в рамках прохода рендеринга, если только у этого подпроцесса нет явной самостоятельной зависимости в графе зависимостей подпрохода.

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

И причина, по которой у вас не может быть других зависимостей, восходит к TBR.График зависимостей является неотъемлемой частью прохода рендеринга, чтобы позволить TBR заранее знать, какова взаимосвязь между подпроходами.Это позволяет им знать, могут ли они создать свой идеальный рендерер, и когда / где он может сломаться.

Поскольку модель проходов рендеринга TBR делает такое ожидание непрактичным, нет смысла позволять вам давать такие команды.

2 голосов
/ 14 мая 2019

Потому что renderpass - это специальная конструкция, которая подразумевает фокусировку работы исключительно на кадровом буфере.

Кроме того, каждый из подпроцессов разрешается запускать параллельно, если между ними нет явной зависимости.

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

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

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

...