asahi: add =bodump debug help

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32434>
This commit is contained in:
Alyssa Rosenzweig 2024-11-28 21:00:47 -05:00 committed by Marge Bot
parent 8caddd2ca1
commit 751bd986fb
3 changed files with 156 additions and 2 deletions

View file

@ -6,6 +6,9 @@
#include "agx_bo.h"
#include <inttypes.h>
#include <stdlib.h>
#include "util/hash_table.h"
#include "util/ralloc.h"
#include "agx_device.h"
#include "decode.h"
@ -168,6 +171,152 @@ agx_bo_reference(struct agx_bo *bo)
}
}
struct label_stat {
const char *label;
uint32_t count;
size_t alloc_B;
size_t mapped_B;
};
static void
account_bo(struct label_stat *stat, struct agx_bo *bo)
{
stat->count++;
stat->alloc_B += bo->size;
if (bo->_map != NULL)
stat->mapped_B += bo->size;
}
static void
print_size(FILE *fp, size_t size_B)
{
if (size_B >= (1024 * 1024 * 1024)) {
fprintf(fp, "%.1f GiB", (double)size_B / (double)(1024 * 1024 * 1024));
} else if (size_B >= (1024 * 1024)) {
fprintf(fp, "%.1f MiB", (double)size_B / (double)(1024 * 1024));
} else if (size_B >= 1024) {
fprintf(fp, "%zu KiB", DIV_ROUND_UP(size_B, 1024));
} else {
fprintf(fp, "%zu B", size_B);
}
}
static void
print_stat(FILE *fp, struct label_stat *stat)
{
const char *BOLD = "\e[1m";
const char *RESET = "\e[0m";
fprintf(fp, "%s%s%s: ", BOLD, stat->label, RESET);
print_size(fp, stat->alloc_B);
if (stat->mapped_B) {
fprintf(fp, ", mapped ");
print_size(fp, stat->mapped_B);
}
fprintf(fp, ", %u BOs\n", stat->count);
}
static int
compare_size(const void *a_, const void *b_)
{
const struct label_stat *const *label_a = a_;
const struct label_stat *const *label_b = b_;
size_t a = (*label_a)->alloc_B;
size_t b = (*label_b)->alloc_B;
return (a > b) ? 1 : (a < b) ? -1 : 0;
}
static void
agx_bo_dump_all(struct agx_device *dev)
{
struct label_stat accum = {.label = "Total"};
struct hash_table *totals = _mesa_string_hash_table_create(NULL);
bool verbose = dev->debug & AGX_DBG_BODUMPVERBOSE;
if (verbose)
fprintf(stderr, "---\n");
for (uint32_t handle = 0; handle < dev->max_handle; handle++) {
struct agx_bo *bo = agx_lookup_bo(dev, handle);
if (!bo->size)
continue;
if (verbose) {
fprintf(stderr, "%u: %s %zu KiB\n", handle, bo->label,
bo->size / 1024);
}
account_bo(&accum, bo);
assert(bo->label != NULL && "Everything must be labeled");
struct hash_entry *ent = _mesa_hash_table_search(totals, bo->label);
struct label_stat *ls;
if (ent != NULL) {
ls = ent->data;
} else {
ls = rzalloc(totals, struct label_stat);
ls->label = bo->label;
_mesa_hash_table_insert(totals, bo->label, ls);
}
account_bo(ls, bo);
}
if (verbose) {
fprintf(stderr, "\n");
}
unsigned nr_labels = _mesa_hash_table_num_entries(totals);
struct label_stat **stats =
rzalloc_array(totals, struct label_stat *, nr_labels);
unsigned i = 0;
hash_table_foreach(totals, ent) {
assert(i < nr_labels);
stats[i++] = ent->data;
}
assert(i == nr_labels);
/* Sort labels in ascending order of size */
qsort(stats, nr_labels, sizeof(struct label_stat *), compare_size);
for (i = 0; i < nr_labels; ++i) {
print_stat(stderr, stats[i]);
}
print_stat(stderr, &accum);
if (verbose)
fprintf(stderr, "---\n\n");
else
fprintf(stderr, "\n");
ralloc_free(totals);
}
static void
agx_bo_dump_all_periodic(struct agx_device *dev)
{
if (likely(!(dev->debug & (AGX_DBG_BODUMP | AGX_DBG_BODUMPVERBOSE))))
return;
static time_t agx_last_dumped_time = 0;
time_t now = time(NULL);
if (now == agx_last_dumped_time)
return;
agx_bo_dump_all(dev);
agx_last_dumped_time = now;
}
void
agx_bo_unreference(struct agx_device *dev, struct agx_bo *bo)
{
@ -193,6 +342,8 @@ agx_bo_unreference(struct agx_device *dev, struct agx_bo *bo)
agx_bo_free(dev, bo);
}
agx_bo_dump_all_periodic(dev);
pthread_mutex_unlock(&dev->bo_map_lock);
}
@ -240,5 +391,6 @@ agx_bo_create(struct agx_device *dev, size_t size, unsigned align,
if (dev->debug & AGX_DBG_TRACE)
agxdecode_track_alloc(dev->agxdecode, bo);
agx_bo_dump_all_periodic(dev);
return bo;
}

View file

@ -46,6 +46,7 @@ asahi_simple_ioctl(struct agx_device *dev, unsigned cmd, void *req)
/* clang-format off */
static const struct debug_named_value agx_debug_options[] = {
{"trace", AGX_DBG_TRACE, "Trace the command stream"},
{"bodump", AGX_DBG_BODUMP, "Periodically dump live BOs"},
{"no16", AGX_DBG_NO16, "Disable 16-bit support"},
{"perf", AGX_DBG_PERF, "Print performance warnings"},
#ifndef NDEBUG
@ -67,6 +68,7 @@ static const struct debug_named_value agx_debug_options[] = {
{"scratch", AGX_DBG_SCRATCH, "Debug scratch memory usage"},
{"1queue", AGX_DBG_1QUEUE, "Force usage of a single queue for multiple contexts"},
{"nosoft", AGX_DBG_NOSOFT, "Disable soft fault optimizations"},
{"bodumpverbose", AGX_DBG_BODUMPVERBOSE, "Include extra info with dumps"},
DEBUG_NAMED_VALUE_END
};
/* clang-format on */

View file

@ -30,7 +30,7 @@ static const uint64_t AGX_SUPPORTED_INCOMPAT_FEATURES =
enum agx_dbg {
AGX_DBG_TRACE = BITFIELD_BIT(0),
/* bit 1 unused */
AGX_DBG_BODUMP = BITFIELD_BIT(1),
AGX_DBG_NO16 = BITFIELD_BIT(2),
AGX_DBG_DIRTY = BITFIELD_BIT(3),
AGX_DBG_PRECOMPILE = BITFIELD_BIT(4),
@ -46,7 +46,7 @@ enum agx_dbg {
AGX_DBG_SMALLTILE = BITFIELD_BIT(14),
AGX_DBG_NOMSAA = BITFIELD_BIT(15),
AGX_DBG_NOSHADOW = BITFIELD_BIT(16),
/* bit 17 unused */
AGX_DBG_BODUMPVERBOSE = BITFIELD_BIT(17),
AGX_DBG_SCRATCH = BITFIELD_BIT(18),
AGX_DBG_NOSOFT = BITFIELD_BIT(19),
AGX_DBG_FEEDBACK = BITFIELD_BIT(20),