在尝试实现一个将影响灯光分配给簇的简单计算着色器时,我遇到了一个意外的行为(对于像我这样的菜鸟来说很好):
我用glDispatchCompute(32,32,32)调用这个着色器;并且它应该为每个调用将一个[light counter + 8个索引]写入“indices”缓冲区。但是在调试时,我发现我对该缓冲区的写入在调用之间重叠,即使我使用了唯一的clusterId。我通过索引值[outIndexStart]超过8和视觉闪烁来检测它。
根据文档,gl_GlobalInvocationID是gl_WorkGroupID * gl_WorkGroupSize + gl_LocalInvocationID。但是如果将所有本地大小设置为1,写入问题就消失了。为什么local_size会以这种方式影响代码?我如何推理在这里选择它的值?
#version 430
layout (local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
uniform int lightCount;
const unsigned int clusterSize = 32;
const unsigned int clusterSquared = clusterSize * clusterSize;
struct LightInfo {
vec4 color;
vec3 position;
float radius;
};
layout(std430, binding = 0) buffer occupancyGrid {
int exists[];
};
layout(std430, binding = 2) buffer lightInfos
{
LightInfo lights [];
};
layout(std430, binding = 1) buffer outputList {
int indices[];
};
void main(){
unsigned int clusterId = gl_GlobalInvocationID.x + gl_GlobalInvocationID.y * clusterSize + gl_GlobalInvocationID.z * clusterSquared;
if(exists[clusterId] == 0)
return;
//... not so relevant calculations
unsigned int outIndexStart = clusterId * 9;
unsigned int outOffset = 1;
for(int i = 0; i < lightCount && outOffset < 9; i++){
if(distance(lights[i].position, wordSpace.xyz) < lights[i].radius) {
indices[outIndexStart + outOffset] = i;
indices[outIndexStart]++;
outOffset++;
}
}
}
1条答案
按热度按时间oxosxuxt1#
让我们看看两个声明:
和
local_size
声明说每个工作组将有4x4x4次调用,也就是64次,而clusterSize
声明说每个工作组只有32次调用。如果要解决此问题,请使用系统提供的实际本地大小常量:
您甚至可以这样做: