diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index a8f7dc1e0a126..9ac21f7cfaf8c 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -42205,7 +42205,6 @@ ORIGIN: ../../../flutter/impeller/entity/shaders/rrect_blur.vert + ../../../flut ORIGIN: ../../../flutter/impeller/entity/shaders/runtime_effect.vert + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/solid_fill.frag + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/solid_fill.vert + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/impeller/entity/shaders/texture_downsample.frag + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/texture_fill.frag + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/texture_fill.vert + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/texture_fill_strict_src.frag + ../../../flutter/LICENSE @@ -45090,7 +45089,6 @@ FILE: ../../../flutter/impeller/entity/shaders/rrect_blur.vert FILE: ../../../flutter/impeller/entity/shaders/runtime_effect.vert FILE: ../../../flutter/impeller/entity/shaders/solid_fill.frag FILE: ../../../flutter/impeller/entity/shaders/solid_fill.vert -FILE: ../../../flutter/impeller/entity/shaders/texture_downsample.frag FILE: ../../../flutter/impeller/entity/shaders/texture_fill.frag FILE: ../../../flutter/impeller/entity/shaders/texture_fill.vert FILE: ../../../flutter/impeller/entity/shaders/texture_fill_strict_src.frag diff --git a/impeller/aiks/aiks_blur_unittests.cc b/impeller/aiks/aiks_blur_unittests.cc index 95d7b1d10f568..c2cafa39be77f 100644 --- a/impeller/aiks/aiks_blur_unittests.cc +++ b/impeller/aiks/aiks_blur_unittests.cc @@ -1041,6 +1041,160 @@ TEST_P(AiksTest, GuassianBlurUpdatesMipmapContents) { ASSERT_TRUE(OpenPlaygroundHere(callback)); } +TEST_P(AiksTest, GaussianBlurSetsMipCountOnPass) { + Canvas canvas; + canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()}); + canvas.SaveLayer({}, std::nullopt, + ImageFilter::MakeBlur(Sigma(3), Sigma(3), + FilterContents::BlurStyle::kNormal, + Entity::TileMode::kClamp)); + canvas.Restore(); + + Picture picture = canvas.EndRecordingAsPicture(); + EXPECT_EQ(4, picture.pass->GetRequiredMipCount()); +} + +TEST_P(AiksTest, GaussianBlurAllocatesCorrectMipCountRenderTarget) { + size_t blur_required_mip_count = + GetParam() == PlaygroundBackend::kOpenGLES ? 1 : 4; + + Canvas canvas; + canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()}); + canvas.SaveLayer({}, std::nullopt, + ImageFilter::MakeBlur(Sigma(3), Sigma(3), + FilterContents::BlurStyle::kNormal, + Entity::TileMode::kClamp)); + canvas.Restore(); + + Picture picture = canvas.EndRecordingAsPicture(); + std::shared_ptr cache = + std::make_shared(GetContext()->GetResourceAllocator()); + AiksContext aiks_context(GetContext(), nullptr, cache); + picture.ToImage(aiks_context, {100, 100}); + + size_t max_mip_count = 0; + for (auto it = cache->GetRenderTargetDataBegin(); + it != cache->GetRenderTargetDataEnd(); ++it) { + max_mip_count = std::max(it->config.mip_count, max_mip_count); + } + EXPECT_EQ(max_mip_count, blur_required_mip_count); +} + +TEST_P(AiksTest, GaussianBlurMipMapNestedLayer) { + fml::testing::LogCapture log_capture; + size_t blur_required_mip_count = + GetParam() == PlaygroundBackend::kOpenGLES ? 1 : 4; + + Canvas canvas; + canvas.DrawPaint({.color = Color::Wheat()}); + canvas.SaveLayer({.blend_mode = BlendMode::kMultiply}); + canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()}); + canvas.SaveLayer({}, std::nullopt, + ImageFilter::MakeBlur(Sigma(30), Sigma(30), + FilterContents::BlurStyle::kNormal, + Entity::TileMode::kClamp)); + canvas.DrawCircle({200, 200}, 50, {.color = Color::Chartreuse()}); + + Picture picture = canvas.EndRecordingAsPicture(); + std::shared_ptr cache = + std::make_shared(GetContext()->GetResourceAllocator()); + AiksContext aiks_context(GetContext(), nullptr, cache); + picture.ToImage(aiks_context, {100, 100}); + + size_t max_mip_count = 0; + for (auto it = cache->GetRenderTargetDataBegin(); + it != cache->GetRenderTargetDataEnd(); ++it) { + max_mip_count = std::max(it->config.mip_count, max_mip_count); + } + EXPECT_EQ(max_mip_count, blur_required_mip_count); + // The log is FML_DLOG, so only check in debug builds. +#ifndef NDEBUG + if (GetParam() != PlaygroundBackend::kOpenGLES) { + EXPECT_EQ(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError), + std::string::npos); + } else { + EXPECT_NE(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError), + std::string::npos); + } +#endif +} + +TEST_P(AiksTest, GaussianBlurMipMapImageFilter) { + size_t blur_required_mip_count = + GetParam() == PlaygroundBackend::kOpenGLES ? 1 : 4; + fml::testing::LogCapture log_capture; + Canvas canvas; + canvas.SaveLayer( + {.image_filter = ImageFilter::MakeBlur(Sigma(30), Sigma(30), + FilterContents::BlurStyle::kNormal, + Entity::TileMode::kClamp)}); + canvas.DrawCircle({200, 200}, 50, {.color = Color::Chartreuse()}); + + Picture picture = canvas.EndRecordingAsPicture(); + std::shared_ptr cache = + std::make_shared(GetContext()->GetResourceAllocator()); + AiksContext aiks_context(GetContext(), nullptr, cache); + picture.ToImage(aiks_context, {1024, 768}); + + size_t max_mip_count = 0; + for (auto it = cache->GetRenderTargetDataBegin(); + it != cache->GetRenderTargetDataEnd(); ++it) { + max_mip_count = std::max(it->config.mip_count, max_mip_count); + } + EXPECT_EQ(max_mip_count, blur_required_mip_count); + // The log is FML_DLOG, so only check in debug builds. +#ifndef NDEBUG + if (GetParam() != PlaygroundBackend::kOpenGLES) { + EXPECT_EQ(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError), + std::string::npos); + } else { + EXPECT_NE(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError), + std::string::npos); + } +#endif +} + +TEST_P(AiksTest, GaussianBlurMipMapSolidColor) { + size_t blur_required_mip_count = + GetParam() == PlaygroundBackend::kOpenGLES ? 1 : 4; + fml::testing::LogCapture log_capture; + Canvas canvas; + canvas.DrawPath(PathBuilder{} + .MoveTo({100, 100}) + .LineTo({200, 100}) + .LineTo({150, 200}) + .LineTo({50, 200}) + .Close() + .TakePath(), + {.color = Color::Chartreuse(), + .image_filter = ImageFilter::MakeBlur( + Sigma(30), Sigma(30), FilterContents::BlurStyle::kNormal, + Entity::TileMode::kClamp)}); + + Picture picture = canvas.EndRecordingAsPicture(); + std::shared_ptr cache = + std::make_shared(GetContext()->GetResourceAllocator()); + AiksContext aiks_context(GetContext(), nullptr, cache); + picture.ToImage(aiks_context, {1024, 768}); + + size_t max_mip_count = 0; + for (auto it = cache->GetRenderTargetDataBegin(); + it != cache->GetRenderTargetDataEnd(); ++it) { + max_mip_count = std::max(it->config.mip_count, max_mip_count); + } + EXPECT_EQ(max_mip_count, blur_required_mip_count); + // The log is FML_DLOG, so only check in debug builds. +#ifndef NDEBUG + if (GetParam() != PlaygroundBackend::kOpenGLES) { + EXPECT_EQ(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError), + std::string::npos); + } else { + EXPECT_NE(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError), + std::string::npos); + } +#endif +} + TEST_P(AiksTest, MaskBlurDoesntStretchContents) { Scalar sigma = 70; auto callback = [&](AiksContext& renderer) -> std::optional { diff --git a/impeller/aiks/canvas.cc b/impeller/aiks/canvas.cc index 917df48bd3a82..33e449e3eac40 100644 --- a/impeller/aiks/canvas.cc +++ b/impeller/aiks/canvas.cc @@ -185,6 +185,37 @@ void Canvas::Save(uint32_t total_content_depth) { Save(false, total_content_depth); } +namespace { +class MipCountVisitor : public ImageFilterVisitor { + public: + virtual void Visit(const BlurImageFilter& filter) { + required_mip_count_ = FilterContents::kBlurFilterRequiredMipCount; + } + virtual void Visit(const LocalMatrixImageFilter& filter) { + required_mip_count_ = 1; + } + virtual void Visit(const DilateImageFilter& filter) { + required_mip_count_ = 1; + } + virtual void Visit(const ErodeImageFilter& filter) { + required_mip_count_ = 1; + } + virtual void Visit(const MatrixImageFilter& filter) { + required_mip_count_ = 1; + } + virtual void Visit(const ComposeImageFilter& filter) { + required_mip_count_ = 1; + } + virtual void Visit(const ColorImageFilter& filter) { + required_mip_count_ = 1; + } + int32_t GetRequiredMipCount() const { return required_mip_count_; } + + private: + int32_t required_mip_count_ = -1; +}; +} // namespace + void Canvas::Save(bool create_subpass, uint32_t total_content_depth, BlendMode blend_mode, @@ -209,6 +240,11 @@ void Canvas::Save(bool create_subpass, return filter; }; subpass->SetBackdropFilter(backdrop_filter_proc); + MipCountVisitor mip_count_visitor; + backdrop_filter->Visit(mip_count_visitor); + current_pass_->SetRequiredMipCount( + std::max(current_pass_->GetRequiredMipCount(), + mip_count_visitor.GetRequiredMipCount())); } subpass->SetBlendMode(blend_mode); current_pass_ = GetCurrentPass().AddSubpass(std::move(subpass)); @@ -837,6 +873,11 @@ void Canvas::SaveLayer(const Paint& paint, new_layer_pass.SetBoundsLimit(bounds, bounds_promise); } + if (paint.image_filter) { + MipCountVisitor mip_count_visitor; + paint.image_filter->Visit(mip_count_visitor); + new_layer_pass.SetRequiredMipCount(mip_count_visitor.GetRequiredMipCount()); + } // When applying a save layer, absorb any pending distributed opacity. Paint paint_copy = paint; paint_copy.color.alpha *= transform_stack_.back().distributed_opacity; diff --git a/impeller/entity/BUILD.gn b/impeller/entity/BUILD.gn index d91d56cdfe5fe..d4363be8d7804 100644 --- a/impeller/entity/BUILD.gn +++ b/impeller/entity/BUILD.gn @@ -50,7 +50,6 @@ impeller_shaders("entity_shaders") { "shaders/blending/vertices_uber.frag", "shaders/gradients/fast_gradient.vert", "shaders/gradients/fast_gradient.frag", - "shaders/texture_downsample.frag", ] } diff --git a/impeller/entity/contents/content_context.cc b/impeller/entity/contents/content_context.cc index d1975f9f3f90a..35d51c4795d54 100644 --- a/impeller/entity/contents/content_context.cc +++ b/impeller/entity/contents/content_context.cc @@ -428,7 +428,6 @@ ContentContext::ContentContext( {static_cast(BlendSelectValues::kSoftLight), supports_decal}); } - texture_downsample_pipelines_.CreateDefault(*context_, options_trianglestrip); rrect_blur_pipelines_.CreateDefault(*context_, options_trianglestrip); texture_strict_src_pipelines_.CreateDefault(*context_, options); tiled_texture_pipelines_.CreateDefault(*context_, options, {supports_decal}); diff --git a/impeller/entity/contents/content_context.h b/impeller/entity/contents/content_context.h index 8e947d2efa5a3..083412ecebeb8 100644 --- a/impeller/entity/contents/content_context.h +++ b/impeller/entity/contents/content_context.h @@ -48,7 +48,6 @@ #include "impeller/entity/solid_fill.vert.h" #include "impeller/entity/srgb_to_linear_filter.frag.h" #include "impeller/entity/sweep_gradient_fill.frag.h" -#include "impeller/entity/texture_downsample.frag.h" #include "impeller/entity/texture_fill.frag.h" #include "impeller/entity/texture_fill.vert.h" #include "impeller/entity/texture_fill_strict_src.frag.h" @@ -111,9 +110,6 @@ using RRectBlurPipeline = RenderPipelineHandle; using TexturePipeline = RenderPipelineHandle; -using TextureDownsamplePipeline = - RenderPipelineHandle; using TextureStrictSrcPipeline = RenderPipelineHandle; @@ -594,11 +590,6 @@ class ContentContext { return GetPipeline(blend_softlight_pipelines_, opts); } - std::shared_ptr> GetDownsamplePipeline( - ContentContextOptions opts) const { - return GetPipeline(texture_downsample_pipelines_, opts); - } - // Framebuffer Advanced Blends std::shared_ptr> GetFramebufferBlendColorPipeline(ContentContextOptions opts) const { @@ -890,7 +881,6 @@ class ContentContext { sweep_gradient_ssbo_fill_pipelines_; mutable Variants rrect_blur_pipelines_; mutable Variants texture_pipelines_; - mutable Variants texture_downsample_pipelines_; mutable Variants texture_strict_src_pipelines_; #ifdef IMPELLER_ENABLE_OPENGLES mutable Variants diff --git a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc index ad184172317df..fe35f8f784cd3 100644 --- a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc +++ b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc @@ -9,7 +9,6 @@ #include "flutter/fml/make_copyable.h" #include "impeller/entity/contents/clip_contents.h" #include "impeller/entity/contents/content_context.h" -#include "impeller/entity/texture_downsample.frag.h" #include "impeller/entity/texture_fill.frag.h" #include "impeller/entity/texture_fill.vert.h" #include "impeller/renderer/render_pass.h" @@ -20,6 +19,8 @@ namespace impeller { using GaussianBlurVertexShader = GaussianBlurPipeline::VertexShader; using GaussianBlurFragmentShader = GaussianBlurPipeline::FragmentShader; +const int32_t GaussianBlurFilterContents::kBlurFilterRequiredMipCount = 4; + namespace { constexpr Scalar kMaxSigma = 500.0f; @@ -130,13 +131,28 @@ std::optional GetSnapshot(const std::shared_ptr& input, const ContentContext& renderer, const Entity& entity, const std::optional& coverage_hint) { + int32_t mip_count = GaussianBlurFilterContents::kBlurFilterRequiredMipCount; + if (renderer.GetContext()->GetBackendType() == + Context::BackendType::kOpenGLES) { + // TODO(https://github.com/flutter/flutter/issues/141732): Implement mip map + // generation on opengles. + mip_count = 1; + } + std::optional input_snapshot = input->GetSnapshot("GaussianBlur", renderer, entity, - /*coverage_limit=*/coverage_hint); + /*coverage_limit=*/coverage_hint, + /*mip_count=*/mip_count); if (!input_snapshot.has_value()) { return std::nullopt; } + // In order to avoid shimmering in downsampling step, we should have mips. + if (input_snapshot->texture->GetMipCount() <= 1) { + FML_DLOG(ERROR) << GaussianBlurFilterContents::kNoMipsError; + } + FML_DCHECK(!input_snapshot->texture->NeedsMipmapGeneration()); + return input_snapshot; } @@ -226,7 +242,6 @@ DownsamplePassArgs CalculateDownsamplePassArgs( Scalar desired_scalar = std::min(GaussianBlurFilterContents::CalculateScale(scaled_sigma.x), GaussianBlurFilterContents::CalculateScale(scaled_sigma.y)); - // TODO(jonahwilliams): If desired_scalar is 1.0 and we fully acquired the // gutter from the expanded_coverage_hint, we can skip the downsample pass. // pass. @@ -312,106 +327,50 @@ fml::StatusOr MakeDownsampleSubpass( const SamplerDescriptor& sampler_descriptor, const DownsamplePassArgs& pass_args, Entity::TileMode tile_mode) { - // If the texture already had mip levels generated, then we can use the - // original downsample shader. - if (pass_args.effective_scalar.x >= 0.5f || - (!input_texture->NeedsMipmapGeneration() && - input_texture->GetTextureDescriptor().mip_count > 1)) { - ContentContext::SubpassCallback subpass_callback = - [&](const ContentContext& renderer, RenderPass& pass) { - HostBuffer& host_buffer = renderer.GetTransientsBuffer(); - - pass.SetCommandLabel("Gaussian blur downsample"); - auto pipeline_options = OptionsFromPass(pass); - pipeline_options.primitive_type = PrimitiveType::kTriangleStrip; - pass.SetPipeline(renderer.GetTexturePipeline(pipeline_options)); - - TextureFillVertexShader::FrameInfo frame_info; - frame_info.mvp = Matrix::MakeOrthographic(ISize(1, 1)); - frame_info.texture_sampler_y_coord_scale = 1.0; - - TextureFillFragmentShader::FragInfo frag_info; - frag_info.alpha = 1.0; - - const Quad& uvs = pass_args.uvs; - BindVertices(pass, host_buffer, - { - {Point(0, 0), uvs[0]}, - {Point(1, 0), uvs[1]}, - {Point(0, 1), uvs[2]}, - {Point(1, 1), uvs[3]}, - }); - - SamplerDescriptor linear_sampler_descriptor = sampler_descriptor; - SetTileMode(&linear_sampler_descriptor, renderer, tile_mode); - linear_sampler_descriptor.mag_filter = MinMagFilter::kLinear; - linear_sampler_descriptor.min_filter = MinMagFilter::kLinear; - TextureFillVertexShader::BindFrameInfo( - pass, host_buffer.EmplaceUniform(frame_info)); - TextureFillFragmentShader::BindFragInfo( - pass, host_buffer.EmplaceUniform(frag_info)); - TextureFillFragmentShader::BindTextureSampler( - pass, input_texture, - renderer.GetContext()->GetSamplerLibrary()->GetSampler( - linear_sampler_descriptor)); - - return pass.Draw().ok(); - }; - return renderer.MakeSubpass("Gaussian Blur Filter", pass_args.subpass_size, - command_buffer, subpass_callback); - } else { - // This assumes we don't scale below 1/8 - Scalar edge = 1.0; - Scalar ratio = 0.25; - if (pass_args.effective_scalar.x <= 0.125f) { - edge = 3.0; - ratio = 0.0625; - } - ContentContext::SubpassCallback subpass_callback = - [&](const ContentContext& renderer, RenderPass& pass) { - HostBuffer& host_buffer = renderer.GetTransientsBuffer(); - - pass.SetCommandLabel("Gaussian blur downsample"); - auto pipeline_options = OptionsFromPass(pass); - pipeline_options.primitive_type = PrimitiveType::kTriangleStrip; - pass.SetPipeline(renderer.GetDownsamplePipeline(pipeline_options)); - - TextureFillVertexShader::FrameInfo frame_info; - frame_info.mvp = Matrix::MakeOrthographic(ISize(1, 1)); - frame_info.texture_sampler_y_coord_scale = 1.0; - - TextureDownsampleFragmentShader::FragInfo frag_info; - frag_info.edge = edge; - frag_info.ratio = ratio; - frag_info.pixel_size = Vector2(1.0f / Size(input_texture->GetSize())); - - const Quad& uvs = pass_args.uvs; - BindVertices(pass, host_buffer, - { - {Point(0, 0), uvs[0]}, - {Point(1, 0), uvs[1]}, - {Point(0, 1), uvs[2]}, - {Point(1, 1), uvs[3]}, - }); - - SamplerDescriptor linear_sampler_descriptor = sampler_descriptor; - SetTileMode(&linear_sampler_descriptor, renderer, tile_mode); - linear_sampler_descriptor.mag_filter = MinMagFilter::kLinear; - linear_sampler_descriptor.min_filter = MinMagFilter::kLinear; - TextureFillVertexShader::BindFrameInfo( - pass, host_buffer.EmplaceUniform(frame_info)); - TextureDownsampleFragmentShader::BindFragInfo( - pass, host_buffer.EmplaceUniform(frag_info)); - TextureDownsampleFragmentShader::BindTextureSampler( - pass, input_texture, - renderer.GetContext()->GetSamplerLibrary()->GetSampler( - linear_sampler_descriptor)); - - return pass.Draw().ok(); - }; - return renderer.MakeSubpass("Gaussian Blur Filter", pass_args.subpass_size, - command_buffer, subpass_callback); - } + ContentContext::SubpassCallback subpass_callback = + [&](const ContentContext& renderer, RenderPass& pass) { + HostBuffer& host_buffer = renderer.GetTransientsBuffer(); + + pass.SetCommandLabel("Gaussian blur downsample"); + auto pipeline_options = OptionsFromPass(pass); + pipeline_options.primitive_type = PrimitiveType::kTriangleStrip; + pass.SetPipeline(renderer.GetTexturePipeline(pipeline_options)); + + TextureFillVertexShader::FrameInfo frame_info; + frame_info.mvp = Matrix::MakeOrthographic(ISize(1, 1)); + frame_info.texture_sampler_y_coord_scale = 1.0; + + TextureFillFragmentShader::FragInfo frag_info; + frag_info.alpha = 1.0; + + const Quad& uvs = pass_args.uvs; + BindVertices(pass, host_buffer, + { + {Point(0, 0), uvs[0]}, + {Point(1, 0), uvs[1]}, + {Point(0, 1), uvs[2]}, + {Point(1, 1), uvs[3]}, + }); + + SamplerDescriptor linear_sampler_descriptor = sampler_descriptor; + SetTileMode(&linear_sampler_descriptor, renderer, tile_mode); + linear_sampler_descriptor.mag_filter = MinMagFilter::kLinear; + linear_sampler_descriptor.min_filter = MinMagFilter::kLinear; + TextureFillVertexShader::BindFrameInfo( + pass, host_buffer.EmplaceUniform(frame_info)); + TextureFillFragmentShader::BindFragInfo( + pass, host_buffer.EmplaceUniform(frag_info)); + TextureFillFragmentShader::BindTextureSampler( + pass, input_texture, + renderer.GetContext()->GetSamplerLibrary()->GetSampler( + linear_sampler_descriptor)); + + return pass.Draw().ok(); + }; + fml::StatusOr render_target = + renderer.MakeSubpass("Gaussian Blur Filter", pass_args.subpass_size, + command_buffer, subpass_callback); + return render_target; } fml::StatusOr MakeBlurSubpass( @@ -578,6 +537,9 @@ Entity ApplyBlurStyle(FilterContents::BlurStyle blur_style, } } // namespace +std::string_view GaussianBlurFilterContents::kNoMipsError = + "Applying gaussian blur without mipmap."; + GaussianBlurFilterContents::GaussianBlurFilterContents( Scalar sigma_x, Scalar sigma_y, diff --git a/impeller/entity/contents/filters/gaussian_blur_filter_contents.h b/impeller/entity/contents/filters/gaussian_blur_filter_contents.h index 4408858e08b2c..3c91d23e65bb0 100644 --- a/impeller/entity/contents/filters/gaussian_blur_filter_contents.h +++ b/impeller/entity/contents/filters/gaussian_blur_filter_contents.h @@ -46,6 +46,9 @@ GaussianBlurPipeline::FragmentShader::KernelSamples LerpHackKernelSamples( /// Note: This will replace `DirectionalGaussianBlurFilterContents`. class GaussianBlurFilterContents final : public FilterContents { public: + static std::string_view kNoMipsError; + static const int32_t kBlurFilterRequiredMipCount; + explicit GaussianBlurFilterContents( Scalar sigma_x, Scalar sigma_y, diff --git a/impeller/entity/shaders/texture_downsample.frag b/impeller/entity/shaders/texture_downsample.frag deleted file mode 100644 index 8b512fe29abf5..0000000000000 --- a/impeller/entity/shaders/texture_downsample.frag +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -precision mediump float; - -#include -#include - -uniform f16sampler2D texture_sampler; - -uniform FragInfo { - float edge; - float ratio; - vec2 pixel_size; -} -frag_info; - -in highp vec2 v_texture_coords; - -out vec4 frag_color; - -void main() { - vec4 total = vec4(0.0); - for (float i = -frag_info.edge; i <= frag_info.edge; i += 2) { - for (float j = -frag_info.edge; j <= frag_info.edge; j += 2) { - total += (texture(texture_sampler, - v_texture_coords + frag_info.pixel_size * vec2(i, j), - float16_t(kDefaultMipBias)) * - frag_info.ratio); - } - } - frag_color = total; -} diff --git a/impeller/tools/malioc.json b/impeller/tools/malioc.json index 65d69603b1dac..b0ac489c58bb2 100644 --- a/impeller/tools/malioc.json +++ b/impeller/tools/malioc.json @@ -4729,126 +4729,6 @@ } } }, - "flutter/impeller/entity/gles/texture_downsample.frag.gles": { - "Mali-G78": { - "core": "Mali-G78", - "filename": "flutter/impeller/entity/gles/texture_downsample.frag.gles", - "has_side_effects": false, - "has_uniform_computation": true, - "modifies_coverage": false, - "reads_color_buffer": false, - "type": "Fragment", - "uses_late_zs_test": false, - "uses_late_zs_update": false, - "variants": { - "Main": { - "fp16_arithmetic": 80, - "has_stack_spilling": false, - "performance": { - "longest_path_bound_pipelines": [ - null - ], - "longest_path_cycles": [ - null, - null, - null, - null, - null, - null, - null - ], - "pipelines": [ - "arith_total", - "arith_fma", - "arith_cvt", - "arith_sfu", - "load_store", - "varying", - "texture" - ], - "shortest_path_bound_pipelines": [ - "arith_total", - "arith_cvt" - ], - "shortest_path_cycles": [ - 0.0625, - 0.0, - 0.0625, - 0.0, - 0.0, - 0.0, - 0.0 - ], - "total_bound_pipelines": [ - "arith_total", - "arith_cvt", - "varying", - "texture" - ], - "total_cycles": [ - 0.25, - 0.125, - 0.25, - 0.0, - 0.0, - 0.25, - 0.25 - ] - }, - "stack_spill_bytes": 0, - "thread_occupancy": 100, - "uniform_registers_used": 6, - "work_registers_used": 19 - } - } - }, - "Mali-T880": { - "core": "Mali-T880", - "filename": "flutter/impeller/entity/gles/texture_downsample.frag.gles", - "has_uniform_computation": false, - "type": "Fragment", - "variants": { - "Main": { - "has_stack_spilling": false, - "performance": { - "longest_path_bound_pipelines": [ - null - ], - "longest_path_cycles": [ - null, - null, - null - ], - "pipelines": [ - "arithmetic", - "load_store", - "texture" - ], - "shortest_path_bound_pipelines": [ - "arithmetic", - "load_store" - ], - "shortest_path_cycles": [ - 1.0, - 1.0, - 0.0 - ], - "total_bound_pipelines": [ - "arithmetic" - ], - "total_cycles": [ - 3.3333332538604736, - 1.0, - 1.0 - ] - }, - "thread_occupancy": 100, - "uniform_registers_used": 1, - "work_registers_used": 4 - } - } - } - }, "flutter/impeller/entity/gles/texture_fill.frag.gles": { "Mali-G78": { "core": "Mali-G78", @@ -7442,78 +7322,6 @@ } } }, - "flutter/impeller/entity/texture_downsample.frag.vkspv": { - "Mali-G78": { - "core": "Mali-G78", - "filename": "flutter/impeller/entity/texture_downsample.frag.vkspv", - "has_side_effects": false, - "has_uniform_computation": true, - "modifies_coverage": false, - "reads_color_buffer": false, - "type": "Fragment", - "uses_late_zs_test": false, - "uses_late_zs_update": false, - "variants": { - "Main": { - "fp16_arithmetic": 40, - "has_stack_spilling": false, - "performance": { - "longest_path_bound_pipelines": [ - null - ], - "longest_path_cycles": [ - null, - null, - null, - null, - null, - null, - null - ], - "pipelines": [ - "arith_total", - "arith_fma", - "arith_cvt", - "arith_sfu", - "load_store", - "varying", - "texture" - ], - "shortest_path_bound_pipelines": [ - "arith_total", - "arith_cvt" - ], - "shortest_path_cycles": [ - 0.109375, - 0.0, - 0.109375, - 0.0, - 0.0, - 0.0, - 0.0 - ], - "total_bound_pipelines": [ - "arith_total", - "arith_cvt" - ], - "total_cycles": [ - 0.328125, - 0.09375, - 0.328125, - 0.0, - 0.0, - 0.25, - 0.25 - ] - }, - "stack_spill_bytes": 0, - "thread_occupancy": 100, - "uniform_registers_used": 8, - "work_registers_used": 14 - } - } - } - }, "flutter/impeller/entity/texture_fill.frag.vkspv": { "Mali-G78": { "core": "Mali-G78",