mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-26 23:40:10 +01:00
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:
parent
8caddd2ca1
commit
751bd986fb
3 changed files with 156 additions and 2 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue