#glsl #compute-shader
#glsl #вычислительный шейдер
Вопрос:
Я хотел бы имитировать логическое сокращение в вычислительном шейдере с помощью одной bool
переменной (не массива), просто инициализируя переменную false
значением, которое могут видеть все потоки, а затем заставляя каждый поток либо вносить true
значение в сокращение, записывая его в переменную, либо вносить false
значение, ничего не делая.
Пример:
shared bool someNumberIsBig;
// ...
void main()
{
uint id = gl_LocalInvocationID.x;
uint gid = gl_GlobalInvocationID.x;
if (id == 0) someNumberIsBig = false;
memoryBarrierShared();
barrier();
uint oneNumber = someBuffer[gid];
if (oneNumber > 5) someNumberIsBig = true; // WOW that's big
memoryBarrierShared();
barrier();
if (someNumberIsBig)
{
// do some work, with dynamic uniformity even, and with an
// assurance that at least one number was indeed big... or not??
}
}
Мне это кажется простым, но, возможно, конкурирующие записи в одно и то же местоположение могут каким-то образом вызвать проблему. Полагаюсь ли я здесь на какое-либо неопределенное или зависящее от реализации поведение?
(Другим способом сделать то, что я хочу сделать, было бы записать все bools в общий массив, а затем запустить явный алгоритм сокращения массива. Моя интуиция наивно подсказывает мне, что это было бы медленнее, чем указано выше, но, возможно, на самом деле это было бы не так… в любом случае, я просто спрашиваю здесь, правильно ли приведенное выше, независимо от его эффективности.)
Ответ №1:
Общая память всегда дорогая. Вы можете увидеть довольно хорошее объяснение, почему из статьи о ложном разделении.
Но если вы все еще хотите использовать общую память, это поддерживается. Единственная проблема с ними — это некогерентная память и порядок выполнения. Но ваш пример решает проблему как с барьером памяти, так и с барьером выполнения. Если вы хотите выполнять более сложные операции с общей памятью, вам придется использовать атомарные встроенные функции. Более подробную информацию можно найти в OGL wiki.