diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 1eea39602fd..ec72288032b 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -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); diff --git a/src/compiler/nir/nir_opt_fragdepth.c b/src/compiler/nir/nir_opt_fragdepth.c index 9c0fb17a7d6..4c8e3ff8cce 100644 --- a/src/compiler/nir/nir_opt_fragdepth.c +++ b/src/compiler/nir/nir_opt_fragdepth.c @@ -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; diff --git a/src/gallium/drivers/radeonsi/si_shader.h b/src/gallium/drivers/radeonsi/si_shader.h index 3978f4813d8..13144b606cb 100644 --- a/src/gallium/drivers/radeonsi/si_shader.h +++ b/src/gallium/drivers/radeonsi/si_shader.h @@ -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 */ diff --git a/src/gallium/drivers/radeonsi/si_shader_info.c b/src/gallium/drivers/radeonsi/si_shader_info.c index 57e59f82862..a097f78ccad 100644 --- a/src/gallium/drivers/radeonsi/si_shader_info.c +++ b/src/gallium/drivers/radeonsi/si_shader_info.c @@ -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 || diff --git a/src/gallium/drivers/radeonsi/si_state_shaders.cpp b/src/gallium/drivers/radeonsi/si_state_shaders.cpp index fc00fdd516f..4032e179055 100644 --- a/src/gallium/drivers/radeonsi/si_state_shaders.cpp +++ b/src/gallium/drivers/radeonsi/si_state_shaders.cpp @@ -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);