agx: Remap fragment shader varyings explicitly

Needed to handle fragcoord.z correctly, for example. Step 1, at least.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11718>
This commit is contained in:
Alyssa Rosenzweig 2021-06-12 20:47:45 -04:00 committed by Marge Bot
parent 32f4be5dd7
commit 6a657b17b9
5 changed files with 83 additions and 28 deletions

View File

@ -122,7 +122,8 @@ agx_emit_load_vary_flat(agx_builder *b, nir_intrinsic_instr *instr)
nir_src *offset = nir_get_io_offset_src(instr);
assert(nir_src_is_const(*offset) && "no indirects");
unsigned imm_index = nir_intrinsic_base(instr) + nir_src_as_uint(*offset);
unsigned imm_index = b->shader->varyings[nir_intrinsic_base(instr)];
imm_index += nir_src_as_uint(*offset);
agx_index chan[4] = { agx_null() };
@ -150,8 +151,8 @@ agx_emit_load_vary(agx_builder *b, nir_intrinsic_instr *instr)
nir_src *offset = nir_get_io_offset_src(instr);
assert(nir_src_is_const(*offset) && "no indirects");
unsigned imm_index = (4 * nir_intrinsic_base(instr)) + nir_src_as_uint(*offset);
imm_index += 1;
unsigned imm_index = b->shader->varyings[nir_intrinsic_base(instr)];
imm_index += nir_src_as_uint(*offset);
return agx_ld_vary_to(b, agx_dest_index(&instr->dest),
agx_immediate(imm_index), components, true);
@ -1124,6 +1125,51 @@ agx_remap_varyings_vs(nir_shader *nir)
}
}
static void
agx_remap_varyings_fs(nir_shader *nir, struct agx_varyings *varyings,
unsigned *remap)
{
struct agx_varying_packed *packed = varyings->packed;
unsigned base = 0;
agx_pack(packed, VARYING, cfg) {
cfg.type = AGX_VARYING_TYPE_FRAGCOORD_W;
cfg.components = 1;
cfg.slot_1 = cfg.slot_2 = base;
}
base++;
packed++;
agx_pack(packed, VARYING, cfg) {
cfg.type = AGX_VARYING_TYPE_FRAGCOORD_Z;
cfg.components = 1;
cfg.slot_1 = cfg.slot_2 = base;
}
base++;
packed++;
nir_foreach_shader_in_variable(var, nir) {
assert(var->data.driver_location <= AGX_MAX_VARYINGS);
remap[var->data.driver_location] = base;
agx_pack(packed, VARYING, cfg) {
cfg.type = (var->data.interpolation == INTERP_MODE_FLAT) ?
AGX_VARYING_TYPE_FLAT_LAST :
AGX_VARYING_TYPE_SMOOTH;
cfg.components = 4;
cfg.slot_1 = cfg.slot_2 = base;
}
base += 4;
packed++;
}
varyings->nr_descs = (packed - varyings->packed);
varyings->nr_slots = base;
}
void
agx_compile_shader_nir(nir_shader *nir,
struct agx_shader_key *key,
@ -1180,6 +1226,11 @@ agx_compile_shader_nir(nir_shader *nir,
agx_optimize_nir(nir);
/* Must be last since NIR passes can remap driver_location freely */
if (ctx->stage == MESA_SHADER_FRAGMENT) {
agx_remap_varyings_fs(nir, &out->varyings, ctx->varyings);
}
bool skip_internal = nir->info.internal;
skip_internal &= !(agx_debug & AGX_DBG_INTERNAL);

View File

@ -26,6 +26,7 @@
#include "compiler/nir/nir.h"
#include "util/u_dynarray.h"
#include "asahi/lib/agx_pack.h"
enum agx_push_type {
/* Array of 64-bit pointers to the base addresses (BASES) and array of
@ -76,10 +77,17 @@ struct agx_push {
/* Arbitrary */
#define AGX_MAX_PUSH_RANGES (16)
#define AGX_MAX_VARYINGS (32)
struct agx_varyings {
unsigned nr_descs, nr_slots;
struct agx_varying_packed packed[AGX_MAX_VARYINGS];
};
struct agx_shader_info {
unsigned push_ranges;
struct agx_push push[AGX_MAX_PUSH_RANGES];
struct agx_varyings varyings;
/* Does the shader read the tilebuffer? */
bool reads_tib;

View File

@ -331,6 +331,9 @@ typedef struct {
struct agx_shader_info *out;
struct agx_shader_key *key;
/* Remapping table for varyings indexed by driver_location */
unsigned varyings[AGX_MAX_VARYINGS];
/* Place to start pushing new values */
unsigned push_base;

View File

@ -44,6 +44,7 @@ agx_compiler = executable(
dependencies : [
idep_nir,
idep_mesautil,
idep_agx_pack,
dep_libdrm,
],
link_with : [

View File

@ -820,6 +820,7 @@ agx_update_shader(struct agx_context *ctx, struct agx_compiled_shader **out,
nir_variable_mode varying_mode = (nir->info.stage == MESA_SHADER_FRAGMENT) ?
nir_var_shader_in : nir_var_shader_out;
struct agx_varyings *varyings = &compiled->info.varyings;
unsigned varying_count = 0;
nir_foreach_variable_with_modes(var, nir, varying_mode) {
@ -829,35 +830,26 @@ agx_update_shader(struct agx_context *ctx, struct agx_compiled_shader **out,
varying_count = MAX2(varying_count, loc + sz);
}
compiled->varying_count = varying_count;
if (nir->info.stage == MESA_SHADER_VERTEX)
compiled->varying_count = varying_count;
unsigned varying_desc_len = AGX_VARYING_HEADER_LENGTH + (1 + varying_count) * AGX_VARYING_LENGTH;
uint8_t *varying_desc = calloc(1, varying_desc_len);
unsigned packed_varying_sz = (AGX_VARYING_HEADER_LENGTH + varyings->nr_descs * AGX_VARYING_LENGTH);
uint8_t *packed_varyings = alloca(packed_varying_sz);
agx_pack(varying_desc, VARYING_HEADER, cfg) {
cfg.slots_1 = 1 + (4 * varying_count);
cfg.slots_2 = 1 + (4 * varying_count);
agx_pack(packed_varyings, VARYING_HEADER, cfg) {
cfg.slots_1 = cfg.slots_2 = varyings->nr_slots;
}
agx_pack(varying_desc + AGX_VARYING_HEADER_LENGTH, VARYING, cfg) {
cfg.type = AGX_VARYING_TYPE_FRAGCOORD_W;
cfg.slot_1 = 0;
cfg.slot_2 = 0;
cfg.components = 4;
}
if (varyings->nr_slots)
compiled->varying_count = varyings->nr_slots;
for (unsigned i = 0; i < varying_count; ++i) {
agx_pack(varying_desc + AGX_VARYING_HEADER_LENGTH + ((i + 1) * AGX_VARYING_LENGTH), VARYING, cfg) {
cfg.slot_1 = 1 + (4 * i);
cfg.slot_2 = 1 + (4 * i);
cfg.components = 4;
}
}
memcpy(packed_varyings + AGX_VARYING_HEADER_LENGTH, varyings->packed,
varyings->nr_descs * AGX_VARYING_LENGTH);
if (binary.size) {
struct agx_device *dev = agx_device(ctx->base.screen);
compiled->bo = agx_bo_create(dev,
ALIGN_POT(binary.size, 256) + ((3 * (AGX_VARYING_HEADER_LENGTH + varying_count * AGX_VARYING_LENGTH)) + 20),
ALIGN_POT(binary.size, 256) + ((3 * packed_varying_sz) + 20),
AGX_MEMORY_TYPE_SHADER);
memcpy(compiled->bo->ptr.cpu, binary.data, binary.size);
@ -866,8 +858,8 @@ agx_update_shader(struct agx_context *ctx, struct agx_compiled_shader **out,
unsigned offs = ALIGN_POT(binary.size, 256);
unsigned unk_offs = offs + 0x40;
for (unsigned copy = 0; copy < 3; ++copy) {
memcpy(((uint8_t *) compiled->bo->ptr.cpu) + offs, varying_desc, varying_desc_len);
offs += varying_desc_len;
memcpy(((uint8_t *) compiled->bo->ptr.cpu) + offs, packed_varyings, packed_varying_sz);
offs += packed_varying_sz;
}
uint16_t *map = (uint16_t *) (((uint8_t *) compiled->bo->ptr.cpu) + unk_offs);
@ -1165,7 +1157,7 @@ demo_unk8(struct agx_compiled_shader *fs, struct agx_pool *pool)
/* Varying related */
uint32_t unk[] = {
/* interpolated count */
0x100c0000, fs->varying_count * 4, 0x0, 0x0, 0x0,
0x100c0000, fs->info.varyings.nr_slots, 0x0, 0x0, 0x0,
};
return agx_pool_upload(pool, unk, sizeof(unk));
@ -1178,7 +1170,7 @@ demo_linkage(struct agx_compiled_shader *vs, struct agx_pool *pool)
agx_pack(t.cpu, LINKAGE, cfg) {
cfg.varying_count = 4 * vs->varying_count;
cfg.unk_1 = 0x10000; // varyings otherwise wrong
cfg.unk_1 = 0x210000; // varyings otherwise wrong
};
return t.gpu;
@ -1288,7 +1280,7 @@ agx_encode_state(struct agx_context *ctx, uint8_t *out,
agx_push_record(&out, 0, zero.gpu);
agx_push_record(&out, 5, demo_unk8(ctx->fs, pool));
agx_push_record(&out, 5, demo_launch_fragment(pool, pipeline_fragment, varyings, ctx->fs->varying_count + 1));
agx_push_record(&out, 5, demo_launch_fragment(pool, pipeline_fragment, varyings, ctx->fs->info.varyings.nr_descs));
agx_push_record(&out, 4, demo_linkage(ctx->vs, pool));
agx_push_record(&out, 7, demo_rasterizer(ctx, pool));
agx_push_record(&out, 5, demo_unk11(pool, is_lines, reads_tib));