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 <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32855>
This commit is contained in:
Marek Olšák
2025-01-01 21:21:39 -05:00
committed by Marge Bot
parent 1278d5286c
commit ff6e3e9f76
7 changed files with 29 additions and 18 deletions
+1 -1
View File
@@ -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. */
+14 -5
View File
@@ -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;
+2 -2
View File
@@ -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));
+2 -1
View File
@@ -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;
+1 -1
View File
@@ -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;
}
+2 -1
View File
@@ -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.
+7 -7
View File
@@ -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 &&