agx: Model perspective coefficient reg in the IR

For perspective-correct interpolation, the W coefficient register is
needed. Instead of hardcoding this to cf0 and special casing, model this
in the IR and let the general handling kick in.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17198>
This commit is contained in:
Alyssa Rosenzweig 2022-08-07 11:45:21 -04:00
parent 24c3084411
commit 14bf020d75
3 changed files with 24 additions and 18 deletions

View file

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

View file

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

View file

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