asahi: port to common stats framework

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Reviewed-by: Mary Guillemard <mary.guillemard@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33814>
diff --git a/src/asahi/clc/asahi_clc.c b/src/asahi/clc/asahi_clc.c
index b19b30f..4bee42e 100644
--- a/src/asahi/clc/asahi_clc.c
+++ b/src/asahi/clc/asahi_clc.c
@@ -353,7 +353,7 @@
             }
 
             nir_shader *clone = nir_shader_clone(NULL, s);
-            agx_compile_shader_nir(clone, &key, NULL, &compiled);
+            agx_compile_shader_nir(clone, &key, &compiled);
             print_shader(fp_c, libfunc->name, *target, v, &compiled);
             free(compiled.binary);
             ralloc_free(clone);
diff --git a/src/asahi/compiler/agx_compile.c b/src/asahi/compiler/agx_compile.c
index aad6c09..14a9f82 100644
--- a/src/asahi/compiler/agx_compile.c
+++ b/src/asahi/compiler/agx_compile.c
@@ -2744,34 +2744,32 @@
    agx_no_varyings(&_b);
 }
 
-static int
-agx_dump_stats(agx_context *ctx, unsigned size, char **out)
+static void
+agx_calc_stats(agx_context *ctx, unsigned size, struct agx2_stats *stats)
 {
-   unsigned nr_ins = 0, spills = 0, fills = 0;
+   struct agx_cycle_estimate cycles = agx_estimate_cycles(ctx);
+
+   *stats = (struct agx2_stats){
+      .alu = cycles.alu,
+      .fscib = cycles.f_scib,
+      .ic = cycles.ic,
+      .code_size = size,
+      .gprs = ctx->max_reg,
+      .uniforms = ctx->out->push_count,
+      .scratch = ctx->scratch_size_B,
+      .threads = agx_occupancy_for_register_count(ctx->max_reg).max_threads,
+      .loops = ctx->loop_count,
+   };
 
    /* Count instructions */
    agx_foreach_instr_global(ctx, I) {
-      nr_ins++;
+      stats->instrs++;
 
       if (I->op == AGX_OPCODE_STACK_STORE)
-         spills++;
+         stats->spills++;
       else if (I->op == AGX_OPCODE_STACK_LOAD)
-         fills++;
+         stats->fills++;
    }
-
-   struct agx_cycle_estimate cycles = agx_estimate_cycles(ctx);
-
-   unsigned nr_threads =
-      agx_occupancy_for_register_count(ctx->max_reg).max_threads;
-
-   return asprintf(
-      out,
-      "%s shader: %u inst, %u alu, %u fscib, %u ic, %u bytes, %u regs, "
-      "%u uniforms, %u scratch, %u threads, %u loops, "
-      "%u:%u spills:fills",
-      gl_shader_stage_name(ctx->stage), nr_ins, cycles.alu, cycles.f_scib,
-      cycles.ic, size, ctx->max_reg, ctx->out->push_count, ctx->scratch_size_B,
-      nr_threads, ctx->loop_count, spills, fills);
 }
 
 static bool
