blob: 2efb3c886e4477c5a9033a5ac9c6bca7a186071e [file] [log] [blame]
joshualitt962cc982015-06-30 07:43:14 -07001/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 *
7 */
8
9#include <VisualBench/VisualBenchmarkStream.h>
joshualittc9dd93c2015-10-15 09:49:31 -070010#include <VisualBench/WrappedBenchmark.h>
joshualitt962cc982015-06-30 07:43:14 -070011#include "GMBench.h"
12#include "SkOSFile.h"
joshualitt98d2e2f2015-10-05 07:23:30 -070013#include "SkPath.h"
joshualitt962cc982015-06-30 07:43:14 -070014#include "SkPictureRecorder.h"
15#include "SkStream.h"
joshualitt98d2e2f2015-10-05 07:23:30 -070016#include "sk_tool_utils.h"
joshualittc9dd93c2015-10-15 09:49:31 -070017#include "VisualFlags.h"
joshualitt962cc982015-06-30 07:43:14 -070018#include "VisualSKPBench.h"
19
cdaltone6d20242015-10-26 13:45:29 -070020#if SK_SUPPORT_GPU
21#include "GrContext.h"
22#endif
23
mtkleinc6f5cac2015-10-01 11:56:56 -070024DEFINE_bool(cpu, false, "Run in CPU mode?");
halcanary96fcdcc2015-08-27 07:41:13 -070025DEFINE_string2(match, m, nullptr,
joshualitt962cc982015-06-30 07:43:14 -070026 "[~][^]substring[$] [...] of bench name to run.\n"
27 "Multiple matches may be separated by spaces.\n"
28 "~ causes a matching bench to always be skipped\n"
29 "^ requires the start of the bench to match\n"
30 "$ requires the end of the bench to match\n"
31 "^ and $ requires an exact match\n"
32 "If a bench does not match any list entry,\n"
33 "it is skipped unless some list entry starts with ~");
34DEFINE_string(skps, "skps", "Directory to read skps from.");
35
joshualitt98d2e2f2015-10-05 07:23:30 -070036// We draw a big nonAA path to warmup the gpu / cpu
37#include "SkPerlinNoiseShader.h"
38class WarmupBench : public Benchmark {
39public:
40 WarmupBench() {
41 sk_tool_utils::make_big_path(fPath);
42 }
43private:
44 const char* onGetName() override { return "warmupbench"; }
45 void onDraw(int loops, SkCanvas* canvas) override {
46 // We draw a big path to warm up the cpu, and then use perlin noise shader to warm up the
47 // gpu
48 SkPaint paint;
49 paint.setStyle(SkPaint::kStroke_Style);
50 paint.setStrokeWidth(2);
51
52 SkPaint perlinPaint;
53 perlinPaint.setShader(SkPerlinNoiseShader::CreateTurbulence(0.1f, 0.1f, 1, 0,
54 nullptr))->unref();
55 SkRect rect = SkRect::MakeLTRB(0., 0., 400., 400.);
56 for (int i = 0; i < loops; i++) {
57 canvas->drawPath(fPath, paint);
58 canvas->drawRect(rect, perlinPaint);
cdaltone6d20242015-10-26 13:45:29 -070059#if SK_SUPPORT_GPU
60 // Ensure the GrContext doesn't batch across draw loops.
61 if (GrContext* context = canvas->getGrContext()) {
62 context->flush();
63 }
64#endif
joshualitt98d2e2f2015-10-05 07:23:30 -070065 }
66 }
67 SkPath fPath;
68};
69
cdaltonc70483f2015-10-26 13:14:36 -070070VisualBenchmarkStream::VisualBenchmarkStream(const SkSurfaceProps& surfaceProps)
71 : fSurfaceProps(surfaceProps)
72 , fBenches(BenchRegistry::Head())
joshualitt962cc982015-06-30 07:43:14 -070073 , fGMs(skiagm::GMRegistry::Head())
halcanary96fcdcc2015-08-27 07:41:13 -070074 , fSourceType(nullptr)
75 , fBenchType(nullptr)
joshualitt98d2e2f2015-10-05 07:23:30 -070076 , fCurrentSKP(0)
77 , fIsWarmedUp(false) {
joshualitt962cc982015-06-30 07:43:14 -070078 for (int i = 0; i < FLAGS_skps.count(); i++) {
79 if (SkStrEndsWith(FLAGS_skps[i], ".skp")) {
80 fSKPs.push_back() = FLAGS_skps[i];
81 } else {
82 SkOSFile::Iter it(FLAGS_skps[i], ".skp");
83 SkString path;
84 while (it.next(&path)) {
85 fSKPs.push_back() = SkOSPath::Join(FLAGS_skps[0], path.c_str());
86 }
87 }
88 }
joshualittc603c142015-10-15 07:18:29 -070089
90 // seed with an initial benchmark
91 // NOTE the initial benchmark will not have preTimingHooks called, but that is okay because
92 // it is the warmupbench
93 this->next();
joshualitt962cc982015-06-30 07:43:14 -070094}
95
96bool VisualBenchmarkStream::ReadPicture(const char* path, SkAutoTUnref<SkPicture>* pic) {
97 // Not strictly necessary, as it will be checked again later,
98 // but helps to avoid a lot of pointless work if we're going to skip it.
99 if (SkCommandLineFlags::ShouldSkip(FLAGS_match, path)) {
100 return false;
101 }
102
103 SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(path));
halcanary96fcdcc2015-08-27 07:41:13 -0700104 if (stream.get() == nullptr) {
joshualitt962cc982015-06-30 07:43:14 -0700105 SkDebugf("Could not read %s.\n", path);
106 return false;
107 }
108
109 pic->reset(SkPicture::CreateFromStream(stream.get()));
halcanary96fcdcc2015-08-27 07:41:13 -0700110 if (pic->get() == nullptr) {
joshualitt962cc982015-06-30 07:43:14 -0700111 SkDebugf("Could not read %s as an SkPicture.\n", path);
112 return false;
113 }
114 return true;
115}
116
117Benchmark* VisualBenchmarkStream::next() {
joshualittc603c142015-10-15 07:18:29 -0700118 Benchmark* bench;
joshualitt98d2e2f2015-10-05 07:23:30 -0700119 if (!fIsWarmedUp) {
120 fIsWarmedUp = true;
joshualittc603c142015-10-15 07:18:29 -0700121 bench = new WarmupBench;
122 } else {
123 // skips non matching benches
124 while ((bench = this->innerNext()) &&
125 (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getUniqueName()) ||
126 !bench->isSuitableFor(Benchmark::kGPU_Backend))) {
127 bench->unref();
128 }
129 }
joshualittc9dd93c2015-10-15 09:49:31 -0700130
131 // TODO move this all to --config
joshualittc603c142015-10-15 07:18:29 -0700132 if (bench && FLAGS_cpu) {
cdaltonc70483f2015-10-26 13:14:36 -0700133 bench = new CpuWrappedBenchmark(fSurfaceProps, bench);
joshualittc9dd93c2015-10-15 09:49:31 -0700134 } else if (bench && FLAGS_nvpr) {
cdaltonc70483f2015-10-26 13:14:36 -0700135 bench = new NvprWrappedBenchmark(fSurfaceProps, bench, 4);
joshualitt98d2e2f2015-10-05 07:23:30 -0700136 }
137
joshualittc603c142015-10-15 07:18:29 -0700138 fBenchmark.reset(bench);
139 return fBenchmark;
joshualitt82874f82015-07-15 08:38:02 -0700140}
141
142Benchmark* VisualBenchmarkStream::innerNext() {
joshualitt962cc982015-06-30 07:43:14 -0700143 while (fBenches) {
halcanary96fcdcc2015-08-27 07:41:13 -0700144 Benchmark* bench = fBenches->factory()(nullptr);
joshualitt962cc982015-06-30 07:43:14 -0700145 fBenches = fBenches->next();
146 if (bench->isVisual()) {
147 fSourceType = "bench";
148 fBenchType = "micro";
149 return bench;
150 }
joshualitt47d280d2015-07-16 14:23:22 -0700151 bench->unref();
joshualitt962cc982015-06-30 07:43:14 -0700152 }
153
154 while (fGMs) {
halcanary96fcdcc2015-08-27 07:41:13 -0700155 SkAutoTDelete<skiagm::GM> gm(fGMs->factory()(nullptr));
joshualitt962cc982015-06-30 07:43:14 -0700156 fGMs = fGMs->next();
157 if (gm->runAsBench()) {
158 fSourceType = "gm";
159 fBenchType = "micro";
halcanary385fe4d2015-08-26 13:07:48 -0700160 return new GMBench(gm.detach());
joshualitt962cc982015-06-30 07:43:14 -0700161 }
162 }
163
164 // Render skps
165 while (fCurrentSKP < fSKPs.count()) {
166 const SkString& path = fSKPs[fCurrentSKP++];
167 SkAutoTUnref<SkPicture> pic;
168 if (!ReadPicture(path.c_str(), &pic)) {
169 continue;
170 }
171
172 SkString name = SkOSPath::Basename(path.c_str());
173 fSourceType = "skp";
174 fBenchType = "playback";
halcanary385fe4d2015-08-26 13:07:48 -0700175 return new VisualSKPBench(name.c_str(), pic.get());
joshualitt962cc982015-06-30 07:43:14 -0700176 }
177
halcanary96fcdcc2015-08-27 07:41:13 -0700178 return nullptr;
joshualitt962cc982015-06-30 07:43:14 -0700179}