Catch more shaders in cache warming
Bug: b/178661709
Test: Confirm with perfetto no unwanted shader compiles during
certain render engine actions
Change-Id: Ib5a523bcdcf8eded74f7ec4ecca526bdceff5039
diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp
index 69c6a09..0cd3b62 100644
--- a/libs/renderengine/skia/Cache.cpp
+++ b/libs/renderengine/skia/Cache.cpp
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
#include "Cache.h"
#include "AutoBackendTexture.h"
#include "SkiaRenderEngine.h"
@@ -26,11 +25,28 @@
#include "ui/Rect.h"
#include "utils/Timers.h"
+#include <android/hardware_buffer.h>
+
namespace android::renderengine::skia {
+namespace {
// Warming shader cache, not framebuffer cache.
constexpr bool kUseFrameBufferCache = false;
+// clang-format off
+// Any non-identity matrix will do.
+const auto kScaleAndTranslate = mat4(0.7f, 0.f, 0.f, 0.f,
+ 0.f, 0.7f, 0.f, 0.f,
+ 0.f, 0.f, 1.f, 0.f,
+ 67.3f, 52.2f, 0.f, 1.f);
+// clang-format on
+// When choosing dataspaces below, whether the match the destination or not determined whether
+// a color correction effect is added to the shader. There may be other additional shader details
+// for particular color spaces.
+// TODO(b/184842383) figure out which color related shaders are necessary
+constexpr auto kDestDataSpace = ui::Dataspace::SRGB;
+} // namespace
+
static void drawShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
sp<GraphicBuffer> dstBuffer) {
// Somewhat arbitrary dimensions, but on screen and slightly shorter, based
@@ -51,23 +67,29 @@
.lightRadius = 2200.0f,
.length = 0.955342f,
},
+ // important that this matches dest so the general shadow fragment shader doesn't
+ // have color correction added, and important that it be srgb, so the *vertex* shader
+ // doesn't have color correction added.
+ .sourceDataspace = kDestDataSpace,
};
auto layers = std::vector<const LayerSettings*>{&layer};
- // The identity matrix will generate the fast shaders, and the second matrix
- // (based on one seen while going from dialer to the home screen) will
- // generate the slower (more general case) version. If we also need a
- // slow version without color correction, we should use this matrix with
- // display.outputDataspace set to SRGB.
- bool identity = true;
- for (const mat4 transform : { mat4(), mat4(0.728872f, 0.f, 0.f, 0.f,
- 0.f, 0.727627f, 0.f, 0.f,
- 0.f, 0.f, 1.f, 0.f,
- 167.355743f, 1852.257812f, 0.f, 1.f) }) {
- layer.geometry.positionTransform = transform;
+ // The identity matrix will generate the fast shader
+ renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, base::unique_fd(),
+ nullptr);
+ // This matrix, which has different scales for x and y, will
+ // generate the slower (more general case) version, which has variants for translucent
+ // casters and rounded rects.
+ // clang-format off
+ layer.geometry.positionTransform = mat4(0.7f, 0.f, 0.f, 0.f,
+ 0.f, 0.8f, 0.f, 0.f,
+ 0.f, 0.f, 1.f, 0.f,
+ 0.f, 0.f, 0.f, 1.f);
+ // clang-format on
+ for (auto translucent : {false, true}) {
+ layer.shadow.casterIsTranslucent = translucent;
renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache,
base::unique_fd(), nullptr);
- identity = false;
}
}
@@ -89,33 +111,25 @@
}},
};
- // This matrix is based on actual data seen when opening the dialer.
- // translate and scale creates new shaders when combined with rounded corners
- // clang-format off
- auto scale_and_translate = mat4(.19f, .0f, .0f, .0f,
- .0f, .19f, .0f, .0f,
- .0f, .0f, 1.f, .0f,
- 169.f, 1527.f, .0f, 1.f);
- // clang-format on
+ auto threeCornerRadii = {0.0f, 0.05f, 50.f};
+ auto oneCornerRadius = {50.f};
// Test both drawRect and drawRRect
auto layers = std::vector<const LayerSettings*>{&layer};
- for (auto transform : {mat4(), scale_and_translate}) {
- layer.geometry.positionTransform = transform;
- // fractional corner radius creates a shader that is used during home button swipe
- for (float roundedCornersRadius : {0.0f, 0.05f, 500.f}) {
+ for (bool identity : {true, false}) {
+ layer.geometry.positionTransform = identity ? mat4() : kScaleAndTranslate;
+ // Corner radii less than 0.5 creates a special shader. This likely occurs in real usage
+ // due to animating corner radius.
+ // For the non-idenity matrix, only the large corner radius will create a new shader.
+ for (float roundedCornersRadius : identity ? threeCornerRadii : oneCornerRadius) {
// roundedCornersCrop is always set, but it is this radius that triggers the behavior
layer.geometry.roundedCornersRadius = roundedCornersRadius;
- // No need to check UNKNOWN, which is treated as SRGB.
- for (auto dataspace : {ui::Dataspace::SRGB, ui::Dataspace::DISPLAY_P3}) {
- layer.sourceDataspace = dataspace;
- for (bool isOpaque : {true, false}) {
- layer.source.buffer.isOpaque = isOpaque;
- for (auto alpha : {half(.23999f), half(1.0f)}) {
- layer.alpha = alpha;
- renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache,
- base::unique_fd(), nullptr);
- }
+ for (bool isOpaque : {true, false}) {
+ layer.source.buffer.isOpaque = isOpaque;
+ for (auto alpha : {half(.23999f), half(1.0f)}) {
+ layer.alpha = alpha;
+ renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache,
+ base::unique_fd(), nullptr);
}
}
}
@@ -139,11 +153,89 @@
};
auto layers = std::vector<const LayerSettings*>{&layer};
- renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, base::unique_fd(),
- nullptr);
+ for (auto transform : {mat4(), kScaleAndTranslate}) {
+ layer.geometry.positionTransform = transform;
+ for (float roundedCornersRadius : {0.0f, 0.05f, 50.f}) {
+ layer.geometry.roundedCornersRadius = roundedCornersRadius;
+ renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache,
+ base::unique_fd(), nullptr);
+ }
+ }
}
+static void drawBlurLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
+ sp<GraphicBuffer> dstBuffer) {
+ const Rect& displayRect = display.physicalDisplay;
+ FloatRect rect(0, 0, displayRect.width(), displayRect.height());
+ LayerSettings layer{
+ .geometry =
+ Geometry{
+ .boundaries = rect,
+ },
+ .alpha = 1,
+ };
+
+ auto layers = std::vector<const LayerSettings*>{&layer};
+ for (int radius : {9, 60}) {
+ layer.backgroundBlurRadius = radius;
+ renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache,
+ base::unique_fd(), nullptr);
+ }
+}
+
+namespace {
+
+struct AHardwareBuffer_deleter {
+ void operator()(AHardwareBuffer* ahb) const { AHardwareBuffer_release(ahb); }
+};
+
+std::unique_ptr<AHardwareBuffer, AHardwareBuffer_deleter> makeAHardwareBuffer() {
+ AHardwareBuffer* buffer = nullptr;
+
+ int w = 32;
+ int h = 32;
+
+ AHardwareBuffer_Desc hwbDesc;
+ hwbDesc.width = w;
+ hwbDesc.height = h;
+ hwbDesc.layers = 1;
+ hwbDesc.usage = AHARDWAREBUFFER_USAGE_CPU_READ_NEVER | AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER |
+ AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
+ hwbDesc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
+ // The following three are not used in the allocate
+ hwbDesc.stride = 0;
+ hwbDesc.rfu0 = 0;
+ hwbDesc.rfu1 = 0;
+
+ if (int error = AHardwareBuffer_allocate(&hwbDesc, &buffer)) {
+ ALOGE("Failed to allocated hardware buffer, error: %d", error);
+ if (buffer) {
+ AHardwareBuffer_release(buffer);
+ }
+ return nullptr;
+ }
+ return std::unique_ptr<AHardwareBuffer, AHardwareBuffer_deleter>(buffer);
+}
+} // namespace
+
+//
+// The collection of shaders cached here were found by using perfetto to record shader compiles
+// during actions that involve RenderEngine, logging the layer settings, and the shader code
+// and reproducing those settings here.
+//
+// It is helpful when debugging this to turn on
+// in SkGLRenderEngine.cpp:
+// kPrintLayerSettings = true
+// kFlushAfterEveryLayer = true
+// in external/skia/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp
+// gPrintSKSL = true
+//
+// TODO(b/184631553) cache the shader involved in youtube pip return.
void Cache::primeShaderCache(SkiaRenderEngine* renderengine) {
+ const int previousCount = renderengine->reportShadersCompiled();
+ if (previousCount) {
+ ALOGD("%d Shaders already compiled before Cache::primeShaderCache ran\n", previousCount);
+ }
const nsecs_t timeBefore = systemTime();
// The dimensions should not matter, so long as we draw inside them.
const Rect displayRect(0, 0, 1080, 2340);
@@ -151,7 +243,7 @@
.physicalDisplay = displayRect,
.clip = displayRect,
.maxLuminance = 500,
- .outputDataspace = ui::Dataspace::DISPLAY_P3,
+ .outputDataspace = kDestDataSpace,
};
const int64_t usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
@@ -166,12 +258,28 @@
sp<GraphicBuffer> srcBuffer =
new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888, 1,
usage, "drawImageLayer_src");
+
drawSolidLayers(renderengine, display, dstBuffer);
drawShadowLayers(renderengine, display, srcBuffer);
+ drawBlurLayers(renderengine, display, dstBuffer);
+ // The majority of shaders are related to sampling images.
drawImageLayers(renderengine, display, dstBuffer, srcBuffer);
+
+ // Draw image layers again sampling from an AHardwareBuffer if it is possible to create one.
+ if (auto ahb = makeAHardwareBuffer()) {
+ sp<GraphicBuffer> externalBuffer = GraphicBuffer::fromAHardwareBuffer(ahb.get());
+ // TODO(b/184665179) doubles number of image shader compilations, but only somewhere
+ // between 6 and 8 will occur in real uses.
+ drawImageLayers(renderengine, display, dstBuffer, externalBuffer);
+ renderengine->unbindExternalTextureBuffer(externalBuffer->getId());
+ }
+
+ renderengine->unbindExternalTextureBuffer(srcBuffer->getId());
+
const nsecs_t timeAfter = systemTime();
const float compileTimeMs = static_cast<float>(timeAfter - timeBefore) / 1.0E6;
- ALOGD("shader cache generated in %f ms\n", compileTimeMs);
+ const int shadersCompiled = renderengine->reportShadersCompiled();
+ ALOGD("Shader cache generated %d shaders in %f ms\n", shadersCompiled, compileTimeMs);
}
} // namespace android::renderengine::skia
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index 94a0dca..fb7e285 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -56,6 +56,12 @@
#include "skia/debug/SkiaCapture.h"
#include "system/graphics-base-v1.0.h"
+namespace {
+// Debugging settings
+static const bool kPrintLayerSettings = false;
+static const bool kFlushAfterEveryLayer = false;
+} // namespace
+
bool checkGlError(const char* op, int lineNumber);
namespace android {
@@ -285,6 +291,10 @@
numShaders, cached);
}
+int SkiaGLRenderEngine::reportShadersCompiled() {
+ return mSkSLCacheMonitor.shadersCachedSinceLastCall();
+}
+
SkiaGLRenderEngine::SkiaGLRenderEngine(const RenderEngineCreationArgs& args, EGLDisplay display,
EGLContext ctxt, EGLSurface placeholder,
EGLContext protectedContext, EGLSurface protectedPlaceholder)
@@ -735,6 +745,17 @@
for (const auto& layer : layers) {
ATRACE_NAME("DrawLayer");
+ if (kPrintLayerSettings) {
+ std::stringstream ls;
+ PrintTo(*layer, &ls);
+ auto debugs = ls.str();
+ int pos = 0;
+ while (pos < debugs.size()) {
+ ALOGD("cache_debug %s", debugs.substr(pos, 1000).c_str());
+ pos += 1000;
+ }
+ }
+
sk_sp<SkImage> blurInput;
if (blurCompositionLayer == layer) {
LOG_ALWAYS_FATAL_IF(activeSurface == dstSurface);
@@ -956,6 +977,10 @@
} else {
canvas->drawRect(bounds, paint);
}
+ if (kFlushAfterEveryLayer) {
+ ATRACE_NAME("flush surface");
+ activeSurface->flush();
+ }
}
surfaceAutoSaveRestore.restore();
mCapture->endCapture();
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h
index 25557f1..8e77c16 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.h
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.h
@@ -66,6 +66,7 @@
bool supportsBackgroundBlur() override { return mBlurFilter != nullptr; }
void assertShadersCompiled(int numShaders) override;
void onPrimaryDisplaySizeChanged(ui::Size size) override;
+ int reportShadersCompiled() override;
protected:
void dump(std::string& result) override;
diff --git a/libs/renderengine/skia/SkiaRenderEngine.h b/libs/renderengine/skia/SkiaRenderEngine.h
index 59d7e2f..51ef088 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.h
+++ b/libs/renderengine/skia/SkiaRenderEngine.h
@@ -59,6 +59,7 @@
virtual bool cleanupPostRender(CleanupMode) override { return true; };
virtual int getContextPriority() override { return 0; }
virtual void assertShadersCompiled(int numShaders) {}
+ virtual int reportShadersCompiled() { return 0; }
};
} // namespace skia