diff --git a/src/asahi/compiler/agx_compile.c b/src/asahi/compiler/agx_compile.c index 994dfb71e9e..b12ec1f88fb 100644 --- a/src/asahi/compiler/agx_compile.c +++ b/src/asahi/compiler/agx_compile.c @@ -376,6 +376,8 @@ agx_emit_load_vary(agx_builder *b, agx_index dest, nir_intrinsic_instr *instr) /* TODO: Interpolation modes */ assert(bary != NULL); assert(bary->intrinsic == nir_intrinsic_load_barycentric_pixel); + enum agx_interpolation interp = AGX_INTERPOLATION_CENTER; + agx_index sample_index = agx_zero(); bool perspective = nir_intrinsic_interp_mode(bary) != INTERP_MODE_NOPERSPECTIVE; @@ -395,9 +397,9 @@ agx_emit_load_vary(agx_builder *b, agx_index dest, nir_intrinsic_instr *instr) /* For perspective interpolation, we project (multiply by 1/W) */ if (perspective) { agx_index J = agx_get_cf(b->shader, true, false, VARYING_SLOT_POS, 3, 1); - agx_iterproj_to(b, dest, I, J, components); + agx_iterproj_to(b, dest, I, J, sample_index, components, interp); } else { - agx_iter_to(b, dest, I, components); + agx_iter_to(b, dest, I, sample_index, components, interp); } agx_emit_cached_split(b, dest, components); @@ -644,7 +646,7 @@ agx_emit_load_frag_coord(agx_builder *b, agx_index dst, agx_get_cf(b->shader, true, false, VARYING_SLOT_POS, i, 1); dests[i] = fp32; - agx_iter_to(b, fp32, cf, 1); + agx_iter_to(b, fp32, cf, agx_zero(), 1, AGX_INTERPOLATION_CENTER); } } diff --git a/src/asahi/compiler/agx_compiler.h b/src/asahi/compiler/agx_compiler.h index c0cc32b8729..9bcf3daf8fd 100644 --- a/src/asahi/compiler/agx_compiler.h +++ b/src/asahi/compiler/agx_compiler.h @@ -305,6 +305,9 @@ typedef struct { bool shadow : 1; enum agx_gather gather : 3; + /* TODO: Handle iter ops more efficient */ + enum agx_interpolation interpolation : 2; + /* Final st_vary op */ bool last : 1; diff --git a/src/asahi/compiler/agx_lower_uniform_sources.c b/src/asahi/compiler/agx_lower_uniform_sources.c index 9074da4f025..5615373a16e 100644 --- a/src/asahi/compiler/agx_lower_uniform_sources.c +++ b/src/asahi/compiler/agx_lower_uniform_sources.c @@ -42,6 +42,8 @@ should_lower(enum agx_opcode op, agx_index uniform, unsigned src_index) case AGX_OPCODE_ST_VARY: case AGX_OPCODE_LOCAL_ATOMIC: case AGX_OPCODE_SAMPLE_MASK: + case AGX_OPCODE_ITER: + case AGX_OPCODE_ITERPROJ: return true; default: return false; diff --git a/src/asahi/compiler/agx_opcodes.py b/src/asahi/compiler/agx_opcodes.py index 5761ea94fa4..c1ee840a11f 100644 --- a/src/asahi/compiler/agx_opcodes.py +++ b/src/asahi/compiler/agx_opcodes.py @@ -153,6 +153,14 @@ ATOMIC_OPC = enum("atomic_opc", { 10: 'xor', }) +INTERPOLATION = enum("interpolation", { + 0: 'center', + 1: 'sample', + 2: 'centroid', + # We translate sample -> sample_register at pack time for simplicity + 3: 'sample_register', +}) + FUNOP = lambda x: (x << 28) FUNOP_MASK = FUNOP((1 << 14) - 1) @@ -327,8 +335,14 @@ for is_float in [False, True]: op("bitop", (0x7E, 0x7F, 6, _), srcs = 2, imms = [TRUTH_TABLE]) op("convert", (0x3E | L, 0x7F | L | (0x3 << 38), 6, _), srcs = 2, imms = [ROUND]) -op("iter", (0x21, 0xBF, 8, _), srcs = 1, imms = [CHANNELS]) -op("iterproj", (0x21, 0xBF, 8, _), srcs = 2, imms = [CHANNELS]) + +# Sources are the coeffient register and the sample index (if applicable) +op("iter", (0x21, 0xBF, 8, _), srcs = 2, imms = [CHANNELS, INTERPOLATION]) + +# Sources are the coeffient register for the varying, the coefficient register +# for W, and the sample index (if applicable) +op("iterproj", (0x21, 0xBF, 8, _), srcs = 3, imms = [CHANNELS, INTERPOLATION]) + op("ldcf", (0xA1, 0xBF, 8, _), srcs = 1, imms = [CHANNELS]) op("st_vary", None, dests = 0, srcs = 2, can_eliminate = False) op("no_varyings", (0x80000051, 0xFFFFFFFF, 4, _), dests = 0, can_eliminate = False) diff --git a/src/asahi/compiler/agx_pack.c b/src/asahi/compiler/agx_pack.c index 94cb6ba3264..4d91fc8a792 100644 --- a/src/asahi/compiler/agx_pack.c +++ b/src/asahi/compiler/agx_pack.c @@ -547,14 +547,28 @@ agx_pack_instr(struct util_dynarray *emission, struct util_dynarray *fixups, assert(cf_I < 0x100); assert(cf_J < 0x100); + enum agx_interpolation interp = I->interpolation; + agx_index sample_index = flat ? agx_null() : I->src[perspective ? 2 : 1]; + + /* Fix up the interpolation enum to distinguish the sample index source */ + if (interp == AGX_INTERPOLATION_SAMPLE) { + if (sample_index.type == AGX_INDEX_REGISTER) + interp = AGX_INTERPOLATION_SAMPLE_REGISTER; + else + assert(sample_index.type == AGX_INDEX_IMMEDIATE); + } else { + sample_index = agx_zero(); + } + bool kill = false; // TODO: optimize uint64_t raw = 0x21 | (flat ? (1 << 7) : 0) | (perspective ? (1 << 6) : 0) | ((D & 0xFF) << 7) | (1ull << 15) | /* XXX */ ((cf_I & BITFIELD_MASK(6)) << 16) | ((cf_J & BITFIELD_MASK(6)) << 24) | - (((uint64_t)channels) << 30) | (!flat ? (1ull << 46) : 0) | /* XXX */ - (kill ? (1ull << 52) : 0) | /* XXX */ + (((uint64_t)channels) << 30) | (((uint64_t)sample_index.value) << 32) | + (!flat ? (1ull << 46) : 0) | /* XXX */ + (((uint64_t)interp) << 48) | (kill ? (1ull << 52) : 0) | /* XXX */ (((uint64_t)(D >> 8)) << 56) | ((uint64_t)(cf_I >> 6) << 58) | ((uint64_t)(cf_J >> 6) << 60);