| mtklein | 9200758 | 2014-08-01 07:46:52 -0700 | [diff] [blame] | 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 |  | 
| Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 8 | #include "bench/SKPBench.h" | 
| Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 9 | #include "include/core/SkSurface.h" | 
 | 10 | #include "tools/flags/CommandLineFlags.h" | 
| mtklein | c7f7f46 | 2014-10-21 12:29:25 -0700 | [diff] [blame] | 11 |  | 
| Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 12 | #include "include/gpu/GrContext.h" | 
 | 13 | #include "src/gpu/GrContextPriv.h" | 
| cdalton | e6d2024 | 2015-10-26 13:45:29 -0700 | [diff] [blame] | 14 |  | 
| mtklein | bf9e600 | 2015-06-16 10:41:27 -0700 | [diff] [blame] | 15 | // These CPU tile sizes are not good per se, but they are similar to what Chrome uses. | 
| Mike Klein | 5b3f343 | 2019-03-21 11:42:21 -0500 | [diff] [blame] | 16 | static DEFINE_int(CPUbenchTileW, 256, "Tile width  used for CPU SKP playback."); | 
 | 17 | static DEFINE_int(CPUbenchTileH, 256, "Tile height used for CPU SKP playback."); | 
| mtklein | bf9e600 | 2015-06-16 10:41:27 -0700 | [diff] [blame] | 18 |  | 
| Mike Klein | 5b3f343 | 2019-03-21 11:42:21 -0500 | [diff] [blame] | 19 | static DEFINE_int(GPUbenchTileW, 1600, "Tile width  used for GPU SKP playback."); | 
 | 20 | static DEFINE_int(GPUbenchTileH, 512, "Tile height used for GPU SKP playback."); | 
| mtklein | 9200758 | 2014-08-01 07:46:52 -0700 | [diff] [blame] | 21 |  | 
| robertphillips | 5b69377 | 2014-11-21 06:19:36 -0800 | [diff] [blame] | 22 | SKPBench::SKPBench(const char* name, const SkPicture* pic, const SkIRect& clip, SkScalar scale, | 
| cdalton | b402296 | 2015-06-25 10:51:56 -0700 | [diff] [blame] | 23 |                    bool useMultiPictureDraw, bool doLooping) | 
| mtklein | 9200758 | 2014-08-01 07:46:52 -0700 | [diff] [blame] | 24 |     : fPic(SkRef(pic)) | 
 | 25 |     , fClip(clip) | 
| mtklein | 9628905 | 2014-09-10 12:05:59 -0700 | [diff] [blame] | 26 |     , fScale(scale) | 
| robertphillips | 5b69377 | 2014-11-21 06:19:36 -0800 | [diff] [blame] | 27 |     , fName(name) | 
| cdalton | b402296 | 2015-06-25 10:51:56 -0700 | [diff] [blame] | 28 |     , fUseMultiPictureDraw(useMultiPictureDraw) | 
 | 29 |     , fDoLooping(doLooping) { | 
| tfarina | 0004e7d | 2015-01-26 06:47:55 -0800 | [diff] [blame] | 30 |     fUniqueName.printf("%s_%.2g", name, scale);  // Scale makes this unqiue for perf.skia.org traces. | 
| robertphillips | 5b69377 | 2014-11-21 06:19:36 -0800 | [diff] [blame] | 31 |     if (useMultiPictureDraw) { | 
 | 32 |         fUniqueName.append("_mpd"); | 
 | 33 |     } | 
 | 34 | } | 
 | 35 |  | 
 | 36 | SKPBench::~SKPBench() { | 
 | 37 |     for (int i = 0; i < fSurfaces.count(); ++i) { | 
 | 38 |         fSurfaces[i]->unref(); | 
 | 39 |     } | 
| mtklein | 9200758 | 2014-08-01 07:46:52 -0700 | [diff] [blame] | 40 | } | 
 | 41 |  | 
 | 42 | const char* SKPBench::onGetName() { | 
 | 43 |     return fName.c_str(); | 
 | 44 | } | 
 | 45 |  | 
| mtklein | 9628905 | 2014-09-10 12:05:59 -0700 | [diff] [blame] | 46 | const char* SKPBench::onGetUniqueName() { | 
 | 47 |     return fUniqueName.c_str(); | 
 | 48 | } | 
 | 49 |  | 
