diff options
author | 2020-12-09 13:45:39 -0500 | |
---|---|---|
committer | 2020-12-09 13:45:56 -0500 | |
commit | b5eeb18f0ababf79f465258da380e7f587a4398e (patch) | |
tree | 9db8a59217bef71062eb310f96185f4fe3540042 | |
parent | a3b82500edb0ea66b42040a1ffebdf48101d6b61 (diff) |
Add initial benchmarks for CanvasOp
Also some minor other tweaks
Test: this
Change-Id: Idb8a5955839893ff000de87d4899fd130ede061c
-rw-r--r-- | libs/hwui/Android.bp | 1 | ||||
-rw-r--r-- | libs/hwui/DisplayList.h | 5 | ||||
-rw-r--r-- | libs/hwui/RenderNode.cpp | 2 | ||||
-rw-r--r-- | libs/hwui/canvas/CanvasFrontend.cpp | 7 | ||||
-rw-r--r-- | libs/hwui/canvas/CanvasFrontend.h | 24 | ||||
-rw-r--r-- | libs/hwui/canvas/CanvasOps.h | 6 | ||||
-rw-r--r-- | libs/hwui/canvas/OpBuffer.h | 3 | ||||
-rw-r--r-- | libs/hwui/hwui/Canvas.h | 13 | ||||
-rw-r--r-- | libs/hwui/pipeline/skia/SkiaDisplayList.cpp | 2 | ||||
-rw-r--r-- | libs/hwui/pipeline/skia/SkiaDisplayList.h | 2 | ||||
-rw-r--r-- | libs/hwui/tests/microbench/CanvasOpBench.cpp | 96 | ||||
-rw-r--r-- | libs/hwui/tests/microbench/RenderNodeBench.cpp | 26 | ||||
-rw-r--r-- | libs/hwui/tests/unit/SkiaDisplayListTests.cpp | 2 |
13 files changed, 160 insertions, 29 deletions
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index 1ff1978044b9..0533aa6ad45d 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -672,6 +672,7 @@ cc_benchmark { srcs: [ "tests/microbench/main.cpp", + "tests/microbench/CanvasOpBench.cpp", "tests/microbench/DisplayListCanvasBench.cpp", "tests/microbench/LinearAllocatorBench.cpp", "tests/microbench/PathParserBench.cpp", diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h index dc63e5db4a70..dd2476313b19 100644 --- a/libs/hwui/DisplayList.h +++ b/libs/hwui/DisplayList.h @@ -16,14 +16,15 @@ #pragma once -#include "pipeline/skia/SkiaDisplayList.h" - namespace android { namespace uirenderer { namespace VectorDrawable { class Tree; }; +namespace skiapipeline { +class SkiaDisplayList; +} typedef uirenderer::VectorDrawable::Tree VectorDrawableRoot; /** diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index 31e45558139d..74c70c8969f2 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -380,7 +380,7 @@ void RenderNode::deleteDisplayList(TreeObserver& observer, TreeInfo* info) { if (mDisplayList) { mDisplayList->updateChildren( [&observer, info](RenderNode* child) { child->decParentRefCount(observer, info); }); - if (!mDisplayList->reuseDisplayList(this, info ? &info->canvasContext : nullptr)) { + if (!mDisplayList->reuseDisplayList(this)) { delete mDisplayList; } } diff --git a/libs/hwui/canvas/CanvasFrontend.cpp b/libs/hwui/canvas/CanvasFrontend.cpp index 2c839b0ffc15..8f261c83b8d3 100644 --- a/libs/hwui/canvas/CanvasFrontend.cpp +++ b/libs/hwui/canvas/CanvasFrontend.cpp @@ -21,7 +21,14 @@ namespace android::uirenderer { CanvasStateHelper::CanvasStateHelper(int width, int height) { + resetState(width, height); +} + +void CanvasStateHelper::resetState(int width, int height) { mInitialBounds = SkIRect::MakeWH(width, height); + mSaveStack.clear(); + mClipStack.clear(); + mTransformStack.clear(); mSaveStack.emplace_back(); mClipStack.emplace_back().setRect(mInitialBounds); mTransformStack.emplace_back(); diff --git a/libs/hwui/canvas/CanvasFrontend.h b/libs/hwui/canvas/CanvasFrontend.h index 5fccccb0bb43..d749d2f2596b 100644 --- a/libs/hwui/canvas/CanvasFrontend.h +++ b/libs/hwui/canvas/CanvasFrontend.h @@ -57,9 +57,7 @@ protected: } bool internalSave(SaveEntry saveEntry); - bool internalSave(SaveFlags::Flags flags) { - return internalSave(flagsToSaveEntry(flags)); - } + void internalSaveLayer(const SkCanvas::SaveLayerRec& layerRec) { internalSave({ .clip = true, @@ -90,6 +88,8 @@ protected: return mClipStack[mCurrentClipIndex]; } + void resetState(int width, int height); + public: int saveCount() const { return mSaveStack.size(); } @@ -186,14 +186,26 @@ public: submit(std::move(op)); } - const CanvasOpReceiver& receiver() const { return mReceiver; } + const CanvasOpReceiver& receiver() const { return *mReceiver; } + + CanvasOpReceiver finish() { + auto ret = std::move(mReceiver.value()); + mReceiver.reset(); + return std::move(ret); + } + + template<class... Args> + void reset(int newWidth, int newHeight, Args&&... args) { + resetState(newWidth, newHeight); + mReceiver.emplace(std::forward<Args>(args)...); + } private: - CanvasOpReceiver mReceiver; + std::optional<CanvasOpReceiver> mReceiver; template <CanvasOpType T> void submit(CanvasOp<T>&& op) { - mReceiver.push_container(CanvasOpContainer(std::move(op), transform())); + mReceiver->push_container(CanvasOpContainer(std::move(op), transform())); } }; diff --git a/libs/hwui/canvas/CanvasOps.h b/libs/hwui/canvas/CanvasOps.h index b499733757a8..e2c5eaa0b6a7 100644 --- a/libs/hwui/canvas/CanvasOps.h +++ b/libs/hwui/canvas/CanvasOps.h @@ -277,7 +277,7 @@ struct CanvasOp<CanvasOpType::DrawVertices> { template<> struct CanvasOp<CanvasOpType::DrawImage> { - CanvasOp<CanvasOpType::DrawImageRect>( + CanvasOp( const sk_sp<Bitmap>& bitmap, float left, float top, @@ -303,7 +303,7 @@ struct CanvasOp<CanvasOpType::DrawImage> { template<> struct CanvasOp<CanvasOpType::DrawImageRect> { - CanvasOp<CanvasOpType::DrawImageRect>( + CanvasOp( const sk_sp<Bitmap>& bitmap, SkRect src, SkRect dst, @@ -334,7 +334,7 @@ struct CanvasOp<CanvasOpType::DrawImageRect> { template<> struct CanvasOp<CanvasOpType::DrawImageLattice> { - CanvasOp<CanvasOpType::DrawImageLattice>( + CanvasOp( const sk_sp<Bitmap>& bitmap, SkRect dst, SkCanvas::Lattice lattice, diff --git a/libs/hwui/canvas/OpBuffer.h b/libs/hwui/canvas/OpBuffer.h index 98e385f37a6e..6dc29d9a4bfe 100644 --- a/libs/hwui/canvas/OpBuffer.h +++ b/libs/hwui/canvas/OpBuffer.h @@ -60,9 +60,8 @@ class OpBuffer { return (size + (Alignment - 1)) & -Alignment; } - static constexpr auto STARTING_SIZE = PadAlign(sizeof(BufferHeader)); - public: + static constexpr auto STARTING_SIZE = PadAlign(sizeof(BufferHeader)); using ItemHeader = OpBufferItemHeader<ItemTypes>; OpBuffer() = default; diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h index 4d67166dd8d2..11fa3223a9c8 100644 --- a/libs/hwui/hwui/Canvas.h +++ b/libs/hwui/hwui/Canvas.h @@ -21,6 +21,7 @@ #include <SaveFlags.h> #include <androidfw/ResourceTypes.h> +#include "DisplayList.h" #include "Properties.h" #include "utils/Macros.h" @@ -47,18 +48,6 @@ class CanvasPropertyPaint; class CanvasPropertyPrimitive; class DeferredLayerUpdater; class RenderNode; - -namespace skiapipeline { -class SkiaDisplayList; -} - -/** - * Data structure that holds the list of commands used in display list stream - */ -using DisplayList = skiapipeline::SkiaDisplayList; -} - -namespace uirenderer { namespace VectorDrawable { class Tree; } diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp index 158c3493a90c..c63f5d349311 100644 --- a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp +++ b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp @@ -47,7 +47,7 @@ void SkiaDisplayList::syncContents(const WebViewSyncData& data) { } } -bool SkiaDisplayList::reuseDisplayList(RenderNode* node, renderthread::CanvasContext* context) { +bool SkiaDisplayList::reuseDisplayList(RenderNode* node) { reset(); node->attachAvailableList(this); return true; diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.h b/libs/hwui/pipeline/skia/SkiaDisplayList.h index cdd00db9afdc..f2f19ba2975e 100644 --- a/libs/hwui/pipeline/skia/SkiaDisplayList.h +++ b/libs/hwui/pipeline/skia/SkiaDisplayList.h @@ -98,7 +98,7 @@ public: * * @return true if the displayList will be reused and therefore should not be deleted */ - bool reuseDisplayList(RenderNode* node, renderthread::CanvasContext* context); + bool reuseDisplayList(RenderNode* node); /** * ONLY to be called by RenderNode::syncDisplayList so that we can notify any diff --git a/libs/hwui/tests/microbench/CanvasOpBench.cpp b/libs/hwui/tests/microbench/CanvasOpBench.cpp new file mode 100644 index 000000000000..ef5749e6b79b --- /dev/null +++ b/libs/hwui/tests/microbench/CanvasOpBench.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <benchmark/benchmark.h> + +#include "DisplayList.h" +#include "hwui/Paint.h" +#include "canvas/CanvasOpBuffer.h" +#include "canvas/CanvasFrontend.h" +#include "tests/common/TestUtils.h" + +using namespace android; +using namespace android::uirenderer; + +void BM_CanvasOpBuffer_alloc(benchmark::State& benchState) { + while (benchState.KeepRunning()) { + auto displayList = new CanvasOpBuffer(); + benchmark::DoNotOptimize(displayList); + delete displayList; + } +} +BENCHMARK(BM_CanvasOpBuffer_alloc); + +void BM_CanvasOpBuffer_record_saverestore(benchmark::State& benchState) { + CanvasFrontend<CanvasOpBuffer> canvas(100, 100); + while (benchState.KeepRunning()) { + canvas.reset(100, 100); + canvas.save(SaveFlags::MatrixClip); + canvas.save(SaveFlags::MatrixClip); + benchmark::DoNotOptimize(&canvas); + canvas.restore(); + canvas.restore(); + canvas.finish(); + } +} +BENCHMARK(BM_CanvasOpBuffer_record_saverestore); + +void BM_CanvasOpBuffer_record_saverestoreWithReuse(benchmark::State& benchState) { + CanvasFrontend<CanvasOpBuffer> canvas(100, 100); + + while (benchState.KeepRunning()) { + canvas.reset(100, 100); + canvas.save(SaveFlags::MatrixClip); + canvas.save(SaveFlags::MatrixClip); + benchmark::DoNotOptimize(&canvas); + canvas.restore(); + canvas.restore(); + } +} +BENCHMARK(BM_CanvasOpBuffer_record_saverestoreWithReuse); + +void BM_CanvasOpBuffer_record_simpleBitmapView(benchmark::State& benchState) { + CanvasFrontend<CanvasOpBuffer> canvas(100, 100); + + Paint rectPaint; + sk_sp<Bitmap> iconBitmap(TestUtils::createBitmap(80, 80)); + + while (benchState.KeepRunning()) { + canvas.reset(100, 100); + { + canvas.save(SaveFlags::MatrixClip); + canvas.draw(CanvasOp<CanvasOpType::DrawRect> { + .rect = SkRect::MakeWH(100, 100), + .paint = rectPaint, + }); + canvas.restore(); + } + { + canvas.save(SaveFlags::MatrixClip); + canvas.translate(10, 10); + canvas.draw(CanvasOp<CanvasOpType::DrawImage> { + iconBitmap, + 0, + 0, + SkPaint{} + }); + canvas.restore(); + } + benchmark::DoNotOptimize(&canvas); + canvas.finish(); + } +} +BENCHMARK(BM_CanvasOpBuffer_record_simpleBitmapView); diff --git a/libs/hwui/tests/microbench/RenderNodeBench.cpp b/libs/hwui/tests/microbench/RenderNodeBench.cpp index 206dcd58d785..011939a6e4b2 100644 --- a/libs/hwui/tests/microbench/RenderNodeBench.cpp +++ b/libs/hwui/tests/microbench/RenderNodeBench.cpp @@ -30,3 +30,29 @@ void BM_RenderNode_create(benchmark::State& state) { } } BENCHMARK(BM_RenderNode_create); + +void BM_RenderNode_recordSimple(benchmark::State& state) { + sp<RenderNode> node = new RenderNode(); + std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(100, 100)); + delete canvas->finishRecording(); + + while (state.KeepRunning()) { + canvas->resetRecording(100, 100, node.get()); + canvas->drawColor(0x00000000, SkBlendMode::kSrcOver); + node->setStagingDisplayList(canvas->finishRecording()); + } +} +BENCHMARK(BM_RenderNode_recordSimple); + +void BM_RenderNode_recordSimpleWithReuse(benchmark::State& state) { + sp<RenderNode> node = new RenderNode(); + std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(100, 100)); + delete canvas->finishRecording(); + + while (state.KeepRunning()) { + canvas->resetRecording(100, 100, node.get()); + canvas->drawColor(0x00000000, SkBlendMode::kSrcOver); + canvas->finishRecording()->reuseDisplayList(node.get()); + } +} +BENCHMARK(BM_RenderNode_recordSimpleWithReuse);
\ No newline at end of file diff --git a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp index 2d34b0980546..c63f008c4aed 100644 --- a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp +++ b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp @@ -84,7 +84,7 @@ TEST(SkiaDisplayList, reuseDisplayList) { // attach a displayList for reuse SkiaDisplayList skiaDL; - ASSERT_TRUE(skiaDL.reuseDisplayList(renderNode.get(), nullptr)); + ASSERT_TRUE(skiaDL.reuseDisplayList(renderNode.get())); // detach the list that you just attempted to reuse availableList = renderNode->detachAvailableList(); |