我正在尝试在计算着色器上进行剔除。 我的问题是,我的原子计数器似乎没有被着色器写入,或者它确实被写入但是后来被取消了?
Renderdoc表示它没有数据,但InstancesOut中有值 (见下图)
这是我的计算着色器:
#version 450
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
struct Indirect
{
uint indexCount;
uint instanceCount;
uint firstIndex;
uint vertexOffset;
uint firstInstance;
};
struct Instance
{
vec4 position;
};
layout (binding = 0, std430) buffer IndirectDraws
{
Indirect indirects[];
};
layout (binding = 1) uniform UBO
{
vec4 frustum[6];
} ubo;
layout (binding = 2, std140) readonly buffer Instances
{
Instance instances[];
};
layout (binding = 3, std140) writeonly buffer InstancesOut
{
Instance instancesOut[];
};
layout (binding = 4) buffer Counter
{
uint counter;
};
bool checkFrustrum(vec4 position, float radius)
{
for(uint i = 0; i < 6; i++)
if(dot(position, ubo.frustum[i]) + radius < 0.0)
return false;
return true;
}
layout (local_size_x = 1) in;
void main()
{
uint i = gl_GlobalInvocationID.x + gl_GlobalInvocationID.y * gl_NumWorkGroups.x * gl_WorkGroupSize.x;
uint instanceCount = 0;
if(i == 0)
atomicExchange(counter, 0);
for(uint x = 0; x < indirects[i].instanceCount; x++)
{
vec4 position = instances[indirects[i].firstInstance + x].position;
//if(checkFrustrum(position, 1.0))
//{
instancesOut[atomicAdd(counter, 1)].position = position;
instanceCount++;
//}
}
//indirects[i].instanceCount = instanceCount;
indirects[i].instanceCount = i; // testing
}
Picture of buffers in RenderDoc
感谢您的帮助!
答案 0 :(得分:0)
太多的事情似乎使您误解了同步和工作组的工作原理。
在计算着色器中,原子可让您在工作组之间进行同步。但是,无法保证工作组的执行顺序,因此atomicExchange(counter,0);不保证在其他工作组执行之前发生。错误#1?
工作组大小为1会浪费大量资源,尤其是当您要花费在多个工作组之间进行同步时。工作组中的同步总是最快的,它允许您实际使用gpu资源(大多数GPU被组织到包含SIMD处理器的模块中,这些模块只能一次处理一个工作组上的执行。如果您仅使用大小为1的工作组, ,这些处理器中的31/32或63/64处于闲置状态({caveat,这些处理器中的大多数可以同时在内存中保存多个工作组,但执行仅在任何给定时刻进行一次))。此外,在工作组中,您可以将执行与障碍同步,以确保操作顺序。错误2?
如果仅添加一个,atomicCounterIncrement可能是更好的指令。
在您的特定应用程序中,instancesOut的答案为什么错误?在我看来实际上是正确的,每个输入最终都在输出中,没有保证的顺序(因为您不能保证工作组以特定的顺序执行,即并行执行的工作方式)。如果您希望按顺序排列它们,请根据调用ID进行计算?
至于为什么renderDoc不会在计数器中显示值,我不知道,如果映射正确,它应该有一个值。