• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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