1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker * Copyright © 2020-2021 Collabora, Ltd.
3*61046927SAndroid Build Coastguard Worker * Author: Antonio Caggiano <[email protected]>
4*61046927SAndroid Build Coastguard Worker *
5*61046927SAndroid Build Coastguard Worker * SPDX-License-Identifier: MIT
6*61046927SAndroid Build Coastguard Worker */
7*61046927SAndroid Build Coastguard Worker
8*61046927SAndroid Build Coastguard Worker #include <pps/pps_driver.h>
9*61046927SAndroid Build Coastguard Worker
10*61046927SAndroid Build Coastguard Worker #include <charconv>
11*61046927SAndroid Build Coastguard Worker #include <cstdlib>
12*61046927SAndroid Build Coastguard Worker #include <cstring>
13*61046927SAndroid Build Coastguard Worker #include <optional>
14*61046927SAndroid Build Coastguard Worker #include <thread>
15*61046927SAndroid Build Coastguard Worker
16*61046927SAndroid Build Coastguard Worker #include <docopt/docopt.h>
17*61046927SAndroid Build Coastguard Worker
18*61046927SAndroid Build Coastguard Worker static const char *USAGE =
19*61046927SAndroid Build Coastguard Worker R"(pps-config
20*61046927SAndroid Build Coastguard Worker
21*61046927SAndroid Build Coastguard Worker Usage:
22*61046927SAndroid Build Coastguard Worker pps-config info
23*61046927SAndroid Build Coastguard Worker pps-config dump [--gpu=<n>] [--ids=<n>] [--sec=<n>]
24*61046927SAndroid Build Coastguard Worker pps-config groups [--gpu=<n>]
25*61046927SAndroid Build Coastguard Worker pps-config counters [--gpu=<n>]
26*61046927SAndroid Build Coastguard Worker pps-config (-h | --help)
27*61046927SAndroid Build Coastguard Worker pps-config --version
28*61046927SAndroid Build Coastguard Worker
29*61046927SAndroid Build Coastguard Worker Options:
30*61046927SAndroid Build Coastguard Worker -h --help Show this screen.
31*61046927SAndroid Build Coastguard Worker --version Show version.
32*61046927SAndroid Build Coastguard Worker --gpu=<n> GPU number to query [default: 0].
33*61046927SAndroid Build Coastguard Worker --ids=<n> Comma separated list of numbers.
34*61046927SAndroid Build Coastguard Worker --sec=<n> Seconds to wait before dumping performance counters [default: 1].
35*61046927SAndroid Build Coastguard Worker )";
36*61046927SAndroid Build Coastguard Worker
37*61046927SAndroid Build Coastguard Worker // Tool running mode
38*61046927SAndroid Build Coastguard Worker enum class Mode {
39*61046927SAndroid Build Coastguard Worker // Show help message
40*61046927SAndroid Build Coastguard Worker Help,
41*61046927SAndroid Build Coastguard Worker
42*61046927SAndroid Build Coastguard Worker // Show system information
43*61046927SAndroid Build Coastguard Worker Info,
44*61046927SAndroid Build Coastguard Worker
45*61046927SAndroid Build Coastguard Worker // Show list of available counters
46*61046927SAndroid Build Coastguard Worker Counters,
47*61046927SAndroid Build Coastguard Worker
48*61046927SAndroid Build Coastguard Worker // Groups
49*61046927SAndroid Build Coastguard Worker Groups,
50*61046927SAndroid Build Coastguard Worker
51*61046927SAndroid Build Coastguard Worker // Dump performance counters
52*61046927SAndroid Build Coastguard Worker Dump,
53*61046927SAndroid Build Coastguard Worker };
54*61046927SAndroid Build Coastguard Worker
split(const std::string & list,const std::string & separator)55*61046927SAndroid Build Coastguard Worker std::vector<std::string_view> split(const std::string &list, const std::string &separator)
56*61046927SAndroid Build Coastguard Worker {
57*61046927SAndroid Build Coastguard Worker std::vector<std::string_view> ret;
58*61046927SAndroid Build Coastguard Worker std::string_view list_view = list;
59*61046927SAndroid Build Coastguard Worker while (!list_view.empty()) {
60*61046927SAndroid Build Coastguard Worker size_t pos = list_view.find(separator);
61*61046927SAndroid Build Coastguard Worker if (pos == std::string::npos) {
62*61046927SAndroid Build Coastguard Worker ret.push_back(list_view);
63*61046927SAndroid Build Coastguard Worker break;
64*61046927SAndroid Build Coastguard Worker }
65*61046927SAndroid Build Coastguard Worker ret.push_back(list_view.substr(0, pos));
66*61046927SAndroid Build Coastguard Worker list_view = list_view.substr(pos + separator.length(), list_view.length());
67*61046927SAndroid Build Coastguard Worker }
68*61046927SAndroid Build Coastguard Worker return ret;
69*61046927SAndroid Build Coastguard Worker }
70*61046927SAndroid Build Coastguard Worker
to_counter_id(const std::string_view & view)71*61046927SAndroid Build Coastguard Worker std::optional<uint32_t> to_counter_id(const std::string_view &view)
72*61046927SAndroid Build Coastguard Worker {
73*61046927SAndroid Build Coastguard Worker uint32_t counter_id = 0;
74*61046927SAndroid Build Coastguard Worker
75*61046927SAndroid Build Coastguard Worker auto res = std::from_chars(view.data(), view.data() + view.size(), counter_id);
76*61046927SAndroid Build Coastguard Worker if (res.ec == std::errc::invalid_argument) {
77*61046927SAndroid Build Coastguard Worker return std::nullopt;
78*61046927SAndroid Build Coastguard Worker }
79*61046927SAndroid Build Coastguard Worker
80*61046927SAndroid Build Coastguard Worker return counter_id;
81*61046927SAndroid Build Coastguard Worker }
82*61046927SAndroid Build Coastguard Worker
main(int argc,const char ** argv)83*61046927SAndroid Build Coastguard Worker int main(int argc, const char **argv)
84*61046927SAndroid Build Coastguard Worker {
85*61046927SAndroid Build Coastguard Worker using namespace pps;
86*61046927SAndroid Build Coastguard Worker
87*61046927SAndroid Build Coastguard Worker Mode mode = Mode::Help;
88*61046927SAndroid Build Coastguard Worker auto secs = std::chrono::seconds(1);
89*61046927SAndroid Build Coastguard Worker uint32_t gpu_num = 0;
90*61046927SAndroid Build Coastguard Worker std::vector<uint32_t> counter_ids;
91*61046927SAndroid Build Coastguard Worker
92*61046927SAndroid Build Coastguard Worker auto args =
93*61046927SAndroid Build Coastguard Worker docopt::docopt(USAGE, {std::next(argv), std::next(argv, argc)}, true, "pps-config 0.3");
94*61046927SAndroid Build Coastguard Worker
95*61046927SAndroid Build Coastguard Worker if (args["info"].asBool()) {
96*61046927SAndroid Build Coastguard Worker mode = Mode::Info;
97*61046927SAndroid Build Coastguard Worker }
98*61046927SAndroid Build Coastguard Worker
99*61046927SAndroid Build Coastguard Worker if (args["dump"].asBool()) {
100*61046927SAndroid Build Coastguard Worker mode = Mode::Dump;
101*61046927SAndroid Build Coastguard Worker }
102*61046927SAndroid Build Coastguard Worker
103*61046927SAndroid Build Coastguard Worker if (args["--gpu"]) {
104*61046927SAndroid Build Coastguard Worker gpu_num = static_cast<uint32_t>(args["--gpu"].asLong());
105*61046927SAndroid Build Coastguard Worker }
106*61046927SAndroid Build Coastguard Worker
107*61046927SAndroid Build Coastguard Worker if (args["--ids"]) {
108*61046927SAndroid Build Coastguard Worker auto comma_separated_list = args["--ids"].asString();
109*61046927SAndroid Build Coastguard Worker std::vector<std::string_view> ids_list = split(comma_separated_list, ",");
110*61046927SAndroid Build Coastguard Worker
111*61046927SAndroid Build Coastguard Worker for (auto &id : ids_list) {
112*61046927SAndroid Build Coastguard Worker if (auto counter_id = to_counter_id(id)) {
113*61046927SAndroid Build Coastguard Worker counter_ids.push_back(*counter_id);
114*61046927SAndroid Build Coastguard Worker } else {
115*61046927SAndroid Build Coastguard Worker fprintf(stderr, "Failed to parse counter ids: %s\n", comma_separated_list.c_str());
116*61046927SAndroid Build Coastguard Worker return EXIT_FAILURE;
117*61046927SAndroid Build Coastguard Worker }
118*61046927SAndroid Build Coastguard Worker }
119*61046927SAndroid Build Coastguard Worker }
120*61046927SAndroid Build Coastguard Worker
121*61046927SAndroid Build Coastguard Worker if (args["--sec"]) {
122*61046927SAndroid Build Coastguard Worker secs = std::chrono::seconds(args["--sec"].asLong());
123*61046927SAndroid Build Coastguard Worker }
124*61046927SAndroid Build Coastguard Worker
125*61046927SAndroid Build Coastguard Worker if (args["groups"].asBool()) {
126*61046927SAndroid Build Coastguard Worker mode = Mode::Groups;
127*61046927SAndroid Build Coastguard Worker }
128*61046927SAndroid Build Coastguard Worker
129*61046927SAndroid Build Coastguard Worker if (args["counters"].asBool()) {
130*61046927SAndroid Build Coastguard Worker mode = Mode::Counters;
131*61046927SAndroid Build Coastguard Worker }
132*61046927SAndroid Build Coastguard Worker
133*61046927SAndroid Build Coastguard Worker // Docopt shows the help message for us
134*61046927SAndroid Build Coastguard Worker if (mode == Mode::Help) {
135*61046927SAndroid Build Coastguard Worker return EXIT_SUCCESS;
136*61046927SAndroid Build Coastguard Worker }
137*61046927SAndroid Build Coastguard Worker
138*61046927SAndroid Build Coastguard Worker switch (mode) {
139*61046927SAndroid Build Coastguard Worker default:
140*61046927SAndroid Build Coastguard Worker break;
141*61046927SAndroid Build Coastguard Worker case Mode::Info: {
142*61046927SAndroid Build Coastguard Worker // Header: device name, and whether it is supported or not
143*61046927SAndroid Build Coastguard Worker printf("#%4s %16s %16s\n", "num", "device", "support");
144*61046927SAndroid Build Coastguard Worker
145*61046927SAndroid Build Coastguard Worker auto devices = DrmDevice::create_all();
146*61046927SAndroid Build Coastguard Worker for (auto &device : devices) {
147*61046927SAndroid Build Coastguard Worker auto gpu_num = device.gpu_num;
148*61046927SAndroid Build Coastguard Worker auto name = device.name;
149*61046927SAndroid Build Coastguard Worker auto driver = Driver::get_driver(std::move(device));
150*61046927SAndroid Build Coastguard Worker printf(" %4u %16s %16s\n", gpu_num, name.c_str(), driver ? "yes" : "no");
151*61046927SAndroid Build Coastguard Worker }
152*61046927SAndroid Build Coastguard Worker
153*61046927SAndroid Build Coastguard Worker break;
154*61046927SAndroid Build Coastguard Worker }
155*61046927SAndroid Build Coastguard Worker case Mode::Dump: {
156*61046927SAndroid Build Coastguard Worker if (auto device = DrmDevice::create(gpu_num)) {
157*61046927SAndroid Build Coastguard Worker if (auto driver = Driver::get_driver(std::move(device.value()))) {
158*61046927SAndroid Build Coastguard Worker driver->init_perfcnt();
159*61046927SAndroid Build Coastguard Worker
160*61046927SAndroid Build Coastguard Worker // Enable counters
161*61046927SAndroid Build Coastguard Worker if (counter_ids.empty()) {
162*61046927SAndroid Build Coastguard Worker driver->enable_all_counters();
163*61046927SAndroid Build Coastguard Worker } else {
164*61046927SAndroid Build Coastguard Worker for (auto id : counter_ids) {
165*61046927SAndroid Build Coastguard Worker driver->enable_counter(id);
166*61046927SAndroid Build Coastguard Worker }
167*61046927SAndroid Build Coastguard Worker }
168*61046927SAndroid Build Coastguard Worker
169*61046927SAndroid Build Coastguard Worker driver->enable_perfcnt(std::chrono::nanoseconds(secs).count());
170*61046927SAndroid Build Coastguard Worker std::this_thread::sleep_for(std::chrono::seconds(secs));
171*61046927SAndroid Build Coastguard Worker
172*61046927SAndroid Build Coastguard Worker // Try dumping until it succeeds
173*61046927SAndroid Build Coastguard Worker while (!driver->dump_perfcnt())
174*61046927SAndroid Build Coastguard Worker ;
175*61046927SAndroid Build Coastguard Worker // Try collecting samples until it succeeds
176*61046927SAndroid Build Coastguard Worker while (!driver->next())
177*61046927SAndroid Build Coastguard Worker ;
178*61046927SAndroid Build Coastguard Worker
179*61046927SAndroid Build Coastguard Worker printf("#%32s %32s\n", "counter", "value");
180*61046927SAndroid Build Coastguard Worker for (auto &counter : driver->enabled_counters) {
181*61046927SAndroid Build Coastguard Worker printf(" %32s ", counter.name.c_str());
182*61046927SAndroid Build Coastguard Worker auto value = counter.get_value(*driver);
183*61046927SAndroid Build Coastguard Worker if (auto d_val = std::get_if<double>(&value)) {
184*61046927SAndroid Build Coastguard Worker printf("%32f\n", *d_val);
185*61046927SAndroid Build Coastguard Worker } else if (auto i_val = std::get_if<int64_t>(&value))
186*61046927SAndroid Build Coastguard Worker printf("%32li\n", *i_val);
187*61046927SAndroid Build Coastguard Worker else {
188*61046927SAndroid Build Coastguard Worker printf("%32s\n", "error");
189*61046927SAndroid Build Coastguard Worker }
190*61046927SAndroid Build Coastguard Worker }
191*61046927SAndroid Build Coastguard Worker }
192*61046927SAndroid Build Coastguard Worker }
193*61046927SAndroid Build Coastguard Worker break;
194*61046927SAndroid Build Coastguard Worker }
195*61046927SAndroid Build Coastguard Worker case Mode::Groups: {
196*61046927SAndroid Build Coastguard Worker if (auto device = DrmDevice::create(gpu_num)) {
197*61046927SAndroid Build Coastguard Worker if (auto driver = Driver::get_driver(std::move(device.value()))) {
198*61046927SAndroid Build Coastguard Worker driver->init_perfcnt();
199*61046927SAndroid Build Coastguard Worker printf("#%4s %32s\n", "id", "name");
200*61046927SAndroid Build Coastguard Worker
201*61046927SAndroid Build Coastguard Worker for (auto &group : driver->groups) {
202*61046927SAndroid Build Coastguard Worker printf(" %4u %32s\n", group.id, group.name.c_str());
203*61046927SAndroid Build Coastguard Worker }
204*61046927SAndroid Build Coastguard Worker }
205*61046927SAndroid Build Coastguard Worker }
206*61046927SAndroid Build Coastguard Worker
207*61046927SAndroid Build Coastguard Worker break;
208*61046927SAndroid Build Coastguard Worker }
209*61046927SAndroid Build Coastguard Worker case Mode::Counters: {
210*61046927SAndroid Build Coastguard Worker if (auto device = DrmDevice::create(gpu_num)) {
211*61046927SAndroid Build Coastguard Worker if (auto driver = Driver::get_driver(std::move(device.value()))) {
212*61046927SAndroid Build Coastguard Worker driver->init_perfcnt();
213*61046927SAndroid Build Coastguard Worker printf("#%4s %32s\n", "id", "name");
214*61046927SAndroid Build Coastguard Worker
215*61046927SAndroid Build Coastguard Worker for (uint32_t i = 0; i < driver->counters.size(); ++i) {
216*61046927SAndroid Build Coastguard Worker auto &counter = driver->counters[i];
217*61046927SAndroid Build Coastguard Worker printf(" %4u %32s\n", counter.id, counter.name.c_str());
218*61046927SAndroid Build Coastguard Worker }
219*61046927SAndroid Build Coastguard Worker }
220*61046927SAndroid Build Coastguard Worker }
221*61046927SAndroid Build Coastguard Worker
222*61046927SAndroid Build Coastguard Worker break;
223*61046927SAndroid Build Coastguard Worker }
224*61046927SAndroid Build Coastguard Worker } // switch
225*61046927SAndroid Build Coastguard Worker
226*61046927SAndroid Build Coastguard Worker return EXIT_SUCCESS;
227*61046927SAndroid Build Coastguard Worker }
228