v3d: fix line coords with perspective projection

The algorithm used to rendering smooth lines worked under the assumption
that line coords were in the [0, 1] range. This was correct when using
an orthogonal projection, but not when using a perspective projection.

With a perspective projection (where the value for 1/Wc set in the VPM
is not 1.0), line coords values are also affected by this projection, so
the values are not in this range.

To deal with this, we normalize the line coords using the Wc value so
the range becomes [0, 1], and the smooth line rendering works as
expected.

Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/10496
Fixes: ee4d51f8b2 ("v3d: Add a lowering pass for line smoothing")
Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
Signed-off-by: Juan A. Suarez Romero <jasuarez@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/28072>
(cherry picked from commit 69fbd5cb90)
This commit is contained in:
Juan A. Suarez Romero 2024-03-07 17:52:51 +01:00 committed by Eric Engestrom
parent 0aeacc0883
commit 991396e823
2 changed files with 13 additions and 3 deletions

View file

@ -54,7 +54,7 @@
"description": "v3d: fix line coords with perspective projection",
"nominated": true,
"nomination_type": 1,
"resolution": 0,
"resolution": 1,
"main_sha": null,
"because_sha": "ee4d51f8b2de004b04d02c7edf66ca0608adf16f",
"notes": null

View file

@ -91,13 +91,23 @@ initialise_coverage_var(struct lower_line_smooth_state *state,
nir_def *real_line_width = nir_load_aa_line_width(&b);
/* The line coord varies from 0.0 to 1.0 across the width of the line */
/* According to the PRM, the line coord varies from 0.0 to 1.0 across
* the width of the line. But actually, when a perspective projection
* is used, it is also applied to the line coords, so the values end
* up being between [min_coord, 1], based on the Wc coordinate. We
* need to re-map the values to be between [0.0, 1.0].
*/
nir_def *line_coord = nir_load_line_coord(&b);
nir_def *wc = nir_load_fep_w_v3d(&b, 32);
nir_def *min_coord_val = nir_fsub(&b, nir_imm_float(&b, 1.0f), wc);
nir_def *normalized_line_coord = nir_fdiv(&b,
nir_fsub(&b, line_coord, min_coord_val),
nir_fsub_imm(&b, 1.0, min_coord_val));;
/* fabs(line_coord - 0.5) * real_line_width */
nir_def *pixels_from_center =
nir_fmul(&b, real_line_width,
nir_fabs(&b, nir_fsub(&b, line_coord,
nir_fabs(&b, nir_fsub(&b, normalized_line_coord,
nir_imm_float(&b, 0.5f))));
/* 0.5 - 1/√2 * (pixels_from_center - line_width * 0.5) */