diff --git a/src/intel/compiler/brw_nir.c b/src/intel/compiler/brw_nir.c index d03bb90132c..99c0fe54e59 100644 --- a/src/intel/compiler/brw_nir.c +++ b/src/intel/compiler/brw_nir.c @@ -1095,6 +1095,78 @@ brw_nir_zero_inputs(nir_shader *shader, uint64_t *zero_inputs) nir_metadata_block_index | nir_metadata_dominance, zero_inputs); } +/* Code for Wa_14015590813 may have created input/output variables beyond + * VARYING_SLOT_MAX and removed uses of variables below VARYING_SLOT_MAX. + * Clean it up, so they all stay below VARYING_SLOT_MAX. + */ +static void +brw_mesh_compact_io(nir_shader *mesh, nir_shader *frag) +{ + gl_varying_slot mapping[VARYING_SLOT_MAX] = {0, }; + gl_varying_slot cur = VARYING_SLOT_VAR0; + bool compact = false; + + nir_foreach_shader_out_variable(var, mesh) { + gl_varying_slot location = var->data.location; + if (location < VARYING_SLOT_VAR0) + continue; + assert(location < ARRAY_SIZE(mapping)); + + const struct glsl_type *type = var->type; + if (nir_is_arrayed_io(var, MESA_SHADER_MESH) || var->data.per_view) { + assert(glsl_type_is_array(type)); + type = glsl_get_array_element(type); + } + + if (mapping[location]) + continue; + + unsigned num_slots = glsl_count_attribute_slots(type, false); + + compact |= location + num_slots > VARYING_SLOT_MAX; + + mapping[location] = cur; + cur += num_slots; + } + + if (!compact) + return; + + /* The rest of this function should be hit only for Wa_14015590813. */ + + nir_foreach_shader_out_variable(var, mesh) { + gl_varying_slot location = var->data.location; + if (location < VARYING_SLOT_VAR0) + continue; + location = mapping[location]; + if (location == 0) + continue; + var->data.location = location; + } + + nir_foreach_shader_in_variable(var, frag) { + gl_varying_slot location = var->data.location; + if (location < VARYING_SLOT_VAR0) + continue; + location = mapping[location]; + if (location == 0) + continue; + var->data.location = location; + } + + nir_shader_gather_info(mesh, nir_shader_get_entrypoint(mesh)); + nir_shader_gather_info(frag, nir_shader_get_entrypoint(frag)); + + if (should_print_nir(mesh)) { + printf("%s\n", __func__); + nir_print_shader(mesh, stdout); + } + if (should_print_nir(frag)) { + printf("%s\n", __func__); + nir_print_shader(frag, stdout); + } +} + void brw_nir_link_shaders(const struct brw_compiler *compiler, nir_shader *producer, nir_shader *consumer) @@ -1177,6 +1249,11 @@ brw_nir_link_shaders(const struct brw_compiler *compiler, brw_nir_optimize(producer, compiler, p_is_scalar); brw_nir_optimize(consumer, compiler, c_is_scalar); + + if (producer->info.stage == MESA_SHADER_MESH && + consumer->info.stage == MESA_SHADER_FRAGMENT) { + brw_mesh_compact_io(producer, consumer); + } } NIR_PASS(_, producer, nir_lower_io_to_vector, nir_var_shader_out);