OLD | NEW |
| (Empty) |
1 /* | |
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> | |
10 #include <VisualBench/WrappedBenchmark.h> | |
11 #include "GMBench.h" | |
12 #include "SkOSFile.h" | |
13 #include "SkPath.h" | |
14 #include "SkPictureRecorder.h" | |
15 #include "SkStream.h" | |
16 #include "sk_tool_utils.h" | |
17 #include "VisualFlags.h" | |
18 #include "VisualSKPBench.h" | |
19 | |
20 #if SK_SUPPORT_GPU | |
21 #include "GrContext.h" | |
22 #endif | |
23 | |
24 DEFINE_string2(match, m, nullptr, | |
25 "[~][^]substring[$] [...] of bench name to run.\n" | |
26 "Multiple matches may be separated by spaces.\n" | |
27 "~ causes a matching bench to always be skipped\n" | |
28 "^ requires the start of the bench to match\n" | |
29 "$ requires the end of the bench to match\n" | |
30 "^ and $ requires an exact match\n" | |
31 "If a bench does not match any list entry,\n" | |
32 "it is skipped unless some list entry starts with ~"); | |
33 DEFINE_string(skps, "skps", "Directory to read skps from."); | |
34 DEFINE_bool(warmup, true, "Include a warmup bench? (Excluding the warmup may com
promise results)"); | |
35 | |
36 // We draw a big nonAA path to warmup the gpu / cpu | |
37 #include "SkPerlinNoiseShader.h" | |
38 class WarmupBench : public Benchmark { | |
39 public: | |
40 WarmupBench() { | |
41 sk_tool_utils::make_big_path(fPath); | |
42 fPerlinRect = SkRect::MakeLTRB(0., 0., 400., 400.); | |
43 } | |
44 private: | |
45 const char* onGetName() override { return "warmupbench"; } | |
46 SkIPoint onGetSize() override { | |
47 int w = SkScalarCeilToInt(SkTMax(fPath.getBounds().right(), fPerlinRect.
right())); | |
48 int h = SkScalarCeilToInt(SkTMax(fPath.getBounds().bottom(), fPerlinRect
.bottom())); | |
49 return SkIPoint::Make(w, h); | |
50 } | |
51 void onDraw(int loops, SkCanvas* canvas) override { | |
52 // We draw a big path to warm up the cpu, and then use perlin noise shad
er to warm up the | |
53 // gpu | |
54 SkPaint paint; | |
55 paint.setStyle(SkPaint::kStroke_Style); | |
56 paint.setStrokeWidth(2); | |
57 | |
58 SkPaint perlinPaint; | |
59 perlinPaint.setShader(SkPerlinNoiseShader::MakeTurbulence(0.1f, 0.1f, 1,
0, nullptr)); | |
60 for (int i = 0; i < loops; i++) { | |
61 canvas->drawPath(fPath, paint); | |
62 canvas->drawRect(fPerlinRect, perlinPaint); | |
63 #if SK_SUPPORT_GPU | |
64 // Ensure the GrContext doesn't batch across draw loops. | |
65 if (GrContext* context = canvas->getGrContext()) { | |
66 context->flush(); | |
67 } | |
68 #endif | |
69 } | |
70 } | |
71 SkPath fPath; | |
72 SkRect fPerlinRect; | |
73 }; | |
74 | |
75 VisualBenchmarkStream::VisualBenchmarkStream(const SkSurfaceProps& surfaceProps,
bool justSKP) | |
76 : fSurfaceProps(surfaceProps) | |
77 , fBenches(BenchRegistry::Head()) | |
78 , fGMs(skiagm::GMRegistry::Head()) | |
79 , fSourceType(nullptr) | |
80 , fBenchType(nullptr) | |
81 , fCurrentSKP(0) | |
82 , fIsWarmedUp(false) { | |
83 for (int i = 0; i < FLAGS_skps.count(); i++) { | |
84 if (SkStrEndsWith(FLAGS_skps[i], ".skp")) { | |
85 fSKPs.push_back() = FLAGS_skps[i]; | |
86 } else { | |
87 SkOSFile::Iter it(FLAGS_skps[i], ".skp"); | |
88 SkString path; | |
89 while (it.next(&path)) { | |
90 fSKPs.push_back() = SkOSPath::Join(FLAGS_skps[0], path.c_str()); | |
91 } | |
92 } | |
93 } | |
94 | |
95 if (justSKP) { | |
96 fGMs = nullptr; | |
97 fBenches = nullptr; | |
98 } | |
99 | |
100 // seed with an initial benchmark | |
101 // NOTE the initial benchmark will not have preTimingHooks called, but that
is okay because | |
102 // it is the warmupbench | |
103 this->next(); | |
104 } | |
105 | |
106 sk_sp<SkPicture> VisualBenchmarkStream::ReadPicture(const char path[]) { | |
107 // Not strictly necessary, as it will be checked again later, | |
108 // but helps to avoid a lot of pointless work if we're going to skip it. | |
109 if (SkCommandLineFlags::ShouldSkip(FLAGS_match, path)) { | |
110 return nullptr; | |
111 } | |
112 | |
113 SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(path)); | |
114 if (stream.get() == nullptr) { | |
115 SkDebugf("Could not read %s.\n", path); | |
116 return nullptr; | |
117 } | |
118 | |
119 auto pic = SkPicture::MakeFromStream(stream.get()); | |
120 if (!pic) { | |
121 SkDebugf("Could not read %s as an SkPicture.\n", path); | |
122 } | |
123 return pic; | |
124 } | |
125 | |
126 Benchmark* VisualBenchmarkStream::next() { | |
127 Benchmark* bench; | |
128 if (FLAGS_warmup && !fIsWarmedUp) { | |
129 fIsWarmedUp = true; | |
130 bench = new WarmupBench; | |
131 } else { | |
132 // skips non matching benches | |
133 while ((bench = this->innerNext()) && | |
134 (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getUniqueName
()) || | |
135 !bench->isSuitableFor(Benchmark::kGPU_Backend))) { | |
136 bench->unref(); | |
137 } | |
138 } | |
139 | |
140 // TODO move this all to --config | |
141 if (bench && FLAGS_cpu) { | |
142 bench = new CpuWrappedBenchmark(fSurfaceProps, bench); | |
143 } else if (bench && FLAGS_offscreen) { | |
144 bench = new GpuWrappedBenchmark(fSurfaceProps, bench, FLAGS_msaa); | |
145 } | |
146 | |
147 fBenchmark.reset(bench); | |
148 return fBenchmark; | |
149 } | |
150 | |
151 Benchmark* VisualBenchmarkStream::innerNext() { | |
152 while (fBenches) { | |
153 Benchmark* bench = fBenches->factory()(nullptr); | |
154 fBenches = fBenches->next(); | |
155 if (bench->isVisual()) { | |
156 fSourceType = "bench"; | |
157 fBenchType = "micro"; | |
158 return bench; | |
159 } | |
160 bench->unref(); | |
161 } | |
162 | |
163 while (fGMs) { | |
164 SkAutoTDelete<skiagm::GM> gm(fGMs->factory()(nullptr)); | |
165 fGMs = fGMs->next(); | |
166 if (gm->runAsBench()) { | |
167 fSourceType = "gm"; | |
168 fBenchType = "micro"; | |
169 return new GMBench(gm.release()); | |
170 } | |
171 } | |
172 | |
173 // Render skps | |
174 while (fCurrentSKP < fSKPs.count()) { | |
175 const SkString& path = fSKPs[fCurrentSKP++]; | |
176 sk_sp<SkPicture> pic = ReadPicture(path.c_str()); | |
177 if (!pic) { | |
178 continue; | |
179 } | |
180 | |
181 SkString name = SkOSPath::Basename(path.c_str()); | |
182 fSourceType = "skp"; | |
183 fBenchType = "playback"; | |
184 return new VisualSKPBench(name.c_str(), pic.get()); | |
185 } | |
186 | |
187 return nullptr; | |
188 } | |
OLD | NEW |