struct Configuration { gridSize: vec2f, aspect: vec2f }; @group(0) @binding(0) var config: Configuration; @group(0) @binding(1) var stateIn: array; @group(0) @binding(2) var stateOut: array; fn cellIndex(cell: vec2i) -> u32 { let x = (cell.x % i32(config.gridSize.x)); let y = (cell.y % i32(config.gridSize.y)); return u32(y * i32(config.gridSize.x) + x); } fn cellActive(cell: vec2i) -> u32 { return stateIn[cellIndex(cell)]; } const directions: array = array(vec2i(-1, -1), vec2i(-1, 0), vec2i(-1, 1), vec2i(0, -1), //0, 0) vec2i(0, 1), vec2i(1, -1), vec2i(1, 0), vec2i(1, 1)); @compute @workgroup_size(16) fn computeMain(@builtin(global_invocation_id) globalInvocationId: vec3u) { let cell: vec2i = vec2i(i32(globalInvocationId.x) % i32(config.gridSize.x), i32(globalInvocationId.x) / i32(config.gridSize.y)); var activeNeighbors: u32 = 0; for (var i: u32 = 0; i < 8; i++) { activeNeighbors += cellActive(directions[i] + cell); } let index = cellIndex(cell); switch activeNeighbors { case 2: { stateOut[index] = stateIn[index]; } case 3: { stateOut[index] = 1; } default: { stateOut[index] = 0; } } }