blob: 174a14080eff06fef2db9aa841879e8c288f4e4d [file] [log] [blame]
John Reck94c40fe2014-10-08 09:28:43 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
sergeyv7dc370b2016-06-17 11:21:11 -070017#include "tests/common/LeakChecker.h"
Chris Craik27e58b42015-12-07 10:01:38 -080018#include "tests/common/TestScene.h"
John Reck94c40fe2014-10-08 09:28:43 -070019
John Reck1bcacfd2017-11-03 10:12:19 -070020#include "Properties.h"
Seigo Nonakab6e20132016-11-14 14:07:41 +090021#include "hwui/Typeface.h"
John Reck6104cea2019-01-10 14:37:17 -080022#include "HardwareBitmapUploader.h"
23#include "renderthread/RenderProxy.h"
John Recke248bd12015-08-05 13:53:53 -070024
John Reck1bcacfd2017-11-03 10:12:19 -070025#include <benchmark/benchmark.h>
John Reckb7dd29e2015-10-06 13:28:17 -070026#include <getopt.h>
John Reck1bcacfd2017-11-03 10:12:19 -070027#include <pthread.h>
John Recke702c9c2015-10-07 10:26:02 -070028#include <stdio.h>
John Recke702c9c2015-10-07 10:26:02 -070029#include <unistd.h>
John Reck1bcacfd2017-11-03 10:12:19 -070030#include <string>
John Recke702c9c2015-10-07 10:26:02 -070031#include <unordered_map>
John Reckb7dd29e2015-10-06 13:28:17 -070032#include <vector>
John Reck7f2e5e32015-05-05 11:00:53 -070033
John Reck682573c2015-10-30 10:37:35 -070034#include <errno.h>
John Reck1bcacfd2017-11-03 10:12:19 -070035#include <fcntl.h>
36#include <sys/stat.h>
37#include <sys/types.h>
John Reck682573c2015-10-30 10:37:35 -070038
John Reck94c40fe2014-10-08 09:28:43 -070039using namespace android;
40using namespace android::uirenderer;
Chris Craik27e58b42015-12-07 10:01:38 -080041using namespace android::uirenderer::test;
John Reck94c40fe2014-10-08 09:28:43 -070042
John Reckb7dd29e2015-10-06 13:28:17 -070043static int gRepeatCount = 1;
Chris Craik27e58b42015-12-07 10:01:38 -080044static std::vector<TestScene::Info> gRunTests;
John Reck682573c2015-10-30 10:37:35 -070045static TestScene::Options gOpts;
John Reckf1480762016-07-03 18:28:25 -070046std::unique_ptr<benchmark::BenchmarkReporter> gBenchmarkReporter;
John Reckb7dd29e2015-10-06 13:28:17 -070047
John Reckf1480762016-07-03 18:28:25 -070048void run(const TestScene::Info& info, const TestScene::Options& opts,
John Reck1bcacfd2017-11-03 10:12:19 -070049 benchmark::BenchmarkReporter* reporter);
John Reck16c9d6a2015-11-17 15:51:08 -080050
John Reckb7dd29e2015-10-06 13:28:17 -070051static void printHelp() {
John Reck682573c2015-10-30 10:37:35 -070052 printf(R"(
sergeyv202c10b2016-07-11 17:53:45 -070053USAGE: hwuimacro [OPTIONS] <TESTNAME>
John Reck682573c2015-10-30 10:37:35 -070054
55OPTIONS:
56 -c, --count=NUM NUM loops a test should run (example, number of frames)
57 -r, --runs=NUM Repeat the test(s) NUM times
58 -h, --help Display this help
59 --list List all tests
60 --wait-for-gpu Set this to wait for the GPU before producing the
61 next frame. Note that without locked clocks this will
62 pathologically bad performance due to large idle time
63 --report-frametime[=weight] If set, the test will print to stdout the
64 moving average frametime. Weight is optional, default is 10
65 --cpuset=name Adds the test to the specified cpuset before running
66 Not supported on all devices and needs root
sergeyv202c10b2016-07-11 17:53:45 -070067 --offscreen Render tests off device screen. This option is on by default
68 --onscreen Render tests on device screen. By default tests
69 are offscreen rendered
70 --benchmark_format Set output format. Possible values are tabular, json, csv
John Reck18f442e2018-04-09 16:56:34 -070071 --renderer=TYPE Sets the render pipeline to use. May be skiagl or skiavk
John Reck682573c2015-10-30 10:37:35 -070072)");
John Reckb7dd29e2015-10-06 13:28:17 -070073}
74
75static void listTests() {
76 printf("Tests: \n");
Chris Craik27e58b42015-12-07 10:01:38 -080077 for (auto&& test : TestScene::testMap()) {
John Recke702c9c2015-10-07 10:26:02 -070078 auto&& info = test.second;
79 const char* col1 = info.name.c_str();
80 int dlen = info.description.length();
81 const char* col2 = info.description.c_str();
82 // World's best line breaking algorithm.
83 do {
84 int toPrint = dlen;
85 if (toPrint > 50) {
John Reck1bcacfd2017-11-03 10:12:19 -070086 char* found = (char*)memrchr(col2, ' ', 50);
John Recke702c9c2015-10-07 10:26:02 -070087 if (found) {
88 toPrint = found - col2;
89 } else {
90 toPrint = 50;
91 }
92 }
93 printf("%-20s %.*s\n", col1, toPrint, col2);
94 col1 = "";
95 col2 += toPrint;
96 dlen -= toPrint;
97 while (*col2 == ' ') {
John Reck1bcacfd2017-11-03 10:12:19 -070098 col2++;
99 dlen--;
John Recke702c9c2015-10-07 10:26:02 -0700100 }
101 } while (dlen > 0);
102 printf("\n");
John Reckb7dd29e2015-10-06 13:28:17 -0700103 }
104}
105
John Reck682573c2015-10-30 10:37:35 -0700106static void moveToCpuSet(const char* cpusetName) {
107 if (access("/dev/cpuset/tasks", F_OK)) {
108 fprintf(stderr, "don't have access to cpusets, skipping...\n");
109 return;
110 }
111 static const int BUF_SIZE = 100;
112 char buffer[BUF_SIZE];
113
114 if (snprintf(buffer, BUF_SIZE, "/dev/cpuset/%s/tasks", cpusetName) >= BUF_SIZE) {
115 fprintf(stderr, "Error, cpusetName too large to fit in buffer '%s'\n", cpusetName);
116 return;
117 }
118 int fd = open(buffer, O_WRONLY | O_CLOEXEC);
119 if (fd == -1) {
120 fprintf(stderr, "Error opening file %d\n", errno);
121 return;
122 }
123 pid_t pid = getpid();
124
John Reck1bcacfd2017-11-03 10:12:19 -0700125 int towrite = snprintf(buffer, BUF_SIZE, "%ld", (long)pid);
John Reck682573c2015-10-30 10:37:35 -0700126 if (towrite >= BUF_SIZE) {
127 fprintf(stderr, "Buffer wasn't large enough?\n");
128 } else {
129 if (write(fd, buffer, towrite) != towrite) {
130 fprintf(stderr, "Failed to write, errno=%d", errno);
131 }
132 }
133 close(fd);
134}
135
John Reckf1480762016-07-03 18:28:25 -0700136static bool setBenchmarkFormat(const char* format) {
137 if (!strcmp(format, "tabular")) {
138 gBenchmarkReporter.reset(new benchmark::ConsoleReporter());
139 } else if (!strcmp(format, "json")) {
140 gBenchmarkReporter.reset(new benchmark::JSONReporter());
John Reckf1480762016-07-03 18:28:25 -0700141 } else {
142 fprintf(stderr, "Unknown format '%s'", format);
143 return false;
144 }
145 return true;
146}
147
John Reck113ddd92017-11-09 16:21:21 -0800148static bool setRenderer(const char* renderer) {
John Reck18f442e2018-04-09 16:56:34 -0700149 if (!strcmp(renderer, "skiagl")) {
John Reck113ddd92017-11-09 16:21:21 -0800150 Properties::overrideRenderPipelineType(RenderPipelineType::SkiaGL);
151 } else if (!strcmp(renderer, "skiavk")) {
152 Properties::overrideRenderPipelineType(RenderPipelineType::SkiaVulkan);
153 } else {
154 fprintf(stderr, "Unknown format '%s'", renderer);
155 return false;
156 }
157 return true;
158}
159
John Reck682573c2015-10-30 10:37:35 -0700160// For options that only exist in long-form. Anything in the
161// 0-255 range is reserved for short options (which just use their ASCII value)
162namespace LongOpts {
163enum {
164 Reserved = 255,
165 List,
166 WaitForGpu,
167 ReportFrametime,
168 CpuSet,
John Reckf1480762016-07-03 18:28:25 -0700169 BenchmarkFormat,
sergeyv202c10b2016-07-11 17:53:45 -0700170 Onscreen,
John Reckf1480762016-07-03 18:28:25 -0700171 Offscreen,
John Reck113ddd92017-11-09 16:21:21 -0800172 Renderer,
John Reck682573c2015-10-30 10:37:35 -0700173};
174}
175
John Reckb7dd29e2015-10-06 13:28:17 -0700176static const struct option LONG_OPTIONS[] = {
John Reck1bcacfd2017-11-03 10:12:19 -0700177 {"frames", required_argument, nullptr, 'f'},
178 {"repeat", required_argument, nullptr, 'r'},
179 {"help", no_argument, nullptr, 'h'},
180 {"list", no_argument, nullptr, LongOpts::List},
181 {"wait-for-gpu", no_argument, nullptr, LongOpts::WaitForGpu},
182 {"report-frametime", optional_argument, nullptr, LongOpts::ReportFrametime},
183 {"cpuset", required_argument, nullptr, LongOpts::CpuSet},
184 {"benchmark_format", required_argument, nullptr, LongOpts::BenchmarkFormat},
185 {"onscreen", no_argument, nullptr, LongOpts::Onscreen},
186 {"offscreen", no_argument, nullptr, LongOpts::Offscreen},
John Reck113ddd92017-11-09 16:21:21 -0800187 {"renderer", required_argument, nullptr, LongOpts::Renderer},
John Reck1bcacfd2017-11-03 10:12:19 -0700188 {0, 0, 0, 0}};
John Reckb7dd29e2015-10-06 13:28:17 -0700189
190static const char* SHORT_OPTIONS = "c:r:h";
191
192void parseOptions(int argc, char* argv[]) {
193 int c;
John Reckb7dd29e2015-10-06 13:28:17 -0700194 bool error = false;
195 opterr = 0;
196
197 while (true) {
John Reckb7dd29e2015-10-06 13:28:17 -0700198 /* getopt_long stores the option index here. */
199 int option_index = 0;
200
201 c = getopt_long(argc, argv, SHORT_OPTIONS, LONG_OPTIONS, &option_index);
202
John Reck1bcacfd2017-11-03 10:12:19 -0700203 if (c == -1) break;
John Reckb7dd29e2015-10-06 13:28:17 -0700204
205 switch (c) {
John Reck1bcacfd2017-11-03 10:12:19 -0700206 case 0:
207 // Option set a flag, don't need to do anything
208 // (although none of the current LONG_OPTIONS do this...)
209 break;
John Reckb7dd29e2015-10-06 13:28:17 -0700210
John Reck1bcacfd2017-11-03 10:12:19 -0700211 case LongOpts::List:
212 listTests();
213 exit(EXIT_SUCCESS);
214 break;
John Reckb7dd29e2015-10-06 13:28:17 -0700215
John Reck1bcacfd2017-11-03 10:12:19 -0700216 case 'c':
217 gOpts.count = atoi(optarg);
218 if (!gOpts.count) {
219 fprintf(stderr, "Invalid frames argument '%s'\n", optarg);
John Reck682573c2015-10-30 10:37:35 -0700220 error = true;
221 }
John Reck682573c2015-10-30 10:37:35 -0700222 break;
John Reck682573c2015-10-30 10:37:35 -0700223
John Reck1bcacfd2017-11-03 10:12:19 -0700224 case 'r':
225 gRepeatCount = atoi(optarg);
226 if (!gRepeatCount) {
227 fprintf(stderr, "Invalid repeat argument '%s'\n", optarg);
228 error = true;
229 } else {
230 gRepeatCount = (gRepeatCount > 0 ? gRepeatCount : INT_MAX);
231 }
John Reckf1480762016-07-03 18:28:25 -0700232 break;
John Reckf1480762016-07-03 18:28:25 -0700233
John Reck1bcacfd2017-11-03 10:12:19 -0700234 case LongOpts::ReportFrametime:
235 if (optarg) {
236 gOpts.reportFrametimeWeight = atoi(optarg);
237 if (!gOpts.reportFrametimeWeight) {
238 fprintf(stderr, "Invalid report frametime weight '%s'\n", optarg);
239 error = true;
240 }
241 } else {
242 gOpts.reportFrametimeWeight = 10;
243 }
244 break;
sergeyv202c10b2016-07-11 17:53:45 -0700245
John Reck1bcacfd2017-11-03 10:12:19 -0700246 case LongOpts::WaitForGpu:
247 Properties::waitForGpuCompletion = true;
248 break;
John Reckf1480762016-07-03 18:28:25 -0700249
John Reck1bcacfd2017-11-03 10:12:19 -0700250 case LongOpts::CpuSet:
251 if (!optarg) {
252 error = true;
253 break;
254 }
255 moveToCpuSet(optarg);
256 break;
John Reckb7dd29e2015-10-06 13:28:17 -0700257
John Reck1bcacfd2017-11-03 10:12:19 -0700258 case LongOpts::BenchmarkFormat:
259 if (!optarg) {
260 error = true;
261 break;
262 }
263 if (!setBenchmarkFormat(optarg)) {
264 error = true;
265 }
266 break;
267
John Reck113ddd92017-11-09 16:21:21 -0800268 case LongOpts::Renderer:
269 if (!optarg) {
270 error = true;
271 break;
272 }
273 if (!setRenderer(optarg)) {
274 error = true;
275 }
276 break;
277
John Reck1bcacfd2017-11-03 10:12:19 -0700278 case LongOpts::Onscreen:
279 gOpts.renderOffscreen = false;
280 break;
281
282 case LongOpts::Offscreen:
283 gOpts.renderOffscreen = true;
284 break;
285
286 case 'h':
287 printHelp();
288 exit(EXIT_SUCCESS);
289 break;
290
291 case '?':
292 fprintf(stderr, "Unrecognized option '%s'\n", argv[optind - 1]);
Chih-Hung Hsiehe1afb6c2018-10-22 12:25:50 -0700293 [[fallthrough]];
John Reck1bcacfd2017-11-03 10:12:19 -0700294 default:
295 error = true;
296 break;
John Reckb7dd29e2015-10-06 13:28:17 -0700297 }
298 }
299
300 if (error) {
301 fprintf(stderr, "Try 'hwuitest --help' for more information.\n");
302 exit(EXIT_FAILURE);
303 }
304
305 /* Print any remaining command line arguments (not options). */
306 if (optind < argc) {
307 do {
308 const char* test = argv[optind++];
sergeyv202c10b2016-07-11 17:53:45 -0700309 auto pos = TestScene::testMap().find(test);
310 if (pos == TestScene::testMap().end()) {
311 fprintf(stderr, "Unknown test '%s'\n", test);
312 exit(EXIT_FAILURE);
John Reckb7dd29e2015-10-06 13:28:17 -0700313 } else {
sergeyv202c10b2016-07-11 17:53:45 -0700314 gRunTests.push_back(pos->second);
John Reckb7dd29e2015-10-06 13:28:17 -0700315 }
316 } while (optind < argc);
317 } else {
sergeyv202c10b2016-07-11 17:53:45 -0700318 for (auto& iter : TestScene::testMap()) {
319 gRunTests.push_back(iter.second);
320 }
John Reckb7dd29e2015-10-06 13:28:17 -0700321 }
322}
323
Chris Craik03188872015-02-02 18:39:33 -0800324int main(int argc, char* argv[]) {
John Reck682573c2015-10-30 10:37:35 -0700325 // set defaults
326 gOpts.count = 150;
327
Seigo Nonakab6e20132016-11-14 14:07:41 +0900328 Typeface::setRobotoTypefaceForTest();
329
John Reckb7dd29e2015-10-06 13:28:17 -0700330 parseOptions(argc, argv);
John Reckf1480762016-07-03 18:28:25 -0700331 if (!gBenchmarkReporter && gOpts.renderOffscreen) {
332 gBenchmarkReporter.reset(new benchmark::ConsoleReporter());
333 }
334
335 if (gBenchmarkReporter) {
336 size_t name_field_width = 10;
337 for (auto&& test : gRunTests) {
338 name_field_width = std::max<size_t>(name_field_width, test.name.size());
339 }
340 // _50th, _90th, etc...
341 name_field_width += 5;
342
343 benchmark::BenchmarkReporter::Context context;
John Reckf1480762016-07-03 18:28:25 -0700344 context.name_field_width = name_field_width;
345 gBenchmarkReporter->ReportContext(context);
346 }
John Reckb7dd29e2015-10-06 13:28:17 -0700347
348 for (int i = 0; i < gRepeatCount; i++) {
349 for (auto&& test : gRunTests) {
John Reckf1480762016-07-03 18:28:25 -0700350 run(test, gOpts, gBenchmarkReporter.get());
Tim Murray1a0f1c72015-05-06 11:37:37 -0700351 }
352 }
John Reckf1480762016-07-03 18:28:25 -0700353
354 if (gBenchmarkReporter) {
355 gBenchmarkReporter->Finalize();
356 }
357
John Reck6104cea2019-01-10 14:37:17 -0800358 renderthread::RenderProxy::trimMemory(100);
359 HardwareBitmapUploader::terminate();
360
sergeyv7dc370b2016-06-17 11:21:11 -0700361 LeakChecker::checkForLeaks();
John Reck94c40fe2014-10-08 09:28:43 -0700362 return 0;
363}