Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit be43db3

Browse files
[Impeller] Add support for specialization constants redux. (#47678)
Reland of #47432 Also includes: * #47617 * #47637 Fixes the performance on iOS by removing blocking on compilation of shaders. From local testing this has identical before/after numbers. Additional, ensures that we don't unecessarily specialize vertex shaders and notes this restriction in the documentation. ---- Adds support for Specialization constants to Impeller for our usage in the engine. A motivating example has been added in the impeller markdown docs. Fixes flutter/flutter#136210 Fixes flutter/flutter#119357
1 parent 1b20752 commit be43db3

File tree

64 files changed

+1247
-3983
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+1247
-3983
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 8 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -3134,42 +3134,13 @@ ORIGIN: ../../../flutter/impeller/entity/inline_pass_context.cc + ../../../flutt
31343134
ORIGIN: ../../../flutter/impeller/entity/inline_pass_context.h + ../../../flutter/LICENSE
31353135
ORIGIN: ../../../flutter/impeller/entity/render_target_cache.cc + ../../../flutter/LICENSE
31363136
ORIGIN: ../../../flutter/impeller/entity/render_target_cache.h + ../../../flutter/LICENSE
3137-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/advanced_blend.glsl + ../../../flutter/LICENSE
3137+
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/advanced_blend.frag + ../../../flutter/LICENSE
31383138
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/advanced_blend.vert + ../../../flutter/LICENSE
3139-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_color.frag + ../../../flutter/LICENSE
3140-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_colorburn.frag + ../../../flutter/LICENSE
3141-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_colordodge.frag + ../../../flutter/LICENSE
3142-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_darken.frag + ../../../flutter/LICENSE
3143-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_difference.frag + ../../../flutter/LICENSE
3144-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_exclusion.frag + ../../../flutter/LICENSE
3145-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_hardlight.frag + ../../../flutter/LICENSE
3146-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_hue.frag + ../../../flutter/LICENSE
3147-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_lighten.frag + ../../../flutter/LICENSE
3148-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_luminosity.frag + ../../../flutter/LICENSE
3149-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_multiply.frag + ../../../flutter/LICENSE
3150-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_overlay.frag + ../../../flutter/LICENSE
3151-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_saturation.frag + ../../../flutter/LICENSE
3152-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_screen.frag + ../../../flutter/LICENSE
3153-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_softlight.frag + ../../../flutter/LICENSE
31543139
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/blend.frag + ../../../flutter/LICENSE
31553140
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/blend.vert + ../../../flutter/LICENSE
3156-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend.glsl + ../../../flutter/LICENSE
3157-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend.vert + ../../../flutter/LICENSE
3158-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_color.frag + ../../../flutter/LICENSE
3159-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_colorburn.frag + ../../../flutter/LICENSE
3160-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_colordodge.frag + ../../../flutter/LICENSE
3161-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_darken.frag + ../../../flutter/LICENSE
3162-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_difference.frag + ../../../flutter/LICENSE
3163-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_exclusion.frag + ../../../flutter/LICENSE
3164-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_hardlight.frag + ../../../flutter/LICENSE
3165-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_hue.frag + ../../../flutter/LICENSE
3166-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_lighten.frag + ../../../flutter/LICENSE
3167-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_luminosity.frag + ../../../flutter/LICENSE
3168-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_multiply.frag + ../../../flutter/LICENSE
3169-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_overlay.frag + ../../../flutter/LICENSE
3170-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_saturation.frag + ../../../flutter/LICENSE
3171-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_screen.frag + ../../../flutter/LICENSE
3172-
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_softlight.frag + ../../../flutter/LICENSE
3141+
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/blend_select.glsl + ../../../flutter/LICENSE
3142+
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/framebuffer_blend.frag + ../../../flutter/LICENSE
3143+
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/framebuffer_blend.vert + ../../../flutter/LICENSE
31733144
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/porter_duff_blend.frag + ../../../flutter/LICENSE
31743145
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/porter_duff_blend.vert + ../../../flutter/LICENSE
31753146
ORIGIN: ../../../flutter/impeller/entity/shaders/border_mask_blur.frag + ../../../flutter/LICENSE
@@ -5917,42 +5888,13 @@ FILE: ../../../flutter/impeller/entity/inline_pass_context.cc
59175888
FILE: ../../../flutter/impeller/entity/inline_pass_context.h
59185889
FILE: ../../../flutter/impeller/entity/render_target_cache.cc
59195890
FILE: ../../../flutter/impeller/entity/render_target_cache.h
5920-
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend.glsl
5891+
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend.frag
59215892
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend.vert
5922-
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_color.frag
5923-
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_colorburn.frag
5924-
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_colordodge.frag
5925-
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_darken.frag
5926-
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_difference.frag
5927-
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_exclusion.frag
5928-
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_hardlight.frag
5929-
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_hue.frag
5930-
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_lighten.frag
5931-
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_luminosity.frag
5932-
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_multiply.frag
5933-
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_overlay.frag
5934-
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_saturation.frag
5935-
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_screen.frag
5936-
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_softlight.frag
59375893
FILE: ../../../flutter/impeller/entity/shaders/blending/blend.frag
59385894
FILE: ../../../flutter/impeller/entity/shaders/blending/blend.vert
5939-
FILE: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend.glsl
5940-
FILE: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend.vert
5941-
FILE: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_color.frag
5942-
FILE: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_colorburn.frag
5943-
FILE: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_colordodge.frag
5944-
FILE: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_darken.frag
5945-
FILE: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_difference.frag
5946-
FILE: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_exclusion.frag
5947-
FILE: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_hardlight.frag
5948-
FILE: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_hue.frag
5949-
FILE: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_lighten.frag
5950-
FILE: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_luminosity.frag
5951-
FILE: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_multiply.frag
5952-
FILE: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_overlay.frag
5953-
FILE: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_saturation.frag
5954-
FILE: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_screen.frag
5955-
FILE: ../../../flutter/impeller/entity/shaders/blending/ios/framebuffer_blend_softlight.frag
5895+
FILE: ../../../flutter/impeller/entity/shaders/blending/blend_select.glsl
5896+
FILE: ../../../flutter/impeller/entity/shaders/blending/framebuffer_blend.frag
5897+
FILE: ../../../flutter/impeller/entity/shaders/blending/framebuffer_blend.vert
59565898
FILE: ../../../flutter/impeller/entity/shaders/blending/porter_duff_blend.frag
59575899
FILE: ../../../flutter/impeller/entity/shaders/blending/porter_duff_blend.vert
59585900
FILE: ../../../flutter/impeller/entity/shaders/border_mask_blur.frag

impeller/base/comparable.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,8 @@
88
#include <functional>
99
#include <map>
1010
#include <memory>
11-
#include <string>
1211
#include <type_traits>
1312

14-
#include "flutter/fml/hash_combine.h"
15-
#include "flutter/fml/macros.h"
16-
1713
namespace impeller {
1814

1915
struct UniqueID {
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# Specialization Constants
2+
3+
A specialization constant is a named variable that is known to be constant at runtime but not when the shader is authored. These variables are bound to specific values when the shader is compiled on application start up and allow the backend to perform optimizations such as branch elimination and constant folding.
4+
5+
Specialization constants have two possible benefits when used in a shader:
6+
7+
* Improving performance, by removing branching and conditional code.
8+
* Code organization/size, by removing the number of shader source files required.
9+
10+
These goals are related: The number of shaders can be reduce by adding runtime branching to create more generic shaders. Alternatively, branching can be reduced by adding more specialized shader variants. Specialization constants provide a happy medium where the source files can be combined with branching but done so in a way that has no runtime cost.
11+
12+
## Example Usage
13+
14+
Consider the case of the "decal" texture sampling mode. This is implement via clamp-to-border with
15+
a border color set to transparent black. While this functionality is well supported on the Metal and
16+
Vulkan backends, the GLES backend needs to support devices that do not have this extension. As a
17+
result, the following code was used to conditionally decal:
18+
19+
```glsl
20+
// Decal sample if necessary.
21+
vec4 Sample(sampler2D sampler, vec2 coord) {
22+
#ifdef GLES
23+
return IPSampleDecal(sampler, coord)
24+
#else
25+
return texture(sampler, coord);
26+
#endif
27+
}
28+
```
29+
30+
This works great as long as we know that the GLES backend can never do the decal sample mode. This is also "free" as the ifdef branch is evaluated in the compiler. But eventually, we added a runtime check for decal mode as we need to support this on GLES. So the code turned into (approximately) the following:
31+
32+
```glsl
33+
#ifdef GLES
34+
uniform float supports_decal;
35+
#endif
36+
37+
// Decal sample if necessary.
38+
vec4 Sample(sampler2D sampler, vec2 coord) {
39+
#ifdef GLES
40+
if (supports_decal) {
41+
return texture(sampler, coord);
42+
}
43+
return IPSampleDecal(sampler, coord)
44+
#else
45+
return texture(sampler, coord);
46+
#endif
47+
}
48+
```
49+
50+
Now we've got decal support, but we've also got new problems:
51+
52+
* The code is actually quite messy. We have to track different uniform values depending on the backend.
53+
* The GLES backend is still paying some cost for branching, even though we "know" that decal is or isn't supported when the shader is compiled.
54+
55+
### Specialization constants to the rescue
56+
57+
Instead of using a runtime check, we can create a specialization constant that is set when compiling the
58+
shader. This constant will be `1` if decal is supported and `0` otherwise.
59+
60+
```glsl
61+
layout(constant_id = 0) const int supports_decal = 1;
62+
63+
vec4 Sample(sampler2D sampler, vec2 coord) {
64+
if (supports_decal) {
65+
return texture(sampler, coord);
66+
}
67+
return IPSampleDecal(sampler, coord)
68+
}
69+
70+
```
71+
72+
Immediately we realize a number of benefits:
73+
74+
* Code is the same across all backends
75+
* Runtime branching cost is removed as the branch is compiled out.
76+
77+
78+
## Implementation
79+
80+
Only 32bit ints are supported as const values and can be used to represent:
81+
82+
* true/false via 0/1.
83+
* function selection, such as advanced blends. The specialization value maps to a specific blend function. For example, 0 maps to screen and 1 to overlay via a giant if/else macro.
84+
* Only fragment shaders can be specialized. This limitation could be removed with more investment.
85+
86+
*AVOID* adding specialization constants for color values or anything more complex.
87+
88+
Specialization constants are provided to the CreateDefault argument in content_context.cc and aren't a
89+
part of variants. This is intentional: specialization constants shouldn't be used to create (potentially unlimited) runtime variants of a shader.
90+
91+
Backend specific information:
92+
* In the Metal backend, the specialization constants are mapped to a MTLFunctionConstantValues. See also: https://developer.apple.com/documentation/metal/using_function_specialization_to_build_pipeline_variants?language=objc
93+
* In the Vulkan backend, the specialization constants are mapped to VkSpecializationINfo. See also: https://blogs.igalia.com/itoral/2018/03/20/improving-shader-performance-with-vulkans-specialization-constants/
94+
* In the GLES backend, the SPIRV Cross compiler will generate defines named `#ifdef SPIRV_CROSS_CONSTANT_i`, where i is the index of constant. The Impeller runtime will insert `#define SPIRV_CROSS_CONSTANT_i` in the header of the shader.

impeller/entity/BUILD.gn

Lines changed: 3 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,7 @@ impeller_shaders("entity_shaders") {
1515

1616
shaders = [
1717
"shaders/blending/advanced_blend.vert",
18-
"shaders/blending/advanced_blend_color.frag",
19-
"shaders/blending/advanced_blend_colorburn.frag",
20-
"shaders/blending/advanced_blend_colordodge.frag",
21-
"shaders/blending/advanced_blend_darken.frag",
22-
"shaders/blending/advanced_blend_difference.frag",
23-
"shaders/blending/advanced_blend_exclusion.frag",
24-
"shaders/blending/advanced_blend_hardlight.frag",
25-
"shaders/blending/advanced_blend_hue.frag",
26-
"shaders/blending/advanced_blend_lighten.frag",
27-
"shaders/blending/advanced_blend_luminosity.frag",
28-
"shaders/blending/advanced_blend_multiply.frag",
29-
"shaders/blending/advanced_blend_overlay.frag",
30-
"shaders/blending/advanced_blend_saturation.frag",
31-
"shaders/blending/advanced_blend_screen.frag",
32-
"shaders/blending/advanced_blend_softlight.frag",
18+
"shaders/blending/advanced_blend.frag",
3319
"shaders/blending/blend.frag",
3420
"shaders/blending/blend.vert",
3521
"shaders/border_mask_blur.frag",
@@ -115,22 +101,8 @@ impeller_shaders("framebuffer_blend_entity_shaders") {
115101
}
116102

117103
shaders = [
118-
"shaders/blending/ios/framebuffer_blend.vert",
119-
"shaders/blending/ios/framebuffer_blend_color.frag",
120-
"shaders/blending/ios/framebuffer_blend_colorburn.frag",
121-
"shaders/blending/ios/framebuffer_blend_colordodge.frag",
122-
"shaders/blending/ios/framebuffer_blend_darken.frag",
123-
"shaders/blending/ios/framebuffer_blend_difference.frag",
124-
"shaders/blending/ios/framebuffer_blend_exclusion.frag",
125-
"shaders/blending/ios/framebuffer_blend_hardlight.frag",
126-
"shaders/blending/ios/framebuffer_blend_hue.frag",
127-
"shaders/blending/ios/framebuffer_blend_lighten.frag",
128-
"shaders/blending/ios/framebuffer_blend_luminosity.frag",
129-
"shaders/blending/ios/framebuffer_blend_multiply.frag",
130-
"shaders/blending/ios/framebuffer_blend_overlay.frag",
131-
"shaders/blending/ios/framebuffer_blend_saturation.frag",
132-
"shaders/blending/ios/framebuffer_blend_screen.frag",
133-
"shaders/blending/ios/framebuffer_blend_softlight.frag",
104+
"shaders/blending/framebuffer_blend.vert",
105+
"shaders/blending/framebuffer_blend.frag",
134106
]
135107
}
136108

impeller/entity/contents/atlas_contents.cc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -262,8 +262,6 @@ bool AtlasContents::Render(const ContentContext& renderer,
262262
dst_sampler_descriptor.width_address_mode = SamplerAddressMode::kDecal;
263263
dst_sampler_descriptor.height_address_mode = SamplerAddressMode::kDecal;
264264
}
265-
frag_info.supports_decal_sampler_address_mode =
266-
renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode();
267265
auto dst_sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler(
268266
dst_sampler_descriptor);
269267
FS::BindTextureSamplerDst(cmd, texture_, dst_sampler);

0 commit comments

Comments
 (0)