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 <alyssa@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15793>
This commit is contained in:
Alyssa Rosenzweig 2021-12-07 19:14:58 -05:00 committed by Marge Bot
parent 14e7796d4c
commit f79e33f82f

View file

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