blob: b640b90ecd5e155b2461a0f61bebc57ef1acfeba [file] [log] [blame]
John Reck16c9d6a2015-11-17 15:51:08 -08001/*
2 * Copyright (C) 2015 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 "AnimationContext.h"
John Reck16c9d6a2015-11-17 15:51:08 -080018#include "RenderNode.h"
John Reck1bcacfd2017-11-03 10:12:19 -070019#include "renderthread/RenderProxy.h"
20#include "renderthread/RenderTask.h"
Chris Craik27e58b42015-12-07 10:01:38 -080021#include "tests/common/TestContext.h"
22#include "tests/common/TestScene.h"
Chris Craik8160f202015-12-02 14:50:25 -080023#include "tests/common/scenes/TestSceneBase.h"
John Reck322b8ab2019-03-14 13:15:28 -070024#include "utils/TraceUtils.h"
John Reck16c9d6a2015-11-17 15:51:08 -080025
John Reckf1480762016-07-03 18:28:25 -070026#include <benchmark/benchmark.h>
John Reck16c9d6a2015-11-17 15:51:08 -080027#include <gui/Surface.h>
Mark Salyzyn96bf5982016-09-28 16:15:30 -070028#include <log/log.h>
John Reck16c9d6a2015-11-17 15:51:08 -080029#include <ui/PixelFormat.h>
30
John Reck39207682021-05-12 19:10:47 -040031// These are unstable internal APIs in google-benchmark. We should just implement our own variant
32// of these instead, but this was quicker. Disabled-by-default to avoid any breakages when
33// google-benchmark updates if they change anything
34#if 0
35#define USE_SKETCHY_INTERNAL_STATS
36namespace benchmark {
37std::vector<BenchmarkReporter::Run> ComputeStats(
38 const std::vector<BenchmarkReporter::Run> &reports);
39double StatisticsMean(const std::vector<double>& v);
40double StatisticsMedian(const std::vector<double>& v);
41double StatisticsStdDev(const std::vector<double>& v);
42}
43#endif
44
John Reck16c9d6a2015-11-17 15:51:08 -080045using namespace android;
46using namespace android::uirenderer;
47using namespace android::uirenderer::renderthread;
48using namespace android::uirenderer::test;
49
50class ContextFactory : public IContextFactory {
51public:
52 virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) override {
53 return new AnimationContext(clock);
54 }
55};
56
John Reck1bcacfd2017-11-03 10:12:19 -070057template <class T>
John Reck682573c2015-10-30 10:37:35 -070058class ModifiedMovingAverage {
59public:
Chih-Hung Hsiehd53e3be2016-05-03 10:02:51 -070060 explicit ModifiedMovingAverage(int weight) : mWeight(weight) {}
John Reck682573c2015-10-30 10:37:35 -070061
62 T add(T today) {
63 if (!mHasValue) {
64 mAverage = today;
65 } else {
66 mAverage = (((mWeight - 1) * mAverage) + today) / mWeight;
67 }
68 return mAverage;
69 }
70
John Reck1bcacfd2017-11-03 10:12:19 -070071 T average() { return mAverage; }
John Reck682573c2015-10-30 10:37:35 -070072
73private:
74 bool mHasValue = false;
75 int mWeight;
76 T mAverage;
77};
78
John Recka8427802021-05-10 17:47:50 -040079using BenchmarkResults = std::vector<benchmark::BenchmarkReporter::Run>;
80
John Reckf1480762016-07-03 18:28:25 -070081void outputBenchmarkReport(const TestScene::Info& info, const TestScene::Options& opts,
John Recka8427802021-05-10 17:47:50 -040082 double durationInS, int repetationIndex, BenchmarkResults* reports) {
John Reck39207682021-05-12 19:10:47 -040083 using namespace benchmark;
John Recka8427802021-05-10 17:47:50 -040084 benchmark::BenchmarkReporter::Run report;
85 report.repetitions = opts.repeatCount;
86 report.repetition_index = repetationIndex;
Haibo Huang5eb2e962019-04-04 17:29:15 -070087 report.run_name.function_name = info.name;
John Recka8427802021-05-10 17:47:50 -040088 report.iterations = static_cast<int64_t>(opts.frameCount);
John Reckf1480762016-07-03 18:28:25 -070089 report.real_accumulated_time = durationInS;
90 report.cpu_accumulated_time = durationInS;
John Reck39207682021-05-12 19:10:47 -040091 report.counters["FPS"] = opts.frameCount / durationInS;
92 if (opts.reportGpuMemoryUsage) {
93 size_t cpuUsage, gpuUsage;
94 RenderProxy::getMemoryUsage(&cpuUsage, &gpuUsage);
95 report.counters["Rendering RAM"] = Counter{static_cast<double>(cpuUsage + gpuUsage),
96 Counter::kDefaults, Counter::kIs1024};
97 }
John Recka8427802021-05-10 17:47:50 -040098 reports->push_back(report);
John Reckf1480762016-07-03 18:28:25 -070099}
100
John Recka8427802021-05-10 17:47:50 -0400101static void doRun(const TestScene::Info& info, const TestScene::Options& opts, int repetitionIndex,
102 BenchmarkResults* reports) {
John Reck39207682021-05-12 19:10:47 -0400103 if (opts.reportGpuMemoryUsage) {
104 // If we're reporting GPU memory usage we need to first start with a clean slate
105 RenderProxy::purgeCaches();
106 }
sergeyva5c73e32016-09-14 17:49:41 -0700107 Properties::forceDrawFrame = true;
John Reck16c9d6a2015-11-17 15:51:08 -0800108 TestContext testContext;
John Reckf1480762016-07-03 18:28:25 -0700109 testContext.setRenderOffscreen(opts.renderOffscreen);
John Reck16c9d6a2015-11-17 15:51:08 -0800110
111 // create the native surface
Dominik Laskowski69b281d2019-11-22 14:13:12 -0800112 const ui::Size& resolution = getActiveDisplayResolution();
113 const int width = resolution.getWidth();
114 const int height = resolution.getHeight();
John Reck16c9d6a2015-11-17 15:51:08 -0800115 sp<Surface> surface = testContext.surface();
116
John Recked024d22017-11-10 15:06:32 -0800117 std::unique_ptr<TestScene> scene(info.createScene(opts));
118 scene->renderTarget = surface;
119
John Reck1bcacfd2017-11-03 10:12:19 -0700120 sp<RenderNode> rootNode = TestUtils::createNode(
121 0, 0, width, height, [&scene, width, height](RenderProperties& props, Canvas& canvas) {
122 props.setClipToBounds(false);
123 scene->createContent(width, height, canvas);
124 });
John Reck16c9d6a2015-11-17 15:51:08 -0800125
126 ContextFactory factory;
John Reck1bcacfd2017-11-03 10:12:19 -0700127 std::unique_ptr<RenderProxy> proxy(new RenderProxy(false, rootNode.get(), &factory));
John Reck16c9d6a2015-11-17 15:51:08 -0800128 proxy->loadSystemProperties();
Alec Mouri43fe6fc2019-12-23 07:46:19 -0800129 proxy->setSurface(surface.get());
John Reck16c9d6a2015-11-17 15:51:08 -0800130 float lightX = width / 2.0;
John Reck8785ceb2018-10-29 16:45:58 -0700131 proxy->setLightAlpha(255 * 0.075, 255 * 0.15);
132 proxy->setLightGeometry((Vector3){lightX, dp(-200.0f), dp(800.0f)}, dp(800.0f));
John Reck16c9d6a2015-11-17 15:51:08 -0800133
134 // Do a few cold runs then reset the stats so that the caches are all hot
John Reckf1480762016-07-03 18:28:25 -0700135 int warmupFrameCount = 5;
136 if (opts.renderOffscreen) {
137 // Do a few more warmups to try and boost the clocks up
138 warmupFrameCount = 10;
139 }
140 for (int i = 0; i < warmupFrameCount; i++) {
John Reck16c9d6a2015-11-17 15:51:08 -0800141 testContext.waitForVsync();
Jerome Gaillarde218c692019-06-14 12:58:57 +0100142 nsecs_t vsync = systemTime(SYSTEM_TIME_MONOTONIC);
Steven Thomas6fabb5a2020-08-21 16:56:08 -0700143 UiFrameInfoBuilder(proxy->frameInfo())
Jorim Jaggi10f328c2021-01-19 00:08:02 +0100144 .setVsync(vsync, vsync, UiFrameInfoBuilder::INVALID_VSYNC_ID,
145 UiFrameInfoBuilder::UNKNOWN_DEADLINE,
146 UiFrameInfoBuilder::UNKNOWN_FRAME_INTERVAL);
John Reck2de950d2017-01-25 10:58:30 -0800147 proxy->syncAndDrawFrame();
John Reck16c9d6a2015-11-17 15:51:08 -0800148 }
John Reck682573c2015-10-30 10:37:35 -0700149
John Reck16c9d6a2015-11-17 15:51:08 -0800150 proxy->resetProfileInfo();
John Reck682573c2015-10-30 10:37:35 -0700151 proxy->fence();
152
153 ModifiedMovingAverage<double> avgMs(opts.reportFrametimeWeight);
John Reck16c9d6a2015-11-17 15:51:08 -0800154
Jerome Gaillarde218c692019-06-14 12:58:57 +0100155 nsecs_t start = systemTime(SYSTEM_TIME_MONOTONIC);
John Recka8427802021-05-10 17:47:50 -0400156 for (int i = 0; i < opts.frameCount; i++) {
John Reck16c9d6a2015-11-17 15:51:08 -0800157 testContext.waitForVsync();
Jerome Gaillarde218c692019-06-14 12:58:57 +0100158 nsecs_t vsync = systemTime(SYSTEM_TIME_MONOTONIC);
John Reck682573c2015-10-30 10:37:35 -0700159 {
160 ATRACE_NAME("UI-Draw Frame");
Steven Thomas6fabb5a2020-08-21 16:56:08 -0700161 UiFrameInfoBuilder(proxy->frameInfo())
Jorim Jaggi10f328c2021-01-19 00:08:02 +0100162 .setVsync(vsync, vsync, UiFrameInfoBuilder::INVALID_VSYNC_ID,
163 UiFrameInfoBuilder::UNKNOWN_DEADLINE,
164 UiFrameInfoBuilder::UNKNOWN_FRAME_INTERVAL);
John Reck682573c2015-10-30 10:37:35 -0700165 scene->doFrame(i);
John Reck2de950d2017-01-25 10:58:30 -0800166 proxy->syncAndDrawFrame();
John Reck682573c2015-10-30 10:37:35 -0700167 }
John Reck682573c2015-10-30 10:37:35 -0700168 if (opts.reportFrametimeWeight) {
Chris Craik2705c982016-02-03 17:39:40 -0800169 proxy->fence();
Jerome Gaillarde218c692019-06-14 12:58:57 +0100170 nsecs_t done = systemTime(SYSTEM_TIME_MONOTONIC);
John Reck682573c2015-10-30 10:37:35 -0700171 avgMs.add((done - vsync) / 1000000.0);
172 if (i % 10 == 9) {
173 printf("Average frametime %.3fms\n", avgMs.average());
174 }
175 }
John Reck16c9d6a2015-11-17 15:51:08 -0800176 }
John Reckf1480762016-07-03 18:28:25 -0700177 proxy->fence();
Jerome Gaillarde218c692019-06-14 12:58:57 +0100178 nsecs_t end = systemTime(SYSTEM_TIME_MONOTONIC);
John Reck16c9d6a2015-11-17 15:51:08 -0800179
John Recka8427802021-05-10 17:47:50 -0400180 if (reports) {
181 outputBenchmarkReport(info, opts, (end - start) / (double)s2ns(1), repetitionIndex,
182 reports);
John Reckf1480762016-07-03 18:28:25 -0700183 } else {
184 proxy->dumpProfileInfo(STDOUT_FILENO, DumpFlags::JankStats);
185 }
John Reck16c9d6a2015-11-17 15:51:08 -0800186}
John Recka8427802021-05-10 17:47:50 -0400187
188void run(const TestScene::Info& info, const TestScene::Options& opts,
189 benchmark::BenchmarkReporter* reporter) {
190 BenchmarkResults results;
191 for (int i = 0; i < opts.repeatCount; i++) {
192 doRun(info, opts, i, reporter ? &results : nullptr);
193 }
194 if (reporter) {
195 reporter->ReportRuns(results);
196 if (results.size() > 1) {
John Reck39207682021-05-12 19:10:47 -0400197#ifdef USE_SKETCHY_INTERNAL_STATS
198 std::vector<benchmark::internal::Statistics> stats;
199 stats.reserve(3);
200 stats.emplace_back("mean", benchmark::StatisticsMean);
201 stats.emplace_back("median", benchmark::StatisticsMedian);
202 stats.emplace_back("stddev", benchmark::StatisticsStdDev);
203 for (auto& it : results) {
204 it.statistics = &stats;
205 }
206 auto summary = benchmark::ComputeStats(results);
207 reporter->ReportRuns(summary);
208#endif
John Recka8427802021-05-10 17:47:50 -0400209 }
210 }
John Reck39207682021-05-12 19:10:47 -0400211 if (opts.reportGpuMemoryUsageVerbose) {
John Reck66e06d42021-05-11 17:04:54 -0400212 RenderProxy::dumpGraphicsMemory(STDOUT_FILENO, false);
213 }
John Recka8427802021-05-10 17:47:50 -0400214}