mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-22 15:40:11 +01:00
pps: Panfrost pps driver
Add the Panfrost pps driver. v2: Human readable names for counter blocks and use `unreachable`. v3: Use libpanfrost_perf to collect counter values. Signed-off-by: Antonio Caggiano <antonio.caggiano@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10215>
This commit is contained in:
parent
bcf8c7910d
commit
513d1baaea
8 changed files with 424 additions and 0 deletions
21
src/panfrost/ds/.clang-format
Normal file
21
src/panfrost/ds/.clang-format
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
BasedOnStyle: WebKit
|
||||||
|
AlignTrailingComments: 'true'
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: 'false'
|
||||||
|
AllowShortFunctionsOnASingleLine: None
|
||||||
|
AlwaysBreakBeforeMultilineStrings: 'true'
|
||||||
|
BinPackArguments: 'false'
|
||||||
|
BinPackParameters: 'false'
|
||||||
|
BreakBeforeBinaryOperators: None
|
||||||
|
BreakBeforeBraces: Linux
|
||||||
|
ColumnLimit: '100'
|
||||||
|
Cpp11BracedListStyle: 'true'
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: 'false'
|
||||||
|
NamespaceIndentation: None
|
||||||
|
PointerAlignment: Right
|
||||||
|
SortIncludes: 'true'
|
||||||
|
SpaceAfterTemplateKeyword: 'false'
|
||||||
|
Standard: Cpp11
|
||||||
|
TabWidth: '3'
|
||||||
|
IndentWidth: '3'
|
||||||
|
ConstructorInitializerIndentWidth: '3'
|
||||||
|
ContinuationIndentWidth: '3'
|
||||||
31
src/panfrost/ds/meson.build
Normal file
31
src/panfrost/ds/meson.build
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
# Copyright © 2020 Collabora, Ltd.
|
||||||
|
# Author: Antonio Caggiano <antonio.caggiano@collabora.com>
|
||||||
|
# Author: Robert Beckett <bob.beckett@collabora.com>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
pps_panfrost_sources = [
|
||||||
|
'pan_pps_perf.cc',
|
||||||
|
'pan_pps_driver.cc'
|
||||||
|
]
|
||||||
|
|
||||||
|
pps_panfrost_includes = [inc_include, inc_src, inc_tool]
|
||||||
|
|
||||||
|
pps_panfrost_lib = static_library(
|
||||||
|
'pps-panfrost',
|
||||||
|
sources: pps_panfrost_sources,
|
||||||
|
include_directories: pps_panfrost_includes,
|
||||||
|
dependencies: [dep_libdrm, dep_perfetto, libpanfrost_dep, dep_panfrost_perf],
|
||||||
|
cpp_args: '-std=c++17'
|
||||||
|
)
|
||||||
|
|
||||||
|
compile_args_pps_panfrost = ['-DPPS_PANFROST']
|
||||||
|
|
||||||
|
pps_panfrost_dep = declare_dependency(
|
||||||
|
link_with: pps_panfrost_lib,
|
||||||
|
include_directories: pps_panfrost_includes,
|
||||||
|
compile_args: compile_args_pps_panfrost
|
||||||
|
)
|
||||||
|
|
||||||
|
pps_datasources += pps_panfrost_dep
|
||||||
|
with_datasources += 'panfrost'
|
||||||
160
src/panfrost/ds/pan_pps_driver.cc
Normal file
160
src/panfrost/ds/pan_pps_driver.cc
Normal file
|
|
@ -0,0 +1,160 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2019-2021 Collabora, Ltd.
|
||||||
|
* Author: Antonio Caggiano <antonio.caggiano@collabora.com>
|
||||||
|
* Author: Rohan Garg <rohan.garg@collabora.com>
|
||||||
|
* Author: Robert Beckett <bob.beckett@collabora.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "pan_pps_driver.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <perfetto.h>
|
||||||
|
#include <xf86drm.h>
|
||||||
|
|
||||||
|
#include <drm-uapi/panfrost_drm.h>
|
||||||
|
#include <perf/pan_perf.h>
|
||||||
|
#include <util/macros.h>
|
||||||
|
|
||||||
|
#include <pps/pps.h>
|
||||||
|
#include <pps/pps_algorithm.h>
|
||||||
|
|
||||||
|
namespace pps
|
||||||
|
{
|
||||||
|
PanfrostDriver::PanfrostDriver()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PanfrostDriver::~PanfrostDriver()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t PanfrostDriver::get_min_sampling_period_ns()
|
||||||
|
{
|
||||||
|
return 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t find_id_within_group(uint32_t counter_id, const struct panfrost_perf_config *cfg)
|
||||||
|
{
|
||||||
|
for (uint32_t cat_id = 0; cat_id < cfg->n_categories; ++cat_id) {
|
||||||
|
const struct panfrost_perf_category *cat = &cfg->categories[cat_id];
|
||||||
|
if (counter_id < cat->n_counters) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
counter_id -= cat->n_counters;
|
||||||
|
}
|
||||||
|
|
||||||
|
return counter_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<std::vector<CounterGroup>, std::vector<Counter>>
|
||||||
|
PanfrostDriver::create_available_counters(const PanfrostPerf &perf)
|
||||||
|
{
|
||||||
|
std::pair<std::vector<CounterGroup>, std::vector<Counter>> ret;
|
||||||
|
auto &[groups, counters] = ret;
|
||||||
|
|
||||||
|
size_t cid = 0;
|
||||||
|
|
||||||
|
for (uint32_t gid = 0; gid < perf.perf->cfg->n_categories; ++gid) {
|
||||||
|
const auto &category = perf.perf->cfg->categories[gid];
|
||||||
|
CounterGroup group = {};
|
||||||
|
group.id = gid;
|
||||||
|
group.name = category.name;
|
||||||
|
|
||||||
|
for (; cid < category.n_counters; ++cid) {
|
||||||
|
Counter counter = {};
|
||||||
|
counter.id = cid;
|
||||||
|
counter.group = gid;
|
||||||
|
|
||||||
|
uint32_t id_within_group = find_id_within_group(cid, perf.perf->cfg);
|
||||||
|
counter.name = category.counters[id_within_group].name;
|
||||||
|
|
||||||
|
counter.set_getter([](const Counter &c, const Driver &d) {
|
||||||
|
auto &pan_driver = PanfrostDriver::into(d);
|
||||||
|
struct panfrost_perf *perf = pan_driver.perf->perf;
|
||||||
|
uint32_t id_within_group = find_id_within_group(c.id, perf->cfg);
|
||||||
|
const auto counter = &perf->cfg->categories[c.group].counters[id_within_group];
|
||||||
|
return int64_t(panfrost_perf_counter_read(counter, perf));
|
||||||
|
});
|
||||||
|
|
||||||
|
group.counters.push_back(cid);
|
||||||
|
|
||||||
|
counters.emplace_back(counter);
|
||||||
|
}
|
||||||
|
|
||||||
|
groups.push_back(group);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PanfrostDriver::init_perfcnt()
|
||||||
|
{
|
||||||
|
if (!dev) {
|
||||||
|
dev = std::make_unique<PanfrostDevice>(drm_device.fd);
|
||||||
|
}
|
||||||
|
if (!perf) {
|
||||||
|
perf = std::make_unique<PanfrostPerf>(*dev);
|
||||||
|
}
|
||||||
|
if (groups.empty() && counters.empty()) {
|
||||||
|
std::tie(groups, counters) = create_available_counters(*perf);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PanfrostDriver::enable_counter(const uint32_t counter_id)
|
||||||
|
{
|
||||||
|
enabled_counters.push_back(counters[counter_id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PanfrostDriver::enable_all_counters()
|
||||||
|
{
|
||||||
|
enabled_counters.resize(counters.size());
|
||||||
|
for (size_t i = 0; i < counters.size(); ++i) {
|
||||||
|
enabled_counters[i] = counters[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PanfrostDriver::enable_perfcnt(const uint64_t /* sampling_period_ns */)
|
||||||
|
{
|
||||||
|
auto res = perf->enable();
|
||||||
|
if (!check(res, "Failed to enable performance counters")) {
|
||||||
|
if (res == -ENOSYS) {
|
||||||
|
PERFETTO_FATAL("Please enable unstable ioctls with: modprobe panfrost unstable_ioctls=1");
|
||||||
|
}
|
||||||
|
PERFETTO_FATAL("Please verify graphics card");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PanfrostDriver::dump_perfcnt()
|
||||||
|
{
|
||||||
|
last_dump_ts = perfetto::base::GetBootTimeNs().count();
|
||||||
|
|
||||||
|
// Dump performance counters to buffer
|
||||||
|
if (!check(perf->dump(), "Failed to dump performance counters")) {
|
||||||
|
PERFETTO_ELOG("Skipping sample");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t PanfrostDriver::next()
|
||||||
|
{
|
||||||
|
auto ret = last_dump_ts;
|
||||||
|
last_dump_ts = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PanfrostDriver::disable_perfcnt()
|
||||||
|
{
|
||||||
|
perf->disable();
|
||||||
|
perf.reset();
|
||||||
|
dev.reset();
|
||||||
|
groups.clear();
|
||||||
|
counters.clear();
|
||||||
|
enabled_counters.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace pps
|
||||||
61
src/panfrost/ds/pan_pps_driver.h
Normal file
61
src/panfrost/ds/pan_pps_driver.h
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2020-2021 Collabora, Ltd.
|
||||||
|
* Author: Antonio Caggiano <antonio.caggiano@collabora.com>
|
||||||
|
* Author: Rohan Garg <rohan.garg@collabora.com>
|
||||||
|
* Author: Robert Beckett <bob.beckett@collabora.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <pps/pps_driver.h>
|
||||||
|
|
||||||
|
#include "pan_pps_perf.h"
|
||||||
|
|
||||||
|
namespace pps
|
||||||
|
{
|
||||||
|
/// @brief Panfrost implementation of PPS driver.
|
||||||
|
/// This driver queries the GPU through `drm/panfrost_drm.h`, using performance counters ioctls,
|
||||||
|
/// which can be enabled by setting a kernel parameter: `modprobe panfrost unstable_ioctls=1`.
|
||||||
|
/// The ioctl needs a buffer to copy data from kernel to user space.
|
||||||
|
class PanfrostDriver : public Driver
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static inline PanfrostDriver &into(Driver &dri);
|
||||||
|
static inline const PanfrostDriver &into(const Driver &dri);
|
||||||
|
|
||||||
|
/// @param A list of mali counter names
|
||||||
|
/// @return A pair with two lists: counter groups and available counters
|
||||||
|
static std::pair<std::vector<CounterGroup>, std::vector<Counter>> create_available_counters(
|
||||||
|
const PanfrostPerf& perf);
|
||||||
|
|
||||||
|
PanfrostDriver();
|
||||||
|
~PanfrostDriver();
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
uint64_t last_dump_ts = 0;
|
||||||
|
|
||||||
|
std::unique_ptr<PanfrostDevice> dev = nullptr;
|
||||||
|
std::unique_ptr<PanfrostPerf> perf = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
PanfrostDriver &PanfrostDriver::into(Driver &dri)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<PanfrostDriver &>(dri);
|
||||||
|
}
|
||||||
|
|
||||||
|
const PanfrostDriver &PanfrostDriver::into(const Driver &dri)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<const PanfrostDriver &>(dri);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace pps
|
||||||
89
src/panfrost/ds/pan_pps_perf.cc
Normal file
89
src/panfrost/ds/pan_pps_perf.cc
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
#include "pan_pps_perf.h"
|
||||||
|
|
||||||
|
#include <lib/pan_device.h>
|
||||||
|
#include <perf/pan_perf.h>
|
||||||
|
#include <util/ralloc.h>
|
||||||
|
#include <pps/pps.h>
|
||||||
|
|
||||||
|
namespace pps
|
||||||
|
{
|
||||||
|
PanfrostDevice::PanfrostDevice(int fd)
|
||||||
|
: ctx {ralloc_context(nullptr)}
|
||||||
|
, dev {reinterpret_cast<struct panfrost_device*>(new struct panfrost_device())}
|
||||||
|
{
|
||||||
|
assert(fd >= 0);
|
||||||
|
panfrost_open_device(ctx, fd, dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
PanfrostDevice::~PanfrostDevice()
|
||||||
|
{
|
||||||
|
if (ctx) {
|
||||||
|
panfrost_close_device(dev);
|
||||||
|
}
|
||||||
|
if (dev) {
|
||||||
|
delete dev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PanfrostDevice::PanfrostDevice(PanfrostDevice &&o)
|
||||||
|
: ctx {o.ctx}
|
||||||
|
, dev {o.dev}
|
||||||
|
{
|
||||||
|
o.ctx = nullptr;
|
||||||
|
o.dev = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
PanfrostDevice &PanfrostDevice::operator=(PanfrostDevice &&o)
|
||||||
|
{
|
||||||
|
std::swap(ctx, o.ctx);
|
||||||
|
std::swap(dev, o.dev);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
PanfrostPerf::PanfrostPerf(const PanfrostDevice& dev)
|
||||||
|
: perf {reinterpret_cast<struct panfrost_perf *>(rzalloc(nullptr, struct panfrost_perf))}
|
||||||
|
{
|
||||||
|
assert(perf);
|
||||||
|
assert(dev.dev);
|
||||||
|
panfrost_perf_init(perf, dev.dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
PanfrostPerf::~PanfrostPerf()
|
||||||
|
{
|
||||||
|
if (perf) {
|
||||||
|
panfrost_perf_disable(perf);
|
||||||
|
ralloc_free(perf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PanfrostPerf::PanfrostPerf(PanfrostPerf &&o)
|
||||||
|
: perf {o.perf}
|
||||||
|
{
|
||||||
|
o.perf = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
PanfrostPerf &PanfrostPerf::operator=(PanfrostPerf &&o)
|
||||||
|
{
|
||||||
|
std::swap(perf, o.perf);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PanfrostPerf::enable() const
|
||||||
|
{
|
||||||
|
assert(perf);
|
||||||
|
return panfrost_perf_enable(perf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PanfrostPerf::disable() const
|
||||||
|
{
|
||||||
|
assert(perf);
|
||||||
|
panfrost_perf_disable(perf);
|
||||||
|
}
|
||||||
|
|
||||||
|
int PanfrostPerf::dump() const
|
||||||
|
{
|
||||||
|
assert(perf);
|
||||||
|
return panfrost_perf_dump(perf);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace pps
|
||||||
50
src/panfrost/ds/pan_pps_perf.h
Normal file
50
src/panfrost/ds/pan_pps_perf.h
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2021 Collabora, Ltd.
|
||||||
|
* Author: Antonio Caggiano <antonio.caggiano@collabora.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct panfrost_device;
|
||||||
|
struct panfrost_perf;
|
||||||
|
|
||||||
|
namespace pps
|
||||||
|
{
|
||||||
|
class PanfrostDevice
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PanfrostDevice(int fd);
|
||||||
|
~PanfrostDevice();
|
||||||
|
|
||||||
|
PanfrostDevice(const PanfrostDevice &) = delete;
|
||||||
|
PanfrostDevice &operator=(const PanfrostDevice &) = delete;
|
||||||
|
|
||||||
|
PanfrostDevice(PanfrostDevice&&);
|
||||||
|
PanfrostDevice& operator=(PanfrostDevice&&);
|
||||||
|
|
||||||
|
void *ctx = nullptr;
|
||||||
|
struct panfrost_device* dev = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PanfrostPerf
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PanfrostPerf(const PanfrostDevice& dev);
|
||||||
|
~PanfrostPerf();
|
||||||
|
|
||||||
|
PanfrostPerf(const PanfrostPerf &) = delete;
|
||||||
|
PanfrostPerf &operator=(const PanfrostPerf &) = delete;
|
||||||
|
|
||||||
|
PanfrostPerf(PanfrostPerf&&);
|
||||||
|
PanfrostPerf& operator=(PanfrostPerf&&);
|
||||||
|
|
||||||
|
int enable() const;
|
||||||
|
void disable() const;
|
||||||
|
int dump() const;
|
||||||
|
|
||||||
|
struct panfrost_perf *perf = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace pps
|
||||||
|
|
@ -70,3 +70,7 @@ bifrost_compiler = executable(
|
||||||
if with_panfrost_vk
|
if with_panfrost_vk
|
||||||
subdir('vulkan')
|
subdir('vulkan')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if with_perfetto and (with_datasources.contains('panfrost') or with_datasources.contains('auto'))
|
||||||
|
subdir('ds')
|
||||||
|
endif
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,10 @@
|
||||||
#include "intel/ds/intel_pps_driver.h"
|
#include "intel/ds/intel_pps_driver.h"
|
||||||
#endif // PPS_INTEL
|
#endif // PPS_INTEL
|
||||||
|
|
||||||
|
#ifdef PPS_PANFROST
|
||||||
|
#include "panfrost/ds/pan_pps_driver.h"
|
||||||
|
#endif // PPS_PANFROST
|
||||||
|
|
||||||
#include "pps.h"
|
#include "pps.h"
|
||||||
#include "pps_algorithm.h"
|
#include "pps_algorithm.h"
|
||||||
|
|
||||||
|
|
@ -38,6 +42,10 @@ std::unordered_map<std::string, std::unique_ptr<Driver>> create_supported_driver
|
||||||
map.emplace("i915", std::make_unique<IntelDriver>());
|
map.emplace("i915", std::make_unique<IntelDriver>());
|
||||||
#endif // PPS_INTEL
|
#endif // PPS_INTEL
|
||||||
|
|
||||||
|
#ifdef PPS_PANFROST
|
||||||
|
map.emplace("panfrost", std::make_unique<PanfrostDriver>());
|
||||||
|
#endif // PPS_PANFROST
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue