broadcom: Add perfetto data source

Signed-off-by: Christian Gmeiner <cgmeiner@igalia.com>
Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/31751>
This commit is contained in:
Christian Gmeiner 2024-10-15 11:31:49 +02:00 committed by Marge Bot
parent 27fb3c549a
commit 3d2d3b2c10
4 changed files with 268 additions and 0 deletions

View file

@ -0,0 +1,42 @@
# Copyright © 2024 Raspberry Pi Ltd
# Copyright © 2021 Collabora, Ltd.
# Copyright © 2021 Google, Inc
# SPDX-License-Identifier: MIT
pps_broadcom_lib = static_library(
'broadcom-dds',
sources: [
'v3d_pps_driver.cc',
'v3d_pps_driver.h',
],
include_directories: [
inc_tool,
inc_broadcom,
inc_include,
],
dependencies: [
dep_libdrm,
dep_perfetto,
idep_broadcom_perfcntrs,
],
c_args: [no_override_init_args],
)
pps_broadcom_dep = declare_dependency(
link_with: [
pps_broadcom_lib,
libbroadcom_v3d,
],
include_directories: [
inc_tool,
],
compile_args: [
'-DPPS_V3D',
],
)
pps_datasources += pps_broadcom_dep
pps_includes += [
inc_include,
inc_broadcom,
]

View file

@ -0,0 +1,181 @@
/*
* Copyright © 2024 Raspberry Pi Ltd
* SPDX-License-Identifier: MIT
*/
#include "v3d_pps_driver.h"
#include <perfetto.h>
#include <string.h>
#include <string>
#include "perfcntrs/v3d_perfcntrs.h"
#include <xf86drm.h>
namespace pps
{
uint64_t
V3DDriver::get_min_sampling_period_ns()
{
return 100000;
}
bool
V3DDriver::init_perfcnt()
{
const char *v3d_ds_counter_env = getenv("V3D_DS_COUNTER");
if (!v3d_ds_counter_env || v3d_ds_counter_env[0] == '\0')
return false;
bool success = v3d_get_device_info(drm_device.fd, &devinfo, &drmIoctl);
if (!success)
return false;
perfcntrs = v3d_perfcntrs_init(&devinfo, drm_device.fd);
if (!perfcntrs)
return false;
groups.clear();
counters.clear();
enabled_counters.clear();
struct drm_v3d_perfmon_create createreq = { 0 };
CounterGroup group = {};
char *dup = strdup(v3d_ds_counter_env);
char *name = strtok(dup, ",");
while (name != NULL && createreq.ncounters < DRM_V3D_MAX_PERF_COUNTERS) {
const struct v3d_perfcntr_desc *desc = v3d_perfcntrs_get_by_name(perfcntrs, name);
if (desc) {
Counter counter_desc = {};
counter_desc.units = Counter::Units::None;
counter_desc.id = createreq.ncounters;
counter_desc.name = desc->name;
counter_desc.group = group.id;
counter_desc.getter = [this](
const Counter &c, const Driver &dri) -> Counter::Value {
return static_cast<int64_t>(values[c.id]);
};
counters.emplace_back(std::move(counter_desc));
createreq.counters[createreq.ncounters++] = desc->index;
} else {
PERFETTO_ELOG("Unkown performance counter name: %s", name);
}
name = strtok(NULL, ",");
}
free(dup);
if (createreq.ncounters == 0)
return false;
int ret = drmIoctl(drm_device.fd, DRM_IOCTL_V3D_PERFMON_CREATE, &createreq);
if (ret != 0)
PERFETTO_FATAL("Failed to create perfmon %s", strerror(errno));
perfmon_id = createreq.id;
return true;
}
void
V3DDriver::enable_counter(uint32_t counter_id)
{
enabled_counters.push_back(counters[counter_id]);
}
void
V3DDriver::enable_all_counters()
{
enabled_counters.reserve(counters.size());
enabled_counters.insert(enabled_counters.end(), counters.begin(), counters.end());
}
void
V3DDriver::enable_perfcnt(uint64_t sampling_period_ns)
{
struct drm_v3d_perfmon_set_global globalreq = {
.id = perfmon_id,
};
int ret = drmIoctl(drm_device.fd, DRM_IOCTL_V3D_PERFMON_SET_GLOBAL, &globalreq);
if (ret != 0) {
if (errno == ENOTTY)
PERFETTO_FATAL("Failed to set global perfmon. Feature not available - update your kernel");
else
PERFETTO_FATAL("Failed to set global perfmon %s", strerror(errno));
}
}
void
V3DDriver::disable_perfcnt()
{
struct drm_v3d_perfmon_set_global globalreq = {
.flags = DRM_V3D_PERFMON_CLEAR_GLOBAL,
.id = perfmon_id,
};
int ret = drmIoctl(drm_device.fd, DRM_IOCTL_V3D_PERFMON_SET_GLOBAL, &globalreq);
if (ret != 0)
PERFETTO_FATAL("Failed to clear global perfmon %s", strerror(errno));
struct drm_v3d_perfmon_destroy destroyreq = {
.id = perfmon_id,
};
ret = drmIoctl(drm_device.fd, DRM_IOCTL_V3D_PERFMON_DESTROY, &destroyreq);
if (ret != 0)
PERFETTO_FATAL("Failed to destroy perfmon %s", strerror(errno));
}
bool
V3DDriver::dump_perfcnt()
{
last_dump_ts = perfetto::base::GetBootTimeNs().count();
struct drm_v3d_perfmon_get_values req = {
.id = perfmon_id,
.values_ptr = (uintptr_t)values,
};
int ret = drmIoctl(drm_device.fd, DRM_IOCTL_V3D_PERFMON_GET_VALUES, &req);
if (ret != 0) {
PERFETTO_FATAL("Can't request perfmon counters values\n");
return false;
}
return true;
}
uint64_t
V3DDriver::next()
{
auto ret = last_dump_ts;
last_dump_ts = 0;
return ret;
}
uint32_t
V3DDriver::gpu_clock_id() const
{
return perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME;
}
uint64_t
V3DDriver::gpu_timestamp() const
{
return perfetto::base::GetBootTimeNs().count();
}
bool
V3DDriver::cpu_gpu_timestamp(uint64_t &, uint64_t &) const
{
/* Not supported */
return false;
}
} // namespace pps

