blob: b92b9e03fe215b178bd897d017db2e26f6a699d4 [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
Po-Hsien Wang93cc6892020-10-28 17:01:28 -070018// g_list determines should we show the test list.
19int g_list = false;
Po-Hsien Wang00777b22019-04-24 16:37:09 -070020// g_iteration determines the total iteration to run for each test
21int g_iteration = 1;
Po-Hsien Wang93cc6892020-10-28 17:01:28 -070022// g_verbose determines the logging level to print into the screen.
Po-Hsien Wang00777b22019-04-24 16:37:09 -070023int g_verbose = false;
24// g_vlayer enables the vulkan verification layer if it is set.
25int g_vlayer = false;
Po-Hsien Wang513fe192020-10-02 11:40:07 +080026// g_hasty enables the hasty mode. Tests would tries to reuse vulkan instance if
27// possible.
28int g_hasty = false;
Po-Hsien Wang93cc6892020-10-28 17:01:28 -070029// g_spirv_dir is the path to the folder contains spirv code for test.
30std::string g_spirv_dir = "shaders/";
Po-Hsien Wang00777b22019-04-24 16:37:09 -070031
Po-Hsien Wang00777b22019-04-24 16:37:09 -070032// kLongOptions defines the options for argument options.
33const static struct option kLongOptions[] = {
34 {"iterations", required_argument, nullptr, 'i'},
35 {"tests", required_argument, nullptr, 't'},
36 {"blacklist", required_argument, nullptr, 'b'},
Po-Hsien Wang93cc6892020-10-28 17:01:28 -070037 {"spirv_dir", required_argument, nullptr, 's'},
Po-Hsien Wang00777b22019-04-24 16:37:09 -070038 {"help", no_argument, nullptr, 'h'},
Po-Hsien Wang93cc6892020-10-28 17:01:28 -070039 {"list", no_argument, &g_list, 1},
Po-Hsien Wang00777b22019-04-24 16:37:09 -070040 {"vlayer", no_argument, &g_vlayer, 1},
41 {"verbose", no_argument, &g_verbose, 1},
Po-Hsien Wang513fe192020-10-02 11:40:07 +080042 {"hasty", no_argument, &g_hasty, 1},
Po-Hsien Wang00777b22019-04-24 16:37:09 -070043 {0, 0, 0, 0}};
44
45// TimeTest times the test by looping it iteration times.
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070046// @param test: test to be excuted.
47// @param iteration: how many times should the test be executed.
Po-Hsien Wang00777b22019-04-24 16:37:09 -070048inline uint64_t TimeTest(vkbench::testBase* test, uint64_t iteration) {
49 uint64_t start = GetUTime();
Po-Hsien Wang00777b22019-04-24 16:37:09 -070050 try {
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070051 test->Setup();
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070052 } catch (const vk::SystemError& err) {
53 LOG("Setup failed: %s", err.what());
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +080054 test->Cleanup();
55 throw;
Po-Hsien Wang00777b22019-04-24 16:37:09 -070056 }
Po-Hsien Wangaafe13e2020-09-24 14:29:58 +080057 DEFER(test->Cleanup());
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070058
59 try {
60 for (int i = 0; i < iteration; i++) {
61 test->Run();
62 }
63 } catch (const vk::SystemError& err) {
64 LOG("TestRun failed: %s", err.what());
65 throw TEST_FAIL;
Po-Hsien Wang00777b22019-04-24 16:37:09 -070066 }
67 return GetUTime() - start;
68}
69
70// Run the test and pre/post processes.
Po-Hsien Wang00777b22019-04-24 16:37:09 -070071// @param duration_us: The test would to iterate till duration_us is reached.
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070072void Run(vkbench::testBase* test, const uint64_t duration_us = 1000000) {
Po-Hsien Wang00777b22019-04-24 16:37:09 -070073 try {
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070074 test->Initialize();
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070075 } catch (const vk::SystemError& err) {
76 LOG("Test failed to initialize: %s", err.what());
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +080077 test->Destroy();
78 throw;
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070079 }
80 DEFER(test->Destroy());
81
82 // Do some iterations since initial timings may vary.
83 TimeTest(test, 2);
84 // Target minimum iteration is 1s for each test.
85 uint64_t time = 0;
86 uint64_t iteration = 1;
87 double score = -1.f;
88 do {
89 time = TimeTest(test, iteration);
90 DEBUG("iterations: %llu, time: %llu us, time/iter: %llu us", iteration,
91 time, time / iteration)
92 if (time > duration_us) {
93 score = time / iteration;
94 break;
Po-Hsien Wang00777b22019-04-24 16:37:09 -070095 }
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070096 iteration = iteration * 2;
97 } while ((1ull << 40) > iteration);
98 // Returns 0.0 if it ran max iterations in less than test time.
99 if (score <= 0.01f)
100 LOG("%s: measurement may not be accurate.", test->Name())
101 score = test->FormatMeasurement(score);
102 LOG("@RESULT: %46s = %10.2f %-15s", test->Name(), score, test->Unit());
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800103 try {
104 test->SaveImage(((std::string)test->Name()));
105 } catch (std::runtime_error err) {
106 DEBUG("Get runtime_error while SaveImage: %s.", err.what());
107 }
Po-Hsien Wang00777b22019-04-24 16:37:09 -0700108}
109
110void PrintHelp() {
111 LOG(R",(
112Usage: vkbench [OPTIONS]
113 -i, --iterations=N Specify the iterations to run the tests.
114 -t, --tests=TESTS Tests to run in colon separated form.
115 -b, --blacklist=TESTS Tests to not run in colon separated form.
116 --list List the tests available.
117 --verbose Show verbose messages.
Po-Hsien Wang513fe192020-10-02 11:40:07 +0800118 --vlayer Enable vulkan verification layer.
Po-Hsien Wang93cc6892020-10-28 17:01:28 -0700119 --hasty Enable hasty mode.
120 --spirv_dir Path to SPIRV code for test.(default: shaders/)),")
Po-Hsien Wang00777b22019-04-24 16:37:09 -0700121}
122
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700123bool prefixFind(std::vector<std::string> list, std::string name) {
124 for (const std::string item : list) {
125 if (name.rfind(item, 0) == 0) {
126 return true;
127 }
128 }
129 return false;
130}
131
132bool ParseArgv(int argc,
133 char** argv,
134 std::vector<vkbench::testBase*>& all_tests) {
Po-Hsien Wang00777b22019-04-24 16:37:09 -0700135 std::vector<std::string> enabled_tests;
136 std::vector<std::string> disabled_tests;
137 int c;
138 int option_index = 0;
139 while ((c = getopt_long(argc, argv, "i:t:b:", kLongOptions, &option_index)) !=
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700140 -1) {
Po-Hsien Wang00777b22019-04-24 16:37:09 -0700141 if (c == 'i') {
142 g_iteration = atoi(optarg);
143 } else if (c == 't') {
144 enabled_tests = SplitString(std::string(optarg), ':');
145 } else if (c == 'b') {
146 disabled_tests = SplitString(std::string(optarg), ':');
Po-Hsien Wang93cc6892020-10-28 17:01:28 -0700147 } else if (c == 's') {
148 g_spirv_dir = std::string(optarg);
Po-Hsien Wang00777b22019-04-24 16:37:09 -0700149 } else if (c == '?' || c == 'h') {
150 PrintHelp();
151 return false;
152 }
153 }
154
155 if (optind < argc) {
156 ERROR("Unknown argv: ")
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700157 while (optind < argc)
158 ERROR("%s ", argv[optind++])
Po-Hsien Wang00777b22019-04-24 16:37:09 -0700159 return false;
160 }
161
162 all_tests.erase(
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700163 remove_if(all_tests.begin(), all_tests.end(),
164 [enabled_tests, disabled_tests](const vkbench::testBase* test) {
165 bool should_run = enabled_tests.empty() ||
166 prefixFind(enabled_tests, test->Name());
167 should_run &= !prefixFind(disabled_tests, test->Name());
168 if (!should_run)
169 delete test;
170 return !should_run;
171 }),
Po-Hsien Wang00777b22019-04-24 16:37:09 -0700172 all_tests.end());
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700173
Po-Hsien Wang93cc6892020-10-28 17:01:28 -0700174 if (g_list) {
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700175 for (const auto& test : all_tests) {
176 LOG("%s: %s", test->Name(), test->Desp())
177 }
178 return false;
179 }
Po-Hsien Wang00777b22019-04-24 16:37:09 -0700180 return true;
181}
182
183int main(int argc, char* argv[]) {
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700184 vkbench::vkBase simpleVulkan;
185 // all_tests list all the available tests.
186 std::vector<vkbench::testBase*> all_tests = {
187 new vkbench::SubmitTest(10, &simpleVulkan),
188 new vkbench::SubmitTest(100, &simpleVulkan),
189 new vkbench::SubmitTest(1000, &simpleVulkan),
190 new vkbench::SubmitTest(10000, &simpleVulkan),
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800191 new vkbench::SubmitTest(100000, &simpleVulkan),
192 new vkbench::DrawSizeTest(16, &simpleVulkan),
193 new vkbench::DrawSizeTest(64, &simpleVulkan),
194 new vkbench::DrawSizeTest(128, &simpleVulkan),
195 new vkbench::DrawSizeTest(512, &simpleVulkan),
196 new vkbench::DrawSizeTest(1024, &simpleVulkan),
Po-Hsien Wang5372c812020-10-02 09:41:01 +0800197 new vkbench::ClearTest(&simpleVulkan),
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700198 };
Po-Hsien Wang00777b22019-04-24 16:37:09 -0700199
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800200 // Sort to bundle tests using same vulkan instance together.
201 std::stable_sort(all_tests.begin(), all_tests.end(),
202 [](vkbench::testBase* a, vkbench::testBase* b) -> bool {
203 return a->vk < b->vk;
204 });
205
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700206 if (!ParseArgv(argc, argv, all_tests)) {
207 return 0;
208 }
209
Po-Hsien Wang00777b22019-04-24 16:37:09 -0700210 std::map<const char*, int> failed_test;
211 LOG("@TEST_BEGIN")
212 PrintDateTime();
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700213 for (auto i = 0; i < all_tests.size(); i++) {
214 auto& test = all_tests[i];
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800215 for (auto iter = 0; iter < g_iteration; iter++) {
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700216 try {
Po-Hsien Wang513fe192020-10-02 11:40:07 +0800217 if (!test->vk->IsInitialized())
218 test->vk->Initialize();
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700219 Run(test, 1000000);
Po-Hsien Wang513fe192020-10-02 11:40:07 +0800220 if (!g_hasty)
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700221 test->vk->Destroy();
222 } catch (const ERROR_TYPE& type) {
223 switch (type) {
224 case TEST_PASS:
225 break;
226 case TEST_FAIL:
227 failed_test[test->Name()] += 1;
228 break;
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700229 default:
230 ERROR("Unimplemented error type");
231 throw;
232 }
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800233 } catch (const std::runtime_error error) {
234 failed_test[test->Name()] += 1;
235 LOG("Runtime Error: %s", error.what());
Po-Hsien Wang00777b22019-04-24 16:37:09 -0700236 }
237 }
Po-Hsien Wang513fe192020-10-02 11:40:07 +0800238
239 // keep test->vk initialized for the next test.
240 if (g_hasty && test->vk->IsInitialized()) {
241 if (i + 1 >= all_tests.size() || test->vk != all_tests[i + 1]->vk) {
242 test->vk->Destroy();
243 }
244 }
Po-Hsien Wang00777b22019-04-24 16:37:09 -0700245 }
246 PrintDateTime();
247 LOG("@TEST_END")
248
249 for (auto& keyval : failed_test) {
250 LOG("%s failed %d times.", keyval.first, keyval.second)
251 }
252
253 for (auto& test : all_tests) {
254 delete test;
255 }
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700256}