nir: add barycentric coordinates src to load_point_coord_maybe_flipped

Just like other input loads, radeonsi needs to know the barycentric
coordinates for it. This adds the src and determines the optimal barycentric
coordinates in nir_lower_point_smooth, the only producer of the intrinsic.

Reviewed-by: Timur Kristóf <timur.kristof@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33046>
This commit is contained in:
Marek Olšák
2024-12-30 23:40:05 -05:00
committed by Marge Bot
parent 97412fca25
commit 0d961b0723
5 changed files with 66 additions and 10 deletions
+1 -1
View File
@@ -7107,7 +7107,7 @@ nir_opt_preamble(nir_shader *shader,
nir_function_impl *nir_shader_get_preamble(nir_shader *shader);
bool nir_lower_point_smooth(nir_shader *shader);
bool nir_lower_point_smooth(nir_shader *shader, bool set_barycentrics);
bool nir_lower_poly_line_smooth(nir_shader *shader, unsigned num_smooth_aa_sample);
bool nir_mod_analysis(nir_scalar val, nir_alu_type val_type, unsigned div, unsigned *mod);
+3 -1
View File
@@ -2398,7 +2398,9 @@ system_value("sm_id_nv", 1, bit_sizes=[32])
# flipped in hardware based on a state bit. This version of gl_PointCoord
# is defined to be whatever thing the hardware can easily give you, so long as
# it's in normalized coordinates in the range [0, 1] across the point.
intrinsic("load_point_coord_maybe_flipped", dest_comp=2, bit_sizes=[32])
#
# src0 contains barycentrics for interpolation.
intrinsic("load_point_coord_maybe_flipped", dest_comp=2, bit_sizes=[32], src_comp=[2])
# Load texture size values:
+60 -6
View File
@@ -25,6 +25,29 @@
#include "nir_builder.h"
#include "nir_builtin_builder.h"
typedef struct {
bool set_barycentrics;
nir_intrinsic_instr *found_baryc;
} lower_point_smooth_state;
static nir_intrinsic_instr *
find_any_used_barycentrics(nir_function_impl *impl)
{
nir_foreach_block(block, impl) {
nir_foreach_instr(instr, block) {
if (instr->type == nir_instr_type_intrinsic) {
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
if (intr->intrinsic == nir_intrinsic_load_barycentric_pixel ||
intr->intrinsic == nir_intrinsic_load_barycentric_centroid ||
intr->intrinsic == nir_intrinsic_load_barycentric_sample)
return intr;
}
}
}
return NULL;
}
/**
* This NIR lowers pass for point smoothing by modifying the alpha value of
* fragment outputs using the distance from the center of the point.
@@ -32,9 +55,10 @@
*/
static bool
lower_point_smooth(nir_builder *b, nir_intrinsic_instr *intr,
UNUSED void *_state)
lower_point_smooth(nir_builder *b, nir_intrinsic_instr *intr, void *state)
{
lower_point_smooth_state *s = (lower_point_smooth_state *)state;
if (intr->intrinsic != nir_intrinsic_store_output &&
intr->intrinsic != nir_intrinsic_store_deref)
return false;
@@ -59,14 +83,37 @@ lower_point_smooth(nir_builder *b, nir_intrinsic_instr *intr,
b->cursor = nir_before_instr(&intr->instr);
nir_def *coord = nir_load_point_coord_maybe_flipped(b);
/* Determine the barycentric coordinates. */
nir_def *baryc;
if (s->set_barycentrics) {
baryc = nir_load_barycentric_pixel(b, 32,
.interp_mode = INTERP_MODE_SMOOTH);
/* Since point interpolation mostly doesn't care about which barycentrics
* are used, use any that are used by the shader. This is an optimization
* for hw that is faster if only one set of barycentrics is used.
*/
if (s->found_baryc) {
nir_intrinsic_instr *baryc_intr =
nir_instr_as_intrinsic(baryc->parent_instr);
/* Overwrite the intrinsic we just created. */
baryc_intr->intrinsic = s->found_baryc->intrinsic;
nir_intrinsic_set_interp_mode(baryc_intr,
nir_intrinsic_interp_mode(s->found_baryc));
}
} else {
baryc = nir_undef(b, 2, 32);
}
nir_def *coord = nir_load_point_coord_maybe_flipped(b, baryc);
/* point_size = 1.0 / dFdx(gl_PointCoord.x); */
nir_def *point_size = nir_frcp(b, nir_ddx(b, nir_channel(b, coord, 0)));
/* radius = point_size * 0.5 */
nir_def *radius = nir_fmul_imm(b, point_size, 0.5);
;
/**
* Compute the distance of point from centre
@@ -92,12 +139,19 @@ lower_point_smooth(nir_builder *b, nir_intrinsic_instr *intr,
}
bool
nir_lower_point_smooth(nir_shader *shader)
nir_lower_point_smooth(nir_shader *shader, bool set_barycentrics)
{
assert(shader->info.stage == MESA_SHADER_FRAGMENT);
nir_function_impl *impl = nir_shader_get_entrypoint(shader);
lower_point_smooth_state state = {
.set_barycentrics = set_barycentrics,
.found_baryc = set_barycentrics ? find_any_used_barycentrics(impl) : NULL,
};
return nir_shader_intrinsics_pass(shader, lower_point_smooth,
nir_metadata_loop_analysis |
nir_metadata_block_index |
nir_metadata_dominance,
NULL);
&state);
}
+1 -1
View File
@@ -2411,7 +2411,7 @@ static struct nir_shader *si_get_nir_shader(struct si_shader *shader, struct si_
NIR_PASS(progress, nir, nir_lower_poly_line_smooth, SI_NUM_SMOOTH_AA_SAMPLES);
if (key->ps.mono.point_smoothing)
NIR_PASS(progress, nir, nir_lower_point_smooth);
NIR_PASS(progress, nir, nir_lower_point_smooth, true);
NIR_PASS(progress, nir, nir_lower_fragcoord_wtrans);
}
+1 -1
View File
@@ -4029,7 +4029,7 @@ zink_shader_compile(struct zink_screen *screen, bool can_shobj, struct zink_shad
NIR_PASS_V(nir, lower_line_stipple_fs);
if (zink_fs_key(key)->lower_point_smooth) {
NIR_PASS_V(nir, nir_lower_point_smooth);
NIR_PASS_V(nir, nir_lower_point_smooth, false);
NIR_PASS_V(nir, nir_lower_discard_if, nir_lower_discard_if_to_cf);
nir->info.fs.uses_discard = true;
need_optimize = true;