ac/nir: return progress from ac_nir_lower_ps_early

This changes the creation of barycentric coordinate variables to on-demand.
Everything else is ready to return progress.

Reviewed-by: Timur Kristóf <timur.kristof@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33024>
This commit is contained in:
Marek Olšák 2024-12-31 10:11:23 -05:00
parent 234b416ffb
commit 231009be65
3 changed files with 79 additions and 112 deletions

View file

@ -298,7 +298,7 @@ typedef struct {
bool kill_samplemask;
} ac_nir_lower_ps_early_options;
void
bool
ac_nir_lower_ps_early(nir_shader *nir, const ac_nir_lower_ps_early_options *options);
typedef struct {

View file

@ -24,49 +24,65 @@ typedef struct {
nir_variable *linear_center;
nir_variable *linear_centroid;
nir_variable *linear_sample;
bool lower_load_barycentric;
bool seen_color0_alpha;
} lower_ps_early_state;
static void
create_interp_param(nir_builder *b, lower_ps_early_state *s)
static nir_variable *
get_baryc_var_common(nir_builder *b, bool will_replace, nir_variable **var, const char *var_name)
{
if (s->options->force_persp_sample_interp) {
s->persp_center =
nir_local_variable_create(b->impl, glsl_vec_type(2), "persp_center");
if (will_replace) {
if (!*var) {
*var = nir_local_variable_create(b->impl, glsl_vec_type(2), var_name);
}
return *var;
}
return NULL;
}
if (s->options->force_persp_sample_interp ||
s->options->force_persp_center_interp) {
s->persp_centroid =
nir_local_variable_create(b->impl, glsl_vec_type(2), "persp_centroid");
static nir_variable *
get_baryc_var(nir_builder *b, nir_intrinsic_op baryc_op, enum glsl_interp_mode mode,
lower_ps_early_state *s)
{
switch (baryc_op) {
case nir_intrinsic_load_barycentric_pixel:
if (mode == INTERP_MODE_NOPERSPECTIVE) {
return get_baryc_var_common(b, s->options->force_linear_sample_interp, &s->linear_center,
"linear_center");
} else {
return get_baryc_var_common(b, s->options->force_persp_sample_interp, &s->persp_center,
"persp_center");
}
case nir_intrinsic_load_barycentric_centroid:
if (mode == INTERP_MODE_NOPERSPECTIVE) {
return get_baryc_var_common(b, s->options->force_linear_sample_interp ||
s->options->force_linear_center_interp, &s->linear_centroid,
"linear_centroid");
} else {
return get_baryc_var_common(b, s->options->force_persp_sample_interp ||
s->options->force_persp_center_interp, &s->persp_centroid,
"persp_centroid");
}
case nir_intrinsic_load_barycentric_sample:
if (mode == INTERP_MODE_NOPERSPECTIVE) {
return get_baryc_var_common(b, s->options->force_linear_center_interp, &s->linear_sample,
"linear_sample");
} else {
return get_baryc_var_common(b, s->options->force_persp_center_interp, &s->persp_sample,
"persp_sample");
}
default:
return NULL;
}
}
if (s->options->force_persp_center_interp) {
s->persp_sample =
nir_local_variable_create(b->impl, glsl_vec_type(2), "persp_sample");
}
if (s->options->force_linear_sample_interp) {
s->linear_center =
nir_local_variable_create(b->impl, glsl_vec_type(2), "linear_center");
}
if (s->options->force_linear_sample_interp ||
s->options->force_linear_center_interp) {
s->linear_centroid =
nir_local_variable_create(b->impl, glsl_vec_type(2), "linear_centroid");
}
if (s->options->force_linear_center_interp) {
s->linear_sample =
nir_local_variable_create(b->impl, glsl_vec_type(2), "linear_sample");
}
s->lower_load_barycentric =
s->persp_center || s->persp_centroid || s->persp_sample ||
s->linear_center || s->linear_centroid || s->linear_sample;
static void
set_interp_vars(nir_builder *b, nir_def *new_baryc, nir_variable *baryc1, nir_variable *baryc2)
{
if (baryc1)
nir_store_var(b, baryc1, new_baryc, 0x3);
if (baryc2)
nir_store_var(b, baryc2, new_baryc, 0x3);
}
static void
@ -75,83 +91,35 @@ init_interp_param(nir_builder *b, lower_ps_early_state *s)
b->cursor = nir_before_cf_list(&b->impl->body);
if (s->options->force_persp_sample_interp) {
nir_def *sample =
nir_load_barycentric_sample(b, 32, .interp_mode = INTERP_MODE_SMOOTH);
nir_store_var(b, s->persp_center, sample, 0x3);
nir_store_var(b, s->persp_centroid, sample, 0x3);
set_interp_vars(b, nir_load_barycentric_sample(b, 32, .interp_mode = INTERP_MODE_SMOOTH),
s->persp_center, s->persp_centroid);
}
if (s->options->force_linear_sample_interp) {
nir_def *sample =
nir_load_barycentric_sample(b, 32, .interp_mode = INTERP_MODE_NOPERSPECTIVE);
nir_store_var(b, s->linear_center, sample, 0x3);
nir_store_var(b, s->linear_centroid, sample, 0x3);
set_interp_vars(b, nir_load_barycentric_sample(b, 32, .interp_mode = INTERP_MODE_NOPERSPECTIVE),
s->linear_center, s->linear_centroid);
}
if (s->options->force_persp_center_interp) {
nir_def *center =
nir_load_barycentric_pixel(b, 32, .interp_mode = INTERP_MODE_SMOOTH);
nir_store_var(b, s->persp_sample, center, 0x3);
nir_store_var(b, s->persp_centroid, center, 0x3);
set_interp_vars(b, nir_load_barycentric_pixel(b, 32, .interp_mode = INTERP_MODE_SMOOTH),
s->persp_sample, s->persp_centroid);
}
if (s->options->force_linear_center_interp) {
nir_def *center =
nir_load_barycentric_pixel(b, 32, .interp_mode = INTERP_MODE_NOPERSPECTIVE);
nir_store_var(b, s->linear_sample, center, 0x3);
nir_store_var(b, s->linear_centroid, center, 0x3);
set_interp_vars(b, nir_load_barycentric_pixel(b, 32, .interp_mode = INTERP_MODE_NOPERSPECTIVE),
s->linear_sample, s->linear_centroid);
}
}
static bool
rewrite_ps_load_barycentric(nir_builder *b, nir_intrinsic_instr *intrin, lower_ps_early_state *s)
{
enum glsl_interp_mode mode = nir_intrinsic_interp_mode(intrin);
nir_variable *var = NULL;
switch (mode) {
case INTERP_MODE_NONE:
case INTERP_MODE_SMOOTH:
switch (intrin->intrinsic) {
case nir_intrinsic_load_barycentric_pixel:
var = s->persp_center;
break;
case nir_intrinsic_load_barycentric_centroid:
var = s->persp_centroid;
break;
case nir_intrinsic_load_barycentric_sample:
var = s->persp_sample;
break;
default:
break;
}
break;
case INTERP_MODE_NOPERSPECTIVE:
switch (intrin->intrinsic) {
case nir_intrinsic_load_barycentric_pixel:
var = s->linear_center;
break;
case nir_intrinsic_load_barycentric_centroid:
var = s->linear_centroid;
break;
case nir_intrinsic_load_barycentric_sample:
var = s->linear_sample;
break;
default:
break;
}
break;
default:
break;
}
if (!var)
nir_variable *baryc_var = get_baryc_var(b, intrin->intrinsic,
nir_intrinsic_interp_mode(intrin), s);
if (!baryc_var)
return false;
nir_def *replacement = nir_load_var(b, var);
nir_def_replace(&intrin->def, replacement);
nir_def_replace(&intrin->def, nir_load_var(b, baryc_var));
return true;
}
@ -255,7 +223,8 @@ optimize_lower_ps_outputs(nir_builder *b, nir_intrinsic_instr *intrin, lower_ps_
}
}
if (progress && intrin->src[0].ssa != value) {
if (intrin->src[0].ssa != value) {
assert(progress);
nir_src_rewrite(&intrin->src[0], value);
intrin->num_components = value->num_components;
} else {
@ -384,9 +353,7 @@ lower_ps_intrinsic(nir_builder *b, nir_instr *instr, void *state)
case nir_intrinsic_load_barycentric_pixel:
case nir_intrinsic_load_barycentric_centroid:
case nir_intrinsic_load_barycentric_sample:
if (s->lower_load_barycentric)
return rewrite_ps_load_barycentric(b, intrin, s);
break;
return rewrite_ps_load_barycentric(b, intrin, s);
case nir_intrinsic_load_sample_mask_in:
if (s->options->ps_iter_samples > 1)
return lower_ps_load_sample_mask_in(b, intrin, s);
@ -467,7 +434,7 @@ lower_ps_intrinsic(nir_builder *b, nir_instr *instr, void *state)
return false;
}
void
bool
ac_nir_lower_ps_early(nir_shader *nir, const ac_nir_lower_ps_early_options *options)
{
assert(nir->info.stage == MESA_SHADER_FRAGMENT);
@ -480,16 +447,17 @@ ac_nir_lower_ps_early(nir_shader *nir, const ac_nir_lower_ps_early_options *opti
.options = options,
};
create_interp_param(b, &state);
bool progress = nir_shader_instructions_pass(nir, lower_ps_intrinsic,
nir_metadata_control_flow, &state);
nir_shader_instructions_pass(nir, lower_ps_intrinsic,
nir_metadata_control_flow,
&state);
if (state.persp_center || state.persp_centroid || state.persp_sample ||
state.linear_center || state.linear_centroid || state.linear_sample) {
/* This must be after lower_ps_intrinsic. */
init_interp_param(b, &state);
/* This must be after lower_ps_intrinsic. */
init_interp_param(b, &state);
/* Cleanup local variables, as RADV won't do this. */
NIR_PASS(_, nir, nir_lower_vars_to_ssa);
}
/* Cleanup local variables, as RADV won't do this. */
if (state.lower_load_barycentric)
nir_lower_vars_to_ssa(nir);
return progress;
}

View file

@ -2549,7 +2549,7 @@ static struct nir_shader *si_get_nir_shader(struct si_shader *shader, struct si_
.kill_samplemask = key->ps.part.epilog.kill_samplemask,
};
NIR_PASS_V(nir, ac_nir_lower_ps_early, &early_options);
NIR_PASS(progress, nir, ac_nir_lower_ps_early, &early_options);
ac_nir_lower_ps_late_options late_options = {
.gfx_level = sel->screen->info.gfx_level,
@ -2577,8 +2577,7 @@ static struct nir_shader *si_get_nir_shader(struct si_shader *shader, struct si_
.alpha_func = COMPARE_FUNC_ALWAYS,
.spi_shader_col_format_hint = ~0,
};
NIR_PASS_V(nir, ac_nir_lower_ps_early, &early_options);
progress = true;
NIR_PASS(progress, nir, ac_nir_lower_ps_early, &early_options);
}
assert(shader->wave_size == 32 || shader->wave_size == 64);