Flutter Engine
The Flutter Engine
SKPBench.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2014 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#include "bench/GpuTools.h"
9#include "bench/SKPBench.h"
16
17#if defined(SK_GRAPHITE)
21#endif
22
23using namespace skia_private;
24
25// These CPU tile sizes are not good per se, but they are similar to what Chrome uses.
26static DEFINE_int(CPUbenchTileW, 256, "Tile width used for CPU SKP playback.");
27static DEFINE_int(CPUbenchTileH, 256, "Tile height used for CPU SKP playback.");
28
29static DEFINE_int(GPUbenchTileW, 1600, "Tile width used for GPU SKP playback.");
30static DEFINE_int(GPUbenchTileH, 512, "Tile height used for GPU SKP playback.");
31
32SKPBench::SKPBench(const char* name, const SkPicture* pic, const SkIRect& clip, SkScalar scale,
33 bool doLooping)
34 : fPic(SkRef(pic))
35 , fClip(clip)
36 , fScale(scale)
37 , fName(name)
38 , fDoLooping(doLooping) {
39 fUniqueName.printf("%s_%.2g", name, scale); // Scale makes this unqiue for perf.skia.org traces.
40}
41
43 for (int i = 0; i < fSurfaces.size(); ++i) {
44 fSurfaces[i]->unref();
45 }
46}
47
48const char* SKPBench::onGetName() {
49 return fName.c_str();
50}
51
53 return fUniqueName.c_str();
54}
55
58 bounds.intersect(fClip);
59 bounds.intersect(fPic->cullRect().roundOut());
60 SkAssertResult(!bounds.isEmpty());
61
62#if defined(SK_GRAPHITE)
63 const bool gpu = canvas->recordingContext() != nullptr || canvas->recorder() != nullptr;
64#else
65 const bool gpu = canvas->recordingContext() != nullptr;
66#endif
67 int tileW = gpu ? FLAGS_GPUbenchTileW : FLAGS_CPUbenchTileW,
68 tileH = gpu ? FLAGS_GPUbenchTileH : FLAGS_CPUbenchTileH;
69
70 tileW = std::min(tileW, bounds.width());
71 tileH = std::min(tileH, bounds.height());
72
73 int xTiles = SkScalarCeilToInt(bounds.width() / SkIntToScalar(tileW));
74 int yTiles = SkScalarCeilToInt(bounds.height() / SkIntToScalar(tileH));
75
76 fSurfaces.reserve_exact(fSurfaces.size() + (xTiles * yTiles));
77 fTileRects.reserve(xTiles * yTiles);
78
79 SkImageInfo ii = canvas->imageInfo().makeWH(tileW, tileH);
80
81 for (int y = bounds.fTop; y < bounds.fBottom; y += tileH) {
82 for (int x = bounds.fLeft; x < bounds.fRight; x += tileW) {
83 const SkIRect tileRect = SkIRect::MakeXYWH(x, y, tileW, tileH);
84 *fTileRects.append() = tileRect;
85 fSurfaces.emplace_back(canvas->makeSurface(ii));
86
87 // Never want the contents of a tile to include stuff the parent
88 // canvas clips out
90 clip.offset(-SkIntToScalar(tileRect.fLeft), -SkIntToScalar(tileRect.fTop));
91 fSurfaces.back()->getCanvas()->clipRect(clip);
92
93 fSurfaces.back()->getCanvas()->setMatrix(canvas->getLocalToDevice());
94 fSurfaces.back()->getCanvas()->scale(fScale, fScale);
95 }
96 }
97}
98
100 // Draw the last set of tiles into the main canvas in case we're
101 // saving the images
102 for (int i = 0; i < fTileRects.size(); ++i) {
103 sk_sp<SkImage> image(fSurfaces[i]->makeImageSnapshot());
104 canvas->drawImage(image,
105 SkIntToScalar(fTileRects[i].fLeft), SkIntToScalar(fTileRects[i].fTop));
106 }
107
108 fSurfaces.clear();
109 fTileRects.clear();
110}
111
114}
115
117 return SkISize::Make(fClip.width(), fClip.height());
118}
119
120void SKPBench::onDraw(int loops, SkCanvas* canvas) {
121 SkASSERT(fDoLooping || 1 == loops);
122 while (1) {
123 this->drawPicture();
124 if (0 == --loops) {
125 break;
126 }
127
128 // Ensure the gpu backends don't combine ops/tasks across draw loops. Also submit each work
129 // to the gpu so we are measuring the cost of gpu submission and not amortizing one
130 // submission across all loops.
131 auto direct = canvas->recordingContext() ? canvas->recordingContext()->asDirectContext()
132 : nullptr;
133 if (direct) {
134 direct->flushAndSubmit();
135 }
136
137#if defined(SK_GRAPHITE)
138 skgpu::graphite::Recorder* recorder = canvas->recorder();
139 if (recorder) {
140 std::unique_ptr<skgpu::graphite::Recording> recording = recorder->snap();
141 if (recording) {
143 info.fRecording = recording.get();
144 skgpu::graphite::Context* context = recorder->priv().context();
145 context->insertRecording(info);
146 context->submit();
147 }
148 }
149#endif
150 }
151}
152
154 // TODO: remove me
155}
156
158 for (int j = 0; j < fTileRects.size(); ++j) {
159 const SkMatrix trans = SkMatrix::Translate(-fTileRects[j].fLeft / fScale,
160 -fTileRects[j].fTop / fScale);
161 fSurfaces[j]->getCanvas()->drawPicture(fPic.get(), &trans, nullptr);
162 }
163
164 for (int j = 0; j < fTileRects.size(); ++j) {
165 skgpu::Flush(fSurfaces[j].get());
166 }
167}
168
169static void draw_pic_for_stats(SkCanvas* canvas,
170 GrDirectContext* dContext,
171 const SkPicture* picture,
172 TArray<SkString>* keys,
174 dContext->priv().resetGpuStats();
175 dContext->priv().resetContextStats();
176 canvas->drawPicture(picture);
177 dContext->flush();
178
179 dContext->priv().dumpGpuStatsKeyValuePairs(keys, values);
180 dContext->priv().dumpCacheStatsKeyValuePairs(keys, values);
181 dContext->priv().dumpContextStatsKeyValuePairs(keys, values);
182}
183
185 // we do a special single draw and then dump the key / value pairs
186 auto direct = canvas->recordingContext() ? canvas->recordingContext()->asDirectContext()
187 : nullptr;
188 if (!direct) {
189 return;
190 }
191
192 // TODO refactor this out if we want to test other subclasses of skpbench
193 direct->flushAndSubmit();
194 direct->freeGpuResources();
195 direct->resetContext();
196 direct->priv().getGpu()->resetShaderCacheForTesting();
197 draw_pic_for_stats(canvas, direct, fPic.get(), keys, values);
198}
199
201 if (!rContext || !rContext->asDirectContext()) {
202 return false;
203 }
204 // Clear the current DMSAA stats then do a single tiled draw that resets them to the specific
205 // values for our SKP.
206 rContext->asDirectContext()->flushAndSubmit();
207 rContext->priv().dmsaaStats() = {};
208 this->drawPicture(); // Draw tiled for DMSAA stats.
209 rContext->asDirectContext()->flush();
210 return true;
211}
const char * backend
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
const char * fName
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
static DEFINE_int(CPUbenchTileW, 256, "Tile width used for CPU SKP playback.")
static void draw_pic_for_stats(SkCanvas *canvas, GrDirectContext *dContext, const SkPicture *picture, TArray< SkString > *keys, TArray< double > *values)
Definition: SKPBench.cpp:169
#define SkASSERT(cond)
Definition: SkAssert.h:116
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition: SkPath.cpp:3892
static T * SkRef(T *obj)
Definition: SkRefCnt.h:132
#define SkScalarCeilToInt(x)
Definition: SkScalar.h:36
#define SkIntToScalar(x)
Definition: SkScalar.h:57
virtual GrDirectContext * asDirectContext()
void flushAndSubmit(GrSyncCpu sync=GrSyncCpu::kNo)
GrSemaphoresSubmitted flush(const GrFlushInfo &info)
GrDirectContextPriv priv()
GrRecordingContextPriv priv()
~SKPBench() override
Definition: SKPBench.cpp:42
const char * onGetName() override
Definition: SKPBench.cpp:48
void onPerCanvasPreDraw(SkCanvas *) override
Definition: SKPBench.cpp:56
SKPBench(const char *name, const SkPicture *, const SkIRect &devClip, SkScalar scale, bool doLooping)
Definition: SKPBench.cpp:32
void getGpuStats(SkCanvas *, skia_private::TArray< SkString > *keys, skia_private::TArray< double > *values) override
Definition: SKPBench.cpp:184
void onPerCanvasPostDraw(SkCanvas *) override
Definition: SKPBench.cpp:99
bool getDMSAAStats(GrRecordingContext *) override
Definition: SKPBench.cpp:200
virtual void drawMPDPicture()
Definition: SKPBench.cpp:153
void onDraw(int loops, SkCanvas *canvas) override
Definition: SKPBench.cpp:120
const char * onGetUniqueName() override
Definition: SKPBench.cpp:52
virtual void drawPicture()
Definition: SKPBench.cpp:157
bool isSuitableFor(Backend backend) override
Definition: SKPBench.cpp:112
SkISize onGetSize() override
Definition: SKPBench.cpp:116
void clipRect(const SkRect &rect, SkClipOp op, bool doAntiAlias)
Definition: SkCanvas.cpp:1361
sk_sp< SkSurface > makeSurface(const SkImageInfo &info, const SkSurfaceProps *props=nullptr)
Definition: SkCanvas.cpp:1195
virtual GrRecordingContext * recordingContext() const
Definition: SkCanvas.cpp:1637
virtual skgpu::graphite::Recorder * recorder() const
Definition: SkCanvas.cpp:1641
SkM44 getLocalToDevice() const
Definition: SkCanvas.cpp:1633
SkIRect getDeviceClipBounds() const
Definition: SkCanvas.cpp:1607
void setMatrix(const SkM44 &matrix)
Definition: SkCanvas.cpp:1349
void scale(SkScalar sx, SkScalar sy)
Definition: SkCanvas.cpp:1289
void drawPicture(const SkPicture *picture)
Definition: SkCanvas.h:1961
SkImageInfo imageInfo() const
Definition: SkCanvas.cpp:1206
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
Definition: SkCanvas.h:1528
static SkMatrix Translate(SkScalar dx, SkScalar dy)
Definition: SkMatrix.h:91
void offset(SkScalar dx, SkScalar dy, SkPath *dst) const
Definition: SkPath.cpp:1691
virtual SkRect cullRect() const =0
void printf(const char format[],...) SK_PRINTF_LIKE(2
Definition: SkString.cpp:534
const char * c_str() const
Definition: SkString.h:133
SkCanvas * getCanvas()
Definition: SkSurface.cpp:82
int size() const
Definition: SkTDArray.h:138
void reserve(int n)
Definition: SkTDArray.h:187
T * append()
Definition: SkTDArray.h:191
void clear()
Definition: SkTDArray.h:175
T * get() const
Definition: SkRefCnt.h:303
bool submit(SyncToCpu=SyncToCpu::kNo)
Definition: Context.cpp:162
bool insertRecording(const InsertRecordingInfo &)
Definition: Context.cpp:156
std::unique_ptr< Recording > snap()
Definition: Recorder.cpp:159
int size() const
Definition: SkTArray.h:421
void reserve_exact(int n)
Definition: SkTArray.h:181
T & emplace_back(Args &&... args)
Definition: SkTArray.h:248
float SkScalar
Definition: extension.cpp:12
static float min(float r, float g, float b)
Definition: hsl.cpp:48
double y
double x
Optional< SkRect > bounds
Definition: SkRecords.h:189
sk_sp< const SkImage > image
Definition: SkRecords.h:269
sk_sp< const SkPicture > picture
Definition: SkRecords.h:299
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
const myers::Point & get(const myers::Segment &)
void Flush(SkSurface *surface)
Definition: GpuTools.h:25
const Scalar scale
Definition: SkRect.h:32
constexpr int32_t height() const
Definition: SkRect.h:165
int32_t fTop
smaller y-axis bounds
Definition: SkRect.h:34
constexpr int32_t width() const
Definition: SkRect.h:158
static constexpr SkIRect MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h)
Definition: SkRect.h:104
int32_t fLeft
smaller x-axis bounds
Definition: SkRect.h:33
Definition: SkSize.h:16
static constexpr SkISize Make(int32_t w, int32_t h)
Definition: SkSize.h:20
SkImageInfo makeWH(int newWidth, int newHeight) const
Definition: SkImageInfo.h:444
static SkRect Make(const SkISize &size)
Definition: SkRect.h:669
void roundOut(SkIRect *dst) const
Definition: SkRect.h:1241