From f79e33f82f8fadfc6415d1c8c36ce2f45bba9cc7 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Tue, 7 Dec 2021 19:14:58 -0500 Subject: [PATCH] pan/bi: Emit Valhall-style varying stores Varying stores was changed in Valhall. Rather than using attribute descriptors like on Bifrost and Midgard, on Valhall we store to memory directly with hardware-allocated buffers. This requires a new implementation of store_output, with special provisions for writing gl_PointSize from a position shader. Signed-off-by: Alyssa Rosenzweig Part-of: --- src/panfrost/bifrost/bifrost_compile.c | 55 +++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/src/panfrost/bifrost/bifrost_compile.c b/src/panfrost/bifrost/bifrost_compile.c index 04ed1d48ca2..8403782c624 100644 --- a/src/panfrost/bifrost/bifrost_compile.c +++ b/src/panfrost/bifrost/bifrost_compile.c @@ -776,6 +776,39 @@ bifrost_nir_specialize_idvs(nir_builder *b, nir_instr *instr, void *data) return false; } +/** + * Computes the offset in bytes of a varying. This assumes VARYING_SLOT_POS is + * mapped to location=0 and always present. This also assumes each slot + * consumes 16 bytes, which is a worst-case (highp vec4). In the future, this + * should be optimized to support fp16 and partial vectors. There are + * nontrivial interactions with separable shaders, however. + */ +static unsigned +bi_varying_offset(nir_shader *nir, nir_intrinsic_instr *intr) +{ + nir_src *offset = nir_get_io_offset_src(intr); + assert(nir_src_is_const(*offset) && "no indirect varyings on Valhall"); + + unsigned loc = 0; + unsigned slot = nir_intrinsic_base(intr) + nir_src_as_uint(*offset); + + nir_foreach_shader_out_variable(var, nir) { + if ((var->data.location == VARYING_SLOT_POS) || + (var->data.location == VARYING_SLOT_PSIZ)) + continue; + + if (var->data.driver_location > slot) + continue; + + if (var->data.driver_location == slot) + return loc; + + loc += 16; // todo size + } + + unreachable("Unlinked variable"); +} + static void bi_emit_store_vary(bi_builder *b, nir_intrinsic_instr *instr) { @@ -785,7 +818,8 @@ bi_emit_store_vary(bi_builder *b, nir_intrinsic_instr *instr) * but smooth in the FS */ ASSERTED nir_alu_type T = nir_intrinsic_src_type(instr); - assert(nir_alu_type_get_type_size(T) == 32); + ASSERTED unsigned T_size = nir_alu_type_get_type_size(T); + assert(T_size == 32 || (b->shader->arch >= 9 && T_size == 16)); enum bi_register_format regfmt = BI_REGISTER_FORMAT_AUTO; unsigned imm_index = 0; @@ -801,6 +835,7 @@ bi_emit_store_vary(bi_builder *b, nir_intrinsic_instr *instr) assert(nr > 0 && nr <= nir_intrinsic_src_components(instr, 0)); bi_index data = bi_src_index(&instr->src[0]); + bool psiz = (nir_intrinsic_io_semantics(instr).location == VARYING_SLOT_PSIZ); if (b->shader->arch <= 8 && b->shader->idvs == BI_IDVS_POSITION) { /* Bifrost position shaders have a fast path */ @@ -812,9 +847,25 @@ bi_emit_store_vary(bi_builder *b, nir_intrinsic_instr *instr) bi_st_cvt(b, data, bi_register(58), bi_register(59), bi_imm_u32(format), regfmt, nr - 1); + } else if (b->shader->arch >= 9 && b->shader->idvs != BI_IDVS_NONE) { + bi_index index = bi_register(59); + + if (psiz) { + assert(T_size == 16 && "should've been lowered"); + index = bi_iadd_imm_i32(b, index, 4); + } + + bi_index address = bi_lea_buf_imm(b, index); + bool varying = (b->shader->idvs == BI_IDVS_VARYING); + + bi_store(b, nr * nir_src_bit_size(instr->src[0]), + bi_src_index(&instr->src[0]), + address, bi_word(address, 1), + varying ? BI_SEG_VARY : BI_SEG_POS, + varying ? bi_varying_offset(b->shader->nir, instr) : 0); } else if (immediate) { bi_index address = bi_lea_attr_imm(b, - bi_register(61), bi_register(62), + bi_vertex_id(b), bi_instance_id(b), regfmt, imm_index); bi_st_cvt(b, data, address, bi_word(address, 1),