Module: Mesa
Branch: main
Commit: 0c8e7ad47e945425ff1d4bd38656064c35ffda70
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=0c8e7ad47e945425ff1d4bd38656064c35ffda70

Author: Marek Olšák <[email protected]>
Date:   Fri Feb 24 15:40:47 2023 -0500

nir: lower to fragment_mask_fetch/load_amd with EQAA correctly

Fixes: 194add2c232 ("nir: lower image add lower_to_fragment_mask_load_amd 
option")
Reviewed-by: Qiang Yu <[email protected]>
Signed-off-by: Marek Olšák <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21436>

---

 src/compiler/nir/nir_lower_image.c | 21 ++++++++++++++++++++-
 src/compiler/nir/nir_lower_tex.c   | 31 +++++++++++++++++++++----------
 2 files changed, 41 insertions(+), 11 deletions(-)

diff --git a/src/compiler/nir/nir_lower_image.c 
b/src/compiler/nir/nir_lower_image.c
index 7b0fc17db17..15b8cd1cd70 100644
--- a/src/compiler/nir/nir_lower_image.c
+++ b/src/compiler/nir/nir_lower_image.c
@@ -61,6 +61,25 @@ lower_cube_size(nir_builder *b, nir_intrinsic_instr *intrin)
    nir_instr_free(&intrin->instr);
 }
 
+/* Adjust the sample index according to AMD FMASK (fragment mask).
+ *
+ * For uncompressed MSAA surfaces, FMASK should return 0x76543210,
+ * which is the identity mapping. Each nibble says which physical sample
+ * should be fetched to get that sample.
+ *
+ * For example, 0x11111100 means there are only 2 samples stored and
+ * the second sample covers 3/4 of the pixel. When reading samples 0
+ * and 1, return physical sample 0 (determined by the first two 0s
+ * in FMASK), otherwise return physical sample 1.
+ *
+ * The sample index should be adjusted as follows:
+ *   sample_index = ubfe(fmask, sample_index * 4, 3);
+ *
+ * Only extract 3 bits because EQAA can generate number 8 in FMASK, which
+ * means the physical sample index is unknown. We can map 8 to any valid
+ * sample index, and extracting only 3 bits will map it to 0, which works
+ * with all MSAA modes.
+ */
 static void
 lower_image_to_fragment_mask_load(nir_builder *b, nir_intrinsic_instr *intrin)
 {
@@ -96,7 +115,7 @@ lower_image_to_fragment_mask_load(nir_builder *b, 
nir_intrinsic_instr *intrin)
    /* extract real color buffer index from fmask buffer */
    nir_ssa_def *sample_index_old = intrin->src[2].ssa;
    nir_ssa_def *fmask_offset = nir_ishl_imm(b, sample_index_old, 2);
-   nir_ssa_def *fmask_width = nir_imm_int(b, 4);
+   nir_ssa_def *fmask_width = nir_imm_int(b, 3);
    nir_ssa_def *sample_index_new = nir_ubfe(b, fmask, fmask_offset, 
fmask_width);
 
    /* fix color buffer load */
diff --git a/src/compiler/nir/nir_lower_tex.c b/src/compiler/nir/nir_lower_tex.c
index b6ff7761ee4..43d60bce6ec 100644
--- a/src/compiler/nir/nir_lower_tex.c
+++ b/src/compiler/nir/nir_lower_tex.c
@@ -1262,6 +1262,25 @@ nir_lower_txs_cube_array(nir_builder *b, nir_tex_instr 
*tex)
    nir_ssa_def_rewrite_uses_after(&tex->dest.ssa, size, size->parent_instr);
 }
 
+/* Adjust the sample index according to AMD FMASK (fragment mask).
+ *
+ * For uncompressed MSAA surfaces, FMASK should return 0x76543210,
+ * which is the identity mapping. Each nibble says which physical sample
+ * should be fetched to get that sample.
+ *
+ * For example, 0x11111100 means there are only 2 samples stored and
+ * the second sample covers 3/4 of the pixel. When reading samples 0
+ * and 1, return physical sample 0 (determined by the first two 0s
+ * in FMASK), otherwise return physical sample 1.
+ *
+ * The sample index should be adjusted as follows:
+ *   sample_index = ubfe(fmask, sample_index * 4, 3);
+ *
+ * Only extract 3 bits because EQAA can generate number 8 in FMASK, which
+ * means the physical sample index is unknown. We can map 8 to any valid
+ * sample index, and extracting only 3 bits will map it to 0, which works
+ * with all MSAA modes.
+ */
 static void
 nir_lower_ms_txf_to_fragment_fetch(nir_builder *b, nir_tex_instr *tex)
 {
@@ -1295,16 +1314,8 @@ nir_lower_ms_txf_to_fragment_fetch(nir_builder *b, 
nir_tex_instr *tex)
    int ms_index = nir_tex_instr_src_index(tex, nir_tex_src_ms_index);
    assert(ms_index >= 0);
    nir_src sample = tex->src[ms_index].src;
-   nir_ssa_def *new_sample = NULL;
-   if (nir_src_is_const(sample) && (nir_src_as_uint(sample) == 0 || 
nir_src_as_uint(sample) == 7)) {
-      if (nir_src_as_uint(sample) == 7)
-         new_sample = nir_ushr(b, &fmask_fetch->dest.ssa, nir_imm_int(b, 28));
-      else
-         new_sample = nir_iand_imm(b, &fmask_fetch->dest.ssa, 0xf);
-   } else {
-      new_sample = nir_ubitfield_extract(b, &fmask_fetch->dest.ssa,
-                                         nir_imul_imm(b, sample.ssa, 4), 
nir_imm_int(b, 4));
-   }
+   nir_ssa_def *new_sample = nir_ubfe(b, &fmask_fetch->dest.ssa,
+                                      nir_ishl_imm(b, sample.ssa, 2), 
nir_imm_int(b, 3));
 
    /* Update instruction. */
    tex->op = nir_texop_fragment_fetch_amd;

Reply via email to