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

Commit d12a5ffc authored by Cairn Overturf's avatar Cairn Overturf
Browse files

Misc RenderEngine perf fixes

- Disable AA for clip masks when layers are rotated. Generating clip masks on the CPU can take 1-10ms depending on the clip mask size.
- Precache rotated image shaders. This prevents a cache miss when PiP is initially rotated
- Precache box shadow and outline shaders.

Bug: 424160207
Bug: 421025291
Bug: 367464660

Test: Launch, rotate, and exit PiP. Ensure no shaders are compiled.
Flag: EXEMPT bugfix
Change-Id: I905adfb23ac8edbed135d0dc9aff3e2a3c743e77
parent 2f4e35ae
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -228,6 +228,8 @@ static inline void PrintTo(const Geometry& settings, ::std::ostream* os) {
    *os << "Geometry {";
    *os << "\n    .boundaries = ";
    PrintTo(settings.boundaries, os);
    *os << "\n    .originalBounds = ";
    PrintTo(settings.originalBounds, os);
    *os << "\n    .positionTransform = ";
    PrintMatrix(settings.positionTransform, os);
    *os << "\n    .roundedCornersRadiusX = " << settings.roundedCornersRadius.x;
@@ -328,6 +330,10 @@ static inline void PrintTo(const LayerSettings& settings, ::std::ostream* os) {
        *os << "\n    .luts = ";
        PrintTo(settings.luts, os);
    }

    *os << "\n    .borderSettings = " << settings.borderSettings.toString();
    *os << "\n    .boxShadowSettings = " << settings.boxShadowSettings.toString();

    *os << "\n}";
}

+101 −21
Original line number Diff line number Diff line
@@ -67,7 +67,8 @@ const std::array<float, 3> kLayerWhitePoints = {
};
} // namespace

static void drawShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
static void drawElevationShadowLayers(SkiaRenderEngine* renderengine,
                                      const DisplaySettings& display,
                                      const std::shared_ptr<ExternalTexture>& dstTexture) {
    // Somewhat arbitrary dimensions, but on screen and slightly shorter, based
    // on actual use.
@@ -134,6 +135,78 @@ static void drawShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettin
    }
}

static void drawBoxShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
                                const std::shared_ptr<ExternalTexture>& dstTexture) {
    const Rect& displayRect = display.physicalDisplay;

    // The texture must be large enough for two shaders
    // 1. See ComputeBlurredRRectParams in GrBlurUtils.cpp, the dstTexture must be large enough
    //    for the blur to be considered nine patcheable.
    // 2. See TesselationPathRenderer, there must be enough GPU work to choose the CPU path.
    LOG_ALWAYS_FATAL_IF(displayRect.width() < 384 || displayRect.height() < 384,
                        "dstTexture must be at least 256x256");

    gui::BorderSettings borderSettings;
    borderSettings.strokeWidth = 2.0f;
    borderSettings.color = 666747334;

    gui::BoxShadowSettings boxShadowSettings;
    gui::BoxShadowSettings::BoxShadowParams shadow1;
    shadow1.blurRadius = 28.0f;
    shadow1.spreadRadius = 0.0f;
    shadow1.color = 167772160;
    shadow1.offsetX = 0.0f;
    shadow1.offsetY = 0.0f;
    boxShadowSettings.boxShadows.push_back(shadow1);

    gui::BoxShadowSettings::BoxShadowParams shadow2;
    shadow2.blurRadius = 16.0f;
    shadow2.spreadRadius = 0.0f;
    shadow2.color = 436207616;
    shadow2.offsetX = 0.0f;
    shadow2.offsetY = 4.0f;
    boxShadowSettings.boxShadows.push_back(shadow2);

    FloatRect rect(20, 20, 250, 250);
    LayerSettings layer{
            .geometry =
                    Geometry{
                            .boundaries = rect,
                            .originalBounds = rect,
                            .roundedCornersRadius = {32.0f, 32.0f},
                            .roundedCornersCrop = rect,
                            .otherCrop = FloatRect(-16384, -16384, 16384, 16384),
                    },
            .source =
                    PixelSource{
                            .solidColor = half3(0.f, 0.f, 0.f),
                    },
            .alpha = 1,
            // setting this is mandatory for shadows and blurs
            .skipContentDraw = true,
            // drawShadow ignores alpha
            .borderSettings = borderSettings,
            .boxShadowSettings = boxShadowSettings,
    };

    {
        SFTRACE_NAME("RotatedClip");
        // This triggers quite a few shaders, not quite sure what they all are.
        layer.geometry.positionTransform = kFlip;
        renderengine->drawLayers(display, {layer}, dstTexture, base::unique_fd());
    }
    {
        SFTRACE_NAME("RRectBlur_NinePatch");
        layer.geometry.positionTransform = mat4();
        renderengine->drawLayers(display, {layer}, dstTexture, base::unique_fd());
    }
    {
        SFTRACE_NAME("ConcavePath_Tessellate");
        layer.geometry.positionTransform = mat4::scale(vec4(1.5f, 1.5f, 1.0f, 1.0f)) * kFlip;
        renderengine->drawLayers(display, {layer}, dstTexture, base::unique_fd());
    }
}

