Mesa (main): pps: Gfx-pps config tool

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri May 7 14:04:32 UTC 2021


Module: Mesa
Branch: main
Commit: 948f780915502f8f4ddce7b2540fdf8db2d7703c
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=948f780915502f8f4ddce7b2540fdf8db2d7703c

Author: Antonio Caggiano <antonio.caggiano at collabora.com>
Date:   Tue Mar 30 18:03:33 2021 +0200

pps: Gfx-pps config tool

Add helpful tool to query pps capabilites such as supported devices,
counters and counter groups, and to dump counter values to stdout.

Signed-off-by: Antonio Caggiano <antonio.caggiano at collabora.com>
Acked-by: Emma Anholt <emma at anholt.net>
Reviewed-by: Rob Clark <robdclark at chromium.org>
Reviewed-by: John Bates <jbates at chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9652>

---

 src/tool/pps/meson.build   |  17 ++++
 src/tool/pps/pps_config.cc | 227 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 244 insertions(+)

diff --git a/src/tool/pps/meson.build b/src/tool/pps/meson.build
index c379a74c847..9ca5e57e003 100644
--- a/src/tool/pps/meson.build
+++ b/src/tool/pps/meson.build
@@ -42,3 +42,20 @@ executable(
   cpp_args: '-std=c++17',
   install: true
 )
+
+config_sources = [
+  'pps_config.cc'
+]
+
+dep_docopt = dependency('docopt', required: false)
+
+if dep_docopt.found()
+  executable(
+    'pps-config',
+    sources: config_sources,
+    include_directories: [include_pps, inc_src],
+    dependencies: [dep_pps, dep_docopt],
+    cpp_args: '-std=c++17',
+    install: true
+  )
+endif
diff --git a/src/tool/pps/pps_config.cc b/src/tool/pps/pps_config.cc
new file mode 100644
index 00000000000..7d8fb2caeb0
--- /dev/null
+++ b/src/tool/pps/pps_config.cc
@@ -0,0 +1,227 @@
+/*
+ * Copyright © 2020-2021 Collabora, Ltd.
+ * Author: Antonio Caggiano <antonio.caggiano at collabora.com>
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include <pps/pps_driver.h>
+
+#include <charconv>
+#include <cstdlib>
+#include <cstring>
+#include <optional>
+#include <thread>
+
+#include <docopt/docopt.h>
+
+static const char *USAGE =
+   R"(pps-config
+
+  Usage:
+	pps-config info
+	pps-config dump [--gpu=<n>] [--ids=<n>] [--sec=<n>]
+	pps-config groups [--gpu=<n>]
+	pps-config counters [--gpu=<n>]
+	pps-config (-h | --help)
+	pps-config --version
+
+  Options:
+	-h --help  Show this screen.
+	--version  Show version.
+	--gpu=<n>  GPU number to query [default: 0].
+	--ids=<n>  Comma separated list of numbers.
+	--sec=<n>  Seconds to wait before dumping performance counters [default: 1].
+)";
+
+// Tool running mode
+enum class Mode {
+   // Show help message
+   Help,
+
+   // Show system information
+   Info,
+
+   // Show list of available counters
+   Counters,
+
+   // Groups
+   Groups,
+
+   // Dump performance counters
+   Dump,
+};
+
+std::vector<std::string_view> split(const std::string &list, const std::string &separator)
+{
+   std::vector<std::string_view> ret;
+   std::string_view list_view = list;
+   while (!list_view.empty()) {
+      size_t pos = list_view.find(separator);
+      if (pos == std::string::npos) {
+         ret.push_back(list_view);
+         break;
+      }
+      ret.push_back(list_view.substr(0, pos));
+      list_view = list_view.substr(pos + separator.length(), list_view.length());
+   }
+   return ret;
+}
+
+std::optional<uint32_t> to_counter_id(const std::string_view &view)
+{
+   uint32_t counter_id = 0;
+
+   auto res = std::from_chars(view.data(), view.data() + view.size(), counter_id);
+   if (res.ec == std::errc::invalid_argument) {
+      return std::nullopt;
+   }
+
+   return counter_id;
+}
+
+int main(int argc, const char **argv)
+{
+   using namespace pps;
+
+   Mode mode = Mode::Help;
+   auto secs = std::chrono::seconds(1);
+   uint32_t gpu_num = 0;
+   std::vector<uint32_t> counter_ids;
+
+   auto args =
+      docopt::docopt(USAGE, {std::next(argv), std::next(argv, argc)}, true, "pps-config 0.3");
+
+   if (args["info"].asBool()) {
+      mode = Mode::Info;
+   }
+
+   if (args["dump"].asBool()) {
+      mode = Mode::Dump;
+   }
+
+   if (args["--gpu"]) {
+      gpu_num = static_cast<uint32_t>(args["--gpu"].asLong());
+   }
+
+   if (args["--ids"]) {
+      auto comma_separated_list = args["--ids"].asString();
+      std::vector<std::string_view> ids_list = split(comma_separated_list, ",");
+
+      for (auto &id : ids_list) {
+         if (auto counter_id = to_counter_id(id)) {
+            counter_ids.push_back(*counter_id);
+         } else {
+            fprintf(stderr, "Failed to parse counter ids: %s\n", comma_separated_list.c_str());
+            return EXIT_FAILURE;
+         }
+      }
+   }
+
+   if (args["--sec"]) {
+      secs = std::chrono::seconds(args["--sec"].asLong());
+   }
+
+   if (args["groups"].asBool()) {
+      mode = Mode::Groups;
+   }
+
+   if (args["counters"].asBool()) {
+      mode = Mode::Counters;
+   }
+
+   // Docopt shows the help message for us
+   if (mode == Mode::Help) {
+      return EXIT_SUCCESS;
+   }
+
+   switch (mode) {
+   default:
+      break;
+   case Mode::Info: {
+      // Header: device name, and whether it is supported or not
+      printf("#%4s %16s %16s\n", "num", "device", "support");
+
+      auto devices = DrmDevice::create_all();
+      for (auto &device : devices) {
+         auto gpu_num = device.gpu_num;
+         auto name = device.name;
+         auto driver = Driver::get_driver(std::move(device));
+         printf(" %4u %16s %16s\n", gpu_num, name.c_str(), driver ? "yes" : "no");
+      }
+
+      break;
+   }
+   case Mode::Dump: {
+      if (auto device = DrmDevice::create(gpu_num)) {
+         if (auto driver = Driver::get_driver(std::move(device.value()))) {
+            driver->init_perfcnt();
+
+            // Enable counters
+            if (counter_ids.empty()) {
+               driver->enable_all_counters();
+            } else {
+               for (auto id : counter_ids) {
+                  driver->enable_counter(id);
+               }
+            }
+
+            driver->enable_perfcnt(std::chrono::nanoseconds(secs).count());
+            std::this_thread::sleep_for(std::chrono::seconds(secs));
+
+            // Try dumping until it succeeds
+            while (!driver->dump_perfcnt())
+               ;
+            // Try collecting samples until it succeeds
+            while (!driver->next())
+               ;
+
+            printf("#%32s %32s\n", "counter", "value");
+            for (auto &counter : driver->enabled_counters) {
+               printf(" %32s ", counter.name.c_str());
+               auto value = counter.get_value(*driver);
+               if (auto d_val = std::get_if<double>(&value)) {
+                  printf("%32f\n", *d_val);
+               } else if (auto i_val = std::get_if<int64_t>(&value))
+                  printf("%32li\n", *i_val);
+               else {
+                  printf("%32s\n", "error");
+               }
+            }
+         }
+      }
+      break;
+   }
+   case Mode::Groups: {
+      if (auto device = DrmDevice::create(gpu_num)) {
+         if (auto driver = Driver::get_driver(std::move(device.value()))) {
+            driver->init_perfcnt();
+            printf("#%4s %32s\n", "id", "name");
+
+            for (auto &group : driver->groups) {
+               printf(" %4u %32s\n", group.id, group.name.c_str());
+            }
+         }
+      }
+
+      break;
+   }
+   case Mode::Counters: {
+      if (auto device = DrmDevice::create(gpu_num)) {
+         if (auto driver = Driver::get_driver(std::move(device.value()))) {
+            driver->init_perfcnt();
+            printf("#%4s %32s\n", "id", "name");
+
+            for (uint32_t i = 0; i < driver->counters.size(); ++i) {
+               auto &counter = driver->counters[i];
+               printf(" %4u %32s\n", counter.id, counter.name.c_str());
+            }
+         }
+      }
+
+      break;
+   }
+   } // switch
+
+   return EXIT_SUCCESS;
+}



More information about the mesa-commit mailing list