Revision control

Copy as Markdown

#version 440
// Builds the indirect draw commands for the visible objects on the GPU, to be
// picked up by QRhiCommandBuffer::buildIndirect(). src[] holds one ready-made
// command per object, uploaded once; this only decides which of them survive.
layout (local_size_x = 64) in;
struct IndexedIndirectDrawCommand
{
uint indexCount;
uint instanceCount;
uint firstIndex;
int vertexOffset;
uint firstInstance;
};
layout(std430, binding = 0) buffer SourceBuf
{
IndexedIndirectDrawCommand src[];
};
layout(std430, binding = 1) buffer CommandBuf
{
IndexedIndirectDrawCommand cmds[];
};
layout(std430, binding = 2) buffer CountBuf
{
uint drawCount;
};
layout(std140, binding = 3) uniform Params
{
uint objectCount;
uint density;
uint compact;
} params;
void main()
{
uint i = gl_GlobalInvocationID.x;
if (i >= params.objectCount)
return;
// Must match visible() on the C++ side, so that both ways of populating the
// indirect command buffer end up drawing the same objects.
uint h = i * 2654435761u;
h ^= h >> 15;
bool visible = (h % 1000u) < params.density;
if (params.compact != 0u) {
// The count is only known to the device, hence the count buffer.
if (visible)
cmds[atomicAdd(drawCount, 1u)] = src[i];
} else {
// No count buffer, so every slot has to hold something. Culled objects
// become draws of zero indices.
cmds[i] = src[i];
if (!visible)
cmds[i].indexCount = 0u;
}
}