Mesa (main): pps: Panfrost pps driver
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Tue Jul 13 11:14:44 UTC 2021
Module: Mesa
Branch: main
Commit: 513d1baaea5eeef3d9bcfdf9f6e2180db8924236
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=513d1baaea5eeef3d9bcfdf9f6e2180db8924236
Author: Antonio Caggiano <antonio.caggiano at collabora.com>
Date: Thu Mar 18 19:29:33 2021 +0100
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 at collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10215>
---
src/panfrost/ds/.clang-format | 21 +++++
src/panfrost/ds/meson.build | 31 ++++++++
src/panfrost/ds/pan_pps_driver.cc | 160 ++++++++++++++++++++++++++++++++++++++
src/panfrost/ds/pan_pps_driver.h | 61 +++++++++++++++
src/panfrost/ds/pan_pps_perf.cc | 89 +++++++++++++++++++++
src/panfrost/ds/pan_pps_perf.h | 50 ++++++++++++
src/panfrost/meson.build | 4 +
src/tool/pps/pps_driver.cc | 8 ++
8 files changed, 424 insertions(+)
diff --git a/src/panfrost/ds/.clang-format b/src/panfrost/ds/.clang-format
new file mode 100644
index 00000000000..41203078b2b
--- /dev/null
+++ b/src/panfrost/ds/.clang-format
@@ -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'
diff --git a/src/panfrost/ds/meson.build b/src/panfrost/ds/meson.build
new file mode 100644
index 00000000000..a31a71561f2
--- /dev/null
+++ b/src/panfrost/ds/meson.build
@@ -0,0 +1,31 @@
+# Copyright © 2020 Collabora, Ltd.
+# Author: Antonio Caggiano <antonio.caggiano at collabora.com>
+# Author: Robert Beckett <bob.beckett at 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'
diff --git a/src/panfrost/ds/pan_pps_driver.cc b/src/panfrost/ds/pan_pps_driver.cc
new file mode 100644
index 00000000000..fbe9263748d
--- /dev/null
+++ b/src/panfrost/ds/pan_pps_driver.cc
@@ -0,0 +1,160 @@
+/*
+ * Copyright © 2019-2021 Collabora, Ltd.
+ * Author: Antonio Caggiano <antonio.caggiano at collabora.com>
+ * Author: Rohan Garg <rohan.garg at collabora.com>
+ * Author: Robert Beckett <bob.beckett at 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
diff --git a/src/panfrost/ds/pan_pps_driver.h b/src/panfrost/ds/pan_pps_driver.h
new file mode 100644
index 00000000000..de764b18aae
--- /dev/null
+++ b/src/panfrost/ds/pan_pps_driver.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright © 2020-2021 Collabora, Ltd.
+ * Author: Antonio Caggiano <antonio.caggiano at collabora.com>
+ * Author: Rohan Garg <rohan.garg at collabora.com>
+ * Author: Robert Beckett <bob.beckett at 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
diff --git a/src/panfrost/ds/pan_pps_perf.cc b/src/panfrost/ds/pan_pps_perf.cc
new file mode 100644
index 00000000000..e8d4a85cf60
--- /dev/null
+++ b/src/panfrost/ds/pan_pps_perf.cc
@@ -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
diff --git a/src/panfrost/ds/pan_pps_perf.h b/src/panfrost/ds/pan_pps_perf.h
new file mode 100644
index 00000000000..48ae2f58e53
--- /dev/null
+++ b/src/panfrost/ds/pan_pps_perf.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright © 2021 Collabora, Ltd.
+ * Author: Antonio Caggiano <antonio.caggiano at 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
diff --git a/src/panfrost/meson.build b/src/panfrost/meson.build
index cd6febe7877..ae4ea71b77c 100644
--- a/src/panfrost/meson.build
+++ b/src/panfrost/meson.build
@@ -70,3 +70,7 @@ bifrost_compiler = executable(
if with_panfrost_vk
subdir('vulkan')
endif
+
+if with_perfetto and (with_datasources.contains('panfrost') or with_datasources.contains('auto'))
+ subdir('ds')
+endif
diff --git a/src/tool/pps/pps_driver.cc b/src/tool/pps/pps_driver.cc
index 239c9666dba..e04c36e6520 100644
--- a/src/tool/pps/pps_driver.cc
+++ b/src/tool/pps/pps_driver.cc
@@ -21,6 +21,10 @@
#include "intel/ds/intel_pps_driver.h"
#endif // PPS_INTEL
+#ifdef PPS_PANFROST
+#include "panfrost/ds/pan_pps_driver.h"
+#endif // PPS_PANFROST
+
#include "pps.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>());
#endif // PPS_INTEL
+#ifdef PPS_PANFROST
+ map.emplace("panfrost", std::make_unique<PanfrostDriver>());
+#endif // PPS_PANFROST
+
return map;
}
More information about the mesa-commit
mailing list