OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-tps / distribute / hypertps-win64 / shaders / stream_compact_index.glsl

54 lines · glsl ref:
#version 450

// ============================================================================
// Stream compaction scatter -- INDEX-ONLY variant.
//
// Instead of copying data from a source buffer, writes the INDEX of each
// active element into the compacted buffer. This is the common case for
// voxel pipelines: flags[i] marks active edges/voxels, and you want the
// list of active indices.
//
// Given:
//   flags[N]       - 1 if element is active, 0 otherwise
//   scan_result[N] - exclusive prefix sum of flags[]
//
// Produces:
//   compacted[scan_result[i]] = i    for all i where flags[i] == 1
//   count[0] = total number of active elements
//
// Dispatch: ceil(N / 256), 1, 1
// ============================================================================

#define THREADS 256

layout(local_size_x = THREADS, local_size_y = 1, local_size_z = 1) in;

layout(set = 0, binding = 0, std430) readonly  buffer FlagsBuf      { uint flags[];       };
layout(set = 0, binding = 1, std430) readonly  buffer ScanBuf       { uint scan_result[];  };
layout(set = 0, binding = 2, std430) writeonly buffer CompactedBuf  { uint compacted[];    };
layout(set = 0, binding = 3, std430)           buffer CountBuf      { uint count[];        };

// Phase B: Push constant replaces UBO — no buffer_update() needed.
layout(push_constant) uniform CompactPushConstants {
    uint N;          // total number of elements
    uint _pad0;
    uint _pad1;
    uint _pad2;
};

void main() {
    uint gid = gl_GlobalInvocationID.x;

    if (gid >= N) return;

    if (flags[gid] != 0u) {
        uint dest = scan_result[gid];
        compacted[dest] = gid;
    }

    // Last thread writes total count.
    if (gid == N - 1) {
        count[0] = scan_result[gid] + flags[gid];
    }
}