Home | History | Annotate | Download | only in microbench
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <benchmark/benchmark.h>
     18 
     19 #include "BakedOpDispatcher.h"
     20 #include "BakedOpRenderer.h"
     21 #include "BakedOpState.h"
     22 #include "FrameBuilder.h"
     23 #include "LayerUpdateQueue.h"
     24 #include "RecordedOp.h"
     25 #include "RecordingCanvas.h"
     26 #include "Vector.h"
     27 #include "tests/common/TestContext.h"
     28 #include "tests/common/TestScene.h"
     29 #include "tests/common/TestUtils.h"
     30 
     31 #include <vector>
     32 
     33 using namespace android;
     34 using namespace android::uirenderer;
     35 using namespace android::uirenderer::renderthread;
     36 using namespace android::uirenderer::test;
     37 
     38 const FrameBuilder::LightGeometry sLightGeometry = {{100, 100, 100}, 50};
     39 const BakedOpRenderer::LightInfo sLightInfo = {128, 128};
     40 
     41 static sp<RenderNode> createTestNode() {
     42     auto node = TestUtils::createNode<RecordingCanvas>(
     43             0, 0, 200, 200, [](RenderProperties& props, RecordingCanvas& canvas) {
     44                 sk_sp<Bitmap> bitmap(TestUtils::createBitmap(10, 10));
     45                 SkPaint paint;
     46 
     47                 // Alternate between drawing rects and bitmaps, with bitmaps overlapping rects.
     48                 // Rects don't overlap bitmaps, so bitmaps should be brought to front as a group.
     49                 canvas.save(SaveFlags::MatrixClip);
     50                 for (int i = 0; i < 30; i++) {
     51                     canvas.translate(0, 10);
     52                     canvas.drawRect(0, 0, 10, 10, paint);
     53                     canvas.drawBitmap(*bitmap, 5, 0, nullptr);
     54                 }
     55                 canvas.restore();
     56             });
     57     TestUtils::syncHierarchyPropertiesAndDisplayList(node);
     58     return node;
     59 }
     60 
     61 void BM_FrameBuilder_defer(benchmark::State& state) {
     62     TestUtils::runOnRenderThread([&state](RenderThread& thread) {
     63         auto node = createTestNode();
     64         while (state.KeepRunning()) {
     65             FrameBuilder frameBuilder(SkRect::MakeWH(100, 200), 100, 200, sLightGeometry,
     66                                       Caches::getInstance());
     67             frameBuilder.deferRenderNode(*node);
     68             benchmark::DoNotOptimize(&frameBuilder);
     69         }
     70     });
     71 }
     72 BENCHMARK(BM_FrameBuilder_defer);
     73 
     74 void BM_FrameBuilder_deferAndRender(benchmark::State& state) {
     75     TestUtils::runOnRenderThread([&state](RenderThread& thread) {
     76         auto node = createTestNode();
     77 
     78         RenderState& renderState = thread.renderState();
     79         Caches& caches = Caches::getInstance();
     80 
     81         while (state.KeepRunning()) {
     82             FrameBuilder frameBuilder(SkRect::MakeWH(100, 200), 100, 200, sLightGeometry, caches);
     83             frameBuilder.deferRenderNode(*node);
     84 
     85             BakedOpRenderer renderer(caches, renderState, true, false, sLightInfo);
     86             frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
     87             benchmark::DoNotOptimize(&renderer);
     88         }
     89     });
     90 }
     91 BENCHMARK(BM_FrameBuilder_deferAndRender);
     92 
     93 static sp<RenderNode> getSyncedSceneNode(const char* sceneName) {
     94     gDisplay = getBuiltInDisplay();  // switch to real display if present
     95 
     96     TestContext testContext;
     97     TestScene::Options opts;
     98     std::unique_ptr<TestScene> scene(TestScene::testMap()[sceneName].createScene(opts));
     99 
    100     sp<RenderNode> rootNode = TestUtils::createNode<RecordingCanvas>(
    101             0, 0, gDisplay.w, gDisplay.h,
    102             [&scene](RenderProperties& props, RecordingCanvas& canvas) {
    103                 scene->createContent(gDisplay.w, gDisplay.h, canvas);
    104             });
    105 
    106     TestUtils::syncHierarchyPropertiesAndDisplayList(rootNode);
    107     return rootNode;
    108 }
    109 
    110 static auto SCENES = {
    111         "listview",
    112 };
    113 
    114 void BM_FrameBuilder_defer_scene(benchmark::State& state) {
    115     TestUtils::runOnRenderThread([&state](RenderThread& thread) {
    116         const char* sceneName = *(SCENES.begin() + state.range(0));
    117         state.SetLabel(sceneName);
    118         auto node = getSyncedSceneNode(sceneName);
    119         while (state.KeepRunning()) {
    120             FrameBuilder frameBuilder(SkRect::MakeWH(gDisplay.w, gDisplay.h), gDisplay.w,
    121                                       gDisplay.h, sLightGeometry, Caches::getInstance());
    122             frameBuilder.deferRenderNode(*node);
    123             benchmark::DoNotOptimize(&frameBuilder);
    124         }
    125     });
    126 }
    127 BENCHMARK(BM_FrameBuilder_defer_scene)->DenseRange(0, SCENES.size() - 1);
    128 
    129 void BM_FrameBuilder_deferAndRender_scene(benchmark::State& state) {
    130     TestUtils::runOnRenderThread([&state](RenderThread& thread) {
    131         const char* sceneName = *(SCENES.begin() + state.range(0));
    132         state.SetLabel(sceneName);
    133         auto node = getSyncedSceneNode(sceneName);
    134 
    135         RenderState& renderState = thread.renderState();
    136         Caches& caches = Caches::getInstance();
    137 
    138         while (state.KeepRunning()) {
    139             FrameBuilder frameBuilder(SkRect::MakeWH(gDisplay.w, gDisplay.h), gDisplay.w,
    140                                       gDisplay.h, sLightGeometry, Caches::getInstance());
    141             frameBuilder.deferRenderNode(*node);
    142 
    143             BakedOpRenderer renderer(caches, renderState, true, false, sLightInfo);
    144             frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
    145             benchmark::DoNotOptimize(&renderer);
    146         }
    147     });
    148 }
    149 BENCHMARK(BM_FrameBuilder_deferAndRender_scene)->DenseRange(0, SCENES.size() - 1);
    150