From 6a657b17b9b83d0ef019f109824d88889c44b65d Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Sat, 12 Jun 2021 20:47:45 -0400 Subject: [PATCH] agx: Remap fragment shader varyings explicitly Needed to handle fragcoord.z correctly, for example. Step 1, at least. Signed-off-by: Alyssa Rosenzweig Part-of: --- src/asahi/compiler/agx_compile.c | 57 +++++++++++++++++++++++++++++++++-- src/asahi/compiler/agx_compile.h | 8 +++++ src/asahi/compiler/agx_compiler.h | 3 ++ src/asahi/meson.build | 1 + src/gallium/drivers/asahi/agx_state.c | 42 +++++++++++--------------- 5 files changed, 83 insertions(+), 28 deletions(-) diff --git a/src/asahi/compiler/agx_compile.c b/src/asahi/compiler/agx_compile.c index 16173e2..5f22137 100644 --- a/src/asahi/compiler/agx_compile.c +++ b/src/asahi/compiler/agx_compile.c @@ -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); diff --git a/src/asahi/compiler/agx_compile.h b/src/asahi/compiler/agx_compile.h index 5c90e44..38da1c7 100644 --- a/src/asahi/compiler/agx_compile.h +++ b/src/asahi/compiler/agx_compile.h @@ -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; diff --git a/src/asahi/compiler/agx_compiler.h b/src/asahi/compiler/agx_compiler.h index f8d5078..4cd8930 100644 --- a/src/asahi/compiler/agx_compiler.h +++ b/src/asahi/compiler/agx_compiler.h @@ -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; diff --git a/src/asahi/meson.build b/src/asahi/meson.build index fc7823c..1bb94d5 100644 --- a/src/asahi/meson.build +++ b/src/asahi/meson.build @@ -44,6 +44,7 @@ agx_compiler = executable( dependencies : [ idep_nir, idep_mesautil, + idep_agx_pack, dep_libdrm, ], link_with : [ diff --git a/src/gallium/drivers/asahi/agx_state.c b/src/gallium/drivers/asahi/agx_state.c index 26b9936..74d2ea4 100644 --- a/src/gallium/drivers/asahi/agx_state.c +++ b/src/gallium/drivers/asahi/agx_state.c @@ -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)); -- 2.7.4