View file

@ -0,0 +1,41 @@
/*
* Copyright © 2024 Raspberry Pi Ltd
* SPDX-License-Identifier: MIT
*/
#pragma once
#include "common/v3d_device_info.h"
#include "drm-uapi/v3d_drm.h"
#include "perfcntrs/v3d_perfcntrs.h"
#include "pps/pps_driver.h"
namespace pps
{
class V3DDriver : public Driver
{
public:
uint64_t get_min_sampling_period_ns() override;
bool init_perfcnt() override;
void enable_counter(uint32_t counter_id) override;
void enable_all_counters() override;
void enable_perfcnt(uint64_t sampling_period_ns) override;
void disable_perfcnt() override;
bool dump_perfcnt() override;
uint64_t next() override;
uint32_t gpu_clock_id() const override;
uint64_t gpu_timestamp() const override;
bool cpu_gpu_timestamp(uint64_t &cpu_timestamp,
uint64_t &gpu_timestamp) const override;
private:
struct v3d_device_info devinfo;
struct v3d_perfcntrs *perfcntrs;
uint64_t last_dump_ts = 0;
unsigned int perfmon_id;
uint64_t values[DRM_V3D_MAX_PERF_COUNTERS];
};
} // namespace pps

View file

@ -75,6 +75,10 @@ libbroadcom_v3d = static_library(
subdir('perfcntrs')
if with_perfetto and (with_datasources.contains('v3d') or with_datasources.contains('auto'))
subdir('ds')
endif
if with_broadcom_vk
subdir('vulkan')
endif