GLES 为 float 计算着色器原子操作

GLES compute shader atomic operations for float

我正在使用计算机着色器获取总和值(类型为浮点数),如下所示:

#version 320 es
layout(local_size_x = 640,local_size_y=480,local_size_z=1)
layout(binding = 0) buffer OutputData{
float sum[];
}output;
uniform sampler2D texture_1;
void main()
{
    vec2 texcoord(float(gl_LocalInvocationIndex.x)/640.0f,float(gl_LocalInvocationIndex.y)/480.0f);
    float val = textureLod(texture_1,texcoord,0.0).r;
//where need synchronize
    sum[0] = sum[0]+val;
//Here i want to get the sum of all val in texture_1 first channal
}

我知道有像 atomicAdd() 这样的原子操作,但不支持 float 参数,而 barrier() 似乎不能解决我的问题。 也许我可以将浮点数编码为整数,或者有一些简单的方法可以解决我的问题吗?

Atomics 在性能方面通常很差,尤其是在大量线程并行访问激烈竞争的情况下,因此我不建议将它们用于此用例。

要在这里保持并行性,您确实需要某种多遍缩减策略。伪代码,像这样:

array_size = N
data = input_array

while array_size > 1:
   spawn pass with M = array_size/2 threads.
   thread M: out[M] = data[2*M] + data[2*M+1]
   array_size = M
   data = out

这是一个简单的 2:1 缩减,因此性能为 O(log2(N)),但您可以在每次通过时进行更多缩减,以减少中间存储的内存带宽。对于使用纹理作为输入的 GPU,4:1 非常好(您可以使用 textureGather 甚至简单的线性过滤器在单个纹理操作中加载多个样本)。