static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
                            const std::shared_ptr<ExternalTexture>& dstTexture,
                            const std::shared_ptr<ExternalTexture>& srcTexture) {
@@ -143,8 +216,6 @@ static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySetting
            .geometry =
                    Geometry{
                            .boundaries = rect,
                            // The position transform doesn't matter when the reduced shader mode
                            // in in effect. A matrix transform stage is always included.
                            .positionTransform = mat4(),
                            .roundedCornersCrop = rect,
                    },
@@ -155,6 +226,8 @@ static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySetting
                                          }},
    };

    for (mat4 transform : {mat4(), kFlip}) {
        layer.geometry.positionTransform = transform;
        for (auto dataspace : {kDestDataSpace, kOtherDataSpace}) {
            layer.sourceDataspace = dataspace;
            // Cache shaders for both rects and round rects.
@@ -173,6 +246,7 @@ static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySetting
            }
        }
    }
}

static void drawSolidLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
                            const std::shared_ptr<ExternalTexture>& dstTexture) {
@@ -768,7 +842,7 @@ void Cache::primeShaderCache(SkiaRenderEngine* renderengine, PrimeCacheConfig co
    // The loop is beneficial for debugging and should otherwise be optimized out by the compiler.
    // Adding additional bounds to the loop is useful for verifying that the size of the dst buffer
    // does not impact the shader compilation counts by triggering different behaviors in RE/Skia.
    for (SkSize bounds : {SkSize::Make(128, 128), /*SkSize::Make(1080, 2340)*/}) {
    for (SkSize bounds : {SkSize::Make(384, 384), /*SkSize::Make(1080, 2340)*/}) {
        const nsecs_t timeBefore = systemTime();
        // The dimensions should not matter, so long as we draw inside them.
        const Rect displayRect(0, 0, bounds.fWidth, bounds.fHeight);
@@ -851,9 +925,15 @@ void Cache::primeShaderCache(SkiaRenderEngine* renderengine, PrimeCacheConfig co
        }

        if (config.cacheShadowLayers) {
            {
                SFTRACE_NAME("cacheShadowLayers");
            drawShadowLayers(renderengine, display, srcTexture);
            drawShadowLayers(renderengine, p3Display, srcTexture);
                drawElevationShadowLayers(renderengine, display, srcTexture);
                drawElevationShadowLayers(renderengine, p3Display, srcTexture);
            }
            {
                SFTRACE_NAME("cacheBoxShadows");
                drawBoxShadowLayers(renderengine, display, srcTexture);
            }
        }

        if (renderengine->supportsBackgroundBlur()) {
+6 −0
Original line number Diff line number Diff line
@@ -314,6 +314,12 @@ SkiaRenderEngine::Contexts SkiaGLRenderEngine::createContexts() {
    return contexts;
}

bool SkiaGLRenderEngine::supportsFastRotatedClipRRectAA() const {
    // clipRRect can take 1-10ms depending on the rrect size due to generating the
    // clip mask on the CPU.
    return false;
}

bool SkiaGLRenderEngine::supportsForwardPixelKill() const {
    // ARM gpu support this since 2013
    constexpr std::string kArm = "ARM";
+1 −0
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@ protected:
    // rendering backend
    virtual SkiaRenderEngine::Contexts createContexts();
    bool supportsForwardPixelKill() const override;
    bool supportsFastRotatedClipRRectAA() const override;
    bool supportsProtectedContentImpl() const override;
    bool useProtectedContextImpl(GrProtected isProtected) override;
    void waitFence(SkiaGpuContext* context, base::borrowed_fd fenceFd) override;
+9 −4
Original line number Diff line number Diff line
@@ -874,7 +874,8 @@ void SkiaRenderEngine::drawLayersInternal(
                                   SkData::MakeWithCString(layerSettings.str().c_str()));
        }
        // Layers have a local transform that should be applied to them
        canvas->concat(getSkM44(layer.geometry.positionTransform).asM33());
        SkMatrix positionTransform = getSkM44(layer.geometry.positionTransform).asM33();
        canvas->concat(positionTransform);

        const auto [bounds, roundRectClip] =
                getBoundsAndClip(layer.geometry.boundaries, layer.geometry.roundedCornersCrop,
@@ -957,6 +958,9 @@ void SkiaRenderEngine::drawLayersInternal(
            }
        }

        bool enableAntiAlias =
                supportsFastRotatedClipRRectAA() || positionTransform.rectStaysRect();

        {
            SFTRACE_NAME("OutsetRendering");
            SkRRect otherCrop;
@@ -966,7 +970,7 @@ void SkiaRenderEngine::drawLayersInternal(
            // Outset rendering needs to be clipped by parent.
            SkAutoCanvasRestore acr(canvas, true);
            if (!otherCrop.isEmpty()) {
                canvas->clipRRect(otherCrop, true);
                canvas->clipRRect(otherCrop, enableAntiAlias);
            }

            if (layer.shadow.length > 0) {
@@ -1018,7 +1022,8 @@ void SkiaRenderEngine::drawLayersInternal(
                                   layer.borderSettings.strokeWidth);

                SkPaint paint;
                paint.setAntiAlias(true);
                // When rotated / scaling the lack of AA is imperceptible for the outline.
                paint.setAntiAlias(enableAntiAlias);
                paint.setColor(layer.borderSettings.color);
                paint.setStyle(SkPaint::kFill_Style);
                canvas->drawDRRect(outlineRect, preferredOriginalBounds, paint);
@@ -1291,7 +1296,7 @@ void SkiaRenderEngine::drawLayersInternal(
        }

        if (!roundRectClip.isEmpty()) {
            canvas->clipRRect(roundRectClip, true);
            canvas->clipRRect(roundRectClip, enableAntiAlias);
        }

        if (!bounds.isRect()) {
Loading