nir: add nir_shift_channels helper

for later use

Reviewed-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35999>
This commit is contained in:
Marek Olšák 2025-07-02 19:35:11 -04:00 committed by Marge Bot
parent 5760f92e08
commit 1cc5f7f868
2 changed files with 25 additions and 22 deletions

View file

@ -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);

View file

@ -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