#version 450
// ============================================================================
// Prepare indirect dispatch args + active element count from prefix sum.
//
// Reads the last element of the prefix sum and the last flag to compute
// the total number of active elements:
// total = scan[N-1] + flags[N-1]
//
// Writes:
// out_count[count_idx] = total
// dispatch_args[out_offset + 0..2] = { ceil(active/256), 1, 1 }
//
// This eliminates a GPU->CPU->GPU roundtrip that was previously needed
// to read the active count between scan and intersect/solve stages.
//
// Dispatch: (1, 1, 1) — single invocation
// ============================================================================
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
layout(set = 0, binding = 0, std430) readonly buffer ScanBuf { uint scan_data[]; };
layout(set = 0, binding = 1, std430) readonly buffer FlagsBuf { uint flags_data[]; };
layout(set = 0, binding = 2, std430) writeonly buffer DispatchArgs { uint dispatch_args[]; };
layout(set = 0, binding = 3, std430) buffer CountsBuf { uint out_count[]; };
layout(push_constant) uniform PrepareDispatchPC {
uint N; // total elements in scan/flags arrays
uint out_offset; // offset into dispatch_args (in uints): 0 for edges, 3 for voxels
uint count_idx; // index into out_count[]: 0 for edge_count, 2 for voxel_count
uint _pad;
};
void main() {
uint total_active = scan_data[N - 1u] + flags_data[N - 1u];
out_count[count_idx] = total_active;
uint groups = (total_active + 255u) / 256u;
if (groups == 0u) groups = 1u; // at least 1 group to avoid zero-dispatch
dispatch_args[out_offset + 0u] = groups;
dispatch_args[out_offset + 1u] = 1u;
dispatch_args[out_offset + 2u] = 1u;
}