From 2e6a34bf0e8560a0e4b64b90e730e405d00c13aa Mon Sep 17 00:00:00 2001 From: Christoph Pillmayer Date: Fri, 20 Mar 2026 11:03:17 +0100 Subject: [PATCH] pan/pps: Output counters per block Instead of summing counters from shader cores, and outputting only the counters from the first l2 slice, use the memory layout provided from the kmod to output individual counters for each (category, block, counter) combination. Co-Authored-by: Lukas Zapolskas --- src/panfrost/ds/pan_pps_perf.cpp | 98 +++++++++++++++++++++++++------- 1 file changed, 78 insertions(+), 20 deletions(-) diff --git a/src/panfrost/ds/pan_pps_perf.cpp b/src/panfrost/ds/pan_pps_perf.cpp index 2f6ccbf0217..2a13a3a0088 100644 --- a/src/panfrost/ds/pan_pps_perf.cpp +++ b/src/panfrost/ds/pan_pps_perf.cpp @@ -1,5 +1,6 @@ /* * Copyright © 2021 Collabora, Ltd. + * Copyright © 2026 Arm, Ltd. * SPDX-License-Identifier: MIT */ @@ -86,39 +87,96 @@ PanfrostPerf::get_subinstance() { return perf; } +std::string +format_suffix(const char *fmt, uint8_t idx) +{ + assert(strlen(fmt) < 200 && "fmt unreasonably long"); + char buf[256]; + std::snprintf(buf, sizeof(buf), fmt, idx); + + return std::string(buf); +} + +const char * +get_block_suffix(uint8_t category) +{ + assert(category <= PAN_PERF_COUNTER_CAT_MAX); + + switch (category) { + case PAN_PERF_COUNTER_CAT_MEMSYS: + return " (slice %u)"; + case PAN_PERF_COUNTER_CAT_SHADER: + return " (core %u)"; + default: + return nullptr; + } + + return nullptr; +} + +Counter::Units +convert_pan_units(enum pan_perf_counter_units unit) +{ + switch (unit) { + case PAN_PERF_COUNTER_UNITS_PRIMITIVES: + return Counter::Units::Primitive; + case PAN_PERF_COUNTER_UNITS_INSTRUCTIONS: + return Counter::Units::Instruction; + case PAN_PERF_COUNTER_UNITS_BYTES: + return Counter::Units::Byte; + case PAN_PERF_COUNTER_UNITS_PIXELS: + return Counter::Units::Pixel; + default: + return Counter::Units::None; + } +} + std::pair, std::vector> PanfrostPerf::create_available_counters() const { std::pair, std::vector> ret; auto &[groups, counters] = ret; - size_t cid = 0; + uint32_t global_counter_id = 0; + + const struct pan_perf_category *category = NULL; + for (uint32_t cat_idx = 0; cat_idx < perf->cfg->n_categories; ++cat_idx) { + assert(cat_idx < PAN_PERF_COUNTER_CAT_MAX); + category = &perf->cfg->categories[cat_idx]; - for (uint32_t gid = 0; gid < perf->cfg->n_categories; ++gid) { - const auto &category = perf->cfg->categories[gid]; CounterGroup group = {}; - group.id = gid; - group.name = category.name; + group.id = cat_idx; + group.name = category->name; - for (size_t id = 0; cid < category.n_counters; ++cid) { - Counter counter = {}; - counter.id = cid; - counter.group = gid; + uint32_t n_blocks = perf->mem_layout.category[cat_idx].n_blocks; + for (uint32_t counter_idx = 0; counter_idx < category->n_counters; + ++counter_idx) { + const struct pan_perf_counter *cinfo = + &category->counters[counter_idx]; - counter.name = category.counters[id].name; + for (uint32_t block_idx = 0; block_idx < n_blocks; ++block_idx) { + const char *suffix = get_block_suffix(cat_idx); + const std::string name = + cinfo->name + (suffix ? format_suffix(suffix, block_idx) : ""); - counter.set_getter([=](const Counter &c, const Driver &d) { - auto &pan_driver = PanfrostDriver::into(d); - struct pan_perf *perf = static_cast( + Counter counter = {}; + counter.id = global_counter_id++; + counter.name = name; + counter.group = group.id; + counter.units = convert_pan_units(cinfo->units); + + counter.set_getter([=](const Counter &c, const Driver &d) { + auto &pan_driver = PanfrostDriver::into(d); + struct pan_perf *perf = static_cast( pan_driver.perf->get_subinstance()); - const auto counter = - &perf->cfg->categories[gid].counters[id]; - return int64_t(pan_perf_counter_read(counter, perf)); - }); + return pan_perf_counter_read_raw( + perf, (enum pan_perf_counter_categories)cat_idx, block_idx, + cinfo->offset); + }); - group.counters.push_back(cid++); - - counters.emplace_back(counter); + group.counters.push_back(counter.id); + counters.emplace_back(counter); + } } groups.push_back(group);