diff --git a/src/asahi/compiler/agx_compile.c b/src/asahi/compiler/agx_compile.c index d61d12e83cf..6efd4798503 100644 --- a/src/asahi/compiler/agx_compile.c +++ b/src/asahi/compiler/agx_compile.c @@ -60,7 +60,7 @@ agx_get_cf(agx_context *ctx, bool smooth, bool perspective, unsigned cf_base = varyings->nr_cf; if (slot == VARYING_SLOT_POS) { - assert(offset == 2 || (cf_base == 0 && offset == 3)); + assert(offset == 2 || offset == 3); varyings->reads_z |= (offset == 2); } @@ -356,13 +356,15 @@ agx_emit_load_vary(agx_builder *b, agx_index *dests, nir_intrinsic_instr *instr) nir_src *offset = nir_get_io_offset_src(instr); assert(nir_src_is_const(*offset) && "no indirects"); - /* TODO: Make use of w explicit int he IR */ + /* For perspective interpolation, we need W */ + agx_index J = agx_get_cf(b->shader, true, false, VARYING_SLOT_POS, 3, 1); + agx_index I = agx_get_cf(b->shader, true, true, sem.location + nir_src_as_uint(*offset), 0, components); agx_index vec = agx_vec_for_intr(b->shader, instr); - agx_ld_vary_to(b, vec, I, components, true); + agx_ld_vary_to(b, vec, I, J, components, true); agx_emit_split(b, dests, vec, components); } @@ -502,10 +504,11 @@ agx_emit_load_frag_coord(agx_builder *b, agx_index *dests, nir_intrinsic_instr * AGX_ROUND_RTE), agx_immediate_f(0.5f)); } + agx_index w = agx_get_cf(b->shader, true, false, VARYING_SLOT_POS, 3, 1); agx_index z = agx_get_cf(b->shader, true, false, VARYING_SLOT_POS, 2, 1); - dests[2] = agx_ld_vary(b, z, 1, false); - dests[3] = agx_ld_vary(b, agx_immediate(0), 1, false); /* cf0 is w */ + dests[2] = agx_ld_vary(b, z, agx_null(), 1, false); + dests[3] = agx_ld_vary(b, w, agx_null(), 1, false); } static agx_instr * @@ -1692,15 +1695,8 @@ agx_compile_shader_nir(nir_shader *nir, NIR_PASS_V(nir, nir_lower_discard_if); /* Must be last since NIR passes can remap driver_location freely */ - if (ctx->stage == MESA_SHADER_VERTEX) { + if (ctx->stage == MESA_SHADER_VERTEX) agx_remap_varyings_vs(nir, &out->varyings.vs); - } else if (ctx->stage == MESA_SHADER_FRAGMENT) { - /* Ensure cf0 is W */ - ASSERTED agx_index w = - agx_get_cf(ctx, true, false, VARYING_SLOT_POS, 3, 1); - - assert(w.value == 0); - } bool skip_internal = nir->info.internal; skip_internal &= !(agx_debug & AGX_DBG_INTERNAL); diff --git a/src/asahi/compiler/agx_opcodes.py b/src/asahi/compiler/agx_opcodes.py index c98918d04f8..041366461e2 100644 --- a/src/asahi/compiler/agx_opcodes.py +++ b/src/asahi/compiler/agx_opcodes.py @@ -238,7 +238,7 @@ 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("ld_vary", (0x21, 0xBF, 8, _), srcs = 1, imms = [CHANNELS, PERSPECTIVE]) +op("ld_vary", (0x21, 0xBF, 8, _), srcs = 2, imms = [CHANNELS, PERSPECTIVE]) op("ld_vary_flat", (0xA1, 0xBF, 8, _), srcs = 1, imms = [CHANNELS]) op("st_vary", None, dests = 0, srcs = 2, can_eliminate = False) op("stop", (0x88, 0xFFFF, 2, _), dests = 0, can_eliminate = False) diff --git a/src/asahi/compiler/agx_pack.c b/src/asahi/compiler/agx_pack.c index 2aeb27ae4d7..1be77e5ca05 100644 --- a/src/asahi/compiler/agx_pack.c +++ b/src/asahi/compiler/agx_pack.c @@ -453,13 +453,23 @@ agx_pack_instr(struct util_dynarray *emission, struct util_dynarray *fixups, agx unsigned D = agx_pack_alu_dst(I->dest[0]); unsigned channels = (I->channels & 0x3); assert(I->mask < 0xF); /* 0 indicates full mask */ - agx_index index_src = I->src[0]; - assert(index_src.type == AGX_INDEX_IMMEDIATE); + + agx_index src_I = I->src[0]; + assert(src_I.type == AGX_INDEX_IMMEDIATE); assert(!(flat && I->perspective)); - unsigned cf_I = index_src.value; + + unsigned cf_I = src_I.value; + unsigned cf_J = 0; + + if (I->perspective) { + agx_index src_J = I->src[1]; + assert(src_J.type == AGX_INDEX_IMMEDIATE); + cf_J = src_J.value; + } + assert(cf_I < 0x100); - unsigned cf_J = 0; /* TODO: in the IR */ assert(cf_J < 0x100); + bool kill = false; // TODO: optimize uint64_t raw =