@@ -3461,7 +3459,6 @@
 static unsigned
 agx_compile_function_nir(nir_shader *nir, nir_function_impl *impl,
                          struct agx_shader_key *key,
-                         struct util_debug_callback *debug,
                          struct util_dynarray *binary,
                          struct agx_shader_info *out)
 {
@@ -3629,19 +3626,12 @@
 
    /* Don't dump statistics for preambles, since they're not worth optimizing */
    if (!impl->function->is_preamble) {
-      char *stats;
-      int ret = agx_dump_stats(ctx, binary->size, &stats);
+      agx_calc_stats(ctx, binary->size, &ctx->out->stats);
 
-      if (ret >= 0) {
-         if (agx_should_dump(nir, AGX_DBG_SHADERDB)) {
-            fprintf(stderr, "SHADER-DB: %s - %s\n", nir->info.label ?: "",
-                    stats);
-         }
-
-         if (debug)
-            util_debug_message(debug, SHADER_INFO, "%s", stats);
-
-         free(stats);
+      if (agx_should_dump(nir, AGX_DBG_SHADERDB)) {
+         agx2_stats_fprintf(stderr,
+                            _mesa_shader_stage_to_abbrev(nir->info.stage),
+                            &ctx->out->stats);
       }
    }
 
@@ -3769,7 +3759,6 @@
 
 void
 agx_compile_shader_nir(nir_shader *nir, struct agx_shader_key *key,
-                       struct util_debug_callback *debug,
                        struct agx_shader_part *out)
 {
    agx_compiler_debug = agx_get_compiler_debug();
@@ -3849,7 +3838,7 @@
 
    nir_foreach_function_with_impl(func, impl, nir) {
       unsigned offset =
-         agx_compile_function_nir(nir, impl, key, debug, &binary, &out->info);
+         agx_compile_function_nir(nir, impl, key, &binary, &out->info);
 
       if (func->is_preamble) {
          info->preamble_offset = offset;
diff --git a/src/asahi/compiler/agx_compile.h b/src/asahi/compiler/agx_compile.h
index ca4979f..9285728 100644
--- a/src/asahi/compiler/agx_compile.h
+++ b/src/asahi/compiler/agx_compile.h
@@ -6,6 +6,7 @@
 #pragma once
 
 #include "compiler/nir/nir.h"
+#include "util/shader_stats.h"
 #include "util/u_dynarray.h"
 #include "util/u_tristate.h"
 #include "shader_enums.h"
@@ -154,6 +155,8 @@
     * registers as specified hre.
     */
    struct agx_rodata rodata;
+
+   struct agx2_stats stats;
 };
 
 struct agx_precompiled_kernel_info {
@@ -305,7 +308,6 @@
                           nir_intrinsic_instr *high, void *data);
 
 void agx_compile_shader_nir(nir_shader *nir, struct agx_shader_key *key,
-                            struct util_debug_callback *debug,
                             struct agx_shader_part *out);
 
 struct agx_occupancy {
diff --git a/src/asahi/lib/agx_bg_eot.c b/src/asahi/lib/agx_bg_eot.c
index 68b8a97..2b1325a 100644
--- a/src/asahi/lib/agx_bg_eot.c
+++ b/src/asahi/lib/agx_bg_eot.c
@@ -52,7 +52,7 @@
 
    struct agx_bg_eot_shader *res = rzalloc(cache->ht, struct agx_bg_eot_shader);
    struct agx_shader_part bin;
-   agx_compile_shader_nir(shader, key, NULL, &bin);
+   agx_compile_shader_nir(shader, key, &bin);
 
    res->info = bin.info;
    res->ptr = agx_pool_upload_aligned_with_bo(
diff --git a/src/asahi/vulkan/hk_cmd_draw.c b/src/asahi/vulkan/hk_cmd_draw.c
index 4133062..54c0b50 100644
--- a/src/asahi/vulkan/hk_cmd_draw.c
+++ b/src/asahi/vulkan/hk_cmd_draw.c
@@ -1672,7 +1672,7 @@
    struct agx_shader_part *part =
       rzalloc(dev->prolog_epilog.ht, struct agx_shader_part);
 
-   agx_compile_shader_nir(b.shader, &backend_key, NULL, part);
+   agx_compile_shader_nir(b.shader, &backend_key, part);
 
    ralloc_free(b.shader);
 
diff --git a/src/asahi/vulkan/hk_shader.c b/src/asahi/vulkan/hk_shader.c
index 695ad0a..bd0d965 100644
--- a/src/asahi/vulkan/hk_shader.c
+++ b/src/asahi/vulkan/hk_shader.c
@@ -963,7 +963,7 @@
    if (lock)
       simple_mtx_lock(lock);
 
-   agx_compile_shader_nir(nir, &backend_key, NULL, &shader->b);
+   agx_compile_shader_nir(nir, &backend_key, &shader->b);
 
    if (lock)
       simple_mtx_unlock(lock);
@@ -1460,24 +1460,7 @@
     * with zink.
     */
    struct hk_shader *shader = hk_any_variant(obj);
-
-   vk_outarray_append_typed(VkPipelineExecutableStatisticKHR, &out, stat)
-   {
-      VK_COPY_STR(stat->name, "Code Size");
-      VK_COPY_STR(stat->description,
-                  "Size of the compiled shader binary, in bytes");
-      stat->format = VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR;
-      stat->value.u64 = shader->code_size;
-   }
-
-   vk_outarray_append_typed(VkPipelineExecutableStatisticKHR, &out, stat)
-   {
-      VK_COPY_STR(stat->name, "Number of GPRs");
-      VK_COPY_STR(stat->description, "Number of GPRs used by this pipeline");
-      stat->format = VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR;
-      stat->value.u64 = shader->b.info.nr_gprs;
-   }
-
+   vk_add_agx2_stats(out, &shader->b.info.stats);
    return vk_outarray_status(&out);
 }
 
diff --git a/src/gallium/drivers/asahi/agx_state.c b/src/gallium/drivers/asahi/agx_state.c
index b33564f..479b4ac 100644
--- a/src/gallium/drivers/asahi/agx_state.c
+++ b/src/gallium/drivers/asahi/agx_state.c
@@ -1554,7 +1554,10 @@
       key.fs.cf_base = cf_base;
    }
 
-   agx_compile_shader_nir(nir, &key, debug, &compiled->b);
+   agx_compile_shader_nir(nir, &key, &compiled->b);
+
+   agx2_stats_util_debug(debug, _mesa_shader_stage_to_abbrev(nir->info.stage),
+                         &compiled->b.info.stats);
 
    if (compiled->b.info.binary_size && !secondary) {
       compiled->bo = agx_bo_create(dev, compiled->b.info.binary_size, 0,
@@ -1577,7 +1580,6 @@
 static struct agx_compiled_shader *
 agx_compile_variant(struct agx_device *dev, struct pipe_context *pctx,
                     struct agx_uncompiled_shader *so,
-                    struct util_debug_callback *debug,
                     union asahi_shader_key *key_)
 {
    struct blob_reader reader;
@@ -1679,8 +1681,8 @@
    NIR_PASS(_, nir, agx_nir_lower_multisampled_image_store);
 
    struct agx_compiled_shader *compiled = agx_compile_nir(
-      dev, nir, debug, so->type, false, so->type != PIPE_SHADER_FRAGMENT, false,
-      0, attrib_components_read);
+      dev, nir, &pctx->debug, so->type, false, so->type != PIPE_SHADER_FRAGMENT,
+      false, 0, attrib_components_read);
 
    if (so->type == PIPE_SHADER_FRAGMENT) {
       /* XXX: don't replicate this all over the driver */
@@ -1696,14 +1698,15 @@
 
    /* Compile auxiliary programs */
    if (gs_count) {
-      compiled->gs_count = agx_compile_nir(dev, gs_count, debug, so->type,
-                                           false, true, false, 0, NULL);
+      compiled->gs_count = agx_compile_nir(
+         dev, gs_count, &pctx->debug, so->type, false, true, false, 0, NULL);
       compiled->gs_count->so = so;
    }
 
    if (pre_gs) {
-      compiled->pre_gs = agx_compile_nir(
-         dev, pre_gs, debug, PIPE_SHADER_COMPUTE, false, true, false, 0, NULL);
+      compiled->pre_gs =
+         agx_compile_nir(dev, pre_gs, &pctx->debug, PIPE_SHADER_COMPUTE, false,
+                         true, false, 0, NULL);
    }
 
    if (gs_copy) {
@@ -1723,8 +1726,8 @@
       NIR_PASS(_, gs_copy, agx_nir_lower_uvs, &uvs);
 
       compiled->gs_copy =
-         agx_compile_nir(dev, gs_copy, debug, PIPE_SHADER_GEOMETRY, false, true,
-                         false, 0, NULL);
+         agx_compile_nir(dev, gs_copy, &pctx->debug, PIPE_SHADER_GEOMETRY,
+                         false, true, false, 0, NULL);
       compiled->gs_copy->so = so;
       compiled->gs_copy->stage = so->type;
       compiled->gs_copy->uvs = uvs;
@@ -1743,14 +1746,13 @@
 static struct agx_compiled_shader *
 agx_get_shader_variant(struct agx_screen *screen, struct pipe_context *pctx,
                        struct agx_uncompiled_shader *so,
-                       struct util_debug_callback *debug,
                        union asahi_shader_key *key)
 {
    struct agx_compiled_shader *compiled =
       agx_disk_cache_retrieve(screen, so, key);
 
    if (!compiled) {
-      compiled = agx_compile_variant(&screen->dev, pctx, so, debug, key);
+      compiled = agx_compile_variant(&screen->dev, pctx, so, key);
       agx_disk_cache_store(screen->disk_cache, so, key, compiled);
    }
 
@@ -2001,19 +2003,16 @@
    if ((so->type == PIPE_SHADER_TESS_CTRL) ||
        (so->type == PIPE_SHADER_FRAGMENT && !so->info.uses_fbfetch)) {
       union asahi_shader_key key = {0};
-      agx_get_shader_variant(agx_screen(pctx->screen), pctx, so, &pctx->debug,
-                             &key);
+      agx_get_shader_variant(agx_screen(pctx->screen), pctx, so, &key);
    } else if (so->type == PIPE_SHADER_VERTEX) {
       union asahi_shader_key key = {
          .vs.hw = next_stage == MESA_SHADER_FRAGMENT,
       };
-      agx_get_shader_variant(agx_screen(pctx->screen), pctx, so, &pctx->debug,
-                             &key);
+      agx_get_shader_variant(agx_screen(pctx->screen), pctx, so, &key);
 
       if (!next_stage) {
          key.vs.hw = true;
-         agx_get_shader_variant(agx_screen(pctx->screen), pctx, so,
-                                &pctx->debug, &key);
+         agx_get_shader_variant(agx_screen(pctx->screen), pctx, so, &key);
       }
    } else if (dev->debug & AGX_DBG_PRECOMPILE) {
       union asahi_shader_key key = {0};
@@ -2033,7 +2032,7 @@
          unreachable("Unknown shader stage in shader-db precompile");
       }
 
-      agx_compile_variant(dev, pctx, so, &pctx->debug, &key);
+      agx_compile_variant(dev, pctx, so, &key);
    }
 
    return so;
@@ -2060,8 +2059,7 @@
    nir_shader *nir = (void *)cso->prog;
 
    agx_shader_initialize(dev, so, nir, ctx->support_lod_bias, ctx->robust);
-   agx_get_shader_variant(agx_screen(pctx->screen), pctx, so, &pctx->debug,
-                          &key);
+   agx_get_shader_variant(agx_screen(pctx->screen), pctx, so, &key);
 
    /* We're done with the NIR, throw it away */
    ralloc_free(nir);
@@ -2073,8 +2071,8 @@
                            struct pipe_compute_state_object_info *info)
 {
    union asahi_shader_key key = {0};
-   struct agx_compiled_shader *so = agx_get_shader_variant(
-      agx_screen(pctx->screen), pctx, cso, &pctx->debug, &key);
+   struct agx_compiled_shader *so =
+      agx_get_shader_variant(agx_screen(pctx->screen), pctx, cso, &key);
 
    info->max_threads =
       agx_occupancy_for_register_count(so->b.info.nr_gprs).max_threads;
@@ -2102,7 +2100,7 @@
    }
 
    struct agx_screen *screen = agx_screen(ctx->base.screen);
-   *out = agx_get_shader_variant(screen, &ctx->base, so, &ctx->base.debug, key);
+   *out = agx_get_shader_variant(screen, &ctx->base, so, key);
    return true;
 }
 
diff --git a/src/util/shader_stats.xml b/src/util/shader_stats.xml
index 467fc4a..89b37e1 100644
--- a/src/util/shader_stats.xml
+++ b/src/util/shader_stats.xml
@@ -1,2 +1,16 @@
 <shaderdb>
+   <isa name="AGX2">
+      <stat name="Instructions" display="Instrs">Instruction count</stat>
+      <stat name="ALU">Estimated ALU cycle count</stat>
+      <stat name="FSCIB">Estimated F16/F32/SCIB cycle count</stat>
+      <stat name="IC">Estimated IC cycle count</stat>
+      <stat name="Code size">Binary size in bytes</stat>
+      <stat name="GPRs" type="u16">Number of 16-bit GPRs</stat>
+      <stat name="Uniforms" type="u16">Number of 16-bit uniform registers</stat>
+      <stat name="Scratch">Scratch size per thread in bytes</stat>
+      <stat name="Threads" more="better" type="u16">Maximum number of threads in flight on a compute unit</stat>
+      <stat name="Loops">Number of hardware loops</stat>
+      <stat name="Spills">Number of spill (stack store) instructions</stat>
+      <stat name="Fills">Number of fill (stack load) instructions</stat>
+    </isa>
 </shaderdb>