Я правильно понимаю GLSL memoryBarrier? - PullRequest
0 голосов
/ 09 мая 2019

Цитата из здесь :

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

Хорошо, скажем, я хочу сделать это в шейдере фрагмента:

void main() {
    ivec2 fc = ivec2(gl_FragCoord.xy);
    vec4 f = imageLoad(image, fc);
    f *= 2;
    imageStore(image, fc, f);
}

Я считаю, что для этого не требуется memoryBarrier() между imageLoad и imageStore.И следующее делает:

out vec4 OUT;

void main() {
    ivec2 fc = ivec2(gl_FragCoord.xy);
    imageStore(image, fc, vec4(5));
    vec4 f = imageLoad(image, fc);
    OUT = f * 2;
}

Правильно ли я понимаю GLSL memoryBarrier?

1 Ответ

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

Сценарии, которые вы разместили здесь, зависят от неустановленной и неизвестной информации, вещей, которые вы, вероятно, предполагаете о природе вашего процесса рендеринга, о которой вы не заявили, предполагая, что они не имеют значения.Хотя они очень сильно , как мы увидим здесь.

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

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

См. шейдерФункции memoryBarrier и квалификаторы coherent предназначены для чтения значений, записанных отдельными вызовами шейдеров.Чтение значения, записанного вашим вызовом, не является проблемой.Так что вам даже не нужно coherent здесь, ни в том, ни в другом случае.

Отсюда и необходимость первоначального предположения.Потому что, если это предположение исчезнет, ​​если когда-либо будет какое-либо перекрытие между фрагментами, так что два вызова будут пытаться записать в одно и то же место, оба случая равны undefined memoryBarrier не изменит это .Почему?

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...