From ff6e3e9f76dcf2232d48a18529c396acb8340dee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Wed, 1 Jan 2025 21:21:39 -0500 Subject: [PATCH] nir: add next_stage param to nir_slot_is_varying & nir_remove_sysval_output The result of nir_slot_is_varying depends on what the next shader stage is, and nir_remove_sysval_output uses it. Reviewed-by: Alyssa Rosenzweig Part-of: --- src/amd/common/nir/ac_nir_opt_outputs.c | 2 +- src/compiler/nir/nir.c | 19 ++++++++++++++----- src/compiler/nir/nir.h | 4 ++-- src/compiler/nir/nir_lower_io_to_scalar.c | 3 ++- src/compiler/nir/nir_opt_clip_cull_const.c | 2 +- src/compiler/nir/nir_validate.c | 3 ++- src/gallium/drivers/radeonsi/si_shader.c | 14 +++++++------- 7 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/amd/common/nir/ac_nir_opt_outputs.c b/src/amd/common/nir/ac_nir_opt_outputs.c index 45b9381c30b..c04e146e146 100644 --- a/src/amd/common/nir/ac_nir_opt_outputs.c +++ b/src/amd/common/nir/ac_nir_opt_outputs.c @@ -254,7 +254,7 @@ bool ac_nir_optimize_outputs(nir_shader *nir, bool sprite_tex_disallowed, nir_io_semantics sem = nir_intrinsic_io_semantics(intr); /* Only process varyings that appear as param exports. */ - if (!nir_slot_is_varying(sem.location) || sem.no_varying) + if (!nir_slot_is_varying(sem.location, MESA_SHADER_FRAGMENT) || sem.no_varying) continue; /* We can't optimize texture coordinates if sprite_coord_enable can override them. */ diff --git a/src/compiler/nir/nir.c b/src/compiler/nir/nir.c index 208f1185ef8..0c49a9e952d 100644 --- a/src/compiler/nir/nir.c +++ b/src/compiler/nir/nir.c @@ -3493,11 +3493,18 @@ nir_slot_is_sysval_output(gl_varying_slot slot, gl_shader_stage next_shader) /** * Whether an input/output slot is consumed by the next shader stage, * or written by the previous shader stage. + * + * Pass MESA_SHADER_NONE if the next shader is unknown. */ bool -nir_slot_is_varying(gl_varying_slot slot) +nir_slot_is_varying(gl_varying_slot slot, gl_shader_stage next_shader) { + bool unknown = next_shader == MESA_SHADER_NONE; + bool exactly_before_fs = next_shader == MESA_SHADER_FRAGMENT || unknown; + bool at_most_before_gs = next_shader <= MESA_SHADER_GEOMETRY || unknown; + return slot >= VARYING_SLOT_VAR0 || + (slot == VARYING_SLOT_POS && at_most_before_gs) || slot == VARYING_SLOT_COL0 || slot == VARYING_SLOT_COL1 || slot == VARYING_SLOT_BFC0 || @@ -3505,6 +3512,7 @@ nir_slot_is_varying(gl_varying_slot slot) slot == VARYING_SLOT_FOGC || (slot >= VARYING_SLOT_TEX0 && slot <= VARYING_SLOT_TEX7) || slot == VARYING_SLOT_PNTC || + (slot == VARYING_SLOT_CLIP_VERTEX && at_most_before_gs) || slot == VARYING_SLOT_CLIP_DIST0 || slot == VARYING_SLOT_CLIP_DIST1 || slot == VARYING_SLOT_CULL_DIST0 || @@ -3513,7 +3521,8 @@ nir_slot_is_varying(gl_varying_slot slot) slot == VARYING_SLOT_LAYER || slot == VARYING_SLOT_VIEWPORT || slot == VARYING_SLOT_TESS_LEVEL_OUTER || - slot == VARYING_SLOT_TESS_LEVEL_INNER; + slot == VARYING_SLOT_TESS_LEVEL_INNER || + (slot == VARYING_SLOT_VIEW_INDEX && exactly_before_fs); } bool @@ -3521,7 +3530,7 @@ nir_slot_is_sysval_output_and_varying(gl_varying_slot slot, gl_shader_stage next_shader) { return nir_slot_is_sysval_output(slot, next_shader) && - nir_slot_is_varying(slot); + nir_slot_is_varying(slot, next_shader); } /** @@ -3551,11 +3560,11 @@ nir_remove_varying(nir_intrinsic_instr *intr, gl_shader_stage next_shader) * logic. If the instruction has no other use, it's removed. */ bool -nir_remove_sysval_output(nir_intrinsic_instr *intr) +nir_remove_sysval_output(nir_intrinsic_instr *intr, gl_shader_stage next_shader) { nir_io_semantics sem = nir_intrinsic_io_semantics(intr); - if ((!sem.no_varying && nir_slot_is_varying(sem.location)) || + if ((!sem.no_varying && nir_slot_is_varying(sem.location, next_shader)) || nir_instr_xfb_write_mask(intr)) { /* Demote the store instruction. */ sem.no_sysval_output = true; diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 2d98ed86bdc..cdcbdc8b99e 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -5696,11 +5696,11 @@ nir_opt_varyings(nir_shader *producer, nir_shader *consumer, bool spirv, bool nir_slot_is_sysval_output(gl_varying_slot slot, gl_shader_stage next_shader); -bool nir_slot_is_varying(gl_varying_slot slot); +bool nir_slot_is_varying(gl_varying_slot slot, gl_shader_stage next_shader); bool nir_slot_is_sysval_output_and_varying(gl_varying_slot slot, gl_shader_stage next_shader); bool nir_remove_varying(nir_intrinsic_instr *intr, gl_shader_stage next_shader); -bool nir_remove_sysval_output(nir_intrinsic_instr *intr); +bool nir_remove_sysval_output(nir_intrinsic_instr *intr, gl_shader_stage next_shader); bool nir_lower_amul(nir_shader *shader, int (*type_size)(const struct glsl_type *, bool)); diff --git a/src/compiler/nir/nir_lower_io_to_scalar.c b/src/compiler/nir/nir_lower_io_to_scalar.c index d28d4667372..49b102028a7 100644 --- a/src/compiler/nir/nir_lower_io_to_scalar.c +++ b/src/compiler/nir/nir_lower_io_to_scalar.c @@ -161,7 +161,8 @@ lower_store_output_to_scalar(nir_builder *b, nir_intrinsic_instr *intr) */ if ((sem.no_sysval_output || !nir_slot_is_sysval_output(sem.location, MESA_SHADER_NONE)) && - (sem.no_varying || !nir_slot_is_varying(sem.location)) && + (sem.no_varying || + !nir_slot_is_varying(sem.location, MESA_SHADER_NONE)) && !has_xfb) continue; diff --git a/src/compiler/nir/nir_opt_clip_cull_const.c b/src/compiler/nir/nir_opt_clip_cull_const.c index 9026d50605c..0132f0e7b83 100644 --- a/src/compiler/nir/nir_opt_clip_cull_const.c +++ b/src/compiler/nir/nir_opt_clip_cull_const.c @@ -42,7 +42,7 @@ opt_clip_cull(nir_builder *b, nir_intrinsic_instr *intr, void *unused) return false; } - nir_remove_sysval_output(intr); + nir_remove_sysval_output(intr, MESA_SHADER_FRAGMENT); return true; } diff --git a/src/compiler/nir/nir_validate.c b/src/compiler/nir/nir_validate.c index e4351b2942c..b687a6904af 100644 --- a/src/compiler/nir/nir_validate.c +++ b/src/compiler/nir/nir_validate.c @@ -784,7 +784,8 @@ validate_intrinsic_instr(nir_intrinsic_instr *instr, validate_state *state) validate_assert(state, (nir_slot_is_sysval_output(sem.location, MESA_SHADER_NONE) && !sem.no_sysval_output) || - (nir_slot_is_varying(sem.location) && !sem.no_varying) || + (nir_slot_is_varying(sem.location, MESA_SHADER_NONE) && + !sem.no_varying) || nir_instr_xfb_write_mask(instr) || /* TCS can set no_varying and no_sysval_output, meaning * that the output is only read by TCS and not TES. diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c index e3481bccbad..23759797bc9 100644 --- a/src/gallium/drivers/radeonsi/si_shader.c +++ b/src/gallium/drivers/radeonsi/si_shader.c @@ -1673,7 +1673,7 @@ static bool si_nir_kill_outputs(nir_shader *nir, const union si_shader_key *key) assert(intr->num_components == 1); /* only scalar stores expected */ nir_io_semantics sem = nir_intrinsic_io_semantics(intr); - if (nir_slot_is_varying(sem.location) && + if (nir_slot_is_varying(sem.location, MESA_SHADER_FRAGMENT) && key->ge.opt.kill_outputs & (1ull << si_shader_io_get_unique_index(sem.location))) progress |= nir_remove_varying(intr, MESA_SHADER_FRAGMENT); @@ -1681,7 +1681,7 @@ static bool si_nir_kill_outputs(nir_shader *nir, const union si_shader_key *key) switch (sem.location) { case VARYING_SLOT_PSIZ: if (key->ge.opt.kill_pointsize) - progress |= nir_remove_sysval_output(intr); + progress |= nir_remove_sysval_output(intr, MESA_SHADER_FRAGMENT); break; case VARYING_SLOT_CLIP_VERTEX: @@ -1690,7 +1690,7 @@ static bool si_nir_kill_outputs(nir_shader *nir, const union si_shader_key *key) */ if ((key->ge.opt.kill_clip_distances & SI_USER_CLIP_PLANE_MASK) == SI_USER_CLIP_PLANE_MASK) - progress |= nir_remove_sysval_output(intr); + progress |= nir_remove_sysval_output(intr, MESA_SHADER_FRAGMENT); break; case VARYING_SLOT_CLIP_DIST0: @@ -1701,7 +1701,7 @@ static bool si_nir_kill_outputs(nir_shader *nir, const union si_shader_key *key) nir_intrinsic_component(intr); if (key->ge.opt.kill_clip_distances & BITFIELD_BIT(index)) - progress |= nir_remove_sysval_output(intr); + progress |= nir_remove_sysval_output(intr, MESA_SHADER_FRAGMENT); } break; @@ -1710,7 +1710,7 @@ static bool si_nir_kill_outputs(nir_shader *nir, const union si_shader_key *key) progress |= nir_remove_varying(intr, MESA_SHADER_FRAGMENT); if (key->ge.opt.kill_layer) - progress |= nir_remove_sysval_output(intr); + progress |= nir_remove_sysval_output(intr, MESA_SHADER_FRAGMENT); break; } } @@ -2033,7 +2033,7 @@ static void si_nir_assign_param_offsets(nir_shader *nir, struct si_shader *shade outputs_written |= BITFIELD64_BIT(sem.location); /* Assign the param index if it's unassigned. */ - if (nir_slot_is_varying(sem.location) && !sem.no_varying && + if (nir_slot_is_varying(sem.location, MESA_SHADER_FRAGMENT) && !sem.no_varying && (sem.gs_streams & 0x3) == 0 && info->vs_output_param_offset[sem.location] == AC_EXP_PARAM_DEFAULT_VAL_0000) { /* The semantic and the base should be the same as in si_shader_info. */ @@ -2763,7 +2763,7 @@ si_nir_generate_gs_copy_shader(struct si_screen *sscreen, unsigned semantic = gsinfo->output_semantic[i]; /* Skip if no channel writes to stream 0. */ - if (!nir_slot_is_varying(semantic) || + if (!nir_slot_is_varying(semantic, MESA_SHADER_FRAGMENT) || (gsinfo->output_streams[i] & 0x03 && gsinfo->output_streams[i] & 0x0c && gsinfo->output_streams[i] & 0x30 &&