radeonsi: replace gl_FrontFacing with a constant if one side is always culled

Reviewed-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26307>
This commit is contained in:
Marek Olšák 2023-11-20 07:06:29 -05:00 committed by Marge Bot
parent 1afe6f3321
commit 55d81214c9
6 changed files with 50 additions and 10 deletions

View File

@ -587,6 +587,11 @@ static bool lower_intrinsic(nir_builder *b, nir_instr *instr, struct lower_abi_s
case nir_intrinsic_load_alpha_reference_amd:
replacement = ac_nir_load_arg(b, &args->ac, args->alpha_reference);
break;
case nir_intrinsic_load_front_face:
if (!key->ps.opt.force_front_face_input)
return false;
replacement = nir_imm_bool(b, key->ps.opt.force_front_face_input == 1);
break;
case nir_intrinsic_load_barycentric_optimize_amd: {
nir_def *prim_mask = ac_nir_load_arg(b, &args->ac, args->ac.prim_mask);
/* enabled when bit 31 is set */

View File

@ -2645,6 +2645,10 @@ si_set_spi_ps_input_config(struct si_shader *shader)
const struct si_shader_info *info = &sel->info;
const union si_shader_key *key = &shader->key;
/* TODO: This should be determined from the final NIR instead of the input NIR,
* otherwise LLVM will have a performance advantage here because it determines
* VGPR inputs for each shader variant after LLVM optimizations.
*/
shader->config.spi_ps_input_ena =
S_0286CC_PERSP_CENTER_ENA(info->uses_persp_center) |
S_0286CC_PERSP_CENTROID_ENA(info->uses_persp_centroid) |
@ -2652,7 +2656,7 @@ si_set_spi_ps_input_config(struct si_shader *shader)
S_0286CC_LINEAR_CENTER_ENA(info->uses_linear_center) |
S_0286CC_LINEAR_CENTROID_ENA(info->uses_linear_centroid) |
S_0286CC_LINEAR_SAMPLE_ENA(info->uses_linear_sample) |
S_0286CC_FRONT_FACE_ENA(info->uses_frontface) |
S_0286CC_FRONT_FACE_ENA(info->uses_frontface && !key->ps.opt.force_front_face_input) |
S_0286CC_SAMPLE_COVERAGE_ENA(info->reads_samplemask) |
S_0286CC_ANCILLARY_ENA(info->uses_sampleid || info->uses_layer_id);

View File

@ -797,6 +797,9 @@ struct si_shader_key_ps {
unsigned prefer_mono : 1;
unsigned inline_uniforms:1;
/* This eliminates the FRONT_FACE input VGPR as well as shader code using it. */
int force_front_face_input : 2; /* 0 = gl_FrontFacing, 1 = true, -1 = false */
/* This must be kept last to limit the number of variants
* depending only on the uniform values.
*/

View File

@ -1061,6 +1061,14 @@ static void *si_create_rs_state(struct pipe_context *ctx, const struct pipe_rast
}
}
/* Force gl_FrontFacing to true or false if the other face is culled. */
if (util_bitcount(state->cull_face) == 1) {
if (state->cull_face & PIPE_FACE_FRONT)
rs->force_front_face_input = -1;
else
rs->force_front_face_input = 1;
}
unsigned spi_interp_control_0 =
S_0286D4_FLAT_SHADE_ENA(1) |
S_0286D4_PNT_SPRITE_ENA(state->point_quad_rasterization) |
@ -1256,8 +1264,7 @@ static void si_bind_rs_state(struct pipe_context *ctx, void *state)
if (old_rs->multisample_enable != rs->multisample_enable)
si_ps_key_update_framebuffer_blend_rasterizer(sctx);
if (old_rs->two_side != rs->two_side ||
old_rs->flatshade != rs->flatshade ||
if (old_rs->flatshade != rs->flatshade ||
old_rs->clamp_fragment_color != rs->clamp_fragment_color)
si_ps_key_update_rasterizer(sctx);
@ -1276,7 +1283,9 @@ static void si_bind_rs_state(struct pipe_context *ctx, void *state)
old_rs->line_smooth != rs->line_smooth ||
old_rs->poly_smooth != rs->poly_smooth ||
old_rs->polygon_mode_is_points != rs->polygon_mode_is_points ||
old_rs->poly_stipple_enable != rs->poly_stipple_enable)
old_rs->poly_stipple_enable != rs->poly_stipple_enable ||
old_rs->two_side != rs->two_side ||
old_rs->force_front_face_input != rs->force_front_face_input)
si_vs_ps_key_update_rast_prim_smooth_stipple(sctx);
/* Used by si_get_vs_key_outputs in si_update_shaders: */

View File

@ -85,6 +85,7 @@ struct si_state_rasterizer {
unsigned polygon_mode_is_points : 1;
unsigned perpendicular_end_caps : 1;
unsigned bottom_edge_rule : 1;
int force_front_face_input : 2;
};
struct si_dsa_stencil_ref_part {

View File

@ -1872,6 +1872,14 @@ static void si_shader_ps(struct si_screen *sscreen, struct si_shader *shader)
assert(!shader->key.ps.part.prolog.force_linear_sample_interp ||
(!G_0286CC_LINEAR_CENTER_ENA(input_ena) && !G_0286CC_LINEAR_CENTROID_ENA(input_ena)));
/* color_two_side always enables FRONT_FACE. Since st/mesa disables two-side colors if the back
* face is culled, the only case when both color_two_side and force_front_face_input can be set
* is when the front face is culled (which means force_front_face_input == -1).
*/
assert(!shader->key.ps.opt.force_front_face_input || !G_0286CC_FRONT_FACE_ENA(input_ena) ||
(shader->key.ps.part.prolog.color_two_side &&
shader->key.ps.opt.force_front_face_input == -1));
/* Validate cases when the optimizations are off (read as implications). */
assert(shader->key.ps.part.prolog.bc_optimize_for_persp ||
!G_0286CC_PERSP_CENTER_ENA(input_ena) || !G_0286CC_PERSP_CENTROID_ENA(input_ena));
@ -2241,7 +2249,9 @@ void si_update_ps_inputs_read_or_disabled(struct si_context *sctx)
void si_vs_ps_key_update_rast_prim_smooth_stipple(struct si_context *sctx)
{
struct si_shader_ctx_state *hw_vs = si_get_vs(sctx);
if (!hw_vs->cso)
struct si_shader_selector *ps = sctx->shader.ps.cso;
if (!hw_vs->cso || !ps)
return;
struct si_state_rasterizer *rs = sctx->queued.named.rasterizer;
@ -2249,33 +2259,44 @@ void si_vs_ps_key_update_rast_prim_smooth_stipple(struct si_context *sctx)
union si_shader_key *ps_key = &sctx->shader.ps.key;
bool old_kill_pointsize = vs_key->ge.opt.kill_pointsize;
bool old_color_two_side = ps_key->ps.part.prolog.color_two_side;
bool old_poly_stipple = ps_key->ps.part.prolog.poly_stipple;
bool old_poly_line_smoothing = ps_key->ps.mono.poly_line_smoothing;
bool old_point_smoothing = ps_key->ps.mono.point_smoothing;
int old_force_front_face_input = ps_key->ps.opt.force_front_face_input;
if (sctx->current_rast_prim == MESA_PRIM_POINTS) {
vs_key->ge.opt.kill_pointsize = 0;
ps_key->ps.part.prolog.color_two_side = 0;
ps_key->ps.part.prolog.poly_stipple = 0;
ps_key->ps.mono.poly_line_smoothing = 0;
ps_key->ps.mono.point_smoothing = rs->point_smooth;
ps_key->ps.opt.force_front_face_input = ps->info.uses_frontface;
} else if (util_prim_is_lines(sctx->current_rast_prim)) {
vs_key->ge.opt.kill_pointsize = hw_vs->cso->info.writes_psize;
ps_key->ps.part.prolog.color_two_side = 0;
ps_key->ps.part.prolog.poly_stipple = 0;
ps_key->ps.mono.poly_line_smoothing = rs->line_smooth && sctx->framebuffer.nr_samples <= 1;
ps_key->ps.mono.point_smoothing = 0;
ps_key->ps.opt.force_front_face_input = ps->info.uses_frontface;
} else {
/* Triangles. */
vs_key->ge.opt.kill_pointsize = hw_vs->cso->info.writes_psize &&
!rs->polygon_mode_is_points;
ps_key->ps.part.prolog.color_two_side = rs->two_side && ps->info.colors_read;
ps_key->ps.part.prolog.poly_stipple = rs->poly_stipple_enable;
ps_key->ps.mono.poly_line_smoothing = rs->poly_smooth && sctx->framebuffer.nr_samples <= 1;
ps_key->ps.mono.point_smoothing = 0;
ps_key->ps.opt.force_front_face_input = rs->force_front_face_input &&
ps->info.uses_frontface;
}
if (vs_key->ge.opt.kill_pointsize != old_kill_pointsize ||
ps_key->ps.part.prolog.color_two_side != old_color_two_side ||
ps_key->ps.part.prolog.poly_stipple != old_poly_stipple ||
ps_key->ps.mono.poly_line_smoothing != old_poly_line_smoothing ||
ps_key->ps.mono.point_smoothing != old_point_smoothing)
ps_key->ps.mono.point_smoothing != old_point_smoothing ||
ps_key->ps.opt.force_front_face_input != old_force_front_face_input)
sctx->do_update_shaders = true;
}
@ -2486,16 +2507,13 @@ void si_ps_key_update_rasterizer(struct si_context *sctx)
if (!sel)
return;
bool old_color_two_side = key->ps.part.prolog.color_two_side;
bool old_flatshade_colors = key->ps.part.prolog.flatshade_colors;
bool old_clamp_color = key->ps.part.epilog.clamp_color;
key->ps.part.prolog.color_two_side = rs->two_side && sel->info.colors_read;
key->ps.part.prolog.flatshade_colors = rs->flatshade && sel->info.uses_interp_color;
key->ps.part.epilog.clamp_color = rs->clamp_fragment_color;
if (key->ps.part.prolog.color_two_side != old_color_two_side ||
key->ps.part.prolog.flatshade_colors != old_flatshade_colors ||
if (key->ps.part.prolog.flatshade_colors != old_flatshade_colors ||
key->ps.part.epilog.clamp_color != old_clamp_color)
sctx->do_update_shaders = true;
}