Skip to content

Commit b5df290

Browse files
author
Jonah Williams
authored
[Impeller] porter duff workarounds for Adreno GPU. (#161273)
Part of flutter/flutter#161209 Many Adreno 6XX are having trouble compiling the PorterDuff and ConicalGradient Pipeline. This rewrites the former to use specialization constants to reduce runtime branches. From testing on an S9+, this is sufficient to get it to compile correctly. As a bonus, this should be faster... though it adds more shaders.
1 parent 5f2bf18 commit b5df290

File tree

7 files changed

+215
-53
lines changed

7 files changed

+215
-53
lines changed

engine/src/flutter/impeller/entity/contents/atlas_contents.cc

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,10 @@ bool AtlasContents::Render(const ContentContext& renderer,
9797
pass.SetCommandLabel("DrawAtlas Blend");
9898
#endif // IMPELLER_DEBUG
9999
pass.SetVertexBuffer(geometry_->CreateBlendVertexBuffer(host_buffer));
100-
pass.SetPipeline(
101-
renderer.GetPorterDuffBlendPipeline(OptionsFromPass(pass)));
100+
auto inverted_blend_mode =
101+
InvertPorterDuffBlend(blend_mode).value_or(BlendMode::kSource);
102+
pass.SetPipeline(renderer.GetPorterDuffPipeline(inverted_blend_mode,
103+
OptionsFromPass(pass)));
102104

103105
FS::FragInfo frag_info;
104106
VS::FrameInfo frame_info;
@@ -110,15 +112,6 @@ bool AtlasContents::Render(const ContentContext& renderer,
110112
frag_info.output_alpha = alpha_;
111113
frag_info.input_alpha = 1.0;
112114

113-
auto inverted_blend_mode =
114-
InvertPorterDuffBlend(blend_mode).value_or(BlendMode::kSource);
115-
auto blend_coefficients =
116-
kPorterDuffCoefficients[static_cast<int>(inverted_blend_mode)];
117-
frag_info.src_coeff = blend_coefficients[0];
118-
frag_info.src_coeff_dst_alpha = blend_coefficients[1];
119-
frag_info.dst_coeff = blend_coefficients[2];
120-
frag_info.dst_coeff_src_alpha = blend_coefficients[3];
121-
frag_info.dst_coeff_src_color = blend_coefficients[4];
122115
// These values are ignored on platforms that natively support decal.
123116
frag_info.tmx = static_cast<int>(Entity::TileMode::kDecal);
124117
frag_info.tmy = static_cast<int>(Entity::TileMode::kDecal);

engine/src/flutter/impeller/entity/contents/content_context.cc

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,28 @@ void ContentContextOptions::ApplyToPipelineDescriptor(
220220
desc.SetPolygonMode(wireframe ? PolygonMode::kLine : PolygonMode::kFill);
221221
}
222222

223+
std::array<std::vector<Scalar>, 15> GetPorterDuffSpecConstants(
224+
bool supports_decal) {
225+
Scalar x = supports_decal ? 1 : 0;
226+
return {{
227+
{x, 0, 0, 0, 0, 0}, // Clear
228+
{x, 1, 0, 0, 0, 0}, // Source
229+
{x, 0, 0, 1, 0, 0}, // Destination
230+
{x, 1, 0, 1, -1, 0}, // SourceOver
231+
{x, 1, -1, 1, 0, 0}, // DestinationOver
232+
{x, 0, 1, 0, 0, 0}, // SourceIn
233+
{x, 0, 0, 0, 1, 0}, // DestinationIn
234+
{x, 1, -1, 0, 0, 0}, // SourceOut
235+
{x, 0, 0, 1, -1, 0}, // DestinationOut
236+
{x, 0, 1, 1, -1, 0}, // SourceATop
237+
{x, 1, -1, 0, 1, 0}, // DestinationATop
238+
{x, 1, -1, 1, -1, 0}, // Xor
239+
{x, 1, 0, 1, 0, 0}, // Plus
240+
{x, 0, 0, 0, 0, 1}, // Modulate
241+
{x, 0, 0, 1, 0, -1}, // Screen
242+
}};
243+
}
244+
223245
template <typename PipelineT>
224246
static std::unique_ptr<PipelineT> CreateDefaultPipeline(
225247
const Context& context) {
@@ -352,9 +374,40 @@ ContentContext::ContentContext(
352374
border_mask_blur_pipelines_.CreateDefault(*context_, options_trianglestrip);
353375
color_matrix_color_filter_pipelines_.CreateDefault(*context_,
354376
options_trianglestrip);
355-
porter_duff_blend_pipelines_.CreateDefault(*context_, options_trianglestrip,
356-
{supports_decal});
357377
vertices_uber_shader_.CreateDefault(*context_, options, {supports_decal});
378+
379+
const std::array<std::vector<Scalar>, 15> porter_duff_constants =
380+
GetPorterDuffSpecConstants(supports_decal);
381+
clear_blend_pipelines_.CreateDefault(*context_, options_trianglestrip,
382+
porter_duff_constants[0]);
383+
source_blend_pipelines_.CreateDefault(*context_, options_trianglestrip,
384+
porter_duff_constants[1]);
385+
destination_blend_pipelines_.CreateDefault(*context_, options_trianglestrip,
386+
porter_duff_constants[2]);
387+
source_over_blend_pipelines_.CreateDefault(*context_, options_trianglestrip,
388+
porter_duff_constants[3]);
389+
destination_over_blend_pipelines_.CreateDefault(
390+
*context_, options_trianglestrip, porter_duff_constants[4]);
391+
source_in_blend_pipelines_.CreateDefault(*context_, options_trianglestrip,
392+
porter_duff_constants[5]);
393+
destination_in_blend_pipelines_.CreateDefault(
394+
*context_, options_trianglestrip, porter_duff_constants[6]);
395+
source_out_blend_pipelines_.CreateDefault(*context_, options_trianglestrip,
396+
porter_duff_constants[7]);
397+
destination_out_blend_pipelines_.CreateDefault(
398+
*context_, options_trianglestrip, porter_duff_constants[8]);
399+
source_a_top_blend_pipelines_.CreateDefault(
400+
*context_, options_trianglestrip, porter_duff_constants[9]);
401+
destination_a_top_blend_pipelines_.CreateDefault(
402+
*context_, options_trianglestrip, porter_duff_constants[10]);
403+
xor_blend_pipelines_.CreateDefault(*context_, options_trianglestrip,
404+
porter_duff_constants[11]);
405+
plus_blend_pipelines_.CreateDefault(*context_, options_trianglestrip,
406+
porter_duff_constants[12]);
407+
modulate_blend_pipelines_.CreateDefault(*context_, options_trianglestrip,
408+
porter_duff_constants[13]);
409+
screen_blend_pipelines_.CreateDefault(*context_, options_trianglestrip,
410+
porter_duff_constants[14]);
358411
}
359412

360413
if (context_->GetCapabilities()->SupportsFramebufferFetch()) {

engine/src/flutter/impeller/entity/contents/content_context.h

Lines changed: 135 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "impeller/base/validation.h"
1616
#include "impeller/core/formats.h"
1717
#include "impeller/core/host_buffer.h"
18+
#include "impeller/geometry/color.h"
1819
#include "impeller/renderer/capabilities.h"
1920
#include "impeller/renderer/command_buffer.h"
2021
#include "impeller/renderer/pipeline.h"
@@ -522,8 +523,121 @@ class ContentContext {
522523
return GetPipeline(yuv_to_rgb_filter_pipelines_, opts);
523524
}
524525

525-
PipelineRef GetPorterDuffBlendPipeline(ContentContextOptions opts) const {
526-
return GetPipeline(porter_duff_blend_pipelines_, opts);
526+
// Porter-Duff combined blends.
527+
PipelineRef GetPorterDuffPipeline(BlendMode mode,
528+
ContentContextOptions opts) const {
529+
switch (mode) {
530+
case BlendMode::kClear:
531+
return GetClearBlendPipeline(opts);
532+
case BlendMode::kSource:
533+
return GetSourceBlendPipeline(opts);
534+
case BlendMode::kDestination:
535+
return GetDestinationBlendPipeline(opts);
536+
case BlendMode::kSourceOver:
537+
return GetSourceOverBlendPipeline(opts);
538+
case BlendMode::kDestinationOver:
539+
return GetDestinationOverBlendPipeline(opts);
540+
case BlendMode::kSourceIn:
541+
return GetSourceInBlendPipeline(opts);
542+
case BlendMode::kDestinationIn:
543+
return GetDestinationInBlendPipeline(opts);
544+
case BlendMode::kSourceOut:
545+
return GetSourceOutBlendPipeline(opts);
546+
case BlendMode::kDestinationOut:
547+
return GetDestinationOutBlendPipeline(opts);
548+
case BlendMode::kSourceATop:
549+
return GetSourceATopBlendPipeline(opts);
550+
case BlendMode::kDestinationATop:
551+
return GetDestinationATopBlendPipeline(opts);
552+
case BlendMode::kXor:
553+
return GetXorBlendPipeline(opts);
554+
case BlendMode::kPlus:
555+
return GetPlusBlendPipeline(opts);
556+
case BlendMode::kModulate:
557+
return GetModulateBlendPipeline(opts);
558+
case BlendMode::kScreen:
559+
return GetScreenBlendPipeline(opts);
560+
case BlendMode::kOverlay:
561+
case BlendMode::kDarken:
562+
case BlendMode::kLighten:
563+
case BlendMode::kColorDodge:
564+
case BlendMode::kColorBurn:
565+
case BlendMode::kHardLight:
566+
case BlendMode::kSoftLight:
567+
case BlendMode::kDifference:
568+
case BlendMode::kExclusion:
569+
case BlendMode::kMultiply:
570+
case BlendMode::kHue:
571+
case BlendMode::kSaturation:
572+
case BlendMode::kColor:
573+
case BlendMode::kLuminosity:
574+
VALIDATION_LOG << "Invalid porter duff blend mode "
575+
<< BlendModeToString(mode);
576+
return GetClearBlendPipeline(opts);
577+
break;
578+
}
579+
}
580+
581+
PipelineRef GetClearBlendPipeline(ContentContextOptions opts) const {
582+
return GetPipeline(clear_blend_pipelines_, opts);
583+
}
584+
585+
PipelineRef GetSourceBlendPipeline(ContentContextOptions opts) const {
586+
return GetPipeline(source_blend_pipelines_, opts);
587+
}
588+
589+
PipelineRef GetDestinationBlendPipeline(ContentContextOptions opts) const {
590+
return GetPipeline(destination_blend_pipelines_, opts);
591+
}
592+
593+
PipelineRef GetSourceOverBlendPipeline(ContentContextOptions opts) const {
594+
return GetPipeline(source_over_blend_pipelines_, opts);
595+
}
596+
597+
PipelineRef GetDestinationOverBlendPipeline(
598+
ContentContextOptions opts) const {
599+
return GetPipeline(destination_over_blend_pipelines_, opts);
600+
}
601+
602+
PipelineRef GetSourceInBlendPipeline(ContentContextOptions opts) const {
603+
return GetPipeline(source_in_blend_pipelines_, opts);
604+
}
605+
606+
PipelineRef GetDestinationInBlendPipeline(ContentContextOptions opts) const {
607+
return GetPipeline(destination_in_blend_pipelines_, opts);
608+
}
609+
610+
PipelineRef GetSourceOutBlendPipeline(ContentContextOptions opts) const {
611+
return GetPipeline(source_out_blend_pipelines_, opts);
612+
}
613+
614+
PipelineRef GetDestinationOutBlendPipeline(ContentContextOptions opts) const {
615+
return GetPipeline(destination_out_blend_pipelines_, opts);
616+
}
617+
618+
PipelineRef GetSourceATopBlendPipeline(ContentContextOptions opts) const {
619+
return GetPipeline(source_a_top_blend_pipelines_, opts);
620+
}
621+
622+
PipelineRef GetDestinationATopBlendPipeline(
623+
ContentContextOptions opts) const {
624+
return GetPipeline(destination_a_top_blend_pipelines_, opts);
625+
}
626+
627+
PipelineRef GetXorBlendPipeline(ContentContextOptions opts) const {
628+
return GetPipeline(xor_blend_pipelines_, opts);
629+
}
630+
631+
PipelineRef GetPlusBlendPipeline(ContentContextOptions opts) const {
632+
return GetPipeline(plus_blend_pipelines_, opts);
633+
}
634+
635+
PipelineRef GetModulateBlendPipeline(ContentContextOptions opts) const {
636+
return GetPipeline(modulate_blend_pipelines_, opts);
637+
}
638+
639+
PipelineRef GetScreenBlendPipeline(ContentContextOptions opts) const {
640+
return GetPipeline(screen_blend_pipelines_, opts);
527641
}
528642

529643
// Advanced blends.
@@ -826,7 +940,7 @@ class ContentContext {
826940

827941
void CreateDefault(const Context& context,
828942
const ContentContextOptions& options,
829-
const std::initializer_list<Scalar>& constants = {}) {
943+
const std::vector<Scalar>& constants = {}) {
830944
auto desc = PipelineHandleT::Builder::MakeDefaultPipelineDescriptor(
831945
context, constants);
832946
if (!desc.has_value()) {
@@ -916,7 +1030,24 @@ class ContentContext {
9161030
mutable Variants<ClipPipeline> clip_pipelines_;
9171031
mutable Variants<GlyphAtlasPipeline> glyph_atlas_pipelines_;
9181032
mutable Variants<YUVToRGBFilterPipeline> yuv_to_rgb_filter_pipelines_;
919-
mutable Variants<PorterDuffBlendPipeline> porter_duff_blend_pipelines_;
1033+
1034+
// Porter Duff Blends.
1035+
mutable Variants<PorterDuffBlendPipeline> clear_blend_pipelines_;
1036+
mutable Variants<PorterDuffBlendPipeline> source_blend_pipelines_;
1037+
mutable Variants<PorterDuffBlendPipeline> destination_blend_pipelines_;
1038+
mutable Variants<PorterDuffBlendPipeline> source_over_blend_pipelines_;
1039+
mutable Variants<PorterDuffBlendPipeline> destination_over_blend_pipelines_;
1040+
mutable Variants<PorterDuffBlendPipeline> source_in_blend_pipelines_;
1041+
mutable Variants<PorterDuffBlendPipeline> destination_in_blend_pipelines_;
1042+
mutable Variants<PorterDuffBlendPipeline> source_out_blend_pipelines_;
1043+
mutable Variants<PorterDuffBlendPipeline> destination_out_blend_pipelines_;
1044+
mutable Variants<PorterDuffBlendPipeline> source_a_top_blend_pipelines_;
1045+
mutable Variants<PorterDuffBlendPipeline> destination_a_top_blend_pipelines_;
1046+
mutable Variants<PorterDuffBlendPipeline> xor_blend_pipelines_;
1047+
mutable Variants<PorterDuffBlendPipeline> plus_blend_pipelines_;
1048+
mutable Variants<PorterDuffBlendPipeline> modulate_blend_pipelines_;
1049+
mutable Variants<PorterDuffBlendPipeline> screen_blend_pipelines_;
1050+
9201051
// Advanced blends.
9211052
mutable Variants<BlendColorPipeline> blend_color_pipelines_;
9221053
mutable Variants<BlendColorBurnPipeline> blend_colorburn_pipelines_;

engine/src/flutter/impeller/entity/contents/filters/blend_filter_contents.cc

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ std::optional<Entity> BlendFilterContents::CreateForegroundPorterDuffBlend(
470470
pass.SetVertexBuffer(std::move(vtx_buffer));
471471
auto options = OptionsFromPassAndEntity(pass, entity);
472472
options.primitive_type = PrimitiveType::kTriangleStrip;
473-
pass.SetPipeline(renderer.GetPorterDuffBlendPipeline(options));
473+
pass.SetPipeline(renderer.GetPorterDuffPipeline(blend_mode, options));
474474

475475
FS::FragInfo frag_info;
476476
VS::FrameInfo frame_info;
@@ -497,14 +497,6 @@ std::optional<Entity> BlendFilterContents::CreateForegroundPorterDuffBlend(
497497
: 1.0;
498498
frag_info.output_alpha = 1.0;
499499

500-
auto blend_coefficients =
501-
kPorterDuffCoefficients[static_cast<int>(blend_mode)];
502-
frag_info.src_coeff = blend_coefficients[0];
503-
frag_info.src_coeff_dst_alpha = blend_coefficients[1];
504-
frag_info.dst_coeff = blend_coefficients[2];
505-
frag_info.dst_coeff_src_alpha = blend_coefficients[3];
506-
frag_info.dst_coeff_src_color = blend_coefficients[4];
507-
508500
FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
509501
VS::BindFrameInfo(pass, host_buffer.EmplaceUniform(frame_info));
510502

engine/src/flutter/impeller/entity/contents/vertices_contents.cc

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,10 @@ bool VerticesSimpleBlendContents::Render(const ContentContext& renderer,
151151

152152
auto options = OptionsFromPassAndEntity(pass, entity);
153153
options.primitive_type = geometry_result.type;
154-
pass.SetPipeline(renderer.GetPorterDuffBlendPipeline(options));
154+
auto inverted_blend_mode =
155+
InvertPorterDuffBlend(blend_mode).value_or(BlendMode::kSource);
156+
pass.SetPipeline(
157+
renderer.GetPorterDuffPipeline(inverted_blend_mode, options));
155158

156159
FS::BindTextureSamplerDst(pass, texture, dst_sampler);
157160

@@ -164,16 +167,6 @@ bool VerticesSimpleBlendContents::Render(const ContentContext& renderer,
164167
frag_info.output_alpha = alpha_;
165168
frag_info.input_alpha = 1.0;
166169

167-
auto inverted_blend_mode =
168-
InvertPorterDuffBlend(blend_mode).value_or(BlendMode::kSource);
169-
auto blend_coefficients =
170-
kPorterDuffCoefficients[static_cast<int>(inverted_blend_mode)];
171-
frag_info.src_coeff = blend_coefficients[0];
172-
frag_info.src_coeff_dst_alpha = blend_coefficients[1];
173-
frag_info.dst_coeff = blend_coefficients[2];
174-
frag_info.dst_coeff_src_alpha = blend_coefficients[3];
175-
frag_info.dst_coeff_src_color = blend_coefficients[4];
176-
177170
// These values are ignored if the platform supports native decal mode.
178171
frag_info.tmx = static_cast<int>(tile_mode_x_);
179172
frag_info.tmy = static_cast<int>(tile_mode_y_);

engine/src/flutter/impeller/entity/shaders/blending/porter_duff_blend.frag

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,17 @@ precision mediump float;
99
#include <impeller/texture.glsl>
1010
#include <impeller/types.glsl>
1111

12+
// see GetPorterDuffSpecConstants in content_context.cc for actual constants
1213
layout(constant_id = 0) const float supports_decal = 1.0;
14+
layout(constant_id = 1) const float src_coeff = 1.0;
15+
layout(constant_id = 2) const float src_coeff_dst_alpha = 1.0;
16+
layout(constant_id = 3) const float dst_coeff = 1.0;
17+
layout(constant_id = 4) const float dst_coeff_src_alpha = 1.0;
18+
layout(constant_id = 5) const float dst_coeff_src_color = 1.0;
1319

1420
uniform f16sampler2D texture_sampler_dst;
1521

1622
uniform FragInfo {
17-
float16_t src_coeff;
18-
float16_t src_coeff_dst_alpha;
19-
float16_t dst_coeff;
20-
float16_t dst_coeff_src_alpha;
21-
float16_t dst_coeff_src_color;
2223
float16_t input_alpha;
2324
float16_t output_alpha;
2425
float tmx;
@@ -29,7 +30,7 @@ frag_info;
2930
in vec2 v_texture_coords;
3031
in f16vec4 v_color;
3132

32-
out f16vec4 frag_color;
33+
out vec4 frag_color;
3334

3435
f16vec4 Sample(f16sampler2D texture_sampler,
3536
vec2 texture_coords,
@@ -46,9 +47,8 @@ void main() {
4647
frag_info.tmy) *
4748
frag_info.input_alpha;
4849
f16vec4 src = v_color;
49-
frag_color =
50-
src * (frag_info.src_coeff + dst.a * frag_info.src_coeff_dst_alpha) +
51-
dst * (frag_info.dst_coeff + src.a * frag_info.dst_coeff_src_alpha +
52-
src * frag_info.dst_coeff_src_color);
50+
frag_color = f16vec4(src * (src_coeff + dst.a * src_coeff_dst_alpha) +
51+
dst * (dst_coeff + src.a * dst_coeff_src_alpha +
52+
src * dst_coeff_src_color));
5353
frag_color *= frag_info.output_alpha;
5454
}

0 commit comments

Comments
 (0)