From e6185c3471813dee838f97369fefeac80fe89806 Mon Sep 17 00:00:00 2001 From: Jim Graham Date: Wed, 29 Jan 2025 19:26:14 -0800 Subject: [PATCH] [Impeller] Avoid NaN values when setting up for the fast squircle blur shader (#162421) Fixes https://github.com/flutter/flutter/issues/162128 Zero dimensioned rectangle blurs were causing the setup code to generate NaN values. This condition could also happen for some very thin or short rectangles so rather than just rule out zero-dimensioned rectangles, the uniforms are checked for NaN values and the operation is skipped in those cases. --- .../display_list/aiks_dl_blur_unittests.cc | 22 +++++++++++++++++++ .../contents/solid_rrect_blur_contents.cc | 18 ++++++++++++--- .../testing/impeller_golden_tests_output.txt | 1 + 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/engine/src/flutter/impeller/display_list/aiks_dl_blur_unittests.cc b/engine/src/flutter/impeller/display_list/aiks_dl_blur_unittests.cc index d4d25943552..599c46ea44b 100644 --- a/engine/src/flutter/impeller/display_list/aiks_dl_blur_unittests.cc +++ b/engine/src/flutter/impeller/display_list/aiks_dl_blur_unittests.cc @@ -470,6 +470,28 @@ TEST_P(AiksTest, MaskBlurWithZeroSigmaIsSkipped) { ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); } +TEST_P(AiksTest, MaskBlurOnZeroDimensionIsSkippedWideGamut) { + // Making sure this test is run on a wide gamut enabled backend + EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(), + PixelFormat::kB10G10R10A10XR); + + DisplayListBuilder builder; + builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc); + + DlPaint paint; + paint.setColor(DlColor::kBlue()); + paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 10)); + + // Zero height above + builder.DrawRect(DlRect::MakeLTRB(100, 250, 500, 250), paint); + // Regular rect + builder.DrawRect(DlRect::MakeLTRB(100, 300, 500, 600), paint); + // Zero width to the right + builder.DrawRect(DlRect::MakeLTRB(550, 300, 550, 600), paint); + + ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); +} + struct MaskBlurTestConfig { DlBlurStyle style = DlBlurStyle::kNormal; Scalar sigma = 1.0f; diff --git a/engine/src/flutter/impeller/entity/contents/solid_rrect_blur_contents.cc b/engine/src/flutter/impeller/entity/contents/solid_rrect_blur_contents.cc index 20f01723587..2e69cff52a3 100644 --- a/engine/src/flutter/impeller/entity/contents/solid_rrect_blur_contents.cc +++ b/engine/src/flutter/impeller/entity/contents/solid_rrect_blur_contents.cc @@ -68,7 +68,7 @@ static Point NegPos(Scalar v) { return {std::min(v, 0.0f), std::max(v, 0.0f)}; } -static void SetupFragInfo( +static bool SetupFragInfo( RRectBlurPipeline::FragmentShader::FragInfo& frag_info, Scalar blurSigma, Point center, @@ -96,6 +96,15 @@ static void SetupFragInfo( frag_info.scale = 0.5 * computeErf7(frag_info.sInv * 0.5 * (std::max(rSize.x, rSize.y) - 0.5 * radius)); + + return frag_info.center.IsFinite() && // + frag_info.adjust.IsFinite() && // + std::isfinite(frag_info.minEdge) && // + std::isfinite(frag_info.r1) && // + std::isfinite(frag_info.exponent) && // + std::isfinite(frag_info.sInv) && // + std::isfinite(frag_info.exponentInv) && // + std::isfinite(frag_info.scale); } std::optional SolidRRectBlurContents::GetCoverage( @@ -159,8 +168,11 @@ bool SolidRRectBlurContents::Render(const ContentContext& renderer, positive_rect.GetWidth() * 0.5f), std::clamp(corner_radii_.height, kEhCloseEnough, positive_rect.GetHeight() * 0.5f)); - SetupFragInfo(frag_info, blur_sigma, positive_rect.GetCenter(), - Point(positive_rect.GetSize()), radius); + if (!SetupFragInfo(frag_info, blur_sigma, positive_rect.GetCenter(), + Point(positive_rect.GetSize()), radius)) { + return true; + } + auto& host_buffer = renderer.GetTransientsBuffer(); pass.SetCommandLabel("RRect Shadow"); pass.SetPipeline(renderer.GetRRectBlurPipeline(opts)); diff --git a/engine/src/flutter/testing/impeller_golden_tests_output.txt b/engine/src/flutter/testing/impeller_golden_tests_output.txt index 25d50268e03..d1af556ad96 100644 --- a/engine/src/flutter/testing/impeller_golden_tests_output.txt +++ b/engine/src/flutter/testing/impeller_golden_tests_output.txt @@ -802,6 +802,7 @@ impeller_Play_AiksTest_LinearToSrgbFilterSubpassCollapseOptimization_Vulkan.png impeller_Play_AiksTest_MaskBlurDoesntStretchContents_Metal.png impeller_Play_AiksTest_MaskBlurDoesntStretchContents_OpenGLES.png impeller_Play_AiksTest_MaskBlurDoesntStretchContents_Vulkan.png +impeller_Play_AiksTest_MaskBlurOnZeroDimensionIsSkippedWideGamut_Metal.png impeller_Play_AiksTest_MaskBlurTexture_Metal.png impeller_Play_AiksTest_MaskBlurTexture_OpenGLES.png impeller_Play_AiksTest_MaskBlurTexture_Vulkan.png