blob: 6c8f8e878bf1d4031902ebf32a23777ea8c32b05 [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/**
Leon Scroggins IIIfd37d2a2021-11-03 15:11:48 -040049 * Passed (indirectly - see RunSkiaGLThreaded) to Benchmark::Apply to create a
50 * Benchmark which specifies which RenderEngineType it uses.
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040051 *
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/**
Leon Scroggins IIIfd37d2a2021-11-03 15:11:48 -040065 * Run a benchmark once using SKIA_GL_THREADED.
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040066 */
Leon Scroggins IIIfd37d2a2021-11-03 15:11:48 -040067static void RunSkiaGLThreaded(benchmark::internal::Benchmark* b) {
68 AddRenderEngineType(b, RenderEngine::RenderEngineType::SKIA_GL_THREADED);
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040069}
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
Leon Scroggins IIIb76f17d2021-11-03 15:04:18 -0400114static std::shared_ptr<ExternalTexture> allocateBuffer(RenderEngine& re, uint32_t width,
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400115 uint32_t height,
116 uint64_t extraUsageFlags = 0,
117 std::string name = "output") {
118 return std::make_shared<ExternalTexture>(new GraphicBuffer(width, height,
119 HAL_PIXEL_FORMAT_RGBA_8888, 1,
120 GRALLOC_USAGE_HW_RENDER |
121 GRALLOC_USAGE_HW_TEXTURE |
122 extraUsageFlags,
123 std::move(name)),
124 re,
125 ExternalTexture::Usage::READABLE |
126 ExternalTexture::Usage::WRITEABLE);
127}
128
129static std::shared_ptr<ExternalTexture> copyBuffer(RenderEngine& re,
130 std::shared_ptr<ExternalTexture> original,
131 uint64_t extraUsageFlags, std::string name) {
132 const uint32_t width = original->getBuffer()->getWidth();
133 const uint32_t height = original->getBuffer()->getHeight();
134 auto texture = allocateBuffer(re, width, height, extraUsageFlags, name);
135
136 const Rect displayRect(0, 0, static_cast<int32_t>(width), static_cast<int32_t>(height));
137 DisplaySettings display{
138 .physicalDisplay = displayRect,
139 .clip = displayRect,
140 .maxLuminance = 500,
141 };
142
143 const FloatRect layerRect(0, 0, width, height);
144 LayerSettings layer{
145 .geometry =
146 Geometry{
147 .boundaries = layerRect,
148 },
149 .source =
150 PixelSource{
151 .buffer =
152 Buffer{
153 .buffer = original,
154 },
155 },
156 .alpha = half(1.0f),
157 };
158 auto layers = std::vector<LayerSettings>{layer};
159
160 auto [status, drawFence] =
161 re.drawLayers(display, layers, texture, kUseFrameBufferCache, base::unique_fd()).get();
Leon Scroggins IIIb76f17d2021-11-03 15:04:18 -0400162 sp<Fence> waitFence = sp<Fence>::make(std::move(drawFence));
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400163 waitFence->waitForever(LOG_TAG);
164 return texture;
165}
166
Leon Scroggins IIIb76f17d2021-11-03 15:04:18 -0400167/**
168 * Helper for timing calls to drawLayers.
169 *
170 * Caller needs to create RenderEngine and the LayerSettings, and this takes
171 * care of setting up the display, starting and stopping the timer, calling
172 * drawLayers, and saving (if --save is used).
173 *
174 * This times both the CPU and GPU work initiated by drawLayers. All work done
175 * outside of the for loop is excluded from the timing measurements.
176 */
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400177static void benchDrawLayers(RenderEngine& re, const std::vector<LayerSettings>& layers,
178 benchmark::State& benchState, const char* saveFileName) {
179 auto [width, height] = getDisplaySize();
180 auto outputBuffer = allocateBuffer(re, width, height);
181
182 const Rect displayRect(0, 0, static_cast<int32_t>(width), static_cast<int32_t>(height));
183 DisplaySettings display{
184 .physicalDisplay = displayRect,
185 .clip = displayRect,
186 .maxLuminance = 500,
187 };
188
Leon Scroggins IIIb76f17d2021-11-03 15:04:18 -0400189 // This loop starts and stops the timer.
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400190 for (auto _ : benchState) {
Leon Scroggins IIIb76f17d2021-11-03 15:04:18 -0400191 auto [status, drawFence] = re.drawLayers(display, layers, outputBuffer,
192 kUseFrameBufferCache, base::unique_fd())
193 .get();
194 sp<Fence> waitFence = sp<Fence>::make(std::move(drawFence));
195 waitFence->waitForever(LOG_TAG);
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400196 }
197
198 if (renderenginebench::save() && saveFileName) {
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400199 // Copy to a CPU-accessible buffer so we can encode it.
200 outputBuffer = copyBuffer(re, outputBuffer, GRALLOC_USAGE_SW_READ_OFTEN, "to_encode");
201
202 std::string outFile = base::GetExecutableDirectory();
203 outFile.append("/");
204 outFile.append(saveFileName);
205 outFile.append(".jpg");
206 renderenginebench::encodeToJpeg(outFile.c_str(), outputBuffer->getBuffer());
207 }
208}
209
210///////////////////////////////////////////////////////////////////////////////
211// Benchmarks
212///////////////////////////////////////////////////////////////////////////////
213
214void BM_blur(benchmark::State& benchState) {
215 auto re = createRenderEngine(static_cast<RenderEngine::RenderEngineType>(benchState.range()));
216
217 // Initially use cpu access so we can decode into it with AImageDecoder.
218 auto [width, height] = getDisplaySize();
Leon Scroggins IIIb76f17d2021-11-03 15:04:18 -0400219 auto srcBuffer =
220 allocateBuffer(*re, width, height, GRALLOC_USAGE_SW_WRITE_OFTEN, "decoded_source");
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400221 {
222 std::string srcImage = base::GetExecutableDirectory();
223 srcImage.append("/resources/homescreen.png");
224 renderenginebench::decode(srcImage.c_str(), srcBuffer->getBuffer());
225
226 // Now copy into GPU-only buffer for more realistic timing.
227 srcBuffer = copyBuffer(*re, srcBuffer, 0, "source");
228 }
229
230 const FloatRect layerRect(0, 0, width, height);
231 LayerSettings layer{
232 .geometry =
233 Geometry{
234 .boundaries = layerRect,
235 },
236 .source =
237 PixelSource{
238 .buffer =
239 Buffer{
240 .buffer = srcBuffer,
241 },
242 },
243 .alpha = half(1.0f),
244 };
245 LayerSettings blurLayer{
246 .geometry =
247 Geometry{
248 .boundaries = layerRect,
249 },
250 .alpha = half(1.0f),
251 .skipContentDraw = true,
252 .backgroundBlurRadius = 60,
253 };
254
255 auto layers = std::vector<LayerSettings>{layer, blurLayer};
256 benchDrawLayers(*re, layers, benchState, "blurred");
257}
258
Leon Scroggins IIIfd37d2a2021-11-03 15:11:48 -0400259BENCHMARK(BM_blur)->Apply(RunSkiaGLThreaded);