anv, brw: Use previous shader VUE map for FS input layout when available
Some checks are pending
macOS-CI / macOS-CI (dri) (push) Waiting to run
macOS-CI / macOS-CI (xlib) (push) Waiting to run

The FS compilation needs the VUE map from the previous stage when the FS
has more inputs than SBE_SWIZ can remap.  Recomputing a VUE map just
from FS inputs loses certain slots like multiview slots and extra
position slots (for primitive replication), so high-numbered attributes
can read the wrong source.

When available, pass the previous stage VUE map to the FS compilation
and use it.  Make sure that the payload is sized based on what is read,
in case the previous stage has more outputs than FS reads.

Bugs did not surface when there were just 16 or fewer varying inputs,
because the driver can program SBE_SWIZ to translate the positions in
the previous shader VUE into what the FS wants.  For more inputs, this
mapping is not used, and the FS must use the exact same slots.

Note this is not a problem for pipeline libraries because they use
a different fixed layout.  This is also not an issue with
EXT_shader_object because multiview draws are not allowed with that
extension.

Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/41747>
This commit is contained in:
Caio Oliveira 2026-05-21 18:22:31 -07:00 committed by Marge Bot
parent 3ded84870f
commit c88e30f0e4
2 changed files with 31 additions and 26 deletions

View file

@ -563,6 +563,7 @@ calculate_urb_setup(const struct intel_device_info *devinfo,
const struct brw_fs_prog_key *key,
struct brw_fs_prog_data *prog_data,
nir_shader *nir,
const struct intel_vue_map *prev_stage_vue_map,
const struct brw_mue_map *mue_map,
int *per_primitive_offsets)
{
@ -614,9 +615,12 @@ calculate_urb_setup(const struct intel_device_info *devinfo,
first_read_offset = per_primitive_stride = 0;
}
} else {
brw_compute_vue_map(devinfo, &vue_map, inputs_read,
key->base.vue_layout,
1 /* pos_slots, TODO */);
if (prev_stage_vue_map) {
memcpy(&vue_map, prev_stage_vue_map, sizeof(vue_map));
} else {
brw_compute_vue_map(devinfo, &vue_map, inputs_read,
key->base.vue_layout, 1 /* pos_slots */);
}
brw_compute_per_primitive_map(per_primitive_offsets,
&per_primitive_stride,
&first_read_offset,
@ -677,13 +681,15 @@ calculate_urb_setup(const struct intel_device_info *devinfo,
}
}
int last_slot = first_slot;
for (int slot = first_slot; slot < vue_map.num_slots; slot++) {
int varying = vue_map.slot_to_varying[slot];
if (varying > 0 && (inputs_read & BITFIELD64_BIT(varying))) {
prog_data->urb_setup[varying] = slot - first_slot;
last_slot = slot;
}
}
urb_next = vue_map.num_slots - first_slot;
urb_next = last_slot - first_slot + 1;
}
prog_data->num_varying_inputs = urb_next;
@ -824,6 +830,7 @@ brw_nir_populate_fs_prog_data(nir_shader *shader,
const struct intel_device_info *devinfo,
const struct brw_fs_prog_key *key,
struct brw_fs_prog_data *prog_data,
const struct intel_vue_map *prev_stage_vue_map,
const struct brw_mue_map *mue_map,
int *per_primitive_offsets)
{
@ -999,7 +1006,8 @@ brw_nir_populate_fs_prog_data(nir_shader *shader,
(BITSET_TEST(shader->info.system_values_read, SYSTEM_VALUE_FRAG_COORD_Z) &&
prog_data->coarse_pixel_dispatch != INTEL_NEVER);
calculate_urb_setup(devinfo, key, prog_data, shader, mue_map, per_primitive_offsets);
calculate_urb_setup(devinfo, key, prog_data, shader, prev_stage_vue_map,
mue_map, per_primitive_offsets);
brw_compute_flat_inputs(prog_data, shader);
}
@ -1508,7 +1516,7 @@ brw_compile_fs(const struct brw_compiler *compiler,
memset(per_primitive_offsets, -1, sizeof(per_primitive_offsets));
brw_nir_populate_fs_prog_data(nir, compiler->devinfo, key, prog_data,
params->mue_map,
params->vue_map, params->mue_map,
per_primitive_offsets);
/* From the SKL PRM, Volume 7, "Alpha Coverage":

View file

@ -1000,26 +1000,23 @@ populate_compile_params_mesh(union brw_any_compile_params *params,
static void
populate_compile_params_fs(union brw_any_compile_params *params,
const struct intel_device_info *devinfo,
struct anv_shader_data *shader_data)
struct anv_shader_data *shader_data,
struct anv_shader_data *prev_shader_data)
{
nir_shader *nir = shader_data->info->nir;
/* When using Primitive Replication for multiview, each view gets its own
* position slot.
*/
uint32_t pos_slots = shader_data->use_primitive_replication ?
MAX2(1, util_bitcount(shader_data->key.base.view_mask)) : 1;
/* TODO: Should we find a way to pass this to brw_compile? */
struct intel_vue_map prev_vue_map;
brw_compute_vue_map(devinfo,
&prev_vue_map,
nir->info.inputs_read,
nir->info.separate_shader,
pos_slots);
params->fs.mue_map = shader_data->mue_map;
if (prev_shader_data) {
switch (prev_shader_data->info->stage) {
case MESA_SHADER_VERTEX:
case MESA_SHADER_TESS_EVAL:
case MESA_SHADER_GEOMETRY:
params->fs.vue_map = &prev_shader_data->prog_data.vue.vue_map;
break;
case MESA_SHADER_MESH:
params->fs.mue_map = shader_data->mue_map;
break;
default:
break;
}
}
params->fs.allow_spilling = true;
params->fs.max_polygons = UCHAR_MAX;
@ -2051,7 +2048,7 @@ anv_shader_compile(struct vk_device *vk_device,
prev_shader_data);
break;
case MESA_SHADER_FRAGMENT:
populate_compile_params_fs(&params, devinfo, shader_data);
populate_compile_params_fs(&params, shader_data, prev_shader_data);
break;
case MESA_SHADER_RAYGEN:
case MESA_SHADER_ANY_HIT: