Edit

IABSD.fr/xenocara/lib/mesa/src/tool/pps/pps_config.cc

Branch :

  • Show log

    Commit

  • Author : jsg
    Date : 2022-02-24 01:51:18
    Hash : 50b4ee55
    Message : Import Mesa 21.3.7

  • lib/mesa/src/tool/pps/pps_config.cc
  • /*
     * Copyright © 2020-2021 Collabora, Ltd.
     * Author: Antonio Caggiano <antonio.caggiano@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;
    }