blob: a9264b3914b981e3fec073016e0939e5d4d54d81 [file] [log] [blame]
Leon Scroggins III8fcfa662021-10-12 11:33:30 -04001/*
2 * Copyright 2021 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 <RenderEngineBench.h>
18#include <android-base/file.h>
19#include <benchmark/benchmark.h>
20#include <gui/SurfaceComposerClient.h>
21#include <log/log.h>
22#include <renderengine/ExternalTexture.h>
23#include <renderengine/LayerSettings.h>
24#include <renderengine/RenderEngine.h>
Vishnu Nairdbbe3852022-01-12 20:22:11 -080025#include <renderengine/impl/ExternalTexture.h>
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040026
27#include <mutex>
28
29using namespace android;
30using namespace android::renderengine;
31
Marzia Favaroee1e8ea2024-02-26 17:32:53 +000032// To run tests:
33/**
34 * mmm frameworks/native/libs/renderengine/benchmark;\
35 * adb push $OUT/data/benchmarktest/librenderengine_bench/librenderengine_bench
36 * /data/benchmarktest/librenderengine_bench/librenderengine_bench;\
37 * adb shell /data/benchmarktest/librenderengine_bench/librenderengine_bench
38 *
39 * (64-bit devices: out directory contains benchmarktest64 instead of benchmarktest)
40 */
41
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040042///////////////////////////////////////////////////////////////////////////////
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040043// Helpers for calling drawLayers
44///////////////////////////////////////////////////////////////////////////////
45
46std::pair<uint32_t, uint32_t> getDisplaySize() {
47 // These will be retrieved from a ui::Size, which stores int32_t, but they will be passed
48 // to GraphicBuffer, which wants uint32_t.
49 static uint32_t width, height;
50 std::once_flag once;
51 std::call_once(once, []() {
52 auto surfaceComposerClient = SurfaceComposerClient::getDefault();
Huihong Luo31b5ac22022-08-15 20:38:10 -070053 auto ids = SurfaceComposerClient::getPhysicalDisplayIds();
54 LOG_ALWAYS_FATAL_IF(ids.empty(), "Failed to get any display!");
55 ui::Size resolution = ui::kEmptySize;
56 // find the largest display resolution
57 for (auto id : ids) {
58 auto displayToken = surfaceComposerClient->getPhysicalDisplayToken(id);
59 ui::DisplayMode displayMode;
60 if (surfaceComposerClient->getActiveDisplayMode(displayToken, &displayMode) < 0) {
61 LOG_ALWAYS_FATAL("Failed to get active display mode!");
62 }
63 auto tw = displayMode.resolution.width;
64 auto th = displayMode.resolution.height;
65 LOG_ALWAYS_FATAL_IF(tw <= 0 || th <= 0, "Invalid display size!");
66 if (resolution.width * resolution.height <
67 displayMode.resolution.width * displayMode.resolution.height) {
68 resolution = displayMode.resolution;
69 }
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040070 }
Huihong Luo31b5ac22022-08-15 20:38:10 -070071 width = static_cast<uint32_t>(resolution.width);
72 height = static_cast<uint32_t>(resolution.height);
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040073 });
74 return std::pair<uint32_t, uint32_t>(width, height);
75}
76
Robin Lee26315202021-08-10 22:54:51 +020077static std::unique_ptr<RenderEngine> createRenderEngine(
78 RenderEngine::Threaded threaded, RenderEngine::GraphicsApi graphicsApi,
79 RenderEngine::BlurAlgorithm blurAlgorithm = RenderEngine::BlurAlgorithm::KAWASE) {
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040080 auto args = RenderEngineCreationArgs::Builder()
81 .setPixelFormat(static_cast<int>(ui::PixelFormat::RGBA_8888))
82 .setImageCacheSize(1)
83 .setEnableProtectedContext(true)
84 .setPrecacheToneMapperShaderOnly(false)
Robin Lee26315202021-08-10 22:54:51 +020085 .setBlurAlgorithm(blurAlgorithm)
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040086 .setContextPriority(RenderEngine::ContextPriority::REALTIME)
Leon Scroggins III696bf932024-01-24 15:21:05 -050087 .setThreaded(threaded)
88 .setGraphicsApi(graphicsApi)
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040089 .build();
90 return RenderEngine::create(args);
91}
92
Leon Scroggins IIIb76f17d2021-11-03 15:04:18 -040093static std::shared_ptr<ExternalTexture> allocateBuffer(RenderEngine& re, uint32_t width,
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040094 uint32_t height,
95 uint64_t extraUsageFlags = 0,
96 std::string name = "output") {
Vishnu Nairdbbe3852022-01-12 20:22:11 -080097 return std::make_shared<
Ady Abrahamd11bade2022-08-01 16:18:03 -070098 impl::ExternalTexture>(sp<GraphicBuffer>::make(width, height,
99 HAL_PIXEL_FORMAT_RGBA_8888, 1u,
100 GRALLOC_USAGE_HW_RENDER |
101 GRALLOC_USAGE_HW_TEXTURE |
102 extraUsageFlags,
103 std::move(name)),
Vishnu Nairdbbe3852022-01-12 20:22:11 -0800104 re,
105 impl::ExternalTexture::Usage::READABLE |
106 impl::ExternalTexture::Usage::WRITEABLE);
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400107}
108
109static std::shared_ptr<ExternalTexture> copyBuffer(RenderEngine& re,
110 std::shared_ptr<ExternalTexture> original,
111 uint64_t extraUsageFlags, std::string name) {
112 const uint32_t width = original->getBuffer()->getWidth();
113 const uint32_t height = original->getBuffer()->getHeight();
114 auto texture = allocateBuffer(re, width, height, extraUsageFlags, name);
115
116 const Rect displayRect(0, 0, static_cast<int32_t>(width), static_cast<int32_t>(height));
117 DisplaySettings display{
118 .physicalDisplay = displayRect,
119 .clip = displayRect,
120 .maxLuminance = 500,
121 };
122
123 const FloatRect layerRect(0, 0, width, height);
124 LayerSettings layer{
125 .geometry =
126 Geometry{
127 .boundaries = layerRect,
128 },
129 .source =
130 PixelSource{
131 .buffer =
132 Buffer{
133 .buffer = original,
134 },
135 },
136 .alpha = half(1.0f),
137 };
138 auto layers = std::vector<LayerSettings>{layer};
139
Alec Mourif29700f2023-08-17 21:53:31 +0000140 sp<Fence> waitFence = re.drawLayers(display, layers, texture, base::unique_fd()).get().value();
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400141 waitFence->waitForever(LOG_TAG);
142 return texture;
143}
144
Leon Scroggins IIIb76f17d2021-11-03 15:04:18 -0400145/**
146 * Helper for timing calls to drawLayers.
147 *
148 * Caller needs to create RenderEngine and the LayerSettings, and this takes
149 * care of setting up the display, starting and stopping the timer, calling
150 * drawLayers, and saving (if --save is used).
151 *
152 * This times both the CPU and GPU work initiated by drawLayers. All work done
153 * outside of the for loop is excluded from the timing measurements.
154 */
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400155static void benchDrawLayers(RenderEngine& re, const std::vector<LayerSettings>& layers,
156 benchmark::State& benchState, const char* saveFileName) {
157 auto [width, height] = getDisplaySize();
158 auto outputBuffer = allocateBuffer(re, width, height);
159
160 const Rect displayRect(0, 0, static_cast<int32_t>(width), static_cast<int32_t>(height));
161 DisplaySettings display{
162 .physicalDisplay = displayRect,
163 .clip = displayRect,
164 .maxLuminance = 500,
165 };
166
Leon Scroggins IIIb76f17d2021-11-03 15:04:18 -0400167 // This loop starts and stops the timer.
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400168 for (auto _ : benchState) {
Alec Mourif29700f2023-08-17 21:53:31 +0000169 sp<Fence> waitFence =
170 re.drawLayers(display, layers, outputBuffer, base::unique_fd()).get().value();
Leon Scroggins IIIb76f17d2021-11-03 15:04:18 -0400171 waitFence->waitForever(LOG_TAG);
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400172 }
173
174 if (renderenginebench::save() && saveFileName) {
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400175 // Copy to a CPU-accessible buffer so we can encode it.
176 outputBuffer = copyBuffer(re, outputBuffer, GRALLOC_USAGE_SW_READ_OFTEN, "to_encode");
177
178 std::string outFile = base::GetExecutableDirectory();
179 outFile.append("/");
180 outFile.append(saveFileName);
181 outFile.append(".jpg");
182 renderenginebench::encodeToJpeg(outFile.c_str(), outputBuffer->getBuffer());
183 }
184}
185
Marzia Favaroee1e8ea2024-02-26 17:32:53 +0000186/**
187 * Return a buffer with the image in the provided path, relative to the executable directory
188 */
189static std::shared_ptr<ExternalTexture> createTexture(RenderEngine& re, const char* relPathImg) {
190 // Initially use cpu access so we can decode into it with AImageDecoder.
191 auto [width, height] = getDisplaySize();
192 auto srcBuffer =
193 allocateBuffer(re, width, height, GRALLOC_USAGE_SW_WRITE_OFTEN, "decoded_source");
194 std::string fileName = base::GetExecutableDirectory().append(relPathImg);
195 renderenginebench::decode(fileName.c_str(), srcBuffer->getBuffer());
196 // Now copy into GPU-only buffer for more realistic timing.
197 srcBuffer = copyBuffer(re, srcBuffer, 0, "source");
198 return srcBuffer;
199}
200
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400201///////////////////////////////////////////////////////////////////////////////
202// Benchmarks
203///////////////////////////////////////////////////////////////////////////////
204
Marzia Favaroee1e8ea2024-02-26 17:32:53 +0000205constexpr char kHomescreenPath[] = "/resources/homescreen.png";
206
207/**
208 * Draw a layer with texture and no additional shaders as a baseline to evaluate a shader's impact
209 * on performance
210 */
Leon Scroggins III696bf932024-01-24 15:21:05 -0500211template <class... Args>
Marzia Favaroee1e8ea2024-02-26 17:32:53 +0000212void BM_homescreen(benchmark::State& benchState, Args&&... args) {
Leon Scroggins III696bf932024-01-24 15:21:05 -0500213 auto args_tuple = std::make_tuple(std::move(args)...);
214 auto re = createRenderEngine(static_cast<RenderEngine::Threaded>(std::get<0>(args_tuple)),
Marzia Favaroee1e8ea2024-02-26 17:32:53 +0000215 static_cast<RenderEngine::GraphicsApi>(std::get<1>(args_tuple)));
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400216
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400217 auto [width, height] = getDisplaySize();
Marzia Favaroee1e8ea2024-02-26 17:32:53 +0000218 auto srcBuffer = createTexture(*re, kHomescreenPath);
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400219
Marzia Favaroee1e8ea2024-02-26 17:32:53 +0000220 const FloatRect layerRect(0, 0, width, height);
221 LayerSettings layer{
222 .geometry =
223 Geometry{
224 .boundaries = layerRect,
225 },
226 .source =
227 PixelSource{
228 .buffer =
229 Buffer{
230 .buffer = srcBuffer,
231 },
232 },
233 .alpha = half(1.0f),
234 };
235 auto layers = std::vector<LayerSettings>{layer};
236 benchDrawLayers(*re, layers, benchState, "homescreen");
237}
238
239template <class... Args>
240void BM_homescreen_blur(benchmark::State& benchState, Args&&... args) {
241 auto args_tuple = std::make_tuple(std::move(args)...);
242 auto re = createRenderEngine(static_cast<RenderEngine::Threaded>(std::get<0>(args_tuple)),
243 static_cast<RenderEngine::GraphicsApi>(std::get<1>(args_tuple)));
244
245 auto [width, height] = getDisplaySize();
246 auto srcBuffer = createTexture(*re, kHomescreenPath);
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400247
248 const FloatRect layerRect(0, 0, width, height);
249 LayerSettings layer{
250 .geometry =
251 Geometry{
252 .boundaries = layerRect,
253 },
254 .source =
255 PixelSource{
256 .buffer =
257 Buffer{
258 .buffer = srcBuffer,
259 },
260 },
261 .alpha = half(1.0f),
262 };
263 LayerSettings blurLayer{
264 .geometry =
265 Geometry{
266 .boundaries = layerRect,
267 },
268 .alpha = half(1.0f),
269 .skipContentDraw = true,
270 .backgroundBlurRadius = 60,
271 };
272
273 auto layers = std::vector<LayerSettings>{layer, blurLayer};
Marzia Favaroee1e8ea2024-02-26 17:32:53 +0000274 benchDrawLayers(*re, layers, benchState, "homescreen_blurred");
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400275}
276
Marzia Favaroee1e8ea2024-02-26 17:32:53 +0000277template <class... Args>
278void BM_homescreen_edgeExtension(benchmark::State& benchState, Args&&... args) {
279 auto args_tuple = std::make_tuple(std::move(args)...);
280 auto re = createRenderEngine(static_cast<RenderEngine::Threaded>(std::get<0>(args_tuple)),
281 static_cast<RenderEngine::GraphicsApi>(std::get<1>(args_tuple)));
Robin Lee26315202021-08-10 22:54:51 +0200282
Marzia Favaroee1e8ea2024-02-26 17:32:53 +0000283 auto [width, height] = getDisplaySize();
284 auto srcBuffer = createTexture(*re, kHomescreenPath);
Robin Lee26315202021-08-10 22:54:51 +0200285
Marzia Favaroee1e8ea2024-02-26 17:32:53 +0000286 LayerSettings layer{
287 .geometry =
288 Geometry{
289 .boundaries = FloatRect(0, 0, width, height),
290 },
291 .source =
292 PixelSource{
293 .buffer =
294 Buffer{
295 .buffer = srcBuffer,
296 // Part of the screen is not covered by the texture but
297 // will be filled in by the shader
298 .textureTransform =
299 mat4(mat3(),
300 vec3(width * 0.3f, height * 0.3f, 0.0f)),
301 },
302 },
303 .alpha = half(1.0f),
304 .edgeExtensionEffect =
305 EdgeExtensionEffect(/* left */ true,
306 /* right */ false, /* top */ true, /* bottom */ false),
307 };
308 auto layers = std::vector<LayerSettings>{layer};
309 benchDrawLayers(*re, layers, benchState, "homescreen_edge_extension");
310}
311
312BENCHMARK_CAPTURE(BM_homescreen_blur, gaussian, RenderEngine::Threaded::YES,
313 RenderEngine::GraphicsApi::GL, RenderEngine::BlurAlgorithm::GAUSSIAN);
314
315BENCHMARK_CAPTURE(BM_homescreen_blur, kawase, RenderEngine::Threaded::YES,
316 RenderEngine::GraphicsApi::GL, RenderEngine::BlurAlgorithm::KAWASE);
317
318BENCHMARK_CAPTURE(BM_homescreen_blur, kawase_dual_filter, RenderEngine::Threaded::YES,
Robin Lee26315202021-08-10 22:54:51 +0200319 RenderEngine::GraphicsApi::GL, RenderEngine::BlurAlgorithm::KAWASE_DUAL_FILTER);
Marzia Favaroee1e8ea2024-02-26 17:32:53 +0000320
321BENCHMARK_CAPTURE(BM_homescreen, SkiaGLThreaded, RenderEngine::Threaded::YES,
322 RenderEngine::GraphicsApi::GL);
323
324BENCHMARK_CAPTURE(BM_homescreen_edgeExtension, SkiaGLThreaded, RenderEngine::Threaded::YES,
325 RenderEngine::GraphicsApi::GL);