#version 450
#define INDEX(_x, _y) ((_y) * WIDTH + (_x))
#define IS_CONNECTED(_i0, _i1) (values[_i0] >= 0 && values[_i1] >= 0)
#define LABEL(_idx) (values[_idx])
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
layout(constant_id = 0) const uint WIDTH = 8;
layout(constant_id = 1) const uint HEIGHT = 8;
layout(push_constant) uniform PushConstant {
uint step_index;
};
layout(binding = 0) buffer Binding {
int values[];
};
int findRoot(uint index) {
int v = LABEL(index);
if (v < 0) {
return v;
}
int w = int(index);
while (v != w) {
w = v;
v = LABEL(v);
}
return v;
}
void merge(uint x0) {
uint x1 = x0 + 1;
for (uint y = 0; y < HEIGHT; ++y) {
uint i0 = INDEX(x0, y);
uint i1 = INDEX(x1, y);
if (IS_CONNECTED(i0, i1)) {
int v0 = findRoot(i0);
int v1 = findRoot(i1);
LABEL(max(v0, v1)) = LABEL(min(v0, v1));
}
}
}
void main() {
uint id = gl_GlobalInvocationID.x;
uint steps = WIDTH / (WIDTH >> (step_index + 1));
uint x0 = (id * steps) + (1 << step_index) - 1;
merge(x0);
}