| /* | |
| * Copyright 2019 Google LLC | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include <memory> | |
| #include "bench/Benchmark.h" | |
| #include "include/core/SkCanvas.h" | |
| #include "include/gpu/ganesh/GrDirectContext.h" | |
| #include "include/private/chromium/GrDeferredDisplayListRecorder.h" | |
| #include "include/private/chromium/GrSurfaceCharacterization.h" | |
| static GrSurfaceCharacterization create_characterization(GrDirectContext* direct) { | |
| size_t maxResourceBytes = direct->getResourceCacheLimit(); | |
| if (!direct->colorTypeSupportedAsSurface(kRGBA_8888_SkColorType)) { | |
| return GrSurfaceCharacterization(); | |
| } | |
| SkImageInfo ii = SkImageInfo::Make(32, 32, kRGBA_8888_SkColorType, | |
| kPremul_SkAlphaType, nullptr); | |
| GrBackendFormat backendFormat = direct->defaultBackendFormat(kRGBA_8888_SkColorType, | |
| GrRenderable::kYes); | |
| if (!backendFormat.isValid()) { | |
| return GrSurfaceCharacterization(); | |
| } | |
| SkSurfaceProps props(0x0, kUnknown_SkPixelGeometry); | |
| GrSurfaceCharacterization c = | |
| direct->threadSafeProxy()->createCharacterization(maxResourceBytes, | |
| ii, | |
| backendFormat, | |
| 1, | |
| kTopLeft_GrSurfaceOrigin, | |
| props, | |
| skgpu::Mipmapped::kNo); | |
| return c; | |
| } | |
| // This benchmark tries to simulate how Viz is using SkDDLRecorders. | |
| // For each config it will create a single DDLRecorder which it reuses for all the runs | |
| // For each run it creates a DDL and stores it for later deletion. | |
| class DDLRecorderBench : public Benchmark { | |
| public: | |
| DDLRecorderBench() { } | |
| protected: | |
| bool isSuitableFor(Backend backend) override { return Backend::kGanesh == backend; } | |
| const char* onGetName() override { return "DDLRecorder"; } | |
| void onDraw(int loops, SkCanvas* origCanvas) override { | |
| if (!fRecorder) { | |
| return; | |
| } | |
| SkASSERT(!fDDLs.size()); | |
| fDDLs.reserve(loops); | |
| for (int i = 0; i < loops; ++i) { | |
| SkCanvas* recordingCanvas = fRecorder->getCanvas(); | |
| recordingCanvas->drawRect(SkRect::MakeWH(32, 32), SkPaint()); | |
| fDDLs.emplace_back(fRecorder->detach()); | |
| } | |
| } | |
| private: | |
| // We create one DDLRecorder for all the timing runs and just keep reusing it | |
| void onPerCanvasPreDraw(SkCanvas* origCanvas) override { | |
| auto context = origCanvas->recordingContext()->asDirectContext(); | |
| if (!context) { | |
| return; | |
| } | |
| GrSurfaceCharacterization c = create_characterization(context); | |
| fRecorder = std::make_unique<GrDeferredDisplayListRecorder>(c); | |
| } | |
| // We defer the clean up of the DDLs so it is done outside of the timing loop | |
| void onPostDraw(SkCanvas*) override { | |
| fDDLs.clear(); | |
| } | |
| std::unique_ptr<GrDeferredDisplayListRecorder> fRecorder = nullptr; | |
| std::vector<sk_sp<GrDeferredDisplayList>> fDDLs; | |
| using INHERITED = Benchmark; | |
| }; | |
| DEF_BENCH(return new DDLRecorderBench();) |