diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index f57b0f2e30c3a..f16aa21a7810c 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -43078,15 +43078,19 @@ ORIGIN: ../../../flutter/impeller/entity/shaders/glyph_atlas.frag + ../../../flu ORIGIN: ../../../flutter/impeller/entity/shaders/glyph_atlas.vert + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/gradients/conical_gradient_fill.frag + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/gradients/conical_gradient_ssbo_fill.frag + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/entity/shaders/gradients/conical_gradient_uniform_fill.frag + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/gradients/fast_gradient.frag + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/gradients/fast_gradient.vert + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/gradients/gradient_fill.vert + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/gradients/linear_gradient_fill.frag + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/gradients/linear_gradient_ssbo_fill.frag + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/entity/shaders/gradients/linear_gradient_uniform_fill.frag + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/gradients/radial_gradient_fill.frag + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/gradients/radial_gradient_ssbo_fill.frag + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/entity/shaders/gradients/radial_gradient_uniform_fill.frag + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/gradients/sweep_gradient_fill.frag + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/gradients/sweep_gradient_ssbo_fill.frag + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/entity/shaders/gradients/sweep_gradient_uniform_fill.frag + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/rrect_blur.frag + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/rrect_blur.vert + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/runtime_effect.vert + ../../../flutter/LICENSE @@ -45940,15 +45944,19 @@ FILE: ../../../flutter/impeller/entity/shaders/glyph_atlas.frag FILE: ../../../flutter/impeller/entity/shaders/glyph_atlas.vert FILE: ../../../flutter/impeller/entity/shaders/gradients/conical_gradient_fill.frag FILE: ../../../flutter/impeller/entity/shaders/gradients/conical_gradient_ssbo_fill.frag +FILE: ../../../flutter/impeller/entity/shaders/gradients/conical_gradient_uniform_fill.frag FILE: ../../../flutter/impeller/entity/shaders/gradients/fast_gradient.frag FILE: ../../../flutter/impeller/entity/shaders/gradients/fast_gradient.vert FILE: ../../../flutter/impeller/entity/shaders/gradients/gradient_fill.vert FILE: ../../../flutter/impeller/entity/shaders/gradients/linear_gradient_fill.frag FILE: ../../../flutter/impeller/entity/shaders/gradients/linear_gradient_ssbo_fill.frag +FILE: ../../../flutter/impeller/entity/shaders/gradients/linear_gradient_uniform_fill.frag FILE: ../../../flutter/impeller/entity/shaders/gradients/radial_gradient_fill.frag FILE: ../../../flutter/impeller/entity/shaders/gradients/radial_gradient_ssbo_fill.frag +FILE: ../../../flutter/impeller/entity/shaders/gradients/radial_gradient_uniform_fill.frag FILE: ../../../flutter/impeller/entity/shaders/gradients/sweep_gradient_fill.frag FILE: ../../../flutter/impeller/entity/shaders/gradients/sweep_gradient_ssbo_fill.frag +FILE: ../../../flutter/impeller/entity/shaders/gradients/sweep_gradient_uniform_fill.frag FILE: ../../../flutter/impeller/entity/shaders/rrect_blur.frag FILE: ../../../flutter/impeller/entity/shaders/rrect_blur.vert FILE: ../../../flutter/impeller/entity/shaders/runtime_effect.vert diff --git a/impeller/display_list/aiks_dl_gradient_unittests.cc b/impeller/display_list/aiks_dl_gradient_unittests.cc index 3390a1dec6db3..3d96f941a564a 100644 --- a/impeller/display_list/aiks_dl_gradient_unittests.cc +++ b/impeller/display_list/aiks_dl_gradient_unittests.cc @@ -216,6 +216,123 @@ TEST_P(AiksTest, CanRenderLinearGradientWithOverlappingStopsClamp) { CanRenderLinearGradientWithOverlappingStops(this, DlTileMode::kClamp); } +namespace { +void CanRenderGradientWithIncompleteStops(AiksTest* aiks_test, + DlColorSourceType type) { + const DlTileMode tile_modes[4] = { + DlTileMode::kClamp, + DlTileMode::kRepeat, + DlTileMode::kMirror, + DlTileMode::kDecal, + }; + const DlScalar test_size = 250; + const DlScalar test_border = 25; + const DlScalar gradient_size = 50; + const DlScalar quadrant_size = test_size + test_border * 2; + + DisplayListBuilder builder; + builder.DrawRect(DlRect::MakeWH(quadrant_size * 2, quadrant_size * 2), + DlPaint().setColor(DlColor::kDarkGrey())); + + for (int quadrant = 0; quadrant < 4; quadrant++) { + builder.Save(); + builder.Translate((quadrant & 1) * quadrant_size + test_border, + (quadrant >> 1) * quadrant_size + test_border); + + if (type == DlColorSourceType::kLinearGradient) { + // Alignment lines for the gradient edges/repeats/mirrors/etc. + // (rendered under the gradient so as not to obscure it) + DlPoint center = DlPoint(test_size, test_size) * 0.5; + DlScalar ten_percent = gradient_size * 0.1; + for (int i = gradient_size / 2; i <= test_size / 2; i += gradient_size) { + auto draw_at = [=](DlCanvas& canvas, DlScalar offset, DlColor color) { + DlPaint line_paint; + line_paint.setColor(color); + // strokewidth of 2 straddles the dividing line + line_paint.setStrokeWidth(2.0f); + line_paint.setDrawStyle(DlDrawStyle::kStroke); + + DlPoint along(offset, offset); + DlScalar across_distance = test_size / 2 + 10 - offset; + DlPoint across(across_distance, -across_distance); + + canvas.DrawLine(center - along - across, // + center - along + across, // + line_paint); + canvas.DrawLine(center + along - across, // + center + along + across, // + line_paint); + }; + // White line is at the edge of the gradient + // Grey lines are where the 0.1 and 0.9 color stops land + draw_at(builder, i - ten_percent, DlColor::kMidGrey()); + draw_at(builder, i, DlColor::kWhite()); + draw_at(builder, i + ten_percent, DlColor::kMidGrey()); + } + } + + std::vector colors = { + DlColor::kGreen(), + DlColor::kPurple(), + DlColor::kOrange(), + DlColor::kBlue(), + }; + std::vector stops = {0.1, 0.3, 0.7, 0.9}; + + DlPaint paint; + switch (type) { + case DlColorSourceType::kLinearGradient: + paint.setColorSource(DlColorSource::MakeLinear( + {test_size / 2 - gradient_size / 2, + test_size / 2 - gradient_size / 2}, + {test_size / 2 + gradient_size / 2, + test_size / 2 + gradient_size / 2}, + stops.size(), colors.data(), stops.data(), tile_modes[quadrant])); + break; + case DlColorSourceType::kRadialGradient: + paint.setColorSource(DlColorSource::MakeRadial( + {test_size / 2, test_size / 2}, gradient_size, // + stops.size(), colors.data(), stops.data(), tile_modes[quadrant])); + break; + case DlColorSourceType::kConicalGradient: + paint.setColorSource(DlColorSource::MakeConical( + {test_size / 2, test_size / 2}, 0, + {test_size / 2 + 20, test_size / 2 - 10}, gradient_size, + stops.size(), colors.data(), stops.data(), tile_modes[quadrant])); + break; + case DlColorSourceType::kSweepGradient: + paint.setColorSource(DlColorSource::MakeSweep( + {test_size / 2, test_size / 2}, 0, 45, // + stops.size(), colors.data(), stops.data(), tile_modes[quadrant])); + break; + default: + FML_UNREACHABLE(); + } + + builder.DrawRect(SkRect::MakeXYWH(0, 0, test_size, test_size), paint); + builder.Restore(); + } + + ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build())); +} +} // namespace + +TEST_P(AiksTest, CanRenderLinearGradientWithIncompleteStops) { + CanRenderGradientWithIncompleteStops(this, + DlColorSourceType::kLinearGradient); +} +TEST_P(AiksTest, CanRenderRadialGradientWithIncompleteStops) { + CanRenderGradientWithIncompleteStops(this, + DlColorSourceType::kRadialGradient); +} +TEST_P(AiksTest, CanRenderConicalGradientWithIncompleteStops) { + CanRenderGradientWithIncompleteStops(this, + DlColorSourceType::kConicalGradient); +} +TEST_P(AiksTest, CanRenderSweepGradientWithIncompleteStops) { + CanRenderGradientWithIncompleteStops(this, DlColorSourceType::kSweepGradient); +} + namespace { void CanRenderLinearGradientManyColors(AiksTest* aiks_test, DlTileMode tile_mode) { diff --git a/impeller/entity/BUILD.gn b/impeller/entity/BUILD.gn index 9311d35eb0cf7..48bcb2bc33075 100644 --- a/impeller/entity/BUILD.gn +++ b/impeller/entity/BUILD.gn @@ -18,18 +18,22 @@ impeller_shaders("entity_shaders") { "shaders/blending/advanced_blend.frag", "shaders/clip.frag", "shaders/clip.vert", - "shaders/gradients/conical_gradient_fill.frag", "shaders/glyph_atlas.frag", "shaders/glyph_atlas.vert", "shaders/gradients/gradient_fill.vert", + "shaders/gradients/conical_gradient_fill.frag", + "shaders/gradients/conical_gradient_uniform_fill.frag", "shaders/gradients/linear_gradient_fill.frag", + "shaders/gradients/linear_gradient_uniform_fill.frag", "shaders/gradients/radial_gradient_fill.frag", + "shaders/gradients/radial_gradient_uniform_fill.frag", + "shaders/gradients/sweep_gradient_fill.frag", + "shaders/gradients/sweep_gradient_uniform_fill.frag", "shaders/rrect_blur.vert", "shaders/rrect_blur.frag", "shaders/runtime_effect.vert", "shaders/solid_fill.frag", "shaders/solid_fill.vert", - "shaders/gradients/sweep_gradient_fill.frag", "shaders/texture_fill.frag", "shaders/texture_fill.vert", "shaders/texture_uv_fill.vert", diff --git a/impeller/entity/contents/conical_gradient_contents.cc b/impeller/entity/contents/conical_gradient_contents.cc index 82a9bbff5ea4b..85c2b62403df3 100644 --- a/impeller/entity/contents/conical_gradient_contents.cc +++ b/impeller/entity/contents/conical_gradient_contents.cc @@ -49,12 +49,24 @@ void ConicalGradientContents::SetFocus(std::optional focus, focus_radius_ = radius; } +#define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0])) +#define UNIFORM_FRAG_INFO(t) \ + t##GradientUniformFillPipeline::FragmentShader::FragInfo +#define UNIFORM_COLOR_SIZE ARRAY_LEN(UNIFORM_FRAG_INFO(Conical)::colors) +#define UNIFORM_STOP_SIZE ARRAY_LEN(UNIFORM_FRAG_INFO(Conical)::stop_pairs) +static_assert(UNIFORM_COLOR_SIZE == kMaxUniformGradientStops); +static_assert(UNIFORM_STOP_SIZE == kMaxUniformGradientStops / 2); + bool ConicalGradientContents::Render(const ContentContext& renderer, const Entity& entity, RenderPass& pass) const { if (renderer.GetDeviceCapabilities().SupportsSSBO()) { return RenderSSBO(renderer, entity, pass); } + if (colors_.size() <= kMaxUniformGradientStops && + stops_.size() <= kMaxUniformGradientStops) { + return RenderUniform(renderer, entity, pass); + } return RenderTexture(renderer, entity, pass); } @@ -107,6 +119,49 @@ bool ConicalGradientContents::RenderSSBO(const ContentContext& renderer, }); } +bool ConicalGradientContents::RenderUniform(const ContentContext& renderer, + const Entity& entity, + RenderPass& pass) const { + using VS = ConicalGradientUniformFillPipeline::VertexShader; + using FS = ConicalGradientUniformFillPipeline::FragmentShader; + + VS::FrameInfo frame_info; + frame_info.matrix = GetInverseEffectTransform(); + + PipelineBuilderCallback pipeline_callback = + [&renderer](ContentContextOptions options) { + return renderer.GetConicalGradientUniformFillPipeline(options); + }; + return ColorSourceContents::DrawGeometry( + renderer, entity, pass, pipeline_callback, frame_info, + [this, &renderer, &entity](RenderPass& pass) { + FS::FragInfo frag_info; + frag_info.center = center_; + if (focus_) { + frag_info.focus = focus_.value(); + frag_info.focus_radius = focus_radius_; + } else { + frag_info.focus = center_; + frag_info.focus_radius = 0.0; + } + frag_info.radius = radius_; + frag_info.tile_mode = static_cast(tile_mode_); + frag_info.alpha = + GetOpacityFactor() * + GetGeometry()->ComputeAlphaCoverage(entity.GetTransform()); + frag_info.colors_length = PopulateUniformGradientColors( + colors_, stops_, frag_info.colors, frag_info.stop_pairs); + frag_info.decal_border_color = decal_border_color_; + + pass.SetCommandLabel("ConicalGradientUniformFill"); + + FS::BindFragInfo( + pass, renderer.GetTransientsBuffer().EmplaceUniform(frag_info)); + + return true; + }); +} + bool ConicalGradientContents::RenderTexture(const ContentContext& renderer, const Entity& entity, RenderPass& pass) const { diff --git a/impeller/entity/contents/conical_gradient_contents.h b/impeller/entity/contents/conical_gradient_contents.h index 16d43c74afb64..1174722385c04 100644 --- a/impeller/entity/contents/conical_gradient_contents.h +++ b/impeller/entity/contents/conical_gradient_contents.h @@ -51,6 +51,11 @@ class ConicalGradientContents final : public ColorSourceContents { bool RenderSSBO(const ContentContext& renderer, const Entity& entity, RenderPass& pass) const; + + bool RenderUniform(const ContentContext& renderer, + const Entity& entity, + RenderPass& pass) const; + Point center_; Scalar radius_ = 0.0f; std::vector colors_; diff --git a/impeller/entity/contents/content_context.cc b/impeller/entity/contents/content_context.cc index fe1725e5a8ac6..b3cc2d9932585 100644 --- a/impeller/entity/contents/content_context.cc +++ b/impeller/entity/contents/content_context.cc @@ -308,6 +308,12 @@ ContentContext::ContentContext( conical_gradient_ssbo_fill_pipelines_.CreateDefault(*context_, options); sweep_gradient_ssbo_fill_pipelines_.CreateDefault(*context_, options); } else { + linear_gradient_uniform_fill_pipelines_.CreateDefault(*context_, options); + radial_gradient_uniform_fill_pipelines_.CreateDefault(*context_, options); + conical_gradient_uniform_fill_pipelines_.CreateDefault(*context_, + options); + sweep_gradient_uniform_fill_pipelines_.CreateDefault(*context_, options); + linear_gradient_fill_pipelines_.CreateDefault(*context_, options); radial_gradient_fill_pipelines_.CreateDefault(*context_, options); conical_gradient_fill_pipelines_.CreateDefault(*context_, options); diff --git a/impeller/entity/contents/content_context.h b/impeller/entity/contents/content_context.h index 69d67b97f4657..0cfb4a2623e3e 100644 --- a/impeller/entity/contents/content_context.h +++ b/impeller/entity/contents/content_context.h @@ -56,6 +56,11 @@ #include "impeller/entity/tiled_texture_fill.frag.h" #include "impeller/entity/yuv_to_rgb_filter.frag.h" +#include "impeller/entity/conical_gradient_uniform_fill.frag.h" +#include "impeller/entity/linear_gradient_uniform_fill.frag.h" +#include "impeller/entity/radial_gradient_uniform_fill.frag.h" +#include "impeller/entity/sweep_gradient_uniform_fill.frag.h" + #include "impeller/entity/conical_gradient_ssbo_fill.frag.h" #include "impeller/entity/linear_gradient_ssbo_fill.frag.h" #include "impeller/entity/radial_gradient_ssbo_fill.frag.h" @@ -92,6 +97,18 @@ using ConicalGradientFillPipeline = using SweepGradientFillPipeline = RenderPipelineHandle; +using LinearGradientUniformFillPipeline = + RenderPipelineHandle; +using ConicalGradientUniformFillPipeline = + RenderPipelineHandle; +using RadialGradientUniformFillPipeline = + RenderPipelineHandle; +using SweepGradientUniformFillPipeline = + RenderPipelineHandle; using LinearGradientSSBOFillPipeline = RenderPipelineHandle; @@ -370,6 +387,26 @@ class ContentContext { return GetPipeline(linear_gradient_fill_pipelines_, opts); } + std::shared_ptr> + GetLinearGradientUniformFillPipeline(ContentContextOptions opts) const { + return GetPipeline(linear_gradient_uniform_fill_pipelines_, opts); + } + + std::shared_ptr> + GetRadialGradientUniformFillPipeline(ContentContextOptions opts) const { + return GetPipeline(radial_gradient_uniform_fill_pipelines_, opts); + } + + std::shared_ptr> + GetConicalGradientUniformFillPipeline(ContentContextOptions opts) const { + return GetPipeline(conical_gradient_uniform_fill_pipelines_, opts); + } + + std::shared_ptr> + GetSweepGradientUniformFillPipeline(ContentContextOptions opts) const { + return GetPipeline(sweep_gradient_uniform_fill_pipelines_, opts); + } + std::shared_ptr> GetLinearGradientSSBOFillPipeline(ContentContextOptions opts) const { FML_DCHECK(GetDeviceCapabilities().SupportsSSBO()); @@ -867,6 +904,14 @@ class ContentContext { mutable Variants conical_gradient_fill_pipelines_; mutable Variants sweep_gradient_fill_pipelines_; + mutable Variants + linear_gradient_uniform_fill_pipelines_; + mutable Variants + radial_gradient_uniform_fill_pipelines_; + mutable Variants + conical_gradient_uniform_fill_pipelines_; + mutable Variants + sweep_gradient_uniform_fill_pipelines_; mutable Variants linear_gradient_ssbo_fill_pipelines_; mutable Variants diff --git a/impeller/entity/contents/gradient_generator.cc b/impeller/entity/contents/gradient_generator.cc index 90f489dcfa45f..8aa1984c522c3 100644 --- a/impeller/entity/contents/gradient_generator.cc +++ b/impeller/entity/contents/gradient_generator.cc @@ -67,4 +67,31 @@ std::vector CreateGradientColors(const std::vector& colors, return result; } +int PopulateUniformGradientColors( + const std::vector& colors, + const std::vector& stops, + Vector4 frag_info_colors[kMaxUniformGradientStops], + Vector4 frag_info_stop_pairs[kMaxUniformGradientStops / 2]) { + FML_DCHECK(stops.size() == colors.size()); + + Scalar last_stop = 0; + int index = 0; + for (auto i = 0u; i < stops.size() && i < kMaxUniformGradientStops; i++) { + Scalar cur_stop = stops[i]; + Scalar delta = cur_stop - last_stop; + Scalar inverse_delta = delta == 0.0f ? 0.0 : 1.0 / delta; + frag_info_colors[index] = colors[i]; + if ((i & 1) == 0) { + frag_info_stop_pairs[index / 2].x = cur_stop; + frag_info_stop_pairs[index / 2].y = inverse_delta; + } else { + frag_info_stop_pairs[index / 2].z = cur_stop; + frag_info_stop_pairs[index / 2].w = inverse_delta; + } + last_stop = cur_stop; + index++; + } + return index; +} + } // namespace impeller diff --git a/impeller/entity/contents/gradient_generator.h b/impeller/entity/contents/gradient_generator.h index db48829126e8b..fa6dab716f94a 100644 --- a/impeller/entity/contents/gradient_generator.h +++ b/impeller/entity/contents/gradient_generator.h @@ -44,6 +44,28 @@ static_assert(sizeof(StopData) == 32); std::vector CreateGradientColors(const std::vector& colors, const std::vector& stops); +static constexpr uint32_t kMaxUniformGradientStops = 256u; + +/** + * @brief Populate 2 arrays with the colors and stop data for a gradient + * + * The color data is simply converted to a vec4 format, but the stop data + * is both turned into pairs of {t, inverse_delta} information and also + * stops are themselves paired up into a vec4 format for efficient packing + * in the uniform data. + * + * @param colors colors from gradient + * @param stops stops from gradient + * @param frag_info_colors colors for fragment shader in vec4 format + * @param frag_info_stop_pairs pairs of stop data for shader in vec4 format + * @return count of colors stored + */ +int PopulateUniformGradientColors( + const std::vector& colors, + const std::vector& stops, + Vector4 frag_info_colors[kMaxUniformGradientStops], + Vector4 frag_info_stop_pairs[kMaxUniformGradientStops / 2]); + } // namespace impeller #endif // FLUTTER_IMPELLER_ENTITY_CONTENTS_GRADIENT_GENERATOR_H_ diff --git a/impeller/entity/contents/linear_gradient_contents.cc b/impeller/entity/contents/linear_gradient_contents.cc index 73d533f2d7dbf..7eef8b78fbbbb 100644 --- a/impeller/entity/contents/linear_gradient_contents.cc +++ b/impeller/entity/contents/linear_gradient_contents.cc @@ -186,6 +186,14 @@ bool LinearGradientContents::FastLinearGradient(const ContentContext& renderer, /*force_stencil=*/force_stencil, geom_callback); } +#define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0])) +#define UNIFORM_FRAG_INFO(t) \ + t##GradientUniformFillPipeline::FragmentShader::FragInfo +#define UNIFORM_COLOR_SIZE ARRAY_LEN(UNIFORM_FRAG_INFO(Linear)::colors) +#define UNIFORM_STOP_SIZE ARRAY_LEN(UNIFORM_FRAG_INFO(Linear)::stop_pairs) +static_assert(UNIFORM_COLOR_SIZE == kMaxUniformGradientStops); +static_assert(UNIFORM_STOP_SIZE == kMaxUniformGradientStops / 2); + bool LinearGradientContents::Render(const ContentContext& renderer, const Entity& entity, RenderPass& pass) const { @@ -198,6 +206,10 @@ bool LinearGradientContents::Render(const ContentContext& renderer, if (renderer.GetDeviceCapabilities().SupportsSSBO()) { return RenderSSBO(renderer, entity, pass); } + if (colors_.size() <= kMaxUniformGradientStops && + stops_.size() <= kMaxUniformGradientStops) { + return RenderUniform(renderer, entity, pass); + } return RenderTexture(renderer, entity, pass); } @@ -310,6 +322,44 @@ bool LinearGradientContents::RenderSSBO(const ContentContext& renderer, }); } +bool LinearGradientContents::RenderUniform(const ContentContext& renderer, + const Entity& entity, + RenderPass& pass) const { + using VS = LinearGradientUniformFillPipeline::VertexShader; + using FS = LinearGradientUniformFillPipeline::FragmentShader; + + VS::FrameInfo frame_info; + frame_info.matrix = GetInverseEffectTransform(); + + PipelineBuilderCallback pipeline_callback = + [&renderer](ContentContextOptions options) { + return renderer.GetLinearGradientUniformFillPipeline(options); + }; + return ColorSourceContents::DrawGeometry( + renderer, entity, pass, pipeline_callback, frame_info, + [this, &renderer, &entity](RenderPass& pass) { + FS::FragInfo frag_info; + frag_info.start_point = start_point_; + frag_info.start_to_end = end_point_ - start_point_; + frag_info.alpha = + GetOpacityFactor() * + GetGeometry()->ComputeAlphaCoverage(entity.GetTransform()); + frag_info.tile_mode = static_cast(tile_mode_); + frag_info.colors_length = PopulateUniformGradientColors( + colors_, stops_, frag_info.colors, frag_info.stop_pairs); + frag_info.inverse_dot_start_to_end = + CalculateInverseDotStartToEnd(start_point_, end_point_); + frag_info.decal_border_color = decal_border_color_; + + pass.SetCommandLabel("LinearGradientUniformFill"); + + FS::BindFragInfo( + pass, renderer.GetTransientsBuffer().EmplaceUniform(frag_info)); + + return true; + }); +} + bool LinearGradientContents::ApplyColorFilter( const ColorFilterProc& color_filter_proc) { for (Color& color : colors_) { diff --git a/impeller/entity/contents/linear_gradient_contents.h b/impeller/entity/contents/linear_gradient_contents.h index ae2e12f2bfdaa..1aaccb1e43921 100644 --- a/impeller/entity/contents/linear_gradient_contents.h +++ b/impeller/entity/contents/linear_gradient_contents.h @@ -53,6 +53,10 @@ class LinearGradientContents final : public ColorSourceContents { const Entity& entity, RenderPass& pass) const; + bool RenderUniform(const ContentContext& renderer, + const Entity& entity, + RenderPass& pass) const; + bool FastLinearGradient(const ContentContext& renderer, const Entity& entity, RenderPass& pass) const; diff --git a/impeller/entity/contents/radial_gradient_contents.cc b/impeller/entity/contents/radial_gradient_contents.cc index 31fc52eee3cd3..8fad640b1b607 100644 --- a/impeller/entity/contents/radial_gradient_contents.cc +++ b/impeller/entity/contents/radial_gradient_contents.cc @@ -55,12 +55,24 @@ bool RadialGradientContents::IsOpaque(const Matrix& transform) const { return !AppliesAlphaForStrokeCoverage(transform); } +#define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0])) +#define UNIFORM_FRAG_INFO(t) \ + t##GradientUniformFillPipeline::FragmentShader::FragInfo +#define UNIFORM_COLOR_SIZE ARRAY_LEN(UNIFORM_FRAG_INFO(Radial)::colors) +#define UNIFORM_STOP_SIZE ARRAY_LEN(UNIFORM_FRAG_INFO(Radial)::stop_pairs) +static_assert(UNIFORM_COLOR_SIZE == kMaxUniformGradientStops); +static_assert(UNIFORM_STOP_SIZE == kMaxUniformGradientStops / 2); + bool RadialGradientContents::Render(const ContentContext& renderer, const Entity& entity, RenderPass& pass) const { if (renderer.GetDeviceCapabilities().SupportsSSBO()) { return RenderSSBO(renderer, entity, pass); } + if (colors_.size() <= kMaxUniformGradientStops && + stops_.size() <= kMaxUniformGradientStops) { + return RenderUniform(renderer, entity, pass); + } return RenderTexture(renderer, entity, pass); } @@ -106,6 +118,42 @@ bool RadialGradientContents::RenderSSBO(const ContentContext& renderer, }); } +bool RadialGradientContents::RenderUniform(const ContentContext& renderer, + const Entity& entity, + RenderPass& pass) const { + using VS = RadialGradientUniformFillPipeline::VertexShader; + using FS = RadialGradientUniformFillPipeline::FragmentShader; + + VS::FrameInfo frame_info; + frame_info.matrix = GetInverseEffectTransform(); + + PipelineBuilderCallback pipeline_callback = + [&renderer](ContentContextOptions options) { + return renderer.GetRadialGradientUniformFillPipeline(options); + }; + return ColorSourceContents::DrawGeometry( + renderer, entity, pass, pipeline_callback, frame_info, + [this, &renderer, &entity](RenderPass& pass) { + FS::FragInfo frag_info; + frag_info.center = center_; + frag_info.radius = radius_; + frag_info.tile_mode = static_cast(tile_mode_); + frag_info.alpha = + GetOpacityFactor() * + GetGeometry()->ComputeAlphaCoverage(entity.GetTransform()); + frag_info.colors_length = PopulateUniformGradientColors( + colors_, stops_, frag_info.colors, frag_info.stop_pairs); + frag_info.decal_border_color = decal_border_color_; + + pass.SetCommandLabel("RadialGradientUniformFill"); + + FS::BindFragInfo( + pass, renderer.GetTransientsBuffer().EmplaceUniform(frag_info)); + + return true; + }); +} + bool RadialGradientContents::RenderTexture(const ContentContext& renderer, const Entity& entity, RenderPass& pass) const { diff --git a/impeller/entity/contents/radial_gradient_contents.h b/impeller/entity/contents/radial_gradient_contents.h index 21872d801fe07..f1cff5813c3f8 100644 --- a/impeller/entity/contents/radial_gradient_contents.h +++ b/impeller/entity/contents/radial_gradient_contents.h @@ -52,6 +52,11 @@ class RadialGradientContents final : public ColorSourceContents { bool RenderSSBO(const ContentContext& renderer, const Entity& entity, RenderPass& pass) const; + + bool RenderUniform(const ContentContext& renderer, + const Entity& entity, + RenderPass& pass) const; + Point center_; Scalar radius_; std::vector colors_; diff --git a/impeller/entity/contents/sweep_gradient_contents.cc b/impeller/entity/contents/sweep_gradient_contents.cc index a26d5ac43335a..1dfa1292203a7 100644 --- a/impeller/entity/contents/sweep_gradient_contents.cc +++ b/impeller/entity/contents/sweep_gradient_contents.cc @@ -61,12 +61,24 @@ bool SweepGradientContents::IsOpaque(const Matrix& transform) const { return !AppliesAlphaForStrokeCoverage(transform); } +#define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0])) +#define UNIFORM_FRAG_INFO(t) \ + t##GradientUniformFillPipeline::FragmentShader::FragInfo +#define UNIFORM_COLOR_SIZE ARRAY_LEN(UNIFORM_FRAG_INFO(Sweep)::colors) +#define UNIFORM_STOP_SIZE ARRAY_LEN(UNIFORM_FRAG_INFO(Sweep)::stop_pairs) +static_assert(UNIFORM_COLOR_SIZE == kMaxUniformGradientStops); +static_assert(UNIFORM_STOP_SIZE == kMaxUniformGradientStops / 2); + bool SweepGradientContents::Render(const ContentContext& renderer, const Entity& entity, RenderPass& pass) const { if (renderer.GetDeviceCapabilities().SupportsSSBO()) { return RenderSSBO(renderer, entity, pass); } + if (colors_.size() <= kMaxUniformGradientStops && + stops_.size() <= kMaxUniformGradientStops) { + return RenderUniform(renderer, entity, pass); + } return RenderTexture(renderer, entity, pass); } @@ -116,6 +128,46 @@ bool SweepGradientContents::RenderSSBO(const ContentContext& renderer, }); } +bool SweepGradientContents::RenderUniform(const ContentContext& renderer, + const Entity& entity, + RenderPass& pass) const { + using VS = SweepGradientUniformFillPipeline::VertexShader; + using FS = SweepGradientUniformFillPipeline::FragmentShader; + + VS::FrameInfo frame_info; + frame_info.matrix = GetInverseEffectTransform(); + VS::BindFrameInfo(pass, + renderer.GetTransientsBuffer().EmplaceUniform(frame_info)); + + PipelineBuilderCallback pipeline_callback = + [&renderer](ContentContextOptions options) { + return renderer.GetSweepGradientUniformFillPipeline(options); + }; + return ColorSourceContents::DrawGeometry( + renderer, entity, pass, pipeline_callback, frame_info, + [this, &renderer, &entity](RenderPass& pass) { + FS::FragInfo frag_info; + frag_info.center = center_; + frag_info.bias = bias_; + frag_info.scale = scale_; + frag_info.tile_mode = static_cast(tile_mode_); + frag_info.alpha = + GetOpacityFactor() * + GetGeometry()->ComputeAlphaCoverage(entity.GetTransform()); + frag_info.colors_length = PopulateUniformGradientColors( + colors_, stops_, frag_info.colors, frag_info.stop_pairs); + + frag_info.decal_border_color = decal_border_color_; + + pass.SetCommandLabel("SweepGradientUniformFill"); + + FS::BindFragInfo( + pass, renderer.GetTransientsBuffer().EmplaceUniform(frag_info)); + + return true; + }); +} + bool SweepGradientContents::RenderTexture(const ContentContext& renderer, const Entity& entity, RenderPass& pass) const { diff --git a/impeller/entity/contents/sweep_gradient_contents.h b/impeller/entity/contents/sweep_gradient_contents.h index 81e643d660516..d145987e19f13 100644 --- a/impeller/entity/contents/sweep_gradient_contents.h +++ b/impeller/entity/contents/sweep_gradient_contents.h @@ -54,6 +54,10 @@ class SweepGradientContents final : public ColorSourceContents { const Entity& entity, RenderPass& pass) const; + bool RenderUniform(const ContentContext& renderer, + const Entity& entity, + RenderPass& pass) const; + Point center_; Scalar bias_; Scalar scale_; diff --git a/impeller/entity/shaders/gradients/conical_gradient_uniform_fill.frag b/impeller/entity/shaders/gradients/conical_gradient_uniform_fill.frag new file mode 100644 index 0000000000000..b99f753e98d48 --- /dev/null +++ b/impeller/entity/shaders/gradients/conical_gradient_uniform_fill.frag @@ -0,0 +1,68 @@ +// 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 +#include +#include +#include + +uniform FragInfo { + highp vec2 center; + vec2 focus; + float focus_radius; + float radius; + float tile_mode; + float alpha; + float colors_length; + vec4 decal_border_color; + vec4 colors[256]; + vec4 stop_pairs[128]; +} +frag_info; + +highp in vec2 v_position; + +out vec4 frag_color; + +void main() { + vec2 res = IPComputeConicalT(frag_info.focus, frag_info.focus_radius, + frag_info.center, frag_info.radius, v_position); + + float t = res.x; + vec4 result_color = vec4(0); + if (res.y < 0.0 || + ((t < 0.0 || t > 1.0) && frag_info.tile_mode == kTileModeDecal)) { + result_color = frag_info.decal_border_color; + } else { + t = IPFloatTile(t, frag_info.tile_mode); + + vec2 prev_stop = frag_info.stop_pairs[0].xy; + bool even = false; + for (int i = 1; i < frag_info.colors_length; i++) { + // stop_pairs[i/2].xy = values for stop i + // stop_pairs[i/2].zw = values for stop i+1 + vec2 cur_stop = even ? frag_info.stop_pairs[i / 2].xy + : frag_info.stop_pairs[i / 2].zw; + even = !even; + // stop.x == t value + // stop.y == inverse_delta to next stop + if (t >= prev_stop.x && t <= cur_stop.x) { + if (cur_stop.y > 1000.0) { + result_color = frag_info.colors[i]; + } else { + float ratio = (t - prev_stop.x) * cur_stop.y; + result_color = + mix(frag_info.colors[i - 1], frag_info.colors[i], ratio); + } + break; + } + prev_stop = cur_stop; + } + } + + frag_color = IPPremultiply(result_color) * frag_info.alpha; +} diff --git a/impeller/entity/shaders/gradients/linear_gradient_uniform_fill.frag b/impeller/entity/shaders/gradients/linear_gradient_uniform_fill.frag new file mode 100644 index 0000000000000..ace605876d9be --- /dev/null +++ b/impeller/entity/shaders/gradients/linear_gradient_uniform_fill.frag @@ -0,0 +1,64 @@ +// 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 +#include +#include +#include + +uniform FragInfo { + highp vec2 start_point; + highp vec2 start_to_end; + float alpha; + float tile_mode; + float colors_length; + float inverse_dot_start_to_end; + vec4 decal_border_color; + vec4 colors[256]; + vec4 stop_pairs[128]; +} +frag_info; + +highp in vec2 v_position; + +out vec4 frag_color; + +void main() { + highp vec2 start_to_position = v_position - frag_info.start_point; + highp float t = dot(start_to_position, frag_info.start_to_end) * + frag_info.inverse_dot_start_to_end; + + if ((t < 0.0 || t > 1.0) && frag_info.tile_mode == kTileModeDecal) { + frag_color = frag_info.decal_border_color; + } else { + t = IPFloatTile(t, frag_info.tile_mode); + + vec2 prev_stop = frag_info.stop_pairs[0].xy; + bool even = false; + for (int i = 1; i < frag_info.colors_length; i++) { + // stop_pairs[i/2].xy = values for stop i + // stop_pairs[i/2].zw = values for stop i+1 + vec2 cur_stop = even ? frag_info.stop_pairs[i / 2].xy + : frag_info.stop_pairs[i / 2].zw; + even = !even; + // stop.x == t value + // stop.y == inverse_delta to next stop + if (t >= prev_stop.x && t <= cur_stop.x) { + if (cur_stop.y > 1000.0) { + frag_color = frag_info.colors[i]; + } else { + float ratio = (t - prev_stop.x) * cur_stop.y; + frag_color = mix(frag_info.colors[i - 1], frag_info.colors[i], ratio); + } + break; + } + prev_stop = cur_stop; + } + } + + frag_color = IPPremultiply(frag_color) * frag_info.alpha; +} diff --git a/impeller/entity/shaders/gradients/radial_gradient_uniform_fill.frag b/impeller/entity/shaders/gradients/radial_gradient_uniform_fill.frag new file mode 100644 index 0000000000000..f20163e68652d --- /dev/null +++ b/impeller/entity/shaders/gradients/radial_gradient_uniform_fill.frag @@ -0,0 +1,64 @@ +// 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 +#include +#include +#include + +uniform FragInfo { + highp vec2 center; + float radius; + float tile_mode; + float alpha; + float colors_length; + vec4 decal_border_color; + vec4 colors[256]; + vec4 stop_pairs[128]; +} +frag_info; + +highp in vec2 v_position; + +out vec4 frag_color; + +void main() { + float len = length(v_position - frag_info.center); + float t = len / frag_info.radius; + + vec4 result_color = vec4(0); + if ((t < 0.0 || t > 1.0) && frag_info.tile_mode == kTileModeDecal) { + result_color = frag_info.decal_border_color; + } else { + t = IPFloatTile(t, frag_info.tile_mode); + + vec2 prev_stop = frag_info.stop_pairs[0].xy; + bool even = false; + for (int i = 1; i < frag_info.colors_length; i++) { + // stop_pairs[i/2].xy = values for stop i + // stop_pairs[i/2].zw = values for stop i+1 + vec2 cur_stop = even ? frag_info.stop_pairs[i / 2].xy + : frag_info.stop_pairs[i / 2].zw; + even = !even; + // stop.x == t value + // stop.y == inverse_delta to next stop + if (t >= prev_stop.x && t <= cur_stop.x) { + if (cur_stop.y > 1000.0) { + result_color = frag_info.colors[i]; + } else { + float ratio = (t - prev_stop.x) * cur_stop.y; + result_color = + mix(frag_info.colors[i - 1], frag_info.colors[i], ratio); + } + break; + } + prev_stop = cur_stop; + } + } + + frag_color = IPPremultiply(result_color) * frag_info.alpha; +} diff --git a/impeller/entity/shaders/gradients/sweep_gradient_uniform_fill.frag b/impeller/entity/shaders/gradients/sweep_gradient_uniform_fill.frag new file mode 100644 index 0000000000000..d25b62c5ba857 --- /dev/null +++ b/impeller/entity/shaders/gradients/sweep_gradient_uniform_fill.frag @@ -0,0 +1,65 @@ +// 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. + +#include +#include +#include +#include +#include +#include + +uniform FragInfo { + highp vec2 center; + float bias; + float scale; + float tile_mode; + float alpha; + float colors_length; + vec4 decal_border_color; + vec4 colors[256]; + vec4 stop_pairs[128]; +} +frag_info; + +highp in vec2 v_position; + +out vec4 frag_color; + +void main() { + vec2 coord = v_position - frag_info.center; + float angle = atan(-coord.y, -coord.x); + float t = (angle * k1Over2Pi + 0.5 + frag_info.bias) * frag_info.scale; + + vec4 result_color = vec4(0); + if ((t < 0.0 || t > 1.0) && frag_info.tile_mode == kTileModeDecal) { + result_color = frag_info.decal_border_color; + } else { + t = IPFloatTile(t, frag_info.tile_mode); + + vec2 prev_stop = frag_info.stop_pairs[0].xy; + bool even = false; + for (int i = 1; i < frag_info.colors_length; i++) { + // stop_pairs[i/2].xy = values for stop i + // stop_pairs[i/2].zw = values for stop i+1 + vec2 cur_stop = even ? frag_info.stop_pairs[i / 2].xy + : frag_info.stop_pairs[i / 2].zw; + even = !even; + // stop.x == t value + // stop.y == inverse_delta to next stop + if (t >= prev_stop.x && t <= cur_stop.x) { + if (cur_stop.y > 1000.0) { + result_color = frag_info.colors[i]; + } else { + float ratio = (t - prev_stop.x) * cur_stop.y; + result_color = + mix(frag_info.colors[i - 1], frag_info.colors[i], ratio); + } + break; + } + prev_stop = cur_stop; + } + } + + frag_color = IPPremultiply(result_color) * frag_info.alpha; +} diff --git a/impeller/tools/malioc.json b/impeller/tools/malioc.json index 21d6567c74d83..96e0defe7adcd 100644 --- a/impeller/tools/malioc.json +++ b/impeller/tools/malioc.json @@ -613,6 +613,76 @@ } } }, + "flutter/impeller/entity/conical_gradient_uniform_fill.frag.vkspv": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/conical_gradient_uniform_fill.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": 70, + "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": [ + "varying" + ], + "shortest_path_cycles": [ + 0.1875, + 0.0625, + 0.1875, + 0.0, + 0.0, + 0.25, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 1.5499999523162842, + 0.800000011920929, + 1.5499999523162842, + 0.5, + 4.0, + 0.25, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 36, + "work_registers_used": 18 + } + } + } + }, "flutter/impeller/entity/fast_gradient.frag.vkspv": { "Mali-G78": { "core": "Mali-G78", @@ -1951,6 +2021,121 @@ } } }, + "flutter/impeller/entity/gles/conical_gradient_uniform_fill.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/conical_gradient_uniform_fill.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": 62, + "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": [ + "varying" + ], + "shortest_path_cycles": [ + 0.1875, + 0.0625, + 0.1875, + 0.0, + 0.0, + 0.25, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 1.40625, + 0.84375, + 1.40625, + 0.4375, + 4.0, + 0.25, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 38, + "work_registers_used": 21 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/conical_gradient_uniform_fill.frag.gles", + "has_uniform_computation": true, + "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" + ], + "shortest_path_cycles": [ + 1.649999976158142, + 1.0, + 0.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 20.66666603088379, + 4.0, + 0.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 6, + "work_registers_used": 3 + } + } + } + }, "flutter/impeller/entity/gles/fast_gradient.frag.gles": { "Mali-G78": { "core": "Mali-G78", @@ -3210,6 +3395,121 @@ } } }, + "flutter/impeller/entity/gles/linear_gradient_uniform_fill.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/linear_gradient_uniform_fill.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": 13, + "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": [ + "varying" + ], + "shortest_path_cycles": [ + 0.203125, + 0.203125, + 0.171875, + 0.0625, + 0.0, + 0.25, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.8125, + 0.46875, + 0.8125, + 0.1875, + 4.0, + 0.25, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 12, + "work_registers_used": 21 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/linear_gradient_uniform_fill.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" + ], + "shortest_path_cycles": [ + 2.640000104904175, + 1.0, + 0.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 10.0, + 4.0, + 0.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 3, + "work_registers_used": 3 + } + } + } + }, "flutter/impeller/entity/gles/linear_to_srgb_filter.frag.gles": { "Mali-G78": { "core": "Mali-G78", @@ -3837,6 +4137,121 @@ } } }, + "flutter/impeller/entity/gles/radial_gradient_uniform_fill.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/radial_gradient_uniform_fill.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": 67, + "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": [ + "varying" + ], + "shortest_path_cycles": [ + 0.1875, + 0.171875, + 0.1875, + 0.0625, + 0.0, + 0.25, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.762499988079071, + 0.359375, + 0.762499988079071, + 0.1875, + 4.0, + 0.25, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 10, + "work_registers_used": 21 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/radial_gradient_uniform_fill.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" + ], + "shortest_path_cycles": [ + 2.640000104904175, + 1.0, + 0.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 9.666666984558105, + 4.0, + 0.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 2, + "work_registers_used": 3 + } + } + } + }, "flutter/impeller/entity/gles/rrect_blur.frag.gles": { "Mali-G78": { "core": "Mali-G78", @@ -4652,54 +5067,170 @@ ], "shortest_path_bound_pipelines": [ "arith_total", - "arith_sfu" + "arith_sfu" + ], + "shortest_path_cycles": [ + 0.375, + 0.359375, + 0.25, + 0.375, + 0.0, + 0.25, + 0.0 + ], + "total_bound_pipelines": [ + "arith_total", + "arith_cvt" + ], + "total_cycles": [ + 0.5625, + 0.5, + 0.5625, + 0.375, + 0.0, + 0.25, + 0.25 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 20, + "work_registers_used": 24 + } + } + }, + "Mali-T880": { + "core": "Mali-T880", + "filename": "flutter/impeller/entity/gles/sweep_gradient_fill.frag.gles", + "has_uniform_computation": true, + "type": "Fragment", + "variants": { + "Main": { + "has_stack_spilling": false, + "performance": { + "longest_path_bound_pipelines": [ + "arithmetic" + ], + "longest_path_cycles": [ + 7.920000076293945, + 1.0, + 1.0 + ], + "pipelines": [ + "arithmetic", + "load_store", + "texture" + ], + "shortest_path_bound_pipelines": [ + "arithmetic" + ], + "shortest_path_cycles": [ + 2.9700000286102295, + 1.0, + 0.0 + ], + "total_bound_pipelines": [ + "arithmetic" + ], + "total_cycles": [ + 8.666666984558105, + 1.0, + 1.0 + ] + }, + "thread_occupancy": 100, + "uniform_registers_used": 4, + "work_registers_used": 2 + } + } + } + }, + "flutter/impeller/entity/gles/sweep_gradient_uniform_fill.frag.gles": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/gles/sweep_gradient_uniform_fill.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": 0, + "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_fma" ], "shortest_path_cycles": [ 0.375, - 0.359375, - 0.25, 0.375, + 0.25, + 0.3125, 0.0, 0.25, 0.0 ], "total_bound_pipelines": [ - "arith_total", - "arith_cvt" + "load_store" ], "total_cycles": [ - 0.5625, - 0.5, - 0.5625, - 0.375, - 0.0, + 0.925000011920929, + 0.625, + 0.925000011920929, + 0.4375, + 4.0, 0.25, - 0.25 + 0.0 ] }, "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 20, - "work_registers_used": 24 + "work_registers_used": 25 } } }, "Mali-T880": { "core": "Mali-T880", - "filename": "flutter/impeller/entity/gles/sweep_gradient_fill.frag.gles", - "has_uniform_computation": true, + "filename": "flutter/impeller/entity/gles/sweep_gradient_uniform_fill.frag.gles", + "has_uniform_computation": false, "type": "Fragment", "variants": { "Main": { "has_stack_spilling": false, "performance": { "longest_path_bound_pipelines": [ - "arithmetic" + null ], "longest_path_cycles": [ - 7.920000076293945, - 1.0, - 1.0 + null, + null, + null ], "pipelines": [ "arithmetic", @@ -4718,14 +5249,14 @@ "arithmetic" ], "total_cycles": [ - 8.666666984558105, - 1.0, - 1.0 + 10.333333015441895, + 5.0, + 0.0 ] }, "thread_occupancy": 100, - "uniform_registers_used": 4, - "work_registers_used": 2 + "uniform_registers_used": 3, + "work_registers_used": 3 } } } @@ -6443,6 +6974,76 @@ } } }, + "flutter/impeller/entity/linear_gradient_uniform_fill.frag.vkspv": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/linear_gradient_uniform_fill.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": 35, + "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": [ + "varying" + ], + "shortest_path_cycles": [ + 0.15625, + 0.15625, + 0.15625, + 0.0625, + 0.0, + 0.25, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.84375, + 0.359375, + 0.84375, + 0.25, + 4.0, + 0.25, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 14, + "work_registers_used": 18 + } + } + } + }, "flutter/impeller/entity/linear_to_srgb_filter.frag.vkspv": { "Mali-G78": { "core": "Mali-G78", @@ -6913,6 +7514,76 @@ } } }, + "flutter/impeller/entity/radial_gradient_uniform_fill.frag.vkspv": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/radial_gradient_uniform_fill.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": 58, + "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": [ + "varying" + ], + "shortest_path_cycles": [ + 0.171875, + 0.171875, + 0.171875, + 0.0625, + 0.0, + 0.25, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.84375, + 0.359375, + 0.84375, + 0.25, + 4.0, + 0.25, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 12, + "work_registers_used": 18 + } + } + } + }, "flutter/impeller/entity/rrect_blur.frag.vkspv": { "Mali-G78": { "core": "Mali-G78", @@ -7561,6 +8232,77 @@ } } }, + "flutter/impeller/entity/sweep_gradient_uniform_fill.frag.vkspv": { + "Mali-G78": { + "core": "Mali-G78", + "filename": "flutter/impeller/entity/sweep_gradient_uniform_fill.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": 0, + "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_fma" + ], + "shortest_path_cycles": [ + 0.390625, + 0.390625, + 0.25, + 0.3125, + 0.0, + 0.25, + 0.0 + ], + "total_bound_pipelines": [ + "load_store" + ], + "total_cycles": [ + 0.875, + 0.637499988079071, + 0.875, + 0.5, + 4.0, + 0.25, + 0.0 + ] + }, + "stack_spill_bytes": 0, + "thread_occupancy": 100, + "uniform_registers_used": 20, + "work_registers_used": 23 + } + } + } + }, "flutter/impeller/entity/texture_downsample.frag.vkspv": { "Mali-G78": { "core": "Mali-G78", diff --git a/testing/impeller_golden_tests_output.txt b/testing/impeller_golden_tests_output.txt index 58897eb92243b..fddecde08074b 100644 --- a/testing/impeller_golden_tests_output.txt +++ b/testing/impeller_golden_tests_output.txt @@ -289,6 +289,9 @@ impeller_Play_AiksTest_CanRenderColoredRect_Vulkan.png impeller_Play_AiksTest_CanRenderConicalGradientWithDitheringEnabled_Metal.png impeller_Play_AiksTest_CanRenderConicalGradientWithDitheringEnabled_OpenGLES.png impeller_Play_AiksTest_CanRenderConicalGradientWithDitheringEnabled_Vulkan.png +impeller_Play_AiksTest_CanRenderConicalGradientWithIncompleteStops_Metal.png +impeller_Play_AiksTest_CanRenderConicalGradientWithIncompleteStops_OpenGLES.png +impeller_Play_AiksTest_CanRenderConicalGradientWithIncompleteStops_Vulkan.png impeller_Play_AiksTest_CanRenderConicalGradient_Metal.png impeller_Play_AiksTest_CanRenderConicalGradient_OpenGLES.png impeller_Play_AiksTest_CanRenderConicalGradient_Vulkan.png @@ -382,6 +385,9 @@ impeller_Play_AiksTest_CanRenderLinearGradientWayManyColorsClamp_Vulkan.png impeller_Play_AiksTest_CanRenderLinearGradientWithDitheringEnabled_Metal.png impeller_Play_AiksTest_CanRenderLinearGradientWithDitheringEnabled_OpenGLES.png impeller_Play_AiksTest_CanRenderLinearGradientWithDitheringEnabled_Vulkan.png +impeller_Play_AiksTest_CanRenderLinearGradientWithIncompleteStops_Metal.png +impeller_Play_AiksTest_CanRenderLinearGradientWithIncompleteStops_OpenGLES.png +impeller_Play_AiksTest_CanRenderLinearGradientWithIncompleteStops_Vulkan.png impeller_Play_AiksTest_CanRenderLinearGradientWithOverlappingStopsClamp_Metal.png impeller_Play_AiksTest_CanRenderLinearGradientWithOverlappingStopsClamp_OpenGLES.png impeller_Play_AiksTest_CanRenderLinearGradientWithOverlappingStopsClamp_Vulkan.png @@ -412,6 +418,9 @@ impeller_Play_AiksTest_CanRenderRadialGradientManyColors_Vulkan.png impeller_Play_AiksTest_CanRenderRadialGradientWithDitheringEnabled_Metal.png impeller_Play_AiksTest_CanRenderRadialGradientWithDitheringEnabled_OpenGLES.png impeller_Play_AiksTest_CanRenderRadialGradientWithDitheringEnabled_Vulkan.png +impeller_Play_AiksTest_CanRenderRadialGradientWithIncompleteStops_Metal.png +impeller_Play_AiksTest_CanRenderRadialGradientWithIncompleteStops_OpenGLES.png +impeller_Play_AiksTest_CanRenderRadialGradientWithIncompleteStops_Vulkan.png impeller_Play_AiksTest_CanRenderRadialGradient_Metal.png impeller_Play_AiksTest_CanRenderRadialGradient_OpenGLES.png impeller_Play_AiksTest_CanRenderRadialGradient_Vulkan.png @@ -463,6 +472,9 @@ impeller_Play_AiksTest_CanRenderSweepGradientRepeat_Vulkan.png impeller_Play_AiksTest_CanRenderSweepGradientWithDitheringEnabled_Metal.png impeller_Play_AiksTest_CanRenderSweepGradientWithDitheringEnabled_OpenGLES.png impeller_Play_AiksTest_CanRenderSweepGradientWithDitheringEnabled_Vulkan.png +impeller_Play_AiksTest_CanRenderSweepGradientWithIncompleteStops_Metal.png +impeller_Play_AiksTest_CanRenderSweepGradientWithIncompleteStops_OpenGLES.png +impeller_Play_AiksTest_CanRenderSweepGradientWithIncompleteStops_Vulkan.png impeller_Play_AiksTest_CanRenderTextFrameWithFractionScaling_Metal.png impeller_Play_AiksTest_CanRenderTextFrameWithFractionScaling_OpenGLES.png impeller_Play_AiksTest_CanRenderTextFrameWithFractionScaling_Vulkan.png