Копирование граничных значений между группами в glsl compute shaders - PullRequest
0 голосов
/ 16 октября 2019

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

Вот моя ситуация. У меня есть программа, которая стремится заполнить 3D-текстуру значениями, начиная сверху вниз и опускаясь вниз. Программа заполняет своего рода модель водопада.

Функция, которая принимает значение, связанное с ячейкой в ​​трехмерной текстуре, и ее положение относительно текущей ячейки, т.е. f(x, position), и создает новое значение, добавленное к текущей ячейке. Вы можете думать об этом как о заливке типа

enter image description here

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

Теперь мне не нужно передавать весь блокДанные из соседних блоков мне просто нужны, на каждом шаге, значения соседних блоков, окружающих текущую сетку. Я все еще буду использовать призрачные точки, но мне нужно будет передать «новые» значения, чтобы использовать их.

enter image description here

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

Единственные параметры, которые я вижу:

  • использовать атомарные целочисленные значения для связи между группами, чтобы группы знали, что они могут использовать значение в некоторой глобальной памяти, которая соответствует этим элементам граничных данных
  • делит время выполнения насквозь, копируя значения соседних ячеек в отдельный буфер, а затем снова запускает весь процесс, чтобы учесть новые смежные значения для каждой стороны (в кубе их 6).
  • использовать только один групповой вызов для всей вещи. Может быть достаточно других вещей, которые GPU делает, чтобы гарантировать это
  • , используя несколько вызовов вычислительных шейдеров для каждого "слоя" 3D-текстуры, что потребовало бы сброса значений в глобальную память, а затем считывания их обратно вдля каждого уровня, фактически удваивая стоимость чтения глобальной памяти и вызывая издержки ядра, поскольку каждое ядро ​​должно быть запущено по порядку. Если бы я мог хранить одну и ту же память в общей памяти между вызовами ядра и не перечитывать ее обратно, это уменьшило бы проблему двойной задержки.

Нет ли другого способа скопировать границы в вычислительных шейдерах?

1 Ответ

0 голосов
/ 21 октября 2019

Нет ли другого способа скопировать границы в вычислительных шейдерах?

В общем случае нет.

Нет гарантии, когда будет выполняться соседняя группа границ, так как скопировать то, что еще не существует?

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

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

...