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