116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck/* 216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * Copyright (C) 2015 The Android Open Source Project 316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * 416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * Licensed under the Apache License, Version 2.0 (the "License"); 516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * you may not use this file except in compliance with the License. 616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * You may obtain a copy of the License at 716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * 816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * http://www.apache.org/licenses/LICENSE-2.0 916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * 1016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * Unless required by applicable law or agreed to in writing, software 1116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * distributed under the License is distributed on an "AS IS" BASIS, 1216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * See the License for the specific language governing permissions and 1416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * limitations under the License. 1516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck */ 1616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 1716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck#include "AnimationContext.h" 1816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck#include "RenderNode.h" 1927e58b4f54d693ff1db7ab2edb5d47ca296c1278Chris Craik#include "tests/common/TestContext.h" 2027e58b4f54d693ff1db7ab2edb5d47ca296c1278Chris Craik#include "tests/common/TestScene.h" 218160f20b0aca8c6595d4b385d673f59b6bcd16a4Chris Craik#include "tests/common/scenes/TestSceneBase.h" 2216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck#include "renderthread/RenderProxy.h" 2316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck#include "renderthread/RenderTask.h" 2416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 25f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck#include <benchmark/benchmark.h> 2616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck#include <gui/Surface.h> 2796bf5985d5a360568832fd26b6d5b44236c9343eMark Salyzyn#include <log/log.h> 2816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck#include <ui/PixelFormat.h> 2916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 3016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reckusing namespace android; 3116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reckusing namespace android::uirenderer; 3216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reckusing namespace android::uirenderer::renderthread; 3316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reckusing namespace android::uirenderer::test; 3416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 3516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reckclass ContextFactory : public IContextFactory { 3616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reckpublic: 3716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) override { 3816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck return new AnimationContext(clock); 3916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck } 4016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck}; 4116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 42682573c84b7c21dc8ce4a2375da3961147442c4aJohn Recktemplate<class T> 43682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reckclass ModifiedMovingAverage { 44682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reckpublic: 45d53e3bed1ca4a14b2a86d53eaef6969bd043176eChih-Hung Hsieh explicit ModifiedMovingAverage(int weight) : mWeight(weight) {} 46682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck 47682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck T add(T today) { 48682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck if (!mHasValue) { 49682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck mAverage = today; 50682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck } else { 51682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck mAverage = (((mWeight - 1) * mAverage) + today) / mWeight; 52682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck } 53682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck return mAverage; 54682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck } 55682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck 56682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck T average() { 57682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck return mAverage; 58682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck } 59682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck 60682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reckprivate: 61682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck bool mHasValue = false; 62682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck int mWeight; 63682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck T mAverage; 64682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck}; 65682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck 66f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reckvoid outputBenchmarkReport(const TestScene::Info& info, const TestScene::Options& opts, 67f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck benchmark::BenchmarkReporter* reporter, RenderProxy* proxy, 68f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck double durationInS) { 69f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck using namespace benchmark; 70f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck 71f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck struct ReportInfo { 72f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck int percentile; 73f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck const char* suffix; 74f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck }; 75f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck 76f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck static std::array<ReportInfo, 4> REPORTS = { 77f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck ReportInfo { 50, "_50th" }, 78f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck ReportInfo { 90, "_90th" }, 79f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck ReportInfo { 95, "_95th" }, 80f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck ReportInfo { 99, "_99th" }, 81f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck }; 82f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck 83f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck // Although a vector is used, it must stay with only a single element 84f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck // otherwise the BenchmarkReporter will automatically compute 85f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck // mean and stddev which doesn't make sense for our usage 86f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck std::vector<BenchmarkReporter::Run> reports; 87f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck BenchmarkReporter::Run report; 88f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck report.benchmark_name = info.name; 89f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck report.iterations = static_cast<int64_t>(opts.count); 90f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck report.real_accumulated_time = durationInS; 91f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck report.cpu_accumulated_time = durationInS; 92f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck report.items_per_second = opts.count / durationInS; 93f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck reports.push_back(report); 94f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck reporter->ReportRuns(reports); 95f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck 96f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck // Pretend the percentiles are single-iteration runs of the test 97f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck // If rendering offscreen skip this as it's fps that's more interesting 98f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck // in that test case than percentiles. 99f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck if (!opts.renderOffscreen) { 100f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck for (auto& ri : REPORTS) { 101f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck reports[0].benchmark_name = info.name; 102f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck reports[0].benchmark_name += ri.suffix; 103f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck durationInS = proxy->frameTimePercentile(ri.percentile) / 1000.0; 104f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck reports[0].real_accumulated_time = durationInS; 105f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck reports[0].cpu_accumulated_time = durationInS; 106f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck reports[0].iterations = 1; 107f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck reports[0].items_per_second = 0; 108f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck reporter->ReportRuns(reports); 109f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck } 110f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck } 111f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck} 112f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck 113f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reckvoid run(const TestScene::Info& info, const TestScene::Options& opts, 114f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck benchmark::BenchmarkReporter* reporter) { 11516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck // Switch to the real display 11616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck gDisplay = getBuiltInDisplay(); 11716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 11816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck std::unique_ptr<TestScene> scene(info.createScene(opts)); 11916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 120a5c73e3839129e0079b370bd2723bc0fc4aa6387sergeyv Properties::forceDrawFrame = true; 12116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck TestContext testContext; 122f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck testContext.setRenderOffscreen(opts.renderOffscreen); 12316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 12416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck // create the native surface 12516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck const int width = gDisplay.w; 12616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck const int height = gDisplay.h; 12716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck sp<Surface> surface = testContext.surface(); 12816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 12916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck sp<RenderNode> rootNode = TestUtils::createNode(0, 0, width, height, 13006152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev [&scene, width, height](RenderProperties& props, Canvas& canvas) { 13116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.setClipToBounds(false); 13216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck scene->createContent(width, height, canvas); 13316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 13416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 13516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck ContextFactory factory; 13616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck std::unique_ptr<RenderProxy> proxy(new RenderProxy(false, 13716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck rootNode.get(), &factory)); 13816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck proxy->loadSystemProperties(); 13916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck proxy->initialize(surface); 14016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck float lightX = width / 2.0; 141ab1080c4d075b008cebdd9a2031ebbd51f9c2729John Reck proxy->setup(dp(800.0f), 255 * 0.075, 255 * 0.15); 14216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck proxy->setLightCenter((Vector3){lightX, dp(-200.0f), dp(800.0f)}); 14316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 14416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck // Do a few cold runs then reset the stats so that the caches are all hot 145f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck int warmupFrameCount = 5; 146f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck if (opts.renderOffscreen) { 147f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck // Do a few more warmups to try and boost the clocks up 148f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck warmupFrameCount = 10; 149f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck } 150f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck for (int i = 0; i < warmupFrameCount; i++) { 15116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck testContext.waitForVsync(); 15216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck nsecs_t vsync = systemTime(CLOCK_MONOTONIC); 15316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck UiFrameInfoBuilder(proxy->frameInfo()).setVsync(vsync, vsync); 1542de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck proxy->syncAndDrawFrame(); 15516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck } 156682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck 15716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck proxy->resetProfileInfo(); 158682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck proxy->fence(); 159682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck 160682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck ModifiedMovingAverage<double> avgMs(opts.reportFrametimeWeight); 16116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 162f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck nsecs_t start = systemTime(CLOCK_MONOTONIC); 16316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck for (int i = 0; i < opts.count; i++) { 16416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck testContext.waitForVsync(); 16516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck nsecs_t vsync = systemTime(CLOCK_MONOTONIC); 166682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck { 167682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck ATRACE_NAME("UI-Draw Frame"); 168682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck UiFrameInfoBuilder(proxy->frameInfo()).setVsync(vsync, vsync); 169682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck scene->doFrame(i); 1702de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck proxy->syncAndDrawFrame(); 171682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck } 172682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck if (opts.reportFrametimeWeight) { 1732705c983f5e3299e1481fd98a80fc78bce927527Chris Craik proxy->fence(); 1742705c983f5e3299e1481fd98a80fc78bce927527Chris Craik nsecs_t done = systemTime(CLOCK_MONOTONIC); 175682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck avgMs.add((done - vsync) / 1000000.0); 176682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck if (i % 10 == 9) { 177682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck printf("Average frametime %.3fms\n", avgMs.average()); 178682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck } 179682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck } 18016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck } 181f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck proxy->fence(); 182f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck nsecs_t end = systemTime(CLOCK_MONOTONIC); 18316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 184f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck if (reporter) { 185f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck outputBenchmarkReport(info, opts, reporter, proxy.get(), 186f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck (end - start) / (double) s2ns(1)); 187f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck } else { 188f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck proxy->dumpProfileInfo(STDOUT_FILENO, DumpFlags::JankStats); 189f1480761c1a83aecd09cdd473ec797a41d1a2f3fJohn Reck } 19016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck} 191