blob: 101f519e550625d5b51cee4a3d093e365f02eb8f [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
Leon Scroggins III696bf932024-01-24 15:21:05 -050067static std::unique_ptr<RenderEngine> createRenderEngine(RenderEngine::Threaded threaded,
68 RenderEngine::GraphicsApi graphicsApi) {
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040069 auto args = RenderEngineCreationArgs::Builder()
70 .setPixelFormat(static_cast<int>(ui::PixelFormat::RGBA_8888))
71 .setImageCacheSize(1)
72 .setEnableProtectedContext(true)
73 .setPrecacheToneMapperShaderOnly(false)
74 .setSupportsBackgroundBlur(true)
75 .setContextPriority(RenderEngine::ContextPriority::REALTIME)
Leon Scroggins III696bf932024-01-24 15:21:05 -050076 .setThreaded(threaded)
77 .setGraphicsApi(graphicsApi)
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040078 .build();
79 return RenderEngine::create(args);
80}
81
Leon Scroggins IIIb76f17d2021-11-03 15:04:18 -040082static std::shared_ptr<ExternalTexture> allocateBuffer(RenderEngine& re, uint32_t width,
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040083 uint32_t height,
84 uint64_t extraUsageFlags = 0,
85 std::string name = "output") {
Vishnu Nairdbbe3852022-01-12 20:22:11 -080086 return std::make_shared<
Ady Abrahamd11bade2022-08-01 16:18:03 -070087 impl::ExternalTexture>(sp<GraphicBuffer>::make(width, height,
88 HAL_PIXEL_FORMAT_RGBA_8888, 1u,
89 GRALLOC_USAGE_HW_RENDER |
90 GRALLOC_USAGE_HW_TEXTURE |
91 extraUsageFlags,
92 std::move(name)),
Vishnu Nairdbbe3852022-01-12 20:22:11 -080093 re,
94 impl::ExternalTexture::Usage::READABLE |
95 impl::ExternalTexture::Usage::WRITEABLE);
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040096}
97
98static std::shared_ptr<ExternalTexture> copyBuffer(RenderEngine& re,
99 std::shared_ptr<ExternalTexture> original,
100 uint64_t extraUsageFlags, std::string name) {
101 const uint32_t width = original->getBuffer()->getWidth();
102 const uint32_t height = original->getBuffer()->getHeight();
103 auto texture = allocateBuffer(re, width, height, extraUsageFlags, name);
104
105 const Rect displayRect(0, 0, static_cast<int32_t>(width), static_cast<int32_t>(height));
106 DisplaySettings display{
107 .physicalDisplay = displayRect,
108 .clip = displayRect,
109 .maxLuminance = 500,
110 };
111
112 const FloatRect layerRect(0, 0, width, height);
113 LayerSettings layer{
114 .geometry =
115 Geometry{
116 .boundaries = layerRect,
117 },
118 .source =
119 PixelSource{
120 .buffer =
121 Buffer{
122 .buffer = original,
123 },
124 },
125 .alpha = half(1.0f),
126 };
127 auto layers = std::vector<LayerSettings>{layer};
128
Alec Mourif29700f2023-08-17 21:53:31 +0000129 sp<Fence> waitFence = re.drawLayers(display, layers, texture, base::unique_fd()).get().value();
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400130 waitFence->waitForever(LOG_TAG);
131 return texture;
132}
133
Leon Scroggins IIIb76f17d2021-11-03 15:04:18 -0400134/**
135 * Helper for timing calls to drawLayers.
136 *
137 * Caller needs to create RenderEngine and the LayerSettings, and this takes
138 * care of setting up the display, starting and stopping the timer, calling
139 * drawLayers, and saving (if --save is used).
140 *
141 * This times both the CPU and GPU work initiated by drawLayers. All work done
142 * outside of the for loop is excluded from the timing measurements.
143 */
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400144static void benchDrawLayers(RenderEngine& re, const std::vector<LayerSettings>& layers,
145 benchmark::State& benchState, const char* saveFileName) {
146 auto [width, height] = getDisplaySize();
147 auto outputBuffer = allocateBuffer(re, width, height);
148
149 const Rect displayRect(0, 0, static_cast<int32_t>(width), static_cast<int32_t>(height));
150 DisplaySettings display{
151 .physicalDisplay = displayRect,
152 .clip = displayRect,
153 .maxLuminance = 500,
154 };
155
Leon Scroggins IIIb76f17d2021-11-03 15:04:18 -0400156 // This loop starts and stops the timer.
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400157 for (auto _ : benchState) {
Alec Mourif29700f2023-08-17 21:53:31 +0000158 sp<Fence> waitFence =
159 re.drawLayers(display, layers, outputBuffer, base::unique_fd()).get().value();
Leon Scroggins IIIb76f17d2021-11-03 15:04:18 -0400160 waitFence->waitForever(LOG_TAG);
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400161 }
162
163 if (renderenginebench::save() && saveFileName) {
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400164 // Copy to a CPU-accessible buffer so we can encode it.
165 outputBuffer = copyBuffer(re, outputBuffer, GRALLOC_USAGE_SW_READ_OFTEN, "to_encode");
166
167 std::string outFile = base::GetExecutableDirectory();
168 outFile.append("/");
169 outFile.append(saveFileName);
170 outFile.append(".jpg");
171 renderenginebench::encodeToJpeg(outFile.c_str(), outputBuffer->getBuffer());
172 }
173}
174
175///////////////////////////////////////////////////////////////////////////////
176// Benchmarks
177///////////////////////////////////////////////////////////////////////////////
178
Leon Scroggins III696bf932024-01-24 15:21:05 -0500179template <class... Args>
180void BM_blur(benchmark::State& benchState, Args&&... args) {
181 auto args_tuple = std::make_tuple(std::move(args)...);
182 auto re = createRenderEngine(static_cast<RenderEngine::Threaded>(std::get<0>(args_tuple)),
183 static_cast<RenderEngine::GraphicsApi>(std::get<1>(args_tuple)));
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400184
185 // Initially use cpu access so we can decode into it with AImageDecoder.
186 auto [width, height] = getDisplaySize();
Leon Scroggins IIIb76f17d2021-11-03 15:04:18 -0400187 auto srcBuffer =
188 allocateBuffer(*re, width, height, GRALLOC_USAGE_SW_WRITE_OFTEN, "decoded_source");
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400189 {
190 std::string srcImage = base::GetExecutableDirectory();
191 srcImage.append("/resources/homescreen.png");
192 renderenginebench::decode(srcImage.c_str(), srcBuffer->getBuffer());
193
194 // Now copy into GPU-only buffer for more realistic timing.
195 srcBuffer = copyBuffer(*re, srcBuffer, 0, "source");
196 }
197
198 const FloatRect layerRect(0, 0, width, height);
199 LayerSettings layer{
200 .geometry =
201 Geometry{
202 .boundaries = layerRect,
203 },
204 .source =
205 PixelSource{
206 .buffer =
207 Buffer{
208 .buffer = srcBuffer,
209 },
210 },
211 .alpha = half(1.0f),
212 };
213 LayerSettings blurLayer{
214 .geometry =
215 Geometry{
216 .boundaries = layerRect,
217 },
218 .alpha = half(1.0f),
219 .skipContentDraw = true,
220 .backgroundBlurRadius = 60,
221 };
222
223 auto layers = std::vector<LayerSettings>{layer, blurLayer};
224 benchDrawLayers(*re, layers, benchState, "blurred");
225}
226
Leon Scroggins III696bf932024-01-24 15:21:05 -0500227BENCHMARK_CAPTURE(BM_blur, SkiaGLThreaded, RenderEngine::Threaded::YES,
228 RenderEngine::GraphicsApi::GL);