| robertphillips | 5b69377 | 2014-11-21 06:19:36 -0800 | [diff] [blame] | 50 | void SKPBench::onPerCanvasPreDraw(SkCanvas* canvas) { | 
| Mike Reed | 918e144 | 2017-01-23 11:39:45 -0500 | [diff] [blame] | 51 |     SkIRect bounds = canvas->getDeviceClipBounds(); | 
 | 52 |     SkAssertResult(!bounds.isEmpty()); | 
| robertphillips | 5b69377 | 2014-11-21 06:19:36 -0800 | [diff] [blame] | 53 |  | 
| mtklein | bf9e600 | 2015-06-16 10:41:27 -0700 | [diff] [blame] | 54 |     const bool gpu = canvas->getGrContext() != nullptr; | 
 | 55 |     int tileW = gpu ? FLAGS_GPUbenchTileW : FLAGS_CPUbenchTileW, | 
 | 56 |         tileH = gpu ? FLAGS_GPUbenchTileH : FLAGS_CPUbenchTileH; | 
 | 57 |  | 
 | 58 |     tileW = SkTMin(tileW, bounds.width()); | 
 | 59 |     tileH = SkTMin(tileH, bounds.height()); | 
| bsalomon | cc4d667 | 2015-03-05 13:42:27 -0800 | [diff] [blame] | 60 |  | 
 | 61 |     int xTiles = SkScalarCeilToInt(bounds.width()  / SkIntToScalar(tileW)); | 
 | 62 |     int yTiles = SkScalarCeilToInt(bounds.height() / SkIntToScalar(tileH)); | 
| robertphillips | 5b69377 | 2014-11-21 06:19:36 -0800 | [diff] [blame] | 63 |  | 
| Ben Wagner | 9ec70c6 | 2018-07-12 13:30:47 -0400 | [diff] [blame] | 64 |     fSurfaces.reserve(xTiles * yTiles); | 
| robertphillips | 5b69377 | 2014-11-21 06:19:36 -0800 | [diff] [blame] | 65 |     fTileRects.setReserve(xTiles * yTiles); | 
 | 66 |  | 
| bsalomon | cc4d667 | 2015-03-05 13:42:27 -0800 | [diff] [blame] | 67 |     SkImageInfo ii = canvas->imageInfo().makeWH(tileW, tileH); | 
| robertphillips | 5b69377 | 2014-11-21 06:19:36 -0800 | [diff] [blame] | 68 |  | 
| bsalomon | cc4d667 | 2015-03-05 13:42:27 -0800 | [diff] [blame] | 69 |     for (int y = bounds.fTop; y < bounds.fBottom; y += tileH) { | 
 | 70 |         for (int x = bounds.fLeft; x < bounds.fRight; x += tileW) { | 
 | 71 |             const SkIRect tileRect = SkIRect::MakeXYWH(x, y, tileW, tileH); | 
| robertphillips | 63242d7 | 2014-12-04 08:31:02 -0800 | [diff] [blame] | 72 |             *fTileRects.append() = tileRect; | 
| Ben Wagner | 9ec70c6 | 2018-07-12 13:30:47 -0400 | [diff] [blame] | 73 |             fSurfaces.emplace_back(canvas->makeSurface(ii)); | 
| robertphillips | 63242d7 | 2014-12-04 08:31:02 -0800 | [diff] [blame] | 74 |  | 
 | 75 |             // Never want the contents of a tile to include stuff the parent | 
 | 76 |             // canvas clips out | 
 | 77 |             SkRect clip = SkRect::Make(bounds); | 
 | 78 |             clip.offset(-SkIntToScalar(tileRect.fLeft), -SkIntToScalar(tileRect.fTop)); | 
| Ben Wagner | 9ec70c6 | 2018-07-12 13:30:47 -0400 | [diff] [blame] | 79 |             fSurfaces.back()->getCanvas()->clipRect(clip); | 
| robertphillips | 63242d7 | 2014-12-04 08:31:02 -0800 | [diff] [blame] | 80 |  | 
| Ben Wagner | 9ec70c6 | 2018-07-12 13:30:47 -0400 | [diff] [blame] | 81 |             fSurfaces.back()->getCanvas()->setMatrix(canvas->getTotalMatrix()); | 
 | 82 |             fSurfaces.back()->getCanvas()->scale(fScale, fScale); | 
| robertphillips | 5b69377 | 2014-11-21 06:19:36 -0800 | [diff] [blame] | 83 |         } | 
 | 84 |     } | 
 | 85 | } | 
 | 86 |  | 
 | 87 | void SKPBench::onPerCanvasPostDraw(SkCanvas* canvas) { | 
| robertphillips | 5b69377 | 2014-11-21 06:19:36 -0800 | [diff] [blame] | 88 |     // Draw the last set of tiles into the master canvas in case we're | 
 | 89 |     // saving the images | 
 | 90 |     for (int i = 0; i < fTileRects.count(); ++i) { | 
| reed | 9ce9d67 | 2016-03-17 10:51:11 -0700 | [diff] [blame] | 91 |         sk_sp<SkImage> image(fSurfaces[i]->makeImageSnapshot()); | 
| robertphillips | 186a08e | 2014-11-21 06:53:00 -0800 | [diff] [blame] | 92 |         canvas->drawImage(image, | 
| robertphillips | 5b69377 | 2014-11-21 06:19:36 -0800 | [diff] [blame] | 93 |                           SkIntToScalar(fTileRects[i].fLeft), SkIntToScalar(fTileRects[i].fTop)); | 
| robertphillips | 5b69377 | 2014-11-21 06:19:36 -0800 | [diff] [blame] | 94 |     } | 
 | 95 |  | 
| Ben Wagner | 9ec70c6 | 2018-07-12 13:30:47 -0400 | [diff] [blame] | 96 |     fSurfaces.reset(); | 
| robertphillips | 5b69377 | 2014-11-21 06:19:36 -0800 | [diff] [blame] | 97 |     fTileRects.rewind(); | 
 | 98 | } | 
 | 99 |  | 
