diff --git a/src/gallium/drivers/radeonsi/si_shader.h b/src/gallium/drivers/radeonsi/si_shader.h index b635b696569..ec62ad0830a 100644 --- a/src/gallium/drivers/radeonsi/si_shader.h +++ b/src/gallium/drivers/radeonsi/si_shader.h @@ -363,6 +363,10 @@ struct si_shader_info { bool writes_stencil; /**< does fragment shader write stencil value? */ bool writes_samplemask; /**< does fragment shader write sample mask? */ bool writes_edgeflag; /**< vertex shader outputs edgeflag */ + bool uses_interp_color; + bool uses_persp_center_color; + bool uses_persp_centroid_color; + bool uses_persp_sample_color; bool uses_persp_center; bool uses_persp_centroid; bool uses_persp_sample; diff --git a/src/gallium/drivers/radeonsi/si_shader_nir.c b/src/gallium/drivers/radeonsi/si_shader_nir.c index ae190b2de59..3ad56baf2cd 100644 --- a/src/gallium/drivers/radeonsi/si_shader_nir.c +++ b/src/gallium/drivers/radeonsi/si_shader_nir.c @@ -266,6 +266,37 @@ static void scan_instruction(const struct nir_shader *nir, struct si_shader_info unsigned index = intr->intrinsic == nir_intrinsic_load_color1; uint8_t mask = nir_ssa_def_components_read(&intr->dest.ssa); info->colors_read |= mask << (index * 4); + + switch (info->color_interpolate[index]) { + case INTERP_MODE_SMOOTH: + if (info->color_interpolate_loc[index] == TGSI_INTERPOLATE_LOC_SAMPLE) + info->uses_persp_sample = true; + else if (info->color_interpolate_loc[index] == TGSI_INTERPOLATE_LOC_CENTROID) + info->uses_persp_centroid = true; + else if (info->color_interpolate_loc[index] == TGSI_INTERPOLATE_LOC_CENTER) + info->uses_persp_center = true; + break; + case INTERP_MODE_NOPERSPECTIVE: + if (info->color_interpolate_loc[index] == TGSI_INTERPOLATE_LOC_SAMPLE) + info->uses_linear_sample = true; + else if (info->color_interpolate_loc[index] == TGSI_INTERPOLATE_LOC_CENTROID) + info->uses_linear_centroid = true; + else if (info->color_interpolate_loc[index] == TGSI_INTERPOLATE_LOC_CENTER) + info->uses_linear_center = true; + break; + case INTERP_MODE_COLOR: + /* We don't know the final value. This will be FLAT if flatshading is enabled + * in the rasterizer state, otherwise it will be SMOOTH. + */ + info->uses_interp_color = true; + if (info->color_interpolate_loc[index] == TGSI_INTERPOLATE_LOC_SAMPLE) + info->uses_persp_sample_color = true; + else if (info->color_interpolate_loc[index] == TGSI_INTERPOLATE_LOC_CENTROID) + info->uses_persp_centroid_color = true; + else if (info->color_interpolate_loc[index] == TGSI_INTERPOLATE_LOC_CENTER) + info->uses_persp_center_color = true; + break; + } break; } case nir_intrinsic_load_barycentric_at_offset: /* uses center */ diff --git a/src/gallium/drivers/radeonsi/si_state_shaders.c b/src/gallium/drivers/radeonsi/si_state_shaders.c index 1119fb387af..661147f90d7 100644 --- a/src/gallium/drivers/radeonsi/si_state_shaders.c +++ b/src/gallium/drivers/radeonsi/si_state_shaders.c @@ -2009,7 +2009,7 @@ static inline void si_shader_selector_key(struct pipe_context *ctx, struct si_sh bool is_line = util_prim_is_lines(sctx->current_rast_prim); key->part.ps.prolog.color_two_side = rs->two_side && sel->info.colors_read; - key->part.ps.prolog.flatshade_colors = rs->flatshade && sel->info.colors_read; + key->part.ps.prolog.flatshade_colors = rs->flatshade && sel->info.uses_interp_color; key->part.ps.epilog.alpha_to_one = blend->alpha_to_one && rs->multisample_enable; @@ -2023,30 +2023,35 @@ static inline void si_shader_selector_key(struct pipe_context *ctx, struct si_sh key->part.ps.prolog.samplemask_log_ps_iter = util_logbase2(sctx->ps_iter_samples); } + bool uses_persp_center = sel->info.uses_persp_center || + (!rs->flatshade && sel->info.uses_persp_center_color); + bool uses_persp_centroid = sel->info.uses_persp_centroid || + (!rs->flatshade && sel->info.uses_persp_centroid_color); + bool uses_persp_sample = sel->info.uses_persp_sample || + (!rs->flatshade && sel->info.uses_persp_sample_color); + if (rs->force_persample_interp && rs->multisample_enable && sctx->framebuffer.nr_samples > 1 && sctx->ps_iter_samples > 1) { key->part.ps.prolog.force_persp_sample_interp = - sel->info.uses_persp_center || sel->info.uses_persp_centroid; + uses_persp_center || uses_persp_centroid; key->part.ps.prolog.force_linear_sample_interp = sel->info.uses_linear_center || sel->info.uses_linear_centroid; } else if (rs->multisample_enable && sctx->framebuffer.nr_samples > 1) { key->part.ps.prolog.bc_optimize_for_persp = - sel->info.uses_persp_center && sel->info.uses_persp_centroid; + uses_persp_center && uses_persp_centroid; key->part.ps.prolog.bc_optimize_for_linear = sel->info.uses_linear_center && sel->info.uses_linear_centroid; } else { /* Make sure SPI doesn't compute more than 1 pair * of (i,j), which is the optimization here. */ - key->part.ps.prolog.force_persp_center_interp = sel->info.uses_persp_center + - sel->info.uses_persp_centroid + - sel->info.uses_persp_sample > - 1; + key->part.ps.prolog.force_persp_center_interp = uses_persp_center + + uses_persp_centroid + + uses_persp_sample > 1; key->part.ps.prolog.force_linear_center_interp = sel->info.uses_linear_center + - sel->info.uses_linear_centroid + - sel->info.uses_linear_sample > - 1; + sel->info.uses_linear_centroid + + sel->info.uses_linear_sample > 1; if (sel->info.uses_interp_at_sample) key->mono.u.ps.interpolate_at_sample_force_center = 1;