[Impeller] sped up the linear gradient by moving calculations to the cpu (flutter/engine#53007)

issue: https://github.com/flutter/flutter/issues/148496

The linked issue showed us as ALU bound with the linear gradient, this should relieve some of that pressure.

Tests:  There is already existing golden tests for this, this just changed the performance, no new functionality.

## summary of math improvements:
- (num_colors - 1) * division -> multiplication
- (num_colors - 1) * subtractions removed
- removes 1 `dot()`
- 1 division -> multiplication
- 1 subtraction removed

[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
This commit is contained in:
gaaclarke 2024-05-24 10:40:53 -07:00 committed by GitHub
parent 0d2067cbb6
commit e6b3c034ea
5 changed files with 37 additions and 15 deletions

View File

@ -54,9 +54,15 @@ std::vector<StopData> CreateGradientColors(const std::vector<Color>& colors,
const std::vector<Scalar>& stops) {
FML_DCHECK(stops.size() == colors.size());
std::vector<StopData> result(stops.size());
std::vector<StopData> 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;
}

View File

@ -28,9 +28,12 @@ std::shared_ptr<Texture> 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
*

View File

@ -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<Scalar>(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_);

View File

@ -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;

View File

@ -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
}
}
}