【发布时间】:2022-08-10 07:56:19
【问题描述】:
代码是从OpengGL-Superbible 10 并行计算前缀总和。
所示着色器的本地工作组大小为 1024,这意味着它将处理 2048 个元素的数组,因为每次调用都会计算输出数组的两个元素。共享变量 shared_data 用于存储正在运行的数据。执行开始时,着色器将输入数组中的两个相邻元素加载到数组中。接下来,它执行 barrier() 函数。此步骤可确保所有着色器调用在内部循环开始之前已将其数据加载到共享数组中。
#version 450 core
layout (local_size_x = 1024) in;
layout (binding = 0) coherent buffer block1
{
float input_data[gl_WorkGroupSize.x];
};
layout (binding = 1) coherent buffer block2
{
float output_data[gl_WorkGroupSize.x];
};
shared float shared_data[gl_WorkGroupSize.x * 2];
void main(void)
{
uint id = gl_LocalInvocationID.x;
uint rd_id;
uint wr_id;
uint mask;// The number of steps is the log base 2 of the
// work group size, which should be a power of 2
const uint steps = uint(log2(gl_WorkGroupSize.x)) + 1;
uint step = 0;
// Each invocation is responsible for the content of
// two elements of the output array
shared_data[id * 2] = input_data[id * 2];
shared_data[id * 2 + 1] = input_data[id * 2 + 1];
// Synchronize to make sure that everyone has initialized
// their elements of shared_data[] with data loaded from
// the input arrays
barrier();
memoryBarrierShared();
// For each step...
for (step = 0; step < steps; step++)
{
// Calculate the read and write index in the
// shared array
mask = (1 << step) - 1;
rd_id = ((id >> step) << (step + 1)) + mask;
wr_id = rd_id + 1 + (id & mask);
// Accumulate the read data into our element
shared_data[wr_id] += shared_data[rd_id];
// Synchronize again to make sure that everyone
// has caught up with us
barrier();
memoryBarrierShared();
} // Finally write our data back to the output image
output_data[id * 2] = shared_data[id * 2];
output_data[id * 2 + 1] = shared_data[id * 2 + 1];
}
如何直观地理解rd_id和wr_id的位移操作?为什么它有效?
【问题讨论】:
标签: opengl glsl compute-shader prefix-sum