blob: 719b855348d802815a86499ffb75c5348a5406f3 [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>
25
26#include <mutex>
27
28using namespace android;
29using namespace android::renderengine;
30
31///////////////////////////////////////////////////////////////////////////////
32// Helpers for Benchmark::Apply
33///////////////////////////////////////////////////////////////////////////////
34
35std::string RenderEngineTypeName(RenderEngine::RenderEngineType type) {
36 switch (type) {
37 case RenderEngine::RenderEngineType::SKIA_GL_THREADED:
38 return "skiaglthreaded";
39 case RenderEngine::RenderEngineType::SKIA_GL:
40 return "skiagl";
41 case RenderEngine::RenderEngineType::GLES:
42 case RenderEngine::RenderEngineType::THREADED:
43 LOG_ALWAYS_FATAL("GLESRenderEngine is deprecated - why time it?");
44 return "unused";
45 }
46}
47
48/**
49 * Passed (indirectly - see RunSkiaGL) to Benchmark::Apply to create a Benchmark
50 * which specifies which RenderEngineType it uses.
51 *
52 * This simplifies calling ->Arg(type)->Arg(type) and provides strings to make
53 * it obvious which version is being run.
54 *
55 * @param b The benchmark family
56 * @param type The type of RenderEngine to use.
57 */
58static void AddRenderEngineType(benchmark::internal::Benchmark* b,
59 RenderEngine::RenderEngineType type) {
60 b->Arg(static_cast<int64_t>(type));
61 b->ArgName(RenderEngineTypeName(type));
62}
63
64/**
65 * Run a benchmark once using SKIA_GL.
66 */
67static void RunSkiaGL(benchmark::internal::Benchmark* b) {
68 AddRenderEngineType(b, RenderEngine::RenderEngineType::SKIA_GL);
69}
70
71///////////////////////////////////////////////////////////////////////////////
72// Helpers for calling drawLayers
73///////////////////////////////////////////////////////////////////////////////
74
75std::pair<uint32_t, uint32_t> getDisplaySize() {
76 // These will be retrieved from a ui::Size, which stores int32_t, but they will be passed
77 // to GraphicBuffer, which wants uint32_t.
78 static uint32_t width, height;
79 std::once_flag once;
80 std::call_once(once, []() {
81 auto surfaceComposerClient = SurfaceComposerClient::getDefault();
82 auto displayToken = surfaceComposerClient->getInternalDisplayToken();
83 ui::DisplayMode displayMode;
84 if (surfaceComposerClient->getActiveDisplayMode(displayToken, &displayMode) < 0) {
85 LOG_ALWAYS_FATAL("Failed to get active display mode!");
86 }
87 auto w = displayMode.resolution.width;
88 auto h = displayMode.resolution.height;
89 LOG_ALWAYS_FATAL_IF(w <= 0 || h <= 0, "Invalid display size!");
90 width = static_cast<uint32_t>(w);
91 height = static_cast<uint32_t>(h);
92 });
93 return std::pair<uint32_t, uint32_t>(width, height);
94}
95
96// This value doesn't matter, as it's not read. TODO(b/199918329): Once we remove
97// GLESRenderEngine we can remove this, too.
98static constexpr const bool kUseFrameBufferCache = false;
99
100static std::unique_ptr<RenderEngine> createRenderEngine(RenderEngine::RenderEngineType type) {
101 auto args = RenderEngineCreationArgs::Builder()
102 .setPixelFormat(static_cast<int>(ui::PixelFormat::RGBA_8888))
103 .setImageCacheSize(1)
104 .setEnableProtectedContext(true)
105 .setPrecacheToneMapperShaderOnly(false)
106 .setSupportsBackgroundBlur(true)
107 .setContextPriority(RenderEngine::ContextPriority::REALTIME)
108 .setRenderEngineType(type)
109 .setUseColorManagerment(true)
110 .build();
111 return RenderEngine::create(args);
112}
113
114static std::shared_ptr<ExternalTexture> allocateBuffer(RenderEngine& re,
115 uint32_t width,
116 uint32_t height,
117 uint64_t extraUsageFlags = 0,
118 std::string name = "output") {
119 return std::make_shared<ExternalTexture>(new GraphicBuffer(width, height,
120 HAL_PIXEL_FORMAT_RGBA_8888, 1,
121 GRALLOC_USAGE_HW_RENDER |
122 GRALLOC_USAGE_HW_TEXTURE |
123 extraUsageFlags,
124 std::move(name)),
125 re,
126 ExternalTexture::Usage::READABLE |
127 ExternalTexture::Usage::WRITEABLE);
128}
129
130static std::shared_ptr<ExternalTexture> copyBuffer(RenderEngine& re,
131 std::shared_ptr<ExternalTexture> original,
132 uint64_t extraUsageFlags, std::string name) {
133 const uint32_t width = original->getBuffer()->getWidth();
134 const uint32_t height = original->getBuffer()->getHeight();
135 auto texture = allocateBuffer(re, width, height, extraUsageFlags, name);
136
137 const Rect displayRect(0, 0, static_cast<int32_t>(width), static_cast<int32_t>(height));
138 DisplaySettings display{
139 .physicalDisplay = displayRect,
140 .clip = displayRect,
141 .maxLuminance = 500,
142 };
143
144 const FloatRect layerRect(0, 0, width, height);
145 LayerSettings layer{
146 .geometry =
147 Geometry{
148 .boundaries = layerRect,
149 },
150 .source =
151 PixelSource{
152 .buffer =
153 Buffer{
154 .buffer = original,
155 },
156 },
157 .alpha = half(1.0f),
158 };
159 auto layers = std::vector<LayerSettings>{layer};
160
161 auto [status, drawFence] =
162 re.drawLayers(display, layers, texture, kUseFrameBufferCache, base::unique_fd()).get();
163 sp<Fence> waitFence = new Fence(std::move(drawFence));
164 waitFence->waitForever(LOG_TAG);
165 return texture;
166}
167
168static void benchDrawLayers(RenderEngine& re, const std::vector<LayerSettings>& layers,
169 benchmark::State& benchState, const char* saveFileName) {
170 auto [width, height] = getDisplaySize();
171 auto outputBuffer = allocateBuffer(re, width, height);
172
173 const Rect displayRect(0, 0, static_cast<int32_t>(width), static_cast<int32_t>(height));
174 DisplaySettings display{
175 .physicalDisplay = displayRect,
176 .clip = displayRect,
177 .maxLuminance = 500,
178 };
179
180 base::unique_fd fence;
181 for (auto _ : benchState) {
182 auto [status, drawFence] =
183 re.drawLayers(display, layers, outputBuffer, kUseFrameBufferCache, std::move(fence))
184 .get();
185 fence = std::move(drawFence);
186 }
187
188 if (renderenginebench::save() && saveFileName) {
189 sp<Fence> waitFence = new Fence(std::move(fence));
190 waitFence->waitForever(LOG_TAG);
191
192 // Copy to a CPU-accessible buffer so we can encode it.
193 outputBuffer = copyBuffer(re, outputBuffer, GRALLOC_USAGE_SW_READ_OFTEN, "to_encode");
194
195 std::string outFile = base::GetExecutableDirectory();
196 outFile.append("/");
197 outFile.append(saveFileName);
198 outFile.append(".jpg");
199 renderenginebench::encodeToJpeg(outFile.c_str(), outputBuffer->getBuffer());
200 }
201}
202
203///////////////////////////////////////////////////////////////////////////////
204// Benchmarks
205///////////////////////////////////////////////////////////////////////////////
206
207void BM_blur(benchmark::State& benchState) {
208 auto re = createRenderEngine(static_cast<RenderEngine::RenderEngineType>(benchState.range()));
209
210 // Initially use cpu access so we can decode into it with AImageDecoder.
211 auto [width, height] = getDisplaySize();
212 auto srcBuffer = allocateBuffer(*re, width, height, GRALLOC_USAGE_SW_WRITE_OFTEN,
213 "decoded_source");
214 {
215 std::string srcImage = base::GetExecutableDirectory();
216 srcImage.append("/resources/homescreen.png");
217 renderenginebench::decode(srcImage.c_str(), srcBuffer->getBuffer());
218
219 // Now copy into GPU-only buffer for more realistic timing.
220 srcBuffer = copyBuffer(*re, srcBuffer, 0, "source");
221 }
222
223 const FloatRect layerRect(0, 0, width, height);
224 LayerSettings layer{
225 .geometry =
226 Geometry{
227 .boundaries = layerRect,
228 },
229 .source =
230 PixelSource{
231 .buffer =
232 Buffer{
233 .buffer = srcBuffer,
234 },
235 },
236 .alpha = half(1.0f),
237 };
238 LayerSettings blurLayer{
239 .geometry =
240 Geometry{
241 .boundaries = layerRect,
242 },
243 .alpha = half(1.0f),
244 .skipContentDraw = true,
245 .backgroundBlurRadius = 60,
246 };
247
248 auto layers = std::vector<LayerSettings>{layer, blurLayer};
249 benchDrawLayers(*re, layers, benchState, "blurred");
250}
251
252BENCHMARK(BM_blur)->Apply(RunSkiaGL);