agx: Remap fragment shader varyings explicitly
authorAlyssa Rosenzweig <alyssa@rosenzweig.io>
Sun, 13 Jun 2021 00:47:45 +0000 (20:47 -0400)
committerMarge Bot <eric+marge@anholt.net>
Mon, 5 Jul 2021 20:56:04 +0000 (20:56 +0000)
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>

src/asahi/compiler/agx_compile.c
src/asahi/compiler/agx_compile.h
src/asahi/compiler/agx_compiler.h
src/asahi/meson.build
src/gallium/drivers/asahi/agx_state.c

index 16173e2..5f22137 100644 (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);
 
index 5c90e44..38da1c7 100644 (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;
index f8d5078..4cd8930 100644 (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;
 
index fc7823c..1bb94d5 100644 (file)
@@ -44,6 +44,7 @@ agx_compiler = executable(
   dependencies : [
     idep_nir,
     idep_mesautil,
+    idep_agx_pack,
     dep_libdrm,
   ],
   link_with : [
index 26b9936..74d2ea4 100644 (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));