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;