blob: 7bcfff53488500e093800521eb658ea76720dd4c [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///////////////////////////////////////////////////////////////////////////////
33// Helpers for Benchmark::Apply
34///////////////////////////////////////////////////////////////////////////////
35
36std::string RenderEngineTypeName(RenderEngine::RenderEngineType type) {
37 switch (type) {
38 case RenderEngine::RenderEngineType::SKIA_GL_THREADED:
39 return "skiaglthreaded";
40 case RenderEngine::RenderEngineType::SKIA_GL:
41 return "skiagl";
42 case RenderEngine::RenderEngineType::GLES:
43 case RenderEngine::RenderEngineType::THREADED:
44 LOG_ALWAYS_FATAL("GLESRenderEngine is deprecated - why time it?");
45 return "unused";
46 }
47}
48
49/**
Leon Scroggins IIIfd37d2a2021-11-03 15:11:48 -040050 * Passed (indirectly - see RunSkiaGLThreaded) to Benchmark::Apply to create a
51 * Benchmark which specifies which RenderEngineType it uses.
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040052 *
53 * This simplifies calling ->Arg(type)->Arg(type) and provides strings to make
54 * it obvious which version is being run.
55 *
56 * @param b The benchmark family
57 * @param type The type of RenderEngine to use.
58 */
59static void AddRenderEngineType(benchmark::internal::Benchmark* b,
60 RenderEngine::RenderEngineType type) {
61 b->Arg(static_cast<int64_t>(type));
62 b->ArgName(RenderEngineTypeName(type));
63}
64
65/**
Leon Scroggins IIIfd37d2a2021-11-03 15:11:48 -040066 * Run a benchmark once using SKIA_GL_THREADED.
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040067 */
Leon Scroggins IIIfd37d2a2021-11-03 15:11:48 -040068static void RunSkiaGLThreaded(benchmark::internal::Benchmark* b) {
69 AddRenderEngineType(b, RenderEngine::RenderEngineType::SKIA_GL_THREADED);
Leon Scroggins III8fcfa662021-10-12 11:33:30 -040070}
71
72///////////////////////////////////////////////////////////////////////////////
73// Helpers for calling drawLayers
74///////////////////////////////////////////////////////////////////////////////
75
76std::pair<uint32_t, uint32_t> getDisplaySize() {
77 // These will be retrieved from a ui::Size, which stores int32_t, but they will be passed
78 // to GraphicBuffer, which wants uint32_t.
79 static uint32_t width, height;
80 std::once_flag once;
81 std::call_once(once, []() {
82 auto surfaceComposerClient = SurfaceComposerClient::getDefault();
83 auto displayToken = surfaceComposerClient->getInternalDisplayToken();
84 ui::DisplayMode displayMode;
85 if (surfaceComposerClient->getActiveDisplayMode(displayToken, &displayMode) < 0) {
86 LOG_ALWAYS_FATAL("Failed to get active display mode!");
87 }
88 auto w = displayMode.resolution.width;
89 auto h = displayMode.resolution.height;
90 LOG_ALWAYS_FATAL_IF(w <= 0 || h <= 0, "Invalid display size!");
91 width = static_cast<uint32_t>(w);
92 height = static_cast<uint32_t>(h);
93 });
94 return std::pair<uint32_t, uint32_t>(width, height);
95}
96
97// This value doesn't matter, as it's not read. TODO(b/199918329): Once we remove
98// GLESRenderEngine we can remove this, too.
99static constexpr const bool kUseFrameBufferCache = false;
100
101static std::unique_ptr<RenderEngine> createRenderEngine(RenderEngine::RenderEngineType type) {
102 auto args = RenderEngineCreationArgs::Builder()
103 .setPixelFormat(static_cast<int>(ui::PixelFormat::RGBA_8888))
104 .setImageCacheSize(1)
105 .setEnableProtectedContext(true)
106 .setPrecacheToneMapperShaderOnly(false)
107 .setSupportsBackgroundBlur(true)
108 .setContextPriority(RenderEngine::ContextPriority::REALTIME)
109 .setRenderEngineType(type)
110 .setUseColorManagerment(true)
111 .build();
112 return RenderEngine::create(args);
113}
114
Leon Scroggins IIIb76f17d2021-11-03 15:04:18 -0400115static std::shared_ptr<ExternalTexture> allocateBuffer(RenderEngine& re, uint32_t width,
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400116 uint32_t height,
117 uint64_t extraUsageFlags = 0,
118 std::string name = "output") {
Vishnu Nairdbbe3852022-01-12 20:22:11 -0800119 return std::make_shared<
Ady Abrahamd11bade2022-08-01 16:18:03 -0700120 impl::ExternalTexture>(sp<GraphicBuffer>::make(width, height,
121 HAL_PIXEL_FORMAT_RGBA_8888, 1u,
122 GRALLOC_USAGE_HW_RENDER |
123 GRALLOC_USAGE_HW_TEXTURE |
124 extraUsageFlags,
125 std::move(name)),
Vishnu Nairdbbe3852022-01-12 20:22:11 -0800126 re,
127 impl::ExternalTexture::Usage::READABLE |
128 impl::ExternalTexture::Usage::WRITEABLE);
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400129}
130
131static std::shared_ptr<ExternalTexture> copyBuffer(RenderEngine& re,
132 std::shared_ptr<ExternalTexture> original,
133 uint64_t extraUsageFlags, std::string name) {
134 const uint32_t width = original->getBuffer()->getWidth();
135 const uint32_t height = original->getBuffer()->getHeight();
136 auto texture = allocateBuffer(re, width, height, extraUsageFlags, name);
137
138 const Rect displayRect(0, 0, static_cast<int32_t>(width), static_cast<int32_t>(height));
139 DisplaySettings display{
140 .physicalDisplay = displayRect,
141 .clip = displayRect,
142 .maxLuminance = 500,
143 };
144
145 const FloatRect layerRect(0, 0, width, height);
146 LayerSettings layer{
147 .geometry =
148 Geometry{
149 .boundaries = layerRect,
150 },
151 .source =
152 PixelSource{
153 .buffer =
154 Buffer{
155 .buffer = original,
156 },
157 },
158 .alpha = half(1.0f),
159 };
160 auto layers = std::vector<LayerSettings>{layer};
161
162 auto [status, drawFence] =
163 re.drawLayers(display, layers, texture, kUseFrameBufferCache, base::unique_fd()).get();
Leon Scroggins IIIb76f17d2021-11-03 15:04:18 -0400164 sp<Fence> waitFence = sp<Fence>::make(std::move(drawFence));
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400165 waitFence->waitForever(LOG_TAG);
166 return texture;
167}
168
Leon Scroggins IIIb76f17d2021-11-03 15:04:18 -0400169/**
170 * Helper for timing calls to drawLayers.
171 *
172 * Caller needs to create RenderEngine and the LayerSettings, and this takes
173 * care of setting up the display, starting and stopping the timer, calling
174 * drawLayers, and saving (if --save is used).
175 *
176 * This times both the CPU and GPU work initiated by drawLayers. All work done
177 * outside of the for loop is excluded from the timing measurements.
178 */
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400179static void benchDrawLayers(RenderEngine& re, const std::vector<LayerSettings>& layers,
180 benchmark::State& benchState, const char* saveFileName) {
181 auto [width, height] = getDisplaySize();
182 auto outputBuffer = allocateBuffer(re, width, height);
183
184 const Rect displayRect(0, 0, static_cast<int32_t>(width), static_cast<int32_t>(height));
185 DisplaySettings display{
186 .physicalDisplay = displayRect,
187 .clip = displayRect,
188 .maxLuminance = 500,
189 };
190
Leon Scroggins IIIb76f17d2021-11-03 15:04:18 -0400191 // This loop starts and stops the timer.
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400192 for (auto _ : benchState) {
Leon Scroggins IIIb76f17d2021-11-03 15:04:18 -0400193 auto [status, drawFence] = re.drawLayers(display, layers, outputBuffer,
194 kUseFrameBufferCache, base::unique_fd())
195 .get();
196 sp<Fence> waitFence = sp<Fence>::make(std::move(drawFence));
197 waitFence->waitForever(LOG_TAG);
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400198 }
199
200 if (renderenginebench::save() && saveFileName) {
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400201 // Copy to a CPU-accessible buffer so we can encode it.
202 outputBuffer = copyBuffer(re, outputBuffer, GRALLOC_USAGE_SW_READ_OFTEN, "to_encode");
203
204 std::string outFile = base::GetExecutableDirectory();
205 outFile.append("/");
206 outFile.append(saveFileName);
207 outFile.append(".jpg");
208 renderenginebench::encodeToJpeg(outFile.c_str(), outputBuffer->getBuffer());
209 }
210}
211
212///////////////////////////////////////////////////////////////////////////////
213// Benchmarks
214///////////////////////////////////////////////////////////////////////////////
215
216void BM_blur(benchmark::State& benchState) {
217 auto re = createRenderEngine(static_cast<RenderEngine::RenderEngineType>(benchState.range()));
218
219 // Initially use cpu access so we can decode into it with AImageDecoder.
220 auto [width, height] = getDisplaySize();
Leon Scroggins IIIb76f17d2021-11-03 15:04:18 -0400221 auto srcBuffer =
222 allocateBuffer(*re, width, height, GRALLOC_USAGE_SW_WRITE_OFTEN, "decoded_source");
Leon Scroggins III8fcfa662021-10-12 11:33:30 -0400223 {
224 std::string srcImage = base::GetExecutableDirectory();
225 srcImage.append("/resources/homescreen.png");
226 renderenginebench::decode(srcImage.c_str(), srcBuffer->getBuffer());
227
228 // Now copy into GPU-only buffer for more realistic timing.
229 srcBuffer = copyBuffer(*re, srcBuffer, 0, "source");
230 }
231
232 const FloatRect layerRect(0, 0, width, height);
233 LayerSettings layer{
234 .geometry =
235 Geometry{
236 .boundaries = layerRect,
237 },
238 .source =
239 PixelSource{
240 .buffer =
241 Buffer{
242 .buffer = srcBuffer,
243 },
244 },
245 .alpha = half(1.0f),
246 };
247 LayerSettings blurLayer{
248 .geometry =
249 Geometry{
250 .boundaries = layerRect,
251 },
252 .alpha = half(1.0f),
253 .skipContentDraw = true,
254 .backgroundBlurRadius = 60,
255 };
256
257 auto layers = std::vector<LayerSettings>{layer, blurLayer};
258 benchDrawLayers(*re, layers, benchState, "blurred");
259}
260
Leon Scroggins IIIfd37d2a2021-11-03 15:11:48 -0400261BENCHMARK(BM_blur)->Apply(RunSkiaGLThreaded);