mesa/src/asahi/compiler/agx_nir_lower_layer.c
Alyssa Rosenzweig 7d94f2ee49 agx: Add pass to lower layer ID writes
The hardware needs the layer ID and the viewport index packed together. That
consumes an entire varying slot, if we want those available in the frag shader
we need a separate slot. Add a pass to insert the extra packed write.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
2023-10-01 12:32:12 -04:00

67 lines
2.1 KiB
C

/*
* Copyright 2023 Valve Corporation
* SPDX-License-Identifier: MIT
*/
#include "compiler/nir/nir.h"
#include "compiler/nir/nir_builder.h"
#include "agx_nir.h"
void
agx_nir_lower_layer(nir_shader *s)
{
assert(s->info.stage == MESA_SHADER_VERTEX);
if (!(s->info.outputs_written & (VARYING_BIT_LAYER | VARYING_BIT_VIEWPORT)))
return;
/* Writes are in the last block, search */
nir_function_impl *impl = nir_shader_get_entrypoint(s);
nir_block *last = nir_impl_last_block(impl);
nir_def *layer = NULL, *viewport = NULL;
nir_cursor last_cursor;
nir_foreach_instr(instr, last) {
if (instr->type != nir_instr_type_intrinsic)
continue;
nir_intrinsic_instr *store = nir_instr_as_intrinsic(instr);
if (store->intrinsic != nir_intrinsic_store_output)
continue;
nir_io_semantics sem = nir_intrinsic_io_semantics(store);
nir_def *value = store->src[0].ssa;
if (sem.location == VARYING_SLOT_LAYER) {
assert(layer == NULL && "only written once");
layer = value;
} else if (sem.location == VARYING_SLOT_VIEWPORT) {
assert(viewport == NULL && "only written once");
viewport = value;
} else {
continue;
}
last_cursor = nir_after_instr(&store->instr);
/* Leave the store as a varying-only, no sysval output */
sem.no_sysval_output = true;
nir_intrinsic_set_io_semantics(store, sem);
}
assert((layer || viewport) && "metadata inconsistent with program");
/* Pack together and write out */
nir_builder b = nir_builder_at(last_cursor);
nir_def *zero = nir_imm_intN_t(&b, 0, 16);
nir_def *packed =
nir_pack_32_2x16_split(&b, layer ? nir_u2u16(&b, layer) : zero,
viewport ? nir_u2u16(&b, viewport) : zero);
/* Written with a sysval-only store, no varying output */
nir_store_output(&b, packed, nir_imm_int(&b, 0),
.io_semantics.location = VARYING_SLOT_LAYER,
.io_semantics.num_slots = 1,
.io_semantics.no_varying = true);
}