#version 450 #extension GL_GOOGLE_include_directive : require layout(local_size_x = 8, local_size_y = 8) in; #include "common.glsl" // Performs the moves that won claim arbitration. A mover wins only if it holds the highest // priority on both its source and its target cell, so the winners' cell pairs are disjoint and // no atomics or ordering are needed here. The displaced occupant takes the mover's old slot // (the original's swap-based move primitive, FUN_0070cc00). void main() { ivec2 p = ivec2(gl_GlobalInvocationID.xy); if (p.x >= pc.gw || p.y >= pc.gh) return; uint i = uint(p.y * pc.gw + p.x); uvec4 it = intent[i]; if (it.x == NONE) return; uint t = it.x & 0x7FFFFFFFu; if (claims[i] != it.y || claims[t] != it.y) return; // lost arbitration, retry next pass uint cs = cells[i], ct = cells[t]; vec2 et = ext[t]; if ((it.x >> 31) != 0u) cs ^= DIR_BIT; // gas bounced: flip horizontal direction terrain_age[t] = (cell_mat(cs) << 16) | 0x100u; terrain_age[i] = (cell_mat(ct) << 16) | 0x100u; cells[t] = cs; ext[t] = vec2(uintBitsToFloat(it.z), uintBitsToFloat(it.w)); cells[i] = ct; ext[i] = et; const uint bt = birth[t]; birth[t] = birth[i]; birth[i] = bt; // the age moves with the cell }