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