blob: 77e01f4967ef06c4309a28bfff6f7f846a278bb8 [file] [log] [blame]
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -05001/*
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 */
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050016#include "Cache.h"
17#include "AutoBackendTexture.h"
18#include "SkiaRenderEngine.h"
19#include "android-base/unique_fd.h"
20#include "renderengine/DisplaySettings.h"
21#include "renderengine/LayerSettings.h"
22#include "ui/GraphicBuffer.h"
23#include "ui/GraphicTypes.h"
24#include "ui/PixelFormat.h"
25#include "ui/Rect.h"
26#include "utils/Timers.h"
27
28namespace android::renderengine::skia {
29
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -040030namespace {
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -040031// Warming shader cache, not framebuffer cache.
32constexpr bool kUseFrameBufferCache = false;
33
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -040034// clang-format off
35// Any non-identity matrix will do.
36const auto kScaleAndTranslate = mat4(0.7f, 0.f, 0.f, 0.f,
37 0.f, 0.7f, 0.f, 0.f,
38 0.f, 0.f, 1.f, 0.f,
39 67.3f, 52.2f, 0.f, 1.f);
40// clang-format on
Nathaniel Nifongbf6f7542021-04-27 12:05:16 -040041// When setting layer.sourceDataspace, whether it matches the destination or not determines whether
42// a color correction effect is added to the shader.
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -040043constexpr auto kDestDataSpace = ui::Dataspace::SRGB;
Nathaniel Nifong21e021f2021-04-21 13:15:46 -040044constexpr auto kOtherDataSpace = ui::Dataspace::DISPLAY_P3;
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -040045} // namespace
46
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -040047static void drawShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
Alec Mouria90a5702021-04-16 16:36:21 +000048 const std::shared_ptr<ExternalTexture>& dstTexture) {
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050049 // Somewhat arbitrary dimensions, but on screen and slightly shorter, based
50 // on actual use.
51 FloatRect rect(0, 0, display.physicalDisplay.width(), display.physicalDisplay.height() - 30);
52 LayerSettings layer{
53 .geometry =
54 Geometry{
55 .boundaries = rect,
56 .roundedCornersCrop = rect,
57 },
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -040058 // drawShadow ignores alpha
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050059 .shadow =
60 ShadowSettings{
61 .ambientColor = vec4(0, 0, 0, 0.00935997f),
62 .spotColor = vec4(0, 0, 0, 0.0455841f),
63 .lightPos = vec3(370.508f, -1527.03f, 1650.f),
64 .lightRadius = 2200.0f,
65 .length = 0.955342f,
66 },
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -040067 // important that this matches dest so the general shadow fragment shader doesn't
68 // have color correction added, and important that it be srgb, so the *vertex* shader
69 // doesn't have color correction added.
70 .sourceDataspace = kDestDataSpace,
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050071 };
72
73 auto layers = std::vector<const LayerSettings*>{&layer};
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -040074 // The identity matrix will generate the fast shader
Alec Mouria90a5702021-04-16 16:36:21 +000075 renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, base::unique_fd(),
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -040076 nullptr);
77 // This matrix, which has different scales for x and y, will
78 // generate the slower (more general case) version, which has variants for translucent
79 // casters and rounded rects.
80 // clang-format off
81 layer.geometry.positionTransform = mat4(0.7f, 0.f, 0.f, 0.f,
82 0.f, 0.8f, 0.f, 0.f,
83 0.f, 0.f, 1.f, 0.f,
84 0.f, 0.f, 0.f, 1.f);
85 // clang-format on
86 for (auto translucent : {false, true}) {
87 layer.shadow.casterIsTranslucent = translucent;
Alec Mouria90a5702021-04-16 16:36:21 +000088 renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache,
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050089 base::unique_fd(), nullptr);
90 }
91}
92
93static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
Alec Mouria90a5702021-04-16 16:36:21 +000094 const std::shared_ptr<ExternalTexture>& dstTexture,
95 const std::shared_ptr<ExternalTexture>& srcTexture) {
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050096 const Rect& displayRect = display.physicalDisplay;
97 FloatRect rect(0, 0, displayRect.width(), displayRect.height());
98 LayerSettings layer{
99 .geometry =
100 Geometry{
101 .boundaries = rect,
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500102 .roundedCornersCrop = rect,
103 },
104 .source = PixelSource{.buffer =
105 Buffer{
Alec Mouria90a5702021-04-16 16:36:21 +0000106 .buffer = srcTexture,
John Reckac09e452021-04-07 16:35:37 -0400107 .maxLuminanceNits = 1000.f,
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500108 }},
109 };
110
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400111 auto threeCornerRadii = {0.0f, 0.05f, 50.f};
112 auto oneCornerRadius = {50.f};
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400113
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500114 // Test both drawRect and drawRRect
115 auto layers = std::vector<const LayerSettings*>{&layer};
Nathaniel Nifongbf6f7542021-04-27 12:05:16 -0400116 for (auto dataspace : {kDestDataSpace, kOtherDataSpace}) {
117 layer.sourceDataspace = dataspace;
118 for (bool identity : {true, false}) {
119 layer.geometry.positionTransform = identity ? mat4() : kScaleAndTranslate;
120 // Corner radii less than 0.5 creates a special shader. This likely occurs in real usage
121 // due to animating corner radius.
122 // For the non-idenity matrix, only the large corner radius will create a new shader.
123 for (float roundedCornersRadius : identity ? threeCornerRadii : oneCornerRadius) {
124 // roundedCornersCrop is always set, but it is this radius that triggers the
125 // behavior
126 layer.geometry.roundedCornersRadius = roundedCornersRadius;
127 for (bool isOpaque : {true, false}) {
128 layer.source.buffer.isOpaque = isOpaque;
129 for (auto alpha : {half(.23999f), half(1.0f)}) {
130 layer.alpha = alpha;
131 renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache,
132 base::unique_fd(), nullptr);
133 }
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500134 }
135 }
136 }
137 }
138}
139
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400140static void drawSolidLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
Alec Mouria90a5702021-04-16 16:36:21 +0000141 const std::shared_ptr<ExternalTexture>& dstTexture) {
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400142 const Rect& displayRect = display.physicalDisplay;
143 FloatRect rect(0, 0, displayRect.width(), displayRect.height());
144 LayerSettings layer{
145 .geometry =
146 Geometry{
147 .boundaries = rect,
148 },
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400149 .source =
150 PixelSource{
151 .solidColor = half3(0.1f, 0.2f, 0.3f),
152 },
Alec Mouria90a5702021-04-16 16:36:21 +0000153 .alpha = 1,
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400154 };
155
156 auto layers = std::vector<const LayerSettings*>{&layer};
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400157 for (auto transform : {mat4(), kScaleAndTranslate}) {
158 layer.geometry.positionTransform = transform;
159 for (float roundedCornersRadius : {0.0f, 0.05f, 50.f}) {
160 layer.geometry.roundedCornersRadius = roundedCornersRadius;
Alec Mouria90a5702021-04-16 16:36:21 +0000161 renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache,
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400162 base::unique_fd(), nullptr);
163 }
164 }
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400165}
166
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400167static void drawBlurLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
Alec Mouria90a5702021-04-16 16:36:21 +0000168 const std::shared_ptr<ExternalTexture>& dstTexture) {
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400169 const Rect& displayRect = display.physicalDisplay;
170 FloatRect rect(0, 0, displayRect.width(), displayRect.height());
171 LayerSettings layer{
172 .geometry =
173 Geometry{
174 .boundaries = rect,
175 },
176 .alpha = 1,
177 };
178
179 auto layers = std::vector<const LayerSettings*>{&layer};
180 for (int radius : {9, 60}) {
181 layer.backgroundBlurRadius = radius;
Alec Mouria90a5702021-04-16 16:36:21 +0000182 renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache,
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400183 base::unique_fd(), nullptr);
184 }
185}
186
Nathaniel Nifong2d91c5e2021-05-13 17:14:00 -0400187// The unique feature of these layers is that the boundary is slightly smaller than the rounded
188// rect crop, so the rounded edges intersect that boundary and require a different clipping method.
189static void drawClippedLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
190 const std::shared_ptr<ExternalTexture>& dstTexture,
191 const std::shared_ptr<ExternalTexture>& srcTexture) {
Nathaniel Nifong21e021f2021-04-21 13:15:46 -0400192 const Rect& displayRect = display.physicalDisplay;
Nathaniel Nifong2d91c5e2021-05-13 17:14:00 -0400193 FloatRect rect(0, 0, displayRect.width(), displayRect.height() - 20); // boundary is smaller
194
195 // clang-format off
196 const auto symmetric = mat4(0.9f, 0.f, 0.f, 0.f,
197 0.f, 0.9f, 0.f, 0.f,
198 0.f, 0.f, 1.f, 0.f,
199 8.8f, 8.1f, 0.f, 1.f);
200 const auto asymmetric = mat4(0.9f, 0.f, 0.f, 0.f,
201 0.f, 0.7f, 0.f, 0.f,
202 0.f, 0.f, 1.f, 0.f,
203 8.8f, 8.1f, 0.f, 1.f);
204
205 // clang-format on
Nathaniel Nifong21e021f2021-04-21 13:15:46 -0400206 LayerSettings layer{
207 .geometry =
208 Geometry{
209 .boundaries = rect,
Nathaniel Nifong2d91c5e2021-05-13 17:14:00 -0400210 .roundedCornersRadius = 27, // larger than the 20 above.
211 .roundedCornersCrop =
212 FloatRect(0, 0, displayRect.width(), displayRect.height()),
Nathaniel Nifong21e021f2021-04-21 13:15:46 -0400213 },
214 .source = PixelSource{.buffer =
215 Buffer{
216 .buffer = srcTexture,
Nathaniel Nifong2d91c5e2021-05-13 17:14:00 -0400217 .isOpaque = 0,
John Reckac09e452021-04-07 16:35:37 -0400218 .maxLuminanceNits = 1000.f,
Nathaniel Nifong21e021f2021-04-21 13:15:46 -0400219 }},
220 .sourceDataspace = kOtherDataSpace,
221 };
222
223 auto layers = std::vector<const LayerSettings*>{&layer};
Nathaniel Nifong2d91c5e2021-05-13 17:14:00 -0400224 for (auto transform : {symmetric, asymmetric}) {
225 layer.geometry.positionTransform = transform;
226 // In real use, I saw alpha of 1.0 and 0.999, probably a mistake, but cache both shaders.
227 for (float alpha : {0.5f, 1.f}) {
228 layer.alpha = alpha,
229 renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache,
230 base::unique_fd(), nullptr);
231 }
Nathaniel Nifong21e021f2021-04-21 13:15:46 -0400232 }
233}
234
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400235//
236// The collection of shaders cached here were found by using perfetto to record shader compiles
237// during actions that involve RenderEngine, logging the layer settings, and the shader code
238// and reproducing those settings here.
239//
240// It is helpful when debugging this to turn on
241// in SkGLRenderEngine.cpp:
242// kPrintLayerSettings = true
243// kFlushAfterEveryLayer = true
244// in external/skia/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp
245// gPrintSKSL = true
246//
247// TODO(b/184631553) cache the shader involved in youtube pip return.
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500248void Cache::primeShaderCache(SkiaRenderEngine* renderengine) {
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400249 const int previousCount = renderengine->reportShadersCompiled();
250 if (previousCount) {
251 ALOGD("%d Shaders already compiled before Cache::primeShaderCache ran\n", previousCount);
252 }
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500253
Derek Sollenbergere9a51082021-05-06 14:01:38 -0400254 // The loop is beneficial for debugging and should otherwise be optimized out by the compiler.
255 // Adding additional bounds to the loop is useful for verifying that the size of the dst buffer
256 // does not impact the shader compilation counts by triggering different behaviors in RE/Skia.
257 for (SkSize bounds : {SkSize::Make(128, 128), /*SkSize::Make(1080, 2340)*/}) {
258 const nsecs_t timeBefore = systemTime();
259 // The dimensions should not matter, so long as we draw inside them.
260 const Rect displayRect(0, 0, bounds.fWidth, bounds.fHeight);
261 DisplaySettings display{
262 .physicalDisplay = displayRect,
263 .clip = displayRect,
264 .maxLuminance = 500,
265 .outputDataspace = kDestDataSpace,
266 };
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500267
Derek Sollenbergere9a51082021-05-06 14:01:38 -0400268 const int64_t usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
Alec Mouria90a5702021-04-16 16:36:21 +0000269
Derek Sollenbergere9a51082021-05-06 14:01:38 -0400270 sp<GraphicBuffer> dstBuffer =
271 new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888,
272 1, usage, "primeShaderCache_dst");
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400273
Derek Sollenbergere9a51082021-05-06 14:01:38 -0400274 const auto dstTexture =
275 std::make_shared<ExternalTexture>(dstBuffer, *renderengine,
276 ExternalTexture::Usage::WRITEABLE);
277 // This buffer will be the source for the call to drawImageLayers. Draw
278 // something to it as a placeholder for what an app draws. We should draw
279 // something, but the details are not important. Make use of the shadow layer drawing step
280 // to populate it.
281 sp<GraphicBuffer> srcBuffer =
282 new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888,
283 1, usage, "drawImageLayer_src");
Alec Mouria90a5702021-04-16 16:36:21 +0000284
Derek Sollenbergere9a51082021-05-06 14:01:38 -0400285 const auto srcTexture =
286 std::make_shared<ExternalTexture>(srcBuffer, *renderengine,
287 ExternalTexture::Usage::READABLE |
288 ExternalTexture::Usage::WRITEABLE);
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400289
Derek Sollenbergere9a51082021-05-06 14:01:38 -0400290 drawSolidLayers(renderengine, display, dstTexture);
291 drawShadowLayers(renderengine, display, srcTexture);
292 drawBlurLayers(renderengine, display, dstTexture);
293 // The majority of shaders are related to sampling images.
294 drawImageLayers(renderengine, display, dstTexture, srcTexture);
Nathaniel Nifongf4362402021-04-12 11:41:05 -0400295
Derek Sollenbergere9a51082021-05-06 14:01:38 -0400296 // should be the same as AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
297 const int64_t usageExternal = GRALLOC_USAGE_HW_TEXTURE;
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400298
Derek Sollenbergere9a51082021-05-06 14:01:38 -0400299 sp<GraphicBuffer> externalBuffer =
300 new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888,
301 1, usageExternal, "primeShaderCache_external");
302 const auto externalTexture =
303 std::make_shared<ExternalTexture>(externalBuffer, *renderengine,
304 ExternalTexture::Usage::READABLE);
305 // TODO(b/184665179) doubles number of image shader compilations, but only somewhere
306 // between 6 and 8 will occur in real uses.
307 drawImageLayers(renderengine, display, dstTexture, externalTexture);
Nathaniel Nifong21e021f2021-04-21 13:15:46 -0400308
Derek Sollenbergere9a51082021-05-06 14:01:38 -0400309 // Draw layers for b/185569240.
Nathaniel Nifong2d91c5e2021-05-13 17:14:00 -0400310 drawClippedLayers(renderengine, display, dstTexture, externalTexture);
Derek Sollenbergere9a51082021-05-06 14:01:38 -0400311
312 const nsecs_t timeAfter = systemTime();
313 const float compileTimeMs = static_cast<float>(timeAfter - timeBefore) / 1.0E6;
314 const int shadersCompiled = renderengine->reportShadersCompiled();
315 ALOGD("Shader cache generated %d shaders in %f ms\n", shadersCompiled, compileTimeMs);
316 }
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500317}
318
319} // namespace android::renderengine::skia