diff --git a/engine/src/flutter/impeller/entity/contents/gradient_generator.cc b/engine/src/flutter/impeller/entity/contents/gradient_generator.cc index 2d6431ee8b8..90f489dcfa4 100644 --- a/engine/src/flutter/impeller/entity/contents/gradient_generator.cc +++ b/engine/src/flutter/impeller/entity/contents/gradient_generator.cc @@ -54,9 +54,15 @@ std::vector CreateGradientColors(const std::vector& colors, const std::vector& stops) { FML_DCHECK(stops.size() == colors.size()); - std::vector result(stops.size()); + std::vector result; + result.reserve(stops.size()); + Scalar last_stop = 0; for (auto i = 0u; i < stops.size(); i++) { - result[i] = {.color = colors[i], .stop = stops[i]}; + Scalar delta = stops[i] - last_stop; + Scalar inverse_delta = delta == 0.0f ? 0.0 : 1.0 / delta; + result.emplace_back(StopData{ + .color = colors[i], .stop = stops[i], .inverse_delta = inverse_delta}); + last_stop = stops[i]; } return result; } diff --git a/engine/src/flutter/impeller/entity/contents/gradient_generator.h b/engine/src/flutter/impeller/entity/contents/gradient_generator.h index f6d6213d8cf..db48829126e 100644 --- a/engine/src/flutter/impeller/entity/contents/gradient_generator.h +++ b/engine/src/flutter/impeller/entity/contents/gradient_generator.h @@ -28,9 +28,12 @@ std::shared_ptr CreateGradientTexture( struct StopData { Color color; Scalar stop; - Padding<12> _padding_; + Scalar inverse_delta; + Padding<8> _padding_; }; +static_assert(sizeof(StopData) == 32); + /** * @brief Populate a vector with the color and stop data for a gradient * diff --git a/engine/src/flutter/impeller/entity/contents/linear_gradient_contents.cc b/engine/src/flutter/impeller/entity/contents/linear_gradient_contents.cc index 99f2c79055f..891f6439981 100644 --- a/engine/src/flutter/impeller/entity/contents/linear_gradient_contents.cc +++ b/engine/src/flutter/impeller/entity/contents/linear_gradient_contents.cc @@ -113,6 +113,15 @@ bool LinearGradientContents::RenderTexture(const ContentContext& renderer, }); } +namespace { +Scalar CalculateInverseDotStartToEnd(Point start_point, Point end_point) { + Point start_to_end = end_point - start_point; + Scalar dot = + (start_to_end.x * start_to_end.x + start_to_end.y * start_to_end.y); + return dot == 0.0f ? 0.0f : 1.0f / dot; +} +} // namespace + bool LinearGradientContents::RenderSSBO(const ContentContext& renderer, const Entity& entity, RenderPass& pass) const { @@ -135,6 +144,9 @@ bool LinearGradientContents::RenderSSBO(const ContentContext& renderer, frag_info.tile_mode = static_cast(tile_mode_); frag_info.decal_border_color = decal_border_color_; frag_info.alpha = GetOpacityFactor(); + frag_info.start_to_end = end_point_ - start_point_; + frag_info.inverse_dot_start_to_end = + CalculateInverseDotStartToEnd(start_point_, end_point_); auto& host_buffer = renderer.GetTransientsBuffer(); auto colors = CreateGradientColors(colors_, stops_); diff --git a/engine/src/flutter/impeller/entity/shaders/gradients/linear_gradient_ssbo_fill.frag b/engine/src/flutter/impeller/entity/shaders/gradients/linear_gradient_ssbo_fill.frag index e64c33b4d12..00d5d5529fa 100644 --- a/engine/src/flutter/impeller/entity/shaders/gradients/linear_gradient_ssbo_fill.frag +++ b/engine/src/flutter/impeller/entity/shaders/gradients/linear_gradient_ssbo_fill.frag @@ -12,6 +12,7 @@ precision mediump float; struct ColorPoint { vec4 color; float stop; + float inverse_delta; }; layout(std140) readonly buffer ColorData { @@ -26,6 +27,8 @@ uniform FragInfo { float tile_mode; vec4 decal_border_color; int colors_length; + highp vec2 start_to_end; + float inverse_dot_start_to_end; } frag_info; @@ -34,10 +37,9 @@ highp in vec2 v_position; out vec4 frag_color; void main() { - highp vec2 start_to_end = frag_info.end_point - frag_info.start_point; highp vec2 start_to_position = v_position - frag_info.start_point; - highp float t = - dot(start_to_position, start_to_end) / dot(start_to_end, start_to_end); + 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; @@ -48,11 +50,10 @@ void main() { ColorPoint prev_point = color_data.colors[i - 1]; ColorPoint current_point = color_data.colors[i]; if (t >= prev_point.stop && t <= current_point.stop) { - float delta = (current_point.stop - prev_point.stop); - if (delta < 0.001) { + if (current_point.inverse_delta > 1000.0) { frag_color = current_point.color; } else { - float ratio = (t - prev_point.stop) / delta; + float ratio = (t - prev_point.stop) * current_point.inverse_delta; frag_color = mix(prev_point.color, current_point.color, ratio); } break; diff --git a/engine/src/flutter/impeller/tools/malioc.json b/engine/src/flutter/impeller/tools/malioc.json index 35b83ea0ee6..47994f75c0f 100644 --- a/engine/src/flutter/impeller/tools/malioc.json +++ b/engine/src/flutter/impeller/tools/malioc.json @@ -5737,7 +5737,7 @@ "uses_late_zs_update": false, "variants": { "Main": { - "fp16_arithmetic": 35, + "fp16_arithmetic": 37, "has_stack_spilling": false, "performance": { "longest_path_bound_pipelines": [ @@ -5778,10 +5778,10 @@ "load_store" ], "total_cycles": [ - 0.75, - 0.421875, - 0.75, - 0.625, + 0.71875, + 0.40625, + 0.71875, + 0.5625, 4.0, 0.25, 0.0 @@ -5790,7 +5790,7 @@ "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 24, - "work_registers_used": 17 + "work_registers_used": 21 } } }