blob: 595573d24a734cc97f84447ac5e8277b1c42afe9 [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>
Marzia Favaroa40d5602024-09-24 12:57:37 +000020#include <com_android_graphics_libgui_flags.h>
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040021#include <gui/SurfaceComposerClient.h>
22#include <log/log.h>
23#include <renderengine/ExternalTexture.h>
24#include <renderengine/LayerSettings.h>
25#include <renderengine/RenderEngine.h>
Vishnu Nairdbbe3852022-01-12 20:22:11 -080026#include <renderengine/impl/ExternalTexture.h>
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040027
28#include <mutex>
29
30using namespace android;
31using namespace android::renderengine;
32
Marzia Favaroee1e8ea2024-02-26 17:32:53 +000033// To run tests:
34/**
35 * mmm frameworks/native/libs/renderengine/benchmark;\
36 * adb push $OUT/data/benchmarktest/librenderengine_bench/librenderengine_bench
37 * /data/benchmarktest/librenderengine_bench/librenderengine_bench;\
38 * adb shell /data/benchmarktest/librenderengine_bench/librenderengine_bench
39 *
40 * (64-bit devices: out directory contains benchmarktest64 instead of benchmarktest)
41 */
42
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040043///////////////////////////////////////////////////////////////////////////////
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040044// Helpers for calling drawLayers
45///////////////////////////////////////////////////////////////////////////////
46
47std::pair<uint32_t, uint32_t> getDisplaySize() {
48 // These will be retrieved from a ui::Size, which stores int32_t, but they will be passed
49 // to GraphicBuffer, which wants uint32_t.
50 static uint32_t width, height;
51 std::once_flag once;
52 std::call_once(once, []() {
53 auto surfaceComposerClient = SurfaceComposerClient::getDefault();
Huihong Luo31b5ac22022-08-15 20:38:10 -070054 auto ids = SurfaceComposerClient::getPhysicalDisplayIds();
55 LOG_ALWAYS_FATAL_IF(ids.empty(), "Failed to get any display!");
56 ui::Size resolution = ui::kEmptySize;
57 // find the largest display resolution
58 for (auto id : ids) {
59 auto displayToken = surfaceComposerClient->getPhysicalDisplayToken(id);
60 ui::DisplayMode displayMode;
61 if (surfaceComposerClient->getActiveDisplayMode(displayToken, &displayMode) < 0) {
62 LOG_ALWAYS_FATAL("Failed to get active display mode!");
63 }
64 auto tw = displayMode.resolution.width;
65 auto th = displayMode.resolution.height;
66 LOG_ALWAYS_FATAL_IF(tw <= 0 || th <= 0, "Invalid display size!");
67 if (resolution.width * resolution.height <
68 displayMode.resolution.width * displayMode.resolution.height) {
69 resolution = displayMode.resolution;
70 }
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040071 }
Huihong Luo31b5ac22022-08-15 20:38:10 -070072 width = static_cast<uint32_t>(resolution.width);
73 height = static_cast<uint32_t>(resolution.height);
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040074 });
75 return std::pair<uint32_t, uint32_t>(width, height);
76}
77
Robin Lee26315202021-08-10 22:54:51 +020078static std::unique_ptr<RenderEngine> createRenderEngine(
79 RenderEngine::Threaded threaded, RenderEngine::GraphicsApi graphicsApi,
80 RenderEngine::BlurAlgorithm blurAlgorithm = RenderEngine::BlurAlgorithm::KAWASE) {
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040081 auto args = RenderEngineCreationArgs::Builder()
82 .setPixelFormat(static_cast<int>(ui::PixelFormat::RGBA_8888))
83 .setImageCacheSize(1)
84 .setEnableProtectedContext(true)
85 .setPrecacheToneMapperShaderOnly(false)
Robin Lee26315202021-08-10 22:54:51 +020086 .setBlurAlgorithm(blurAlgorithm)
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040087 .setContextPriority(RenderEngine::ContextPriority::REALTIME)
Leon Scroggins III696bf932024-01-24 15:21:05 -050088 .setThreaded(threaded)
89 .setGraphicsApi(graphicsApi)
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040090 .build();
91 return RenderEngine::create(args);
92}
93
Leon Scroggins IIIb76f17d2021-11-03 15:04:18 -040094static std::shared_ptr<ExternalTexture> allocateBuffer(RenderEngine& re, uint32_t width,
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040095 uint32_t height,
96 uint64_t extraUsageFlags = 0,
97 std::string name = "output") {
Vishnu Nairdbbe3852022-01-12 20:22:11 -080098 return std::make_shared<
Ady Abrahamd11bade2022-08-01 16:18:03 -070099 impl::ExternalTexture>(sp<GraphicBuffer>::make(width, height,
100 HAL_PIXEL_FORMAT_RGBA_8888, 1u,
101 GRALLOC_USAGE_HW_RENDER |
102 GRALLOC_USAGE_HW_TEXTURE |
103 extraUsageFlags,
104 std::move(name)),
Vishnu Nairdbbe3852022-01-12 20:22:11 -0800105 re,
106 impl::ExternalTexture::Usage::READABLE |
107 impl::ExternalTexture::Usage::WRITEABLE);
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400108}
109
110static std::shared_ptr<ExternalTexture> copyBuffer(RenderEngine& re,
111 std::shared_ptr<ExternalTexture> original,
112 uint64_t extraUsageFlags, std::string name) {
113 const uint32_t width = original->getBuffer()->getWidth();
114 const uint32_t height = original->getBuffer()->getHeight();
115 auto texture = allocateBuffer(re, width, height, extraUsageFlags, name);
116
117 const Rect displayRect(0, 0, static_cast<int32_t>(width), static_cast<int32_t>(height));
118 DisplaySettings display{
119 .physicalDisplay = displayRect,
120 .clip = displayRect,
121 .maxLuminance = 500,
122 };
123
124 const FloatRect layerRect(0, 0, width, height);
125 LayerSettings layer{
126 .geometry =
127 Geometry{
128 .boundaries = layerRect,
129 },
130 .source =
131 PixelSource{
132 .buffer =
133 Buffer{
134 .buffer = original,
135 },
136 },
137 .alpha = half(1.0f),
138 };
139 auto layers = std::vector<LayerSettings>{layer};
140
Alec Mourif29700f2023-08-17 21:53:31 +0000141 sp<Fence> waitFence = re.drawLayers(display, layers, texture, base::unique_fd()).get().value();
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400142 waitFence->waitForever(LOG_TAG);
143 return texture;
144}
145
Leon Scroggins IIIb76f17d2021-11-03 15:04:18 -0400146/**
147 * Helper for timing calls to drawLayers.
148 *
149 * Caller needs to create RenderEngine and the LayerSettings, and this takes
150 * care of setting up the display, starting and stopping the timer, calling
151 * drawLayers, and saving (if --save is used).
152 *
153 * This times both the CPU and GPU work initiated by drawLayers. All work done
154 * outside of the for loop is excluded from the timing measurements.
155 */
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400156static void benchDrawLayers(RenderEngine& re, const std::vector<LayerSettings>& layers,
157 benchmark::State& benchState, const char* saveFileName) {
158 auto [width, height] = getDisplaySize();
159 auto outputBuffer = allocateBuffer(re, width, height);
160
161 const Rect displayRect(0, 0, static_cast<int32_t>(width), static_cast<int32_t>(height));
162 DisplaySettings display{
163 .physicalDisplay = displayRect,
164 .clip = displayRect,
165 .maxLuminance = 500,
166 };
167
Leon Scroggins IIIb76f17d2021-11-03 15:04:18 -0400168 // This loop starts and stops the timer.
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400169 for (auto _ : benchState) {
Alec Mourif29700f2023-08-17 21:53:31 +0000170 sp<Fence> waitFence =
171 re.drawLayers(display, layers, outputBuffer, base::unique_fd()).get().value();
Leon Scroggins IIIb76f17d2021-11-03 15:04:18 -0400172 waitFence->waitForever(LOG_TAG);
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400173 }
174
175 if (renderenginebench::save() && saveFileName) {
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400176 // Copy to a CPU-accessible buffer so we can encode it.
177 outputBuffer = copyBuffer(re, outputBuffer, GRALLOC_USAGE_SW_READ_OFTEN, "to_encode");
178
179 std::string outFile = base::GetExecutableDirectory();
180 outFile.append("/");
181 outFile.append(saveFileName);
182 outFile.append(".jpg");
183 renderenginebench::encodeToJpeg(outFile.c_str(), outputBuffer->getBuffer());
184 }
185}
186
Marzia Favaroee1e8ea2024-02-26 17:32:53 +0000187/**
188 * Return a buffer with the image in the provided path, relative to the executable directory
189 */
190static std::shared_ptr<ExternalTexture> createTexture(RenderEngine& re, const char* relPathImg) {
191 // Initially use cpu access so we can decode into it with AImageDecoder.
192 auto [width, height] = getDisplaySize();
193 auto srcBuffer =
194 allocateBuffer(re, width, height, GRALLOC_USAGE_SW_WRITE_OFTEN, "decoded_source");
195 std::string fileName = base::GetExecutableDirectory().append(relPathImg);
196 renderenginebench::decode(fileName.c_str(), srcBuffer->getBuffer());
197 // Now copy into GPU-only buffer for more realistic timing.
198 srcBuffer = copyBuffer(re, srcBuffer, 0, "source");
199 return srcBuffer;
200}
201
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400202///////////////////////////////////////////////////////////////////////////////
203// Benchmarks
204///////////////////////////////////////////////////////////////////////////////
205
Marzia Favaroee1e8ea2024-02-26 17:32:53 +0000206constexpr char kHomescreenPath[] = "/resources/homescreen.png";
207
208/**
209 * Draw a layer with texture and no additional shaders as a baseline to evaluate a shader's impact
210 * on performance
211 */
Leon Scroggins III696bf932024-01-24 15:21:05 -0500212template <class... Args>
Marzia Favaroee1e8ea2024-02-26 17:32:53 +0000213void BM_homescreen(benchmark::State& benchState, Args&&... args) {
Leon Scroggins III696bf932024-01-24 15:21:05 -0500214 auto args_tuple = std::make_tuple(std::move(args)...);
215 auto re = createRenderEngine(static_cast<RenderEngine::Threaded>(std::get<0>(args_tuple)),
Marzia Favaroee1e8ea2024-02-26 17:32:53 +0000216 static_cast<RenderEngine::GraphicsApi>(std::get<1>(args_tuple)));
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400217
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400218 auto [width, height] = getDisplaySize();
Marzia Favaroee1e8ea2024-02-26 17:32:53 +0000219 auto srcBuffer = createTexture(*re, kHomescreenPath);
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400220
Marzia Favaroee1e8ea2024-02-26 17:32:53 +0000221 const FloatRect layerRect(0, 0, width, height);
222 LayerSettings layer{
223 .geometry =
224 Geometry{
225 .boundaries = layerRect,
226 },
227 .source =
228 PixelSource{
229 .buffer =
230 Buffer{
231 .buffer = srcBuffer,
232 },
233 },
234 .alpha = half(1.0f),
235 };
236 auto layers = std::vector<LayerSettings>{layer};
237 benchDrawLayers(*re, layers, benchState, "homescreen");
238}
239
240template <class... Args>
241void BM_homescreen_blur(benchmark::State& benchState, Args&&... args) {
242 auto args_tuple = std::make_tuple(std::move(args)...);
243 auto re = createRenderEngine(static_cast<RenderEngine::Threaded>(std::get<0>(args_tuple)),
244 static_cast<RenderEngine::GraphicsApi>(std::get<1>(args_tuple)));
245
246 auto [width, height] = getDisplaySize();
247 auto srcBuffer = createTexture(*re, kHomescreenPath);
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400248
249 const FloatRect layerRect(0, 0, width, height);
250 LayerSettings layer{
251 .geometry =
252 Geometry{
253 .boundaries = layerRect,
254 },
255 .source =
256 PixelSource{
257 .buffer =
258 Buffer{
259 .buffer = srcBuffer,
260 },
261 },
262 .alpha = half(1.0f),
263 };
264 LayerSettings blurLayer{
265 .geometry =
266 Geometry{
267 .boundaries = layerRect,
268 },
269 .alpha = half(1.0f),
270 .skipContentDraw = true,
271 .backgroundBlurRadius = 60,
272 };
273
274 auto layers = std::vector<LayerSettings>{layer, blurLayer};
Marzia Favaroee1e8ea2024-02-26 17:32:53 +0000275 benchDrawLayers(*re, layers, benchState, "homescreen_blurred");
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400276}
277
Marzia Favaroee1e8ea2024-02-26 17:32:53 +0000278template <class... Args>
279void BM_homescreen_edgeExtension(benchmark::State& benchState, Args&&... args) {
280 auto args_tuple = std::make_tuple(std::move(args)...);
281 auto re = createRenderEngine(static_cast<RenderEngine::Threaded>(std::get<0>(args_tuple)),
282 static_cast<RenderEngine::GraphicsApi>(std::get<1>(args_tuple)));
Robin Lee26315202021-08-10 22:54:51 +0200283
Marzia Favaroee1e8ea2024-02-26 17:32:53 +0000284 auto [width, height] = getDisplaySize();
285 auto srcBuffer = createTexture(*re, kHomescreenPath);
Robin Lee26315202021-08-10 22:54:51 +0200286
Marzia Favaroee1e8ea2024-02-26 17:32:53 +0000287 LayerSettings layer{
288 .geometry =
289 Geometry{
290 .boundaries = FloatRect(0, 0, width, height),
291 },
292 .source =
293 PixelSource{
294 .buffer =
295 Buffer{
296 .buffer = srcBuffer,
297 // Part of the screen is not covered by the texture but
298 // will be filled in by the shader
299 .textureTransform =
300 mat4(mat3(),
301 vec3(width * 0.3f, height * 0.3f, 0.0f)),
302 },
303 },
304 .alpha = half(1.0f),
305 .edgeExtensionEffect =
306 EdgeExtensionEffect(/* left */ true,
307 /* right */ false, /* top */ true, /* bottom */ false),
308 };
309 auto layers = std::vector<LayerSettings>{layer};
310 benchDrawLayers(*re, layers, benchState, "homescreen_edge_extension");
311}
312
313BENCHMARK_CAPTURE(BM_homescreen_blur, gaussian, RenderEngine::Threaded::YES,
314 RenderEngine::GraphicsApi::GL, RenderEngine::BlurAlgorithm::GAUSSIAN);
315
316BENCHMARK_CAPTURE(BM_homescreen_blur, kawase, RenderEngine::Threaded::YES,
317 RenderEngine::GraphicsApi::GL, RenderEngine::BlurAlgorithm::KAWASE);
318
319BENCHMARK_CAPTURE(BM_homescreen_blur, kawase_dual_filter, RenderEngine::Threaded::YES,
Robin Lee26315202021-08-10 22:54:51 +0200320 RenderEngine::GraphicsApi::GL, RenderEngine::BlurAlgorithm::KAWASE_DUAL_FILTER);
Marzia Favaroee1e8ea2024-02-26 17:32:53 +0000321
322BENCHMARK_CAPTURE(BM_homescreen, SkiaGLThreaded, RenderEngine::Threaded::YES,
323 RenderEngine::GraphicsApi::GL);
324
Marzia Favaroa40d5602024-09-24 12:57:37 +0000325#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS_EDGE_EXTENSION_SHADER
Marzia Favaroee1e8ea2024-02-26 17:32:53 +0000326BENCHMARK_CAPTURE(BM_homescreen_edgeExtension, SkiaGLThreaded, RenderEngine::Threaded::YES,
327 RenderEngine::GraphicsApi::GL);
Marzia Favaroa40d5602024-09-24 12:57:37 +0000328#endif