Подтвердить что ты не робот

Как UBOs/SSBOs отличаются от привязок памяти Vulkan shader?

В статье на веб-сайте Imagination я прочитал следующий параграф:

Например, в Vulkan нет эквивалентных точек входа glUniform*(); вместо этого запись в память GPU является единственным способом передачи данных в шейдеры.

Когда вы вызываете glUniform*(), драйвер OpenGL ES обычно должен выделять буфер, управляемый драйверами, и копировать данные на него, управление которыми связано с накладными расходами процессора. В Vulkan вы просто сопоставляете адрес памяти и записываете непосредственно в эту ячейку памяти.

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

4b9b3361

Ответ 1

Из того, что я понимаю, это не спецификация glUniform*(): glUniform*() - это просто пример, используемый автором статьи, чтобы проиллюстрировать, как Vulkan работает в отношении связи между хостом и GPU.

Когда вы вызываете glUniform*(), драйвер OpenGL ES обычно должен выделять буфер, управляемый драйверами, и копировать данные на него, управление которыми несет накладные расходы ЦП.

В этом случае, когда пользователь вызывает glUniform*() с некоторыми данными, эти данные сначала копируются в буфер, принадлежащий реализации OpenGL. Этот буфер, вероятно, закреплен и затем может использоваться драйвером для передачи данных через DMA на устройство. Это два шага:

  • Скопировать данные пользователя в буфер драйвера;
  • Передача содержимого буфера на GPU через DMA.

В Vulkan вы просто сопоставляете адрес памяти и записываете непосредственно в эту ячейку памяти.

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

С точки зрения производительности преимущества очевидны: нулевая копия. Это также означает, что реализация Vulkan может быть проще, поскольку для управления промежуточным буфером не требуется.

Поскольку спецификации еще не выпущены, вот фиктивный пример того, как он может выглядеть:

// Assume Lights is some kind of handle to your buffer/data
float4* lights = vkMap(Lights);

for (int i = 0; i < light_count; ++i) {
    // Goes directly to the device
    lights[i] = make_light(/* stuff */);
}

vkUnmap(lights);