summaryrefslogtreecommitdiff
path: root/src/gallium/auxiliary
diff options
context:
space:
mode:
authorMarek Olšák <marek.olsak@amd.com>2022-07-17 12:21:17 -0400
committerMarge Bot <emma+marge@anholt.net>2022-08-09 19:19:09 +0000
commit2f4b9b7a9505f61877ccd51157cab590a5fe3b24 (patch)
treec2dec7d2b03217bc1e895fb1f120051ab4e2d482 /src/gallium/auxiliary
parent5c7ad4757bef25fd040993d15b3d87ad6f4c82ea (diff)
gallium/u_blitter: make the bilinear filter for MSAA resolving conformant
This implements the bilinear filter exactly like OpenGL. Acked-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17692>
Diffstat (limited to 'src/gallium/auxiliary')
-rw-r--r--src/gallium/auxiliary/util/u_blitter.c2
-rw-r--r--src/gallium/auxiliary/util/u_simple_shaders.c65
-rw-r--r--src/gallium/auxiliary/util/u_simple_shaders.h2
3 files changed, 54 insertions, 15 deletions
diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c
index 85522a16f29..0daa5b77e09 100644
--- a/src/gallium/auxiliary/util/u_blitter.c
+++ b/src/gallium/auxiliary/util/u_blitter.c
@@ -1032,7 +1032,7 @@ static void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx,
assert(!ctx->cached_all_shaders);
if (filter == PIPE_TEX_FILTER_LINEAR) {
*shader = util_make_fs_msaa_resolve_bilinear(pipe, tgsi_tex,
- src_nr_samples);
+ src_nr_samples, ctx->has_txf_txq);
}
else {
*shader = util_make_fs_msaa_resolve(pipe, tgsi_tex,
diff --git a/src/gallium/auxiliary/util/u_simple_shaders.c b/src/gallium/auxiliary/util/u_simple_shaders.c
index 923389a0662..943b5950a89 100644
--- a/src/gallium/auxiliary/util/u_simple_shaders.c
+++ b/src/gallium/auxiliary/util/u_simple_shaders.c
@@ -877,12 +877,12 @@ util_make_fs_msaa_resolve(struct pipe_context *pipe,
void *
util_make_fs_msaa_resolve_bilinear(struct pipe_context *pipe,
enum tgsi_texture_type tgsi_tex,
- unsigned nr_samples)
+ unsigned nr_samples, bool has_txq)
{
struct ureg_program *ureg;
struct ureg_src sampler, coord;
struct ureg_dst out, tmp, top, bottom;
- struct ureg_dst tmp_coord[4], tmp_sum[4];
+ struct ureg_dst tmp_coord[4], tmp_sum[4], weights;
unsigned i, c;
ureg = ureg_create(PIPE_SHADER_FRAGMENT);
@@ -903,21 +903,62 @@ util_make_fs_msaa_resolve_bilinear(struct pipe_context *pipe,
tmp_coord[c] = ureg_DECL_temporary(ureg);
tmp = ureg_DECL_temporary(ureg);
top = ureg_DECL_temporary(ureg);
+ weights = ureg_DECL_temporary(ureg);
bottom = ureg_DECL_temporary(ureg);
/* Instructions. */
for (c = 0; c < 4; c++)
ureg_MOV(ureg, tmp_sum[c], ureg_imm1f(ureg, 0));
- /* Get 4 texture coordinates for the bilinear filter. */
- ureg_F2U(ureg, tmp_coord[0], coord); /* top-left */
- ureg_UADD(ureg, tmp_coord[1], ureg_src(tmp_coord[0]),
- ureg_imm4u(ureg, 1, 0, 0, 0)); /* top-right */
- ureg_UADD(ureg, tmp_coord[2], ureg_src(tmp_coord[0]),
- ureg_imm4u(ureg, 0, 1, 0, 0)); /* bottom-left */
+ /* Bilinear filtering starts with subtracting 0.5 from unnormalized
+ * coordinates.
+ */
+ ureg_MOV(ureg, ureg_writemask(tmp_coord[0], TGSI_WRITEMASK_ZW), coord);
+ ureg_ADD(ureg, ureg_writemask(tmp_coord[0], TGSI_WRITEMASK_XY), coord,
+ ureg_imm2f(ureg, -0.5, -0.5));
+
+ /* Get the filter weights. */
+ ureg_FRC(ureg, ureg_writemask(weights, TGSI_WRITEMASK_XY),
+ ureg_src(tmp_coord[0]));
+
+ /* Convert to integer by flooring to get the top-left coordinates. */
+ ureg_FLR(ureg, ureg_writemask(tmp_coord[0], TGSI_WRITEMASK_XY),
+ ureg_src(tmp_coord[0]));
+ ureg_F2I(ureg, tmp_coord[0], ureg_src(tmp_coord[0]));
+
+ /* Get the bottom-right coordinates. */
ureg_UADD(ureg, tmp_coord[3], ureg_src(tmp_coord[0]),
ureg_imm4u(ureg, 1, 1, 0, 0)); /* bottom-right */
+ /* Clamp to edge. */
+ if (has_txq) {
+ ureg_TXQ(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XY), tgsi_tex,
+ ureg_imm1u(ureg, 0), sampler);
+ ureg_UADD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XY), ureg_src(tmp),
+ ureg_imm2i(ureg, -1, -1)); /* width - 1, height - 1 */
+
+ ureg_IMIN(ureg, ureg_writemask(tmp_coord[0], TGSI_WRITEMASK_XY),
+ ureg_src(tmp_coord[0]), ureg_src(tmp));
+ ureg_IMIN(ureg, ureg_writemask(tmp_coord[3], TGSI_WRITEMASK_XY),
+ ureg_src(tmp_coord[3]), ureg_src(tmp));
+ }
+
+ ureg_IMAX(ureg, ureg_writemask(tmp_coord[0], TGSI_WRITEMASK_XY),
+ ureg_src(tmp_coord[0]), ureg_imm2i(ureg, 0, 0));
+ ureg_IMAX(ureg, ureg_writemask(tmp_coord[3], TGSI_WRITEMASK_XY),
+ ureg_src(tmp_coord[3]), ureg_imm2i(ureg, 0, 0));
+
+ /* Get the remaining top-right and bottom-left coordinates. */
+ ureg_MOV(ureg, ureg_writemask(tmp_coord[1], TGSI_WRITEMASK_X),
+ ureg_src(tmp_coord[3]));
+ ureg_MOV(ureg, ureg_writemask(tmp_coord[1], TGSI_WRITEMASK_YZW),
+ ureg_src(tmp_coord[0])); /* top-right */
+
+ ureg_MOV(ureg, ureg_writemask(tmp_coord[2], TGSI_WRITEMASK_Y),
+ ureg_src(tmp_coord[3]));
+ ureg_MOV(ureg, ureg_writemask(tmp_coord[2], TGSI_WRITEMASK_XZW),
+ ureg_src(tmp_coord[0])); /* bottom-left */
+
for (i = 0; i < nr_samples; i++) {
for (c = 0; c < 4; c++) {
/* Read one sample. */
@@ -936,20 +977,18 @@ util_make_fs_msaa_resolve_bilinear(struct pipe_context *pipe,
ureg_imm1f(ureg, 1.0 / nr_samples));
/* Take the 4 average values and apply a standard bilinear filter. */
- ureg_FRC(ureg, tmp, coord);
-
ureg_LRP(ureg, top,
- ureg_scalar(ureg_src(tmp), 0),
+ ureg_scalar(ureg_src(weights), 0),
ureg_src(tmp_sum[1]),
ureg_src(tmp_sum[0]));
ureg_LRP(ureg, bottom,
- ureg_scalar(ureg_src(tmp), 0),
+ ureg_scalar(ureg_src(weights), 0),
ureg_src(tmp_sum[3]),
ureg_src(tmp_sum[2]));
ureg_LRP(ureg, out,
- ureg_scalar(ureg_src(tmp), 1),
+ ureg_scalar(ureg_src(weights), 1),
ureg_src(bottom),
ureg_src(top));
ureg_END(ureg);
diff --git a/src/gallium/auxiliary/util/u_simple_shaders.h b/src/gallium/auxiliary/util/u_simple_shaders.h
index e278d4108e8..657a68f49df 100644
--- a/src/gallium/auxiliary/util/u_simple_shaders.h
+++ b/src/gallium/auxiliary/util/u_simple_shaders.h
@@ -148,7 +148,7 @@ util_make_fs_msaa_resolve(struct pipe_context *pipe,
void *
util_make_fs_msaa_resolve_bilinear(struct pipe_context *pipe,
enum tgsi_texture_type tgsi_tex,
- unsigned nr_samples);
+ unsigned nr_samples, bool has_txq);
extern void *
util_make_geometry_passthrough_shader(struct pipe_context *pipe,