radeonsi: implement nir_opt_frag_depth using kill_z instead of the NIR pass

This uses si_shader_info to store whether gl_FragDepth can be removed,
and it uses the kill_z epilog flag to do the removal without recompilation.

Reviewed-by: Qiang Yu <yuq825@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32713>
This commit is contained in:
Marek Olšák 2024-12-13 02:12:41 -05:00 committed by Marge Bot
parent b56f47611a
commit 58132d6fc8
5 changed files with 17 additions and 4 deletions

View file

@ -6890,6 +6890,7 @@ bool nir_opt_deref(nir_shader *shader);
bool nir_opt_find_array_copies(nir_shader *shader);
bool nir_def_is_frag_coord_z(nir_def *def);
bool nir_opt_fragdepth(nir_shader *shader);
bool nir_opt_gcm(nir_shader *shader, bool value_number);

View file

@ -31,8 +31,8 @@
* this value to gl_FragDepth, the store instruction is removed.
*/
static bool
ssa_def_is_source_depth(nir_def *def)
bool
nir_def_is_frag_coord_z(nir_def *def)
{
nir_scalar scalar = nir_scalar_resolved(def, 0);
nir_instr *instr = scalar.def->parent_instr;
@ -93,7 +93,7 @@ nir_opt_fragdepth(nir_shader *shader)
/* This isn't the only write: give up on this optimization */
goto end;
} else {
if (ssa_def_is_source_depth(intrin->src[data_src].ssa)) {
if (nir_def_is_frag_coord_z(intrin->src[data_src].ssa)) {
/* We're writing gl_FragCoord.z in gl_FragDepth: remember
* intrin so we can try to remove it later. */
store_intrin = intrin;

View file

@ -517,6 +517,9 @@ struct si_shader_info {
bool reads_samplemask; /**< does fragment shader read sample mask? */
bool reads_tess_factors; /**< If TES reads TESSINNER or TESSOUTER */
bool writes_z; /**< does fragment shader write Z value? */
/* We need both because both can be present in different conditional blocks. */
bool output_z_equals_input_z; /**< gl_FragDepth == gl_FragCoord.z for any write */
bool output_z_is_not_input_z; /**< gl_FragDepth != gl_FragCoord.z for any write */
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 */

View file

@ -279,6 +279,13 @@ static void scan_io_usage(const nir_shader *nir, struct si_shader_info *info,
}
}
}
if (nir->info.stage == MESA_SHADER_FRAGMENT && !is_input && semantic == FRAG_RESULT_DEPTH) {
if (nir_def_is_frag_coord_z(intr->src[0].ssa))
info->output_z_equals_input_z = true;
else
info->output_z_is_not_input_z = true;
}
}
static bool is_bindless_handle_indirect(nir_instr *src)
@ -649,6 +656,7 @@ void si_nir_scan_shader(struct si_screen *sscreen, const struct nir_shader *nir,
}
if (nir->info.stage == MESA_SHADER_FRAGMENT) {
info->output_z_equals_input_z &= !info->output_z_is_not_input_z;
info->allow_flat_shading = !(info->uses_persp_center || info->uses_persp_centroid ||
info->uses_persp_sample || info->uses_linear_center ||
info->uses_linear_centroid || info->uses_linear_sample ||

View file

@ -2601,7 +2601,8 @@ void si_ps_key_update_framebuffer_blend_dsa_rasterizer(struct si_context *sctx)
#endif
key->ps.part.epilog.kill_z = sel->info.writes_z &&
(!sctx->framebuffer.state.zsbuf || !dsa->depth_enabled);
(!sctx->framebuffer.state.zsbuf || !dsa->depth_enabled ||
(sel->info.output_z_equals_input_z && !rs->multisample_enable));
key->ps.part.epilog.kill_stencil = sel->info.writes_stencil &&
(!sctx->framebuffer.has_stencil || !dsa->stencil_enabled);