ac/nir: clamp vertex color outputs in the right place

Reviewed-by: Timur Kristóf <timur.kristof@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33024>
This commit is contained in:
Marek Olšák
2024-12-29 19:10:10 -05:00
parent 4f63b21df0
commit 1026402b7c
6 changed files with 46 additions and 58 deletions
@@ -69,15 +69,6 @@ ac_nir_create_gs_copy_shader(const nir_shader *gs_nir,
nir_load_buffer_amd(&b, 1, 32, gsvs_ring, vtx_offset, zero, zero,
.base = offset,
.access = ACCESS_COHERENT | ACCESS_NON_TEMPORAL);
/* clamp legacy color output */
if (i == VARYING_SLOT_COL0 || i == VARYING_SLOT_COL1 ||
i == VARYING_SLOT_BFC0 || i == VARYING_SLOT_BFC1) {
nir_def *color = out.outputs[i][j];
nir_def *clamp = nir_load_clamp_vertex_color_amd(&b);
out.outputs[i][j] = nir_bcsel(&b, clamp, nir_fsat(&b, color), color);
}
offset += gs_nir->info.gs.vertices_out * 16 * 4;
}
}
@@ -117,6 +108,9 @@ ac_nir_create_gs_copy_shader(const nir_shader *gs_nir,
if (stream_id)
ac_nir_emit_legacy_streamout(&b, stream, info, &out);
/* This should be after streamout and before exports. */
ac_nir_clamp_vertex_color_outputs(&b, &out);
if (stream == 0) {
uint64_t export_outputs = b.shader->info.outputs_written | VARYING_BIT_POS;
if (kill_pointsize)
+3
View File
@@ -179,6 +179,9 @@ ac_nir_pack_ngg_prim_exp_arg(nir_builder *b, unsigned num_vertices_per_primitive
nir_def *vertex_indices[3], nir_def *is_null_prim,
enum amd_gfx_level gfx_level);
void
ac_nir_clamp_vertex_color_outputs(nir_builder *b, ac_nir_prerast_out *out);
#ifdef __cplusplus
}
#endif
+5 -5
View File
@@ -45,7 +45,6 @@ ac_nir_lower_legacy_vs(nir_shader *nir,
bool force_vrs)
{
nir_function_impl *impl = nir_shader_get_entrypoint(nir);
nir_metadata preserved = nir_metadata_control_flow;
nir_builder b = nir_builder_at(nir_after_impl(impl));
@@ -65,10 +64,11 @@ ac_nir_lower_legacy_vs(nir_shader *nir,
nir->info.outputs_written |= BITFIELD64_BIT(VARYING_SLOT_PRIMITIVE_ID);
}
if (!disable_streamout && nir->xfb_info) {
if (!disable_streamout && nir->xfb_info)
ac_nir_emit_legacy_streamout(&b, 0, ac_nir_get_sorted_xfb_info(nir), &out);
preserved = nir_metadata_none;
}
/* This should be after streamout and before exports. */
ac_nir_clamp_vertex_color_outputs(&b, &out);
uint64_t export_outputs = nir->info.outputs_written | VARYING_BIT_POS;
if (kill_pointsize)
@@ -86,5 +86,5 @@ ac_nir_lower_legacy_vs(nir_shader *nir,
&out);
}
nir_metadata_preserve(impl, preserved);
nir_metadata_preserve(impl, nir_metadata_none);
}
+6
View File
@@ -2635,6 +2635,9 @@ ac_nir_lower_ngg_nogs(nir_shader *shader, const ac_nir_lower_ngg_options *option
ngg_nogs_gather_outputs(b, &if_es_thread->then_list, &state);
b->cursor = nir_after_cf_list(&if_es_thread->then_list);
/* This should be after streamout and before exports. */
ac_nir_clamp_vertex_color_outputs(b, &state.out);
if (state.has_user_edgeflags)
ngg_nogs_store_edgeflag_to_lds(b, &state);
@@ -3124,6 +3127,9 @@ ngg_gs_export_vertices(nir_builder *b, nir_def *max_num_out_vtx, nir_def *tid_in
}
}
/* This should be after streamout and before exports. */
ac_nir_clamp_vertex_color_outputs(b, &s->out);
uint64_t export_outputs = b->shader->info.outputs_written | VARYING_BIT_POS;
if (s->options->kill_pointsize)
export_outputs &= ~VARYING_BIT_PSIZ;
+27
View File
@@ -824,3 +824,30 @@ ac_nir_pack_ngg_prim_exp_arg(nir_builder *b, unsigned num_vertices_per_primitive
return arg;
}
void
ac_nir_clamp_vertex_color_outputs(nir_builder *b, ac_nir_prerast_out *out)
{
/* Clamp color outputs. */
if (!(b->shader->info.outputs_written & (VARYING_BIT_COL0 | VARYING_BIT_COL1 |
VARYING_BIT_BFC0 | VARYING_BIT_BFC1)))
return;
nir_def *color_channels[16] = {0};
nir_if *if_clamp = nir_push_if(b, nir_load_clamp_vertex_color_amd(b));
{
for (unsigned i = 0; i < 16; i++) {
const unsigned slot = (i / 8 ? VARYING_SLOT_BFC0 : VARYING_SLOT_COL0) + (i % 8) / 4;
if (out->outputs[slot][i % 4])
color_channels[i] = nir_fsat(b, out->outputs[slot][i % 4]);
}
}
nir_pop_if(b, if_clamp);
for (unsigned i = 0; i < 16; i++) {
if (color_channels[i]) {
const unsigned slot = (i / 8 ? VARYING_SLOT_BFC0 : VARYING_SLOT_COL0) + (i % 8) / 4;
out->outputs[slot][i % 4] = nir_if_phi(b, color_channels[i], out->outputs[slot][i % 4]);
}
}
}
+2 -44
View File
@@ -1803,43 +1803,6 @@ static bool si_nir_kill_ps_outputs(nir_shader *nir, const union si_shader_key *k
nir_metadata_control_flow, (void*)key);
}
static bool clamp_vertex_color_instr(nir_builder *b,
nir_intrinsic_instr *intrin, void *state)
{
if (intrin->intrinsic != nir_intrinsic_store_output)
return false;
unsigned location = nir_intrinsic_io_semantics(intrin).location;
if (location != VARYING_SLOT_COL0 && location != VARYING_SLOT_COL1 &&
location != VARYING_SLOT_BFC0 && location != VARYING_SLOT_BFC1)
return false;
/* no indirect output */
assert(nir_src_is_const(intrin->src[1]) && !nir_src_as_uint(intrin->src[1]));
/* only scalar output */
assert(intrin->src[0].ssa->num_components == 1);
b->cursor = nir_before_instr(&intrin->instr);
nir_def *color = intrin->src[0].ssa;
nir_def *clamp = nir_load_clamp_vertex_color_amd(b);
nir_def *new_color = nir_bcsel(b, clamp, nir_fsat(b, color), color);
nir_src_rewrite(&intrin->src[0], new_color);
return true;
}
static bool si_nir_clamp_vertex_color(nir_shader *nir)
{
uint64_t mask = VARYING_BIT_COL0 | VARYING_BIT_COL1 | VARYING_BIT_BFC0 | VARYING_BIT_BFC1;
if (!(nir->info.outputs_written & mask))
return false;
return nir_shader_intrinsics_pass(nir, clamp_vertex_color_instr,
nir_metadata_control_flow,
NULL);
}
static unsigned si_map_io_driver_location(unsigned semantic)
{
if ((semantic >= VARYING_SLOT_PATCH0 && semantic < VARYING_SLOT_TESS_MAX) ||
@@ -2428,18 +2391,13 @@ static struct nir_shader *si_get_nir_shader(struct si_shader *shader, struct si_
NIR_PASS(progress, nir, nir_lower_non_uniform_access, &options);
}
/* Legacy GS is not the last VGT stage because there is also the GS copy shader. */
bool is_last_vgt_stage =
(nir->info.stage == MESA_SHADER_VERTEX ||
nir->info.stage == MESA_SHADER_TESS_EVAL ||
(nir->info.stage == MESA_SHADER_GEOMETRY && shader->key.ge.as_ngg)) &&
!shader->key.ge.as_ls && !shader->key.ge.as_es;
/* Legacy GS is not last VGT stage because it has GS copy shader. */
bool is_legacy_gs = nir->info.stage == MESA_SHADER_GEOMETRY && !key->ge.as_ngg;
if (is_last_vgt_stage || is_legacy_gs)
NIR_PASS(progress, nir, si_nir_clamp_vertex_color);
if (progress) {
si_nir_opts(sel->screen, nir, true);
late_opts = true;
@@ -2497,7 +2455,7 @@ static struct nir_shader *si_get_nir_shader(struct si_shader *shader, struct si_
sel->screen->options.vrs2x2);
}
progress = true;
} else if (is_legacy_gs) {
} else if (nir->info.stage == MESA_SHADER_GEOMETRY && !key->ge.as_ngg) {
NIR_PASS_V(nir, ac_nir_lower_legacy_gs, false, sel->screen->use_ngg, output_info);
progress = true;
} else if (nir->info.stage == MESA_SHADER_FRAGMENT && shader->is_monolithic) {