| mtklein | 9200758 | 2014-08-01 07:46:52 -0700 | [diff] [blame] | 100 | bool SKPBench::isSuitableFor(Backend backend) { | 
 | 101 |     return backend != kNonRendering_Backend; | 
 | 102 | } | 
 | 103 |  | 
 | 104 | SkIPoint SKPBench::onGetSize() { | 
 | 105 |     return SkIPoint::Make(fClip.width(), fClip.height()); | 
 | 106 | } | 
 | 107 |  | 
| mtklein | a1ebeb2 | 2015-10-01 09:43:39 -0700 | [diff] [blame] | 108 | void SKPBench::onDraw(int loops, SkCanvas* canvas) { | 
| cdalton | b402296 | 2015-06-25 10:51:56 -0700 | [diff] [blame] | 109 |     SkASSERT(fDoLooping || 1 == loops); | 
| cdalton | 31c45bb | 2016-02-22 08:08:25 -0800 | [diff] [blame] | 110 |     while (1) { | 
 | 111 |         if (fUseMultiPictureDraw) { | 
| joshualitt | 261c3ad | 2015-04-27 09:16:57 -0700 | [diff] [blame] | 112 |             this->drawMPDPicture(); | 
| cdalton | 31c45bb | 2016-02-22 08:08:25 -0800 | [diff] [blame] | 113 |         } else { | 
| joshualitt | 261c3ad | 2015-04-27 09:16:57 -0700 | [diff] [blame] | 114 |             this->drawPicture(); | 
| robertphillips | 5b69377 | 2014-11-21 06:19:36 -0800 | [diff] [blame] | 115 |         } | 
| cdalton | 31c45bb | 2016-02-22 08:08:25 -0800 | [diff] [blame] | 116 |         if (0 == --loops) { | 
 | 117 |             break; | 
 | 118 |         } | 
| Brian Salomon | 09d994e | 2016-12-21 11:14:46 -0500 | [diff] [blame] | 119 |         // Ensure the GrContext doesn't combine ops across draw loops. | 
| cdalton | 31c45bb | 2016-02-22 08:08:25 -0800 | [diff] [blame] | 120 |         if (GrContext* context = canvas->getGrContext()) { | 
 | 121 |             context->flush(); | 
 | 122 |         } | 
| cdalton | 31c45bb | 2016-02-22 08:08:25 -0800 | [diff] [blame] | 123 |     } | 
| mtklein | 9200758 | 2014-08-01 07:46:52 -0700 | [diff] [blame] | 124 | } | 
| joshualitt | 261c3ad | 2015-04-27 09:16:57 -0700 | [diff] [blame] | 125 |  | 
 | 126 | void SKPBench::drawMPDPicture() { | 
| Mike Reed | 2319b80 | 2019-11-15 10:39:50 -0500 | [diff] [blame] | 127 |     // TODO: remove me | 
| joshualitt | 261c3ad | 2015-04-27 09:16:57 -0700 | [diff] [blame] | 128 | } | 
 | 129 |  | 
 | 130 | void SKPBench::drawPicture() { | 
 | 131 |     for (int j = 0; j < fTileRects.count(); ++j) { | 
 | 132 |         const SkMatrix trans = SkMatrix::MakeTrans(-fTileRects[j].fLeft / fScale, | 
 | 133 |                                                    -fTileRects[j].fTop / fScale); | 
| Hal Canary | 2db8361 | 2016-11-04 13:02:54 -0400 | [diff] [blame] | 134 |         fSurfaces[j]->getCanvas()->drawPicture(fPic.get(), &trans, nullptr); | 
| joshualitt | 261c3ad | 2015-04-27 09:16:57 -0700 | [diff] [blame] | 135 |     } | 
 | 136 |  | 
 | 137 |     for (int j = 0; j < fTileRects.count(); ++j) { | 
 | 138 |         fSurfaces[j]->getCanvas()->flush(); | 
 | 139 |     } | 
 | 140 | } | 
| joshualitt | e45c81c | 2015-12-02 09:05:37 -0800 | [diff] [blame] | 141 |  | 
| Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 142 | #include "src/gpu/GrGpu.h" | 
| joshualitt | e45c81c | 2015-12-02 09:05:37 -0800 | [diff] [blame] | 143 | static void draw_pic_for_stats(SkCanvas* canvas, GrContext* context, const SkPicture* picture, | 
| Brian Osman | f2ae6af | 2019-03-25 13:32:28 -0400 | [diff] [blame] | 144 |                                SkTArray<SkString>* keys, SkTArray<double>* values) { | 
| Robert Phillips | 9da87e0 | 2019-02-04 13:26:26 -0500 | [diff] [blame] | 145 |     context->priv().resetGpuStats(); | 
| joshualitt | e45c81c | 2015-12-02 09:05:37 -0800 | [diff] [blame] | 146 |     canvas->drawPicture(picture); | 
 | 147 |     canvas->flush(); | 
 | 148 |  | 
| Robert Phillips | 9da87e0 | 2019-02-04 13:26:26 -0500 | [diff] [blame] | 149 |     context->priv().dumpGpuStatsKeyValuePairs(keys, values); | 
 | 150 |     context->priv().dumpCacheStatsKeyValuePairs(keys, values); | 
| joshualitt | e45c81c | 2015-12-02 09:05:37 -0800 | [diff] [blame] | 151 | } | 
| joshualitt | e45c81c | 2015-12-02 09:05:37 -0800 | [diff] [blame] | 152 |  | 
 | 153 | void SKPBench::getGpuStats(SkCanvas* canvas, SkTArray<SkString>* keys, SkTArray<double>* values) { | 
| joshualitt | e45c81c | 2015-12-02 09:05:37 -0800 | [diff] [blame] | 154 |     // we do a special single draw and then dump the key / value pairs | 
 | 155 |     GrContext* context = canvas->getGrContext(); | 
 | 156 |     if (!context) { | 
 | 157 |         return; | 
 | 158 |     } | 
 | 159 |  | 
 | 160 |     // TODO refactor this out if we want to test other subclasses of skpbench | 
 | 161 |     context->flush(); | 
 | 162 |     context->freeGpuResources(); | 
 | 163 |     context->resetContext(); | 
| Robert Phillips | 9da87e0 | 2019-02-04 13:26:26 -0500 | [diff] [blame] | 164 |     context->priv().getGpu()->resetShaderCacheForTesting(); | 
| Brian Osman | f2ae6af | 2019-03-25 13:32:28 -0400 | [diff] [blame] | 165 |     draw_pic_for_stats(canvas, context, fPic.get(), keys, values); | 
| joshualitt | e45c81c | 2015-12-02 09:05:37 -0800 | [diff] [blame] | 166 | } |