blob: 29a05430b10856841be461e213e1bd74e3749d78 [file] [log] [blame]
Po-Hsien Wang00777b22019-04-24 16:37:09 -07001// Copyright 2019 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <getopt.h>
Po-Hsien Wang00777b22019-04-24 16:37:09 -07006#include <unistd.h>
7#include <algorithm>
8#include <iterator>
9#include <map>
10#include <vector>
11
Po-Hsien Wang5372c812020-10-02 09:41:01 +080012#include "clearTest.h"
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070013#include "constant.h"
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +080014#include "drawSizeTest.h"
Po-Hsien Wang00777b22019-04-24 16:37:09 -070015#include "submitTest.h"
16#include "utils.h"
17
18// g_iteration determines the total iteration to run for each test
19int g_iteration = 1;
20// g_verbose determine the logging level to print into the screen.
21int g_verbose = false;
22// g_vlayer enables the vulkan verification layer if it is set.
23int g_vlayer = false;
Po-Hsien Wang00777b22019-04-24 16:37:09 -070024
Po-Hsien Wang00777b22019-04-24 16:37:09 -070025// kLongOptions defines the options for argument options.
26const static struct option kLongOptions[] = {
27 {"iterations", required_argument, nullptr, 'i'},
28 {"tests", required_argument, nullptr, 't'},
29 {"blacklist", required_argument, nullptr, 'b'},
30 {"list", no_argument, nullptr, 'l'},
31 {"help", no_argument, nullptr, 'h'},
Po-Hsien Wang00777b22019-04-24 16:37:09 -070032 {"vlayer", no_argument, &g_vlayer, 1},
33 {"verbose", no_argument, &g_verbose, 1},
34 {0, 0, 0, 0}};
35
36// TimeTest times the test by looping it iteration times.
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070037// @param test: test to be excuted.
38// @param iteration: how many times should the test be executed.
Po-Hsien Wang00777b22019-04-24 16:37:09 -070039inline uint64_t TimeTest(vkbench::testBase* test, uint64_t iteration) {
40 uint64_t start = GetUTime();
Po-Hsien Wang00777b22019-04-24 16:37:09 -070041 try {
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070042 test->Setup();
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070043 } catch (const vk::SystemError& err) {
44 LOG("Setup failed: %s", err.what());
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +080045 test->Cleanup();
46 throw;
Po-Hsien Wang00777b22019-04-24 16:37:09 -070047 }
Po-Hsien Wangaafe13e2020-09-24 14:29:58 +080048 DEFER(test->Cleanup());
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070049
50 try {
51 for (int i = 0; i < iteration; i++) {
52 test->Run();
53 }
54 } catch (const vk::SystemError& err) {
55 LOG("TestRun failed: %s", err.what());
56 throw TEST_FAIL;
Po-Hsien Wang00777b22019-04-24 16:37:09 -070057 }
58 return GetUTime() - start;
59}
60
61// Run the test and pre/post processes.
Po-Hsien Wang00777b22019-04-24 16:37:09 -070062// @param duration_us: The test would to iterate till duration_us is reached.
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070063void Run(vkbench::testBase* test, const uint64_t duration_us = 1000000) {
Po-Hsien Wang00777b22019-04-24 16:37:09 -070064 try {
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070065 test->Initialize();
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070066 } catch (const vk::SystemError& err) {
67 LOG("Test failed to initialize: %s", err.what());
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +080068 test->Destroy();
69 throw;
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070070 }
71 DEFER(test->Destroy());
72
73 // Do some iterations since initial timings may vary.
74 TimeTest(test, 2);
75 // Target minimum iteration is 1s for each test.
76 uint64_t time = 0;
77 uint64_t iteration = 1;
78 double score = -1.f;
79 do {
80 time = TimeTest(test, iteration);
81 DEBUG("iterations: %llu, time: %llu us, time/iter: %llu us", iteration,
82 time, time / iteration)
83 if (time > duration_us) {
84 score = time / iteration;
85 break;
Po-Hsien Wang00777b22019-04-24 16:37:09 -070086 }
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070087 iteration = iteration * 2;
88 } while ((1ull << 40) > iteration);
89 // Returns 0.0 if it ran max iterations in less than test time.
90 if (score <= 0.01f)
91 LOG("%s: measurement may not be accurate.", test->Name())
92 score = test->FormatMeasurement(score);
93 LOG("@RESULT: %46s = %10.2f %-15s", test->Name(), score, test->Unit());
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +080094 try {
95 test->SaveImage(((std::string)test->Name()));
96 } catch (std::runtime_error err) {
97 DEBUG("Get runtime_error while SaveImage: %s.", err.what());
98 }
Po-Hsien Wang00777b22019-04-24 16:37:09 -070099}
100
101void PrintHelp() {
102 LOG(R",(
103Usage: vkbench [OPTIONS]
104 -i, --iterations=N Specify the iterations to run the tests.
105 -t, --tests=TESTS Tests to run in colon separated form.
106 -b, --blacklist=TESTS Tests to not run in colon separated form.
107 --list List the tests available.
108 --verbose Show verbose messages.
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700109 --vlayer Enable vulkan verification layer.),")
Po-Hsien Wang00777b22019-04-24 16:37:09 -0700110}
111
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700112bool prefixFind(std::vector<std::string> list, std::string name) {
113 for (const std::string item : list) {
114 if (name.rfind(item, 0) == 0) {
115 return true;
116 }
117 }
118 return false;
119}
120
121bool ParseArgv(int argc,
122 char** argv,
123 std::vector<vkbench::testBase*>& all_tests) {
Po-Hsien Wang00777b22019-04-24 16:37:09 -0700124 std::vector<std::string> enabled_tests;
125 std::vector<std::string> disabled_tests;
126 int c;
127 int option_index = 0;
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700128 bool print_test = false;
Po-Hsien Wang00777b22019-04-24 16:37:09 -0700129 while ((c = getopt_long(argc, argv, "i:t:b:", kLongOptions, &option_index)) !=
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700130 -1) {
Po-Hsien Wang00777b22019-04-24 16:37:09 -0700131 if (c == 'i') {
132 g_iteration = atoi(optarg);
133 } else if (c == 't') {
134 enabled_tests = SplitString(std::string(optarg), ':');
135 } else if (c == 'b') {
136 disabled_tests = SplitString(std::string(optarg), ':');
137 } else if (c == 'l') {
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700138 print_test = true;
Po-Hsien Wang00777b22019-04-24 16:37:09 -0700139 } else if (c == '?' || c == 'h') {
140 PrintHelp();
141 return false;
142 }
143 }
144
145 if (optind < argc) {
146 ERROR("Unknown argv: ")
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700147 while (optind < argc)
148 ERROR("%s ", argv[optind++])
Po-Hsien Wang00777b22019-04-24 16:37:09 -0700149 return false;
150 }
151
152 all_tests.erase(
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700153 remove_if(all_tests.begin(), all_tests.end(),
154 [enabled_tests, disabled_tests](const vkbench::testBase* test) {
155 bool should_run = enabled_tests.empty() ||
156 prefixFind(enabled_tests, test->Name());
157 should_run &= !prefixFind(disabled_tests, test->Name());
158 if (!should_run)
159 delete test;
160 return !should_run;
161 }),
Po-Hsien Wang00777b22019-04-24 16:37:09 -0700162 all_tests.end());
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700163
164 if (print_test) {
165 for (const auto& test : all_tests) {
166 LOG("%s: %s", test->Name(), test->Desp())
167 }
168 return false;
169 }
Po-Hsien Wang00777b22019-04-24 16:37:09 -0700170 return true;
171}
172
173int main(int argc, char* argv[]) {
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700174 vkbench::vkBase simpleVulkan;
175 // all_tests list all the available tests.
176 std::vector<vkbench::testBase*> all_tests = {
177 new vkbench::SubmitTest(10, &simpleVulkan),
178 new vkbench::SubmitTest(100, &simpleVulkan),
179 new vkbench::SubmitTest(1000, &simpleVulkan),
180 new vkbench::SubmitTest(10000, &simpleVulkan),
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800181 new vkbench::SubmitTest(100000, &simpleVulkan),
182 new vkbench::DrawSizeTest(16, &simpleVulkan),
183 new vkbench::DrawSizeTest(64, &simpleVulkan),
184 new vkbench::DrawSizeTest(128, &simpleVulkan),
185 new vkbench::DrawSizeTest(512, &simpleVulkan),
186 new vkbench::DrawSizeTest(1024, &simpleVulkan),
Po-Hsien Wang5372c812020-10-02 09:41:01 +0800187 new vkbench::ClearTest(&simpleVulkan),
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700188 };
Po-Hsien Wang00777b22019-04-24 16:37:09 -0700189
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800190 // Sort to bundle tests using same vulkan instance together.
191 std::stable_sort(all_tests.begin(), all_tests.end(),
192 [](vkbench::testBase* a, vkbench::testBase* b) -> bool {
193 return a->vk < b->vk;
194 });
195
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700196 if (!ParseArgv(argc, argv, all_tests)) {
197 return 0;
198 }
199
Po-Hsien Wang00777b22019-04-24 16:37:09 -0700200 std::map<const char*, int> failed_test;
201 LOG("@TEST_BEGIN")
202 PrintDateTime();
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700203 for (auto i = 0; i < all_tests.size(); i++) {
204 auto& test = all_tests[i];
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700205 bool reuse_vulkan = false;
206 if (i + 1 < all_tests.size() && all_tests[i]->vk == all_tests[i + 1]->vk) {
207 reuse_vulkan = true;
208 }
209
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800210 for (auto iter = 0; iter < g_iteration; iter++) {
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700211 try {
212 test->vk->Initialize();
213 Run(test, 1000000);
214 if (!reuse_vulkan)
215 test->vk->Destroy();
216 } catch (const ERROR_TYPE& type) {
217 switch (type) {
218 case TEST_PASS:
219 break;
220 case TEST_FAIL:
221 failed_test[test->Name()] += 1;
222 break;
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700223 default:
224 ERROR("Unimplemented error type");
225 throw;
226 }
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800227 } catch (const std::runtime_error error) {
228 failed_test[test->Name()] += 1;
229 LOG("Runtime Error: %s", error.what());
Po-Hsien Wang00777b22019-04-24 16:37:09 -0700230 }
231 }
232 }
233 PrintDateTime();
234 LOG("@TEST_END")
235
236 for (auto& keyval : failed_test) {
237 LOG("%s failed %d times.", keyval.first, keyval.second)
238 }
239
240 for (auto& test : all_tests) {
241 delete test;
242 }
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700243}