Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4fc750d7 authored by Nathaniel Nifong's avatar Nathaniel Nifong
Browse files

Warm cache with additional shaders for render engine

Bug: b/178661709

Test: Confirm via perfetto that after a shell stop and start, app start does not trigger
a shader compile during the drawLayer step of render engine.

CUJ's covered by this cl:
* app open 1st time
* app open 2nd time
* app close with button
* app swipe home button to previous app
* open app switcher in portrait
* return to app from switcher in portrait
* rotate portrait to landscape
* rotate landscape to portrair

CUJ's with compiles that need attention in a subsequent cl
* open app switcher in landscape
* return to app from switcher in landscape
* enter youtube fullscreen
* go to youtube/maps pip
* return from youtube/maps pip

Change-Id: Ia0c63402e8b2f6ee91f59603951602511bfae853
parent ee12e4d5
Loading
Loading
Loading
Loading
+57 −30
Original line number Diff line number Diff line
@@ -28,7 +28,10 @@

namespace android::renderengine::skia {

static void drawShadowLayer(SkiaRenderEngine* renderengine, const DisplaySettings& display,
// Warming shader cache, not framebuffer cache.
constexpr bool kUseFrameBufferCache = false;

static void drawShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
                             sp<GraphicBuffer> dstBuffer) {
    // Somewhat arbitrary dimensions, but on screen and slightly shorter, based
    // on actual use.
@@ -39,6 +42,7 @@ static void drawShadowLayer(SkiaRenderEngine* renderengine, const DisplaySetting
                            .boundaries = rect,
                            .roundedCornersCrop = rect,
                    },
            // drawShadow ignores alpha
            .shadow =
                    ShadowSettings{
                            .ambientColor = vec4(0, 0, 0, 0.00935997f),
@@ -61,9 +65,8 @@ static void drawShadowLayer(SkiaRenderEngine* renderengine, const DisplaySetting
                                               0.f,         0.f,          1.f, 0.f,
                                               167.355743f, 1852.257812f, 0.f, 1.f) }) {
        layer.geometry.positionTransform = transform;
        renderengine->drawLayers(display, layers, dstBuffer, false /* useFrameBufferCache*/,
        renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache,
                                 base::unique_fd(), nullptr);
        renderengine->assertShadersCompiled(identity ? 1 : 2);
        identity = false;
    }
}
@@ -76,14 +79,6 @@ static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySetting
            .geometry =
                    Geometry{
                            .boundaries = rect,
                            // This matrix is based on actual data seen when opening the dialer.
                            // What seems to be important in matching the actual use cases are:
                            // - it is not identity
                            // - the layer will be drawn (not clipped out etc)
                            .positionTransform = mat4(.19f,     .0f, .0f,   .0f,
                                                      .0f,     .19f, .0f,   .0f,
                                                      .0f,      .0f, 1.f,   .0f,
                                                      169.f, 1527.f, .0f,   1.f),
                            .roundedCornersCrop = rect,
                    },
            .source = PixelSource{.buffer =
@@ -94,9 +89,22 @@ static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySetting
                                          }},
    };

    // 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

    // Test both drawRect and drawRRect
    auto layers = std::vector<const LayerSettings*>{&layer};
    for (float roundedCornersRadius : {0.0f, 500.f}) {
    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}) {
            // 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}) {
@@ -105,15 +113,35 @@ static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySetting
                    layer.source.buffer.isOpaque = isOpaque;
                    for (auto alpha : {half(.23999f), half(1.0f)}) {
                        layer.alpha = alpha;
                    renderengine->drawLayers(display, layers, dstBuffer,
                                             false /* useFrameBufferCache*/, base::unique_fd(),
                                             nullptr);
                    renderengine->assertShadersCompiled(1);
                        renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache,
                                                 base::unique_fd(), nullptr);
                    }
                }
            }
        }
    }
}

static void drawSolidLayers(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,
            .source =
                    PixelSource{
                            .solidColor = half3(0.1f, 0.2f, 0.3f),
                    },
    };

    auto layers = std::vector<const LayerSettings*>{&layer};
    renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, base::unique_fd(),
                             nullptr);
}

void Cache::primeShaderCache(SkiaRenderEngine* renderengine) {
    const nsecs_t timeBefore = systemTime();
@@ -133,14 +161,13 @@ void Cache::primeShaderCache(SkiaRenderEngine* renderengine) {
                              usage, "primeShaderCache_dst");
    // This buffer will be the source for the call to drawImageLayers. Draw
    // something to it as a placeholder for what an app draws. We should draw
    // something, but the details are not important. We only need one version of
    // the shadow's SkSL, so draw it here, giving us both a placeholder image
    // and a chance to compile the shadow's SkSL.
    // something, but the details are not important. Make use of the shadow layer drawing step
    // to populate it.
    sp<GraphicBuffer> srcBuffer =
            new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888, 1,
                              usage, "drawImageLayer_src");
    drawShadowLayer(renderengine, display, srcBuffer);

    drawSolidLayers(renderengine, display, dstBuffer);
    drawShadowLayers(renderengine, display, srcBuffer);
    drawImageLayers(renderengine, display, dstBuffer, srcBuffer);
    const nsecs_t timeAfter = systemTime();
    const float compileTimeMs = static_cast<float>(timeAfter - timeBefore) / 1.0E6;