mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[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:
parent
0d2067cbb6
commit
e6b3c034ea
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
*
|
||||
|
||||
@ -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_);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user