nir: lower to fragment_mask_fetch/load_amd with EQAA correctly

Fixes: 194add2c23 ("nir: lower image add lower_to_fragment_mask_load_amd option")
Reviewed-by: Qiang Yu <yuq825@gmail.com>
Signed-off-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21436>
This commit is contained in:
Marek Olšák
2023-02-24 15:40:47 -05:00
committed by Qiang Yu
parent 8313016543
commit 0c8e7ad47e
2 changed files with 41 additions and 11 deletions

View File

@@ -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 */

View File

@@ -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;