+static nir_ssa_def *
+lower_shuffle(nir_builder *b, nir_intrinsic_instr *intrin,
+ bool lower_to_scalar)
+{
+ nir_ssa_def *index = nir_load_subgroup_invocation(b);
+ switch (intrin->intrinsic) {
+ case nir_intrinsic_shuffle_xor:
+ assert(intrin->src[1].is_ssa);
+ index = nir_ixor(b, index, intrin->src[1].ssa);
+ break;
+ case nir_intrinsic_shuffle_up:
+ assert(intrin->src[1].is_ssa);
+ index = nir_isub(b, index, intrin->src[1].ssa);
+ break;
+ case nir_intrinsic_shuffle_down:
+ assert(intrin->src[1].is_ssa);
+ index = nir_iadd(b, index, intrin->src[1].ssa);
+ break;
+ default:
+ unreachable("Invalid intrinsic");
+ }
+
+ nir_intrinsic_instr *shuffle =
+ nir_intrinsic_instr_create(b->shader, nir_intrinsic_shuffle);
+ shuffle->num_components = intrin->num_components;
+ nir_src_copy(&shuffle->src[0], &intrin->src[0], shuffle);
+ shuffle->src[1] = nir_src_for_ssa(index);
+ nir_ssa_dest_init(&shuffle->instr, &shuffle->dest,
+ intrin->dest.ssa.num_components,
+ intrin->dest.ssa.bit_size, NULL);
+
+ if (lower_to_scalar && shuffle->num_components > 1) {
+ return lower_subgroup_op_to_scalar(b, shuffle);
+ } else {
+ nir_builder_instr_insert(b, &shuffle->instr);
+ return &shuffle->dest.ssa;
+ }
+}
+