pan/trace: Add wrappers for Mesa CPU scope traces

Add the PAN_TRACE_SCOPE() and PAN_TRACE_FUNC() wrappers based on
MESA_TRACE_SCOPE_IF() in order to associate a category to each trace
and let users select the set of tracing categories to enable at
run-time through the PAN_CPU_TRACE environment variable. This makes
Panfrost tracing an opt-in and avoids to CPU cost of tracing by
default.

There are 3 categories for now:
  - "lib" for the shared utilities
  - "gl" for the Gallium driver
  - "vk" for the Vulkan driver

Each of these categories are divided into subcategories so that
subsystems can easily be traced ("gl.csf" or "lib.kmod" for instance).

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
Reviewed-by: Ashley Smith <ashley.smith@collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/39407>
This commit is contained in:
Loïc Molinari 2026-01-16 16:30:08 +01:00 committed by Marge Bot
parent c9097e2e13
commit 1bca181580
3 changed files with 196 additions and 0 deletions

View file

@ -48,6 +48,7 @@ libpanfrost_lib_files = files(
'pan_tiler.c',
'pan_layout.c',
'pan_scratch.c',
'pan_trace.c',
'pan_props.c',
'pan_util.c',
'pan_afbc.c',

View file

@ -0,0 +1,102 @@
/*
* Copyright © 2026 Amazon.com, Inc. or its affiliates.
*
* SPDX-License-Identifier: MIT
*/
#include "pan_trace.h"
#include "util/os_misc.h"
#define PAN_TRACE_ENV_VAR "PAN_CPU_TRACE"
#define CATEGORY(str, flag) { str, ARRAY_SIZE(str) - 1, (uint64_t) (flag) }
/* To be kept in sync with the pan_trace_category enum in pan_trace.h. */
/* clang-format off */
static struct {
const char *str;
size_t len;
uint64_t flag;
} categories_table[] = {
/* Library categories. */
CATEGORY("lib.afbc", PAN_TRACE_LIB_AFBC),
CATEGORY("lib.desc", PAN_TRACE_LIB_DESC),
CATEGORY("lib.kmod", PAN_TRACE_LIB_KMOD),
CATEGORY("lib", PAN_TRACE_LIB_AFBC |
PAN_TRACE_LIB_DESC |
PAN_TRACE_LIB_KMOD),
/* Gallium categories. */
CATEGORY("gl.blit", PAN_TRACE_GL_BLIT),
CATEGORY("gl.bo", PAN_TRACE_GL_BO),
CATEGORY("gl.cmdstream", PAN_TRACE_GL_CMDSTREAM),
CATEGORY("gl.context", PAN_TRACE_GL_CONTEXT),
CATEGORY("gl.csf", PAN_TRACE_GL_CSF),
CATEGORY("gl.disk_cache", PAN_TRACE_GL_DISK_CACHE),
CATEGORY("gl.fb_preload", PAN_TRACE_GL_FB_PRELOAD),
CATEGORY("gl.jm", PAN_TRACE_GL_JM),
CATEGORY("gl.job", PAN_TRACE_GL_JOB),
CATEGORY("gl.mempool", PAN_TRACE_GL_MEMPOOL),
CATEGORY("gl.resource", PAN_TRACE_GL_RESOURCE),
CATEGORY("gl.shader", PAN_TRACE_GL_SHADER),
CATEGORY("gl", PAN_TRACE_GL_BLIT |
PAN_TRACE_GL_BO |
PAN_TRACE_GL_CMDSTREAM |
PAN_TRACE_GL_CONTEXT |
PAN_TRACE_GL_CSF |
PAN_TRACE_GL_DISK_CACHE |
PAN_TRACE_GL_FB_PRELOAD |
PAN_TRACE_GL_JM |
PAN_TRACE_GL_JOB |
PAN_TRACE_GL_MEMPOOL |
PAN_TRACE_GL_RESOURCE |
PAN_TRACE_GL_SHADER),
/* Vulkan categories. */
CATEGORY("vk.csf", PAN_TRACE_VK_CSF),
CATEGORY("vk", PAN_TRACE_VK_CSF),
};
/* clang-format on */
uint64_t pan_trace_categories = 0;
static bool
is_separator(char c)
{
return c == ',' || c == ';' || c == ' ';
}
void
pan_trace_init(void)
{
const char *list = os_get_option(PAN_TRACE_ENV_VAR);
const char *str = NULL;
uint64_t categories = 0;
char prev_char = ',';
if (!list)
return;
/* Parse list and flag enabled categories. */
for (int i = 0; prev_char; prev_char = list[i++]) {
if (!is_separator(list[i]) && list[i]) {
if (is_separator(prev_char))
str = &list[i];
} else if (!is_separator(prev_char)) {
for (int j = 0; j < ARRAY_SIZE(categories_table); j++) {
size_t len = &list[i] - str;
if (categories_table[j].len == len &&
!strncasecmp(categories_table[j].str, str, len)) {
categories |= categories_table[j].flag;
break;
}
}
}
}
pan_trace_categories = categories;
}

View file

@ -0,0 +1,93 @@
/*
* Copyright © 2026 Amazon.com, Inc. or its affiliates.
*
* SPDX-License-Identifier: MIT
*/
#ifndef __PAN_TRACE_H
#define __PAN_TRACE_H
#include "util/perf/cpu_trace.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Panfrost wrappers for Mesa CPU scope traces.
*
* CPU tracing (not to be confused with GPU command stream tracing with
* PAN_MESA_DEBUG=trace) is often enabled in release builds. Since each trace
* pushed down the underlying tracing backend (Perfetto, Gpuvis, sysprof, etc)
* has a slight cost, Panfrost extends the Mesa CPU scope traces by
* associating each trace to a category that must be enabled at run-time. This
* allows to keep adding useful trace points into Panfrost without worrying
* about the implied inherent latency.
*
* There are 3 categories ("lib" for the shared utilities, "gl" for Gallium,
* "vk" for PanVK) divided into subcategories so that subsystems can easily be
* traced. A list of categories can be passed to Panfrost through the
* PAN_CPU_TRACE environment variable like that:
*
* $ PAN_CPU_TRACE=gl,lib program
*
* Passing a category enables traces for all its subcategories. Subcategories
* can be passed instead for finer grained traces like that:
*
* $ PAN_CPU_TRACE=gl.blit,gl.bo,gl.job program
*/
/* Panfrost trace categories.
*
* To be kept in sync with the categories_table array in pan_trace.c.
*/
/* clang-format off */
enum pan_trace_category {
/* Library categories. */
PAN_TRACE_LIB_AFBC = BITFIELD_BIT(1), /* "lib.afbc" */
PAN_TRACE_LIB_DESC = BITFIELD_BIT(2), /* "lib.desc" */
PAN_TRACE_LIB_KMOD = BITFIELD_BIT(3), /* "lib.kmod" */
/* Gallium categories. */
PAN_TRACE_GL_BLIT = BITFIELD_BIT(4), /* "gl.blit" */
PAN_TRACE_GL_BO = BITFIELD_BIT(5), /* "gl.bo" */
PAN_TRACE_GL_CMDSTREAM = BITFIELD_BIT(6), /* "gl.cmdstream" */
PAN_TRACE_GL_CONTEXT = BITFIELD_BIT(7), /* "gl.context" */
PAN_TRACE_GL_CSF = BITFIELD_BIT(8), /* "gl.csf" */
PAN_TRACE_GL_DISK_CACHE = BITFIELD_BIT(9), /* "gl.disk_cache" */
PAN_TRACE_GL_FB_PRELOAD = BITFIELD_BIT(10), /* "gl.fb_preload" */
PAN_TRACE_GL_JM = BITFIELD_BIT(11), /* "gl.jm" */
PAN_TRACE_GL_JOB = BITFIELD_BIT(12), /* "gl.job" */
PAN_TRACE_GL_MEMPOOL = BITFIELD_BIT(13), /* "gl.mempool" */
PAN_TRACE_GL_RESOURCE = BITFIELD_BIT(14), /* "gl.resource" */
PAN_TRACE_GL_SHADER = BITFIELD_BIT(15), /* "gl.shader" */
/* Vulkan categories. */
PAN_TRACE_VK_CSF = BITFIELD_BIT(16), /* "vk.csf" */
};
/* clang-format on */
extern uint64_t pan_trace_categories;
/* Add a Mesa CPU scope trace for a given Panfrost category using printf like
* formatting.
*/
#define PAN_TRACE_SCOPE(category, format, ...) \
MESA_TRACE_SCOPE_IF(category & pan_trace_categories, format, ##__VA_ARGS__)
/* Add a Mesa CPU scope trace for a given Panfrost category using current
* function name.
*/
#define PAN_TRACE_FUNC(category) \
MESA_TRACE_FUNC_IF(category & pan_trace_categories)
/* Parse the PAN_CPU_TRACE environment variable and initialize CPU tracing.
* The PAN_CPU_TRACE environment variable stores a list of categories (see
* enum pan_trace_category) separated by a comma, a semicolon or a space.
*/
void pan_trace_init(void);
#ifdef __cplusplus
} /* extern C */
#endif
#endif /* __PAN_TRACE_H */