Vulkan: унифицированные буферы и константы push для статических данных

8

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

  1. Однородные буферы могут быть намного больше, чем константы push.
  2. UBO используют std140, ПК используют std430.
  3. UBO могут быть обновлены в любое время с помощью vkCmdUpdateBuffer (или сопоставления хоста) и сохраняют свои значения, в противном случае ПК необходимо повторно выдвигать для каждого прохода рендеринга. (Что меня удивило - основываясь на названии. Я думал, что буквально буду обновлять константы в конвейере на месте, и эти изменения сохранятся)

В моем сценарии у меня есть данные размером ~ 200 байтов, которые, как я ожидаю, будут в основном постоянными . То есть я буду менять их очень редко. Было бы лучше (при условии, что размер разрешает) использовать константы push, даже если мне нужно повторно отправлять их в каждый буфер команд? Или лучше использовать 200-байтовый UBO и редко обновлять его с помощью vkCmdUpdatebuffer?

Также. что если у меня есть, например, то, float random_seedчто я буду обновлять каждый раз при запуске шейдера? Предполагая, что у меня уже есть UBO, было бы лучше объединить это с UBO, даже если остальная часть UBO постоянна, или я бы получил выгоду от использования констант push для конкретно этой переменной, поэтому я могу избежать необходимости vkCmdUpdateBuffer перед каждым проходом рендеринга?

haasn
источник
Добро пожаловать на сайт обмена компьютерной графикой! Я не знаком с Vulkan, но кажется, что использование UBO будет более эффективным в вашем случае (вы можете попробовать сравнить характеристики обоих подходов в примере программы). С какими графическими API вы знакомы? Также вам может быть интересна эта презентация GDC 2012: не выбрасывайте все это: эффективное управление буфером
wip
Из документации Vulkan : в то время как UBO выделяет блок видеопамяти на GPU (который вы можете обновить позже), Push-константа не использует видеопамять (поэтому она должна предоставляться при каждом вызове draw / compute, иначе шейдер не будет знать, какое значение использовать). Я предполагаю, что он хранится в другой кратковременной, быстрой области хранения на GPU, хотя детали могут зависеть от вашего поставщика GPU.
WIP

Ответы:

8

UBO могут быть обновлены в любое время с помощью vkCmdUpdateBuffer

Из спецификации: «vkCmdUpdateBuffer разрешен только вне прохода рендеринга». Так что «в любое время» это не так.

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

Для общей вещи Push Constant против Uniform, используйте свое суждение. Под «суждением» я имею в виду просто посмотреть, как они работают. Push-константы позволяют вам изменять их данные в любое время, не выполняя тяжеловесных процессов, таких как операции с памятью, синхронизация или изменение состояния дескриптора. Очевидно, они предназначены для часто меняющихся данных. Как часто это «часто»? Ну, это решение суда.

В противном случае профилируйте разницу в производительности.

Николь Болас
источник
2

У меня есть данные размером ~ 200 байтов, которые, как я ожидаю, будут в основном постоянными. То есть я буду менять их очень редко.

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

что если у меня есть, например, float random_seed, который я буду обновлять каждый раз при запуске шейдера?

Это идеальный вариант использования Push Constants. Вы можете сохранить все остальные данные в UBO (или в константах специализации) и изменить это значение с помощью VkCmdPushConstants.

vazgriz
источник