diff --git a/src/amd/common/nir/ac_nir_create_gs_copy_shader.c b/src/amd/common/nir/ac_nir_create_gs_copy_shader.c index 5934e4336ee..d5cc10ca6f0 100644 --- a/src/amd/common/nir/ac_nir_create_gs_copy_shader.c +++ b/src/amd/common/nir/ac_nir_create_gs_copy_shader.c @@ -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) diff --git a/src/amd/common/nir/ac_nir_helpers.h b/src/amd/common/nir/ac_nir_helpers.h index 624a7be5bb9..934e6403c0b 100644 --- a/src/amd/common/nir/ac_nir_helpers.h +++ b/src/amd/common/nir/ac_nir_helpers.h @@ -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 diff --git a/src/amd/common/nir/ac_nir_lower_legacy_vs.c b/src/amd/common/nir/ac_nir_lower_legacy_vs.c index a5b8cf731d4..4cacc0293f7 100644 --- a/src/amd/common/nir/ac_nir_lower_legacy_vs.c +++ b/src/amd/common/nir/ac_nir_lower_legacy_vs.c @@ -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); } diff --git a/src/amd/common/nir/ac_nir_lower_ngg.c b/src/amd/common/nir/ac_nir_lower_ngg.c index 9d8286ab7a1..4fcacbe8868 100644 --- a/src/amd/common/nir/ac_nir_lower_ngg.c +++ b/src/amd/common/nir/ac_nir_lower_ngg.c @@ -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; diff --git a/src/amd/common/nir/ac_nir_prerast_utils.c b/src/amd/common/nir/ac_nir_prerast_utils.c index 7848d8d010d..21bf4aa2e67 100644 --- a/src/amd/common/nir/ac_nir_prerast_utils.c +++ b/src/amd/common/nir/ac_nir_prerast_utils.c @@ -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]); + } + } +} diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c index 503608e8bd4..e438b17dcb4 100644 --- a/src/gallium/drivers/radeonsi/si_shader.c +++ b/src/gallium/drivers/radeonsi/si_shader.c @@ -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) {