1 /* 2 * Copyright 2019 Google LLC 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 <memory> 9 10 #include "bench/Benchmark.h" 11 12 #include "include/core/SkCanvas.h" 13 #include "include/core/SkDeferredDisplayListRecorder.h" 14 #include "include/core/SkSurfaceCharacterization.h" 15 #include "include/gpu/GrDirectContext.h" 16 create_characterization(GrDirectContext * direct)17 static SkSurfaceCharacterization create_characterization(GrDirectContext* direct) { 18 size_t maxResourceBytes = direct->getResourceCacheLimit(); 19 20 if (!direct->colorTypeSupportedAsSurface(kRGBA_8888_SkColorType)) { 21 return SkSurfaceCharacterization(); 22 } 23 24 SkImageInfo ii = SkImageInfo::Make(32, 32, kRGBA_8888_SkColorType, 25 kPremul_SkAlphaType, nullptr); 26 27 GrBackendFormat backendFormat = direct->defaultBackendFormat(kRGBA_8888_SkColorType, 28 GrRenderable::kYes); 29 if (!backendFormat.isValid()) { 30 return SkSurfaceCharacterization(); 31 } 32 33 SkSurfaceProps props(0x0, kUnknown_SkPixelGeometry); 34 35 SkSurfaceCharacterization c = direct->threadSafeProxy()->createCharacterization( 36 maxResourceBytes, ii, backendFormat, 1, 37 kTopLeft_GrSurfaceOrigin, props, false); 38 return c; 39 } 40 41 // This benchmark tries to simulate how Viz is using SkDDLRecorders. 42 // For each config it will create a single DDLRecorder which it reuses for all the runs 43 // For each run it creates a DDL and stores it for later deletion. 44 class DDLRecorderBench : public Benchmark { 45 public: DDLRecorderBench()46 DDLRecorderBench() { } 47 48 protected: isSuitableFor(Backend backend)49 bool isSuitableFor(Backend backend) override { return kGPU_Backend == backend; } 50 onGetName()51 const char* onGetName() override { return "DDLRecorder"; } 52 onDraw(int loops,SkCanvas * origCanvas)53 void onDraw(int loops, SkCanvas* origCanvas) override { 54 if (!fRecorder) { 55 return; 56 } 57 58 SkASSERT(!fDDLs.size()); 59 fDDLs.reserve(loops); 60 61 for (int i = 0; i < loops; ++i) { 62 SkCanvas* recordingCanvas = fRecorder->getCanvas(); 63 64 recordingCanvas->drawRect(SkRect::MakeWH(32, 32), SkPaint()); 65 66 fDDLs.emplace_back(fRecorder->detach()); 67 } 68 } 69 70 private: 71 // We create one DDLRecorder for all the timing runs and just keep reusing it onPerCanvasPreDraw(SkCanvas * origCanvas)72 void onPerCanvasPreDraw(SkCanvas* origCanvas) override { 73 auto context = origCanvas->recordingContext()->asDirectContext(); 74 if (!context) { 75 return; 76 } 77 78 SkSurfaceCharacterization c = create_characterization(context); 79 80 fRecorder = std::make_unique<SkDeferredDisplayListRecorder>(c); 81 } 82 83 // We defer the clean up of the DDLs so it is done outside of the timing loop onPostDraw(SkCanvas *)84 void onPostDraw(SkCanvas*) override { 85 fDDLs.clear(); 86 } 87 88 std::unique_ptr<SkDeferredDisplayListRecorder> fRecorder = nullptr; 89 std::vector<sk_sp<SkDeferredDisplayList>> fDDLs; 90 91 using INHERITED = Benchmark; 92 }; 93 94 DEF_BENCH(return new DDLRecorderBench();) 95