blob: 326d1cec1b75cefb6365eaa96d56461d6883d3c2 [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
32///////////////////////////////////////////////////////////////////////////////
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040033// Helpers for calling drawLayers
34///////////////////////////////////////////////////////////////////////////////
35
36std::pair<uint32_t, uint32_t> getDisplaySize() {
37 // These will be retrieved from a ui::Size, which stores int32_t, but they will be passed
38 // to GraphicBuffer, which wants uint32_t.
39 static uint32_t width, height;
40 std::once_flag once;
41 std::call_once(once, []() {
42 auto surfaceComposerClient = SurfaceComposerClient::getDefault();
Huihong Luo31b5ac22022-08-15 20:38:10 -070043 auto ids = SurfaceComposerClient::getPhysicalDisplayIds();
44 LOG_ALWAYS_FATAL_IF(ids.empty(), "Failed to get any display!");
45 ui::Size resolution = ui::kEmptySize;
46 // find the largest display resolution
47 for (auto id : ids) {
48 auto displayToken = surfaceComposerClient->getPhysicalDisplayToken(id);
49 ui::DisplayMode displayMode;
50 if (surfaceComposerClient->getActiveDisplayMode(displayToken, &displayMode) < 0) {
51 LOG_ALWAYS_FATAL("Failed to get active display mode!");
52 }
53 auto tw = displayMode.resolution.width;
54 auto th = displayMode.resolution.height;
55 LOG_ALWAYS_FATAL_IF(tw <= 0 || th <= 0, "Invalid display size!");
56 if (resolution.width * resolution.height <
57 displayMode.resolution.width * displayMode.resolution.height) {
58 resolution = displayMode.resolution;
59 }
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040060 }
Huihong Luo31b5ac22022-08-15 20:38:10 -070061 width = static_cast<uint32_t>(resolution.width);
62 height = static_cast<uint32_t>(resolution.height);
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040063 });
64 return std::pair<uint32_t, uint32_t>(width, height);
65}
66
Robin Lee26315202021-08-10 22:54:51 +020067static std::unique_ptr<RenderEngine> createRenderEngine(
68 RenderEngine::Threaded threaded, RenderEngine::GraphicsApi graphicsApi,
69 RenderEngine::BlurAlgorithm blurAlgorithm = RenderEngine::BlurAlgorithm::KAWASE) {
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040070 auto args = RenderEngineCreationArgs::Builder()
71 .setPixelFormat(static_cast<int>(ui::PixelFormat::RGBA_8888))
72 .setImageCacheSize(1)
73 .setEnableProtectedContext(true)
74 .setPrecacheToneMapperShaderOnly(false)
Robin Lee26315202021-08-10 22:54:51 +020075 .setBlurAlgorithm(blurAlgorithm)
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040076 .setContextPriority(RenderEngine::ContextPriority::REALTIME)
Leon Scroggins III696bf932024-01-24 15:21:05 -050077 .setThreaded(threaded)
78 .setGraphicsApi(graphicsApi)
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040079 .build();
80 return RenderEngine::create(args);
81}
82
Leon Scroggins IIIb76f17d2021-11-03 15:04:18 -040083static std::shared_ptr<ExternalTexture> allocateBuffer(RenderEngine& re, uint32_t width,
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040084 uint32_t height,
85 uint64_t extraUsageFlags = 0,
86 std::string name = "output") {
Vishnu Nairdbbe3852022-01-12 20:22:11 -080087 return std::make_shared<
Ady Abrahamd11bade2022-08-01 16:18:03 -070088 impl::ExternalTexture>(sp<GraphicBuffer>::make(width, height,
89 HAL_PIXEL_FORMAT_RGBA_8888, 1u,
90 GRALLOC_USAGE_HW_RENDER |
91 GRALLOC_USAGE_HW_TEXTURE |
92 extraUsageFlags,
93 std::move(name)),
Vishnu Nairdbbe3852022-01-12 20:22:11 -080094 re,
95 impl::ExternalTexture::Usage::READABLE |
96 impl::ExternalTexture::Usage::WRITEABLE);
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040097}
98
99static std::shared_ptr<ExternalTexture> copyBuffer(RenderEngine& re,
100 std::shared_ptr<ExternalTexture> original,
101 uint64_t extraUsageFlags, std::string name) {
102 const uint32_t width = original->getBuffer()->getWidth();
103 const uint32_t height = original->getBuffer()->getHeight();
104 auto texture = allocateBuffer(re, width, height, extraUsageFlags, name);
105
106 const Rect displayRect(0, 0, static_cast<int32_t>(width), static_cast<int32_t>(height));
107 DisplaySettings display{
108 .physicalDisplay = displayRect,
109 .clip = displayRect,
110 .maxLuminance = 500,
111 };
112
113 const FloatRect layerRect(0, 0, width, height);
114 LayerSettings layer{
115 .geometry =
116 Geometry{
117 .boundaries = layerRect,
118 },
119 .source =
120 PixelSource{
121 .buffer =
122 Buffer{
123 .buffer = original,
124 },
125 },
126 .alpha = half(1.0f),
127 };
128 auto layers = std::vector<LayerSettings>{layer};
129
Alec Mourif29700f2023-08-17 21:53:31 +0000130 sp<Fence> waitFence = re.drawLayers(display, layers, texture, base::unique_fd()).get().value();
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400131 waitFence->waitForever(LOG_TAG);
132 return texture;
133}
134
Leon Scroggins IIIb76f17d2021-11-03 15:04:18 -0400135/**
136 * Helper for timing calls to drawLayers.
137 *
138 * Caller needs to create RenderEngine and the LayerSettings, and this takes
139 * care of setting up the display, starting and stopping the timer, calling
140 * drawLayers, and saving (if --save is used).
141 *
142 * This times both the CPU and GPU work initiated by drawLayers. All work done
143 * outside of the for loop is excluded from the timing measurements.
144 */
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400145static void benchDrawLayers(RenderEngine& re, const std::vector<LayerSettings>& layers,
146 benchmark::State& benchState, const char* saveFileName) {
147 auto [width, height] = getDisplaySize();
148 auto outputBuffer = allocateBuffer(re, width, height);
149
150 const Rect displayRect(0, 0, static_cast<int32_t>(width), static_cast<int32_t>(height));
151 DisplaySettings display{
152 .physicalDisplay = displayRect,
153 .clip = displayRect,
154 .maxLuminance = 500,
155 };
156
Leon Scroggins IIIb76f17d2021-11-03 15:04:18 -0400157 // This loop starts and stops the timer.
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400158 for (auto _ : benchState) {
Alec Mourif29700f2023-08-17 21:53:31 +0000159 sp<Fence> waitFence =
160 re.drawLayers(display, layers, outputBuffer, base::unique_fd()).get().value();
Leon Scroggins IIIb76f17d2021-11-03 15:04:18 -0400161 waitFence->waitForever(LOG_TAG);
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400162 }
163
164 if (renderenginebench::save() && saveFileName) {
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400165 // Copy to a CPU-accessible buffer so we can encode it.
166 outputBuffer = copyBuffer(re, outputBuffer, GRALLOC_USAGE_SW_READ_OFTEN, "to_encode");
167
168 std::string outFile = base::GetExecutableDirectory();
169 outFile.append("/");
170 outFile.append(saveFileName);
171 outFile.append(".jpg");
172 renderenginebench::encodeToJpeg(outFile.c_str(), outputBuffer->getBuffer());
173 }
174}
175
176///////////////////////////////////////////////////////////////////////////////
177// Benchmarks
178///////////////////////////////////////////////////////////////////////////////
179
Leon Scroggins III696bf932024-01-24 15:21:05 -0500180template <class... Args>
181void BM_blur(benchmark::State& benchState, Args&&... args) {
182 auto args_tuple = std::make_tuple(std::move(args)...);
183 auto re = createRenderEngine(static_cast<RenderEngine::Threaded>(std::get<0>(args_tuple)),
Robin Lee26315202021-08-10 22:54:51 +0200184 static_cast<RenderEngine::GraphicsApi>(std::get<1>(args_tuple)),
185 static_cast<RenderEngine::BlurAlgorithm>(std::get<2>(args_tuple)));
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400186
187 // Initially use cpu access so we can decode into it with AImageDecoder.
188 auto [width, height] = getDisplaySize();
Leon Scroggins IIIb76f17d2021-11-03 15:04:18 -0400189 auto srcBuffer =
190 allocateBuffer(*re, width, height, GRALLOC_USAGE_SW_WRITE_OFTEN, "decoded_source");
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400191 {
192 std::string srcImage = base::GetExecutableDirectory();
193 srcImage.append("/resources/homescreen.png");
194 renderenginebench::decode(srcImage.c_str(), srcBuffer->getBuffer());
195
196 // Now copy into GPU-only buffer for more realistic timing.
197 srcBuffer = copyBuffer(*re, srcBuffer, 0, "source");
198 }
199
200 const FloatRect layerRect(0, 0, width, height);
201 LayerSettings layer{
202 .geometry =
203 Geometry{
204 .boundaries = layerRect,
205 },
206 .source =
207 PixelSource{
208 .buffer =
209 Buffer{
210 .buffer = srcBuffer,
211 },
212 },
213 .alpha = half(1.0f),
214 };
215 LayerSettings blurLayer{
216 .geometry =
217 Geometry{
218 .boundaries = layerRect,
219 },
220 .alpha = half(1.0f),
221 .skipContentDraw = true,
222 .backgroundBlurRadius = 60,
223 };
224
225 auto layers = std::vector<LayerSettings>{layer, blurLayer};
226 benchDrawLayers(*re, layers, benchState, "blurred");
227}
228
Robin Lee26315202021-08-10 22:54:51 +0200229BENCHMARK_CAPTURE(BM_blur, gaussian, RenderEngine::Threaded::YES, RenderEngine::GraphicsApi::GL,
230 RenderEngine::BlurAlgorithm::GAUSSIAN);
231
232BENCHMARK_CAPTURE(BM_blur, kawase, RenderEngine::Threaded::YES, RenderEngine::GraphicsApi::GL,
233 RenderEngine::BlurAlgorithm::KAWASE);
234
235BENCHMARK_CAPTURE(BM_blur, kawase_dual_filter, RenderEngine::Threaded::YES,
236 RenderEngine::GraphicsApi::GL, RenderEngine::BlurAlgorithm::KAWASE_DUAL_FILTER);