diff --git a/src/compiler/nir/nir_builder.h b/src/compiler/nir/nir_builder.h index 6bf4be84aa8..72779cde4dd 100644 --- a/src/compiler/nir/nir_builder.h +++ b/src/compiler/nir/nir_builder.h @@ -1580,6 +1580,29 @@ nir_resize_vector(nir_builder *b, nir_def *src, unsigned num_components) return nir_trim_vector(b, src, num_components); } +/* Shift channels to the left or right. Fill undefined components with .x. + * Examples: + * channel_shift = 1, new_num_components = 4: .xyzw -> .xxyz + * channel_shift = -1, new_num_components = 3: .xyzw -> .yzw + */ +static inline nir_def * +nir_shift_channels(nir_builder *b, nir_def *def, int channel_shift, + unsigned new_num_components) +{ + if (channel_shift == 0) + return nir_resize_vector(b, def, new_num_components); + + assert(abs(channel_shift) < NIR_MAX_VEC_COMPONENTS); + unsigned swizzle[NIR_MAX_VEC_COMPONENTS] = {0}; + + for (int i = 1; i < def->num_components; i++) { + if (i + channel_shift >= 0) + swizzle[i + channel_shift] = i; + } + + return nir_swizzle(b, def, swizzle, new_num_components); +} + nir_def * nir_ssa_for_alu_src(nir_builder *build, nir_alu_instr *instr, unsigned srcn); diff --git a/src/mesa/state_tracker/st_nir_unlower_io_to_vars.c b/src/mesa/state_tracker/st_nir_unlower_io_to_vars.c index 81292a72770..853fe1153d0 100644 --- a/src/mesa/state_tracker/st_nir_unlower_io_to_vars.c +++ b/src/mesa/state_tracker/st_nir_unlower_io_to_vars.c @@ -614,28 +614,8 @@ unlower_io_to_vars(nir_builder *b, nir_intrinsic_instr *intr, void *opaque) if (desc.is_store) { unsigned writemask = nir_intrinsic_write_mask(intr) << desc.component; - nir_def *value = intr->src[0].ssa; - - if (desc.component) { - unsigned new_num_components = desc.component + value->num_components; - unsigned swizzle[4] = {0}; - assert(new_num_components <= 4); - - /* Move components within the vector to the right because we only - * have vec4 stores. The writemask skips the extra components at - * the beginning. - * - * For component = 1: .xyz -> .xxyz - * For component = 2: .xy -> .xxxy - * For component = 3: .x -> .xxxx - */ - for (unsigned i = 1; i < value->num_components; i++) - swizzle[desc.component + i] = i; - - value = nir_swizzle(b, value, swizzle, new_num_components); - } - - value = nir_resize_vector(b, value, num_components); + nir_def *value = nir_shift_channels(b, intr->src[0].ssa, desc.component, + num_components); /* virgl requires scalarized TESS_LEVEL stores because originally * the GLSL compiler never vectorized them. Doing 1 store per bit of