mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[impellerc] Sort uniforms by location in SkSL backend (flutter/engine#34684)
This commit is contained in:
parent
a0861e3872
commit
39d01bcb5e
@ -19,7 +19,7 @@ std::string CompilerSkSL::compile() {
|
||||
}
|
||||
|
||||
options.es = false;
|
||||
options.version = 300;
|
||||
options.version = 100;
|
||||
options.vulkan_semantics = false;
|
||||
options.enable_420pack_extension = false;
|
||||
|
||||
@ -82,7 +82,7 @@ void CompilerSkSL::emit_header() {
|
||||
void CompilerSkSL::emit_uniform(const SPIRVariable& var) {
|
||||
auto& type = get<SPIRType>(var.basetype);
|
||||
add_resource_name(var.self);
|
||||
statement(layout_for_variable(var), variable_decl(var), ";");
|
||||
statement(variable_decl(var), ";");
|
||||
|
||||
// The Flutter FragmentProgram implementation passes additional unifroms along
|
||||
// with shader uniforms that encode the shader width and height.
|
||||
@ -198,6 +198,25 @@ bool CompilerSkSL::emit_uniform_resources() {
|
||||
}
|
||||
}
|
||||
|
||||
// Sort uniforms by location.
|
||||
auto compare_locations = [this](ID id1, ID id2) {
|
||||
auto& flags1 = get_decoration_bitset(id1);
|
||||
auto& flags2 = get_decoration_bitset(id2);
|
||||
// Put the uniforms with no location after the ones that have a location.
|
||||
if (!flags1.get(DecorationLocation)) {
|
||||
return false;
|
||||
}
|
||||
if (!flags2.get(DecorationLocation)) {
|
||||
return true;
|
||||
}
|
||||
// Sort in increasing order of location.
|
||||
return get_decoration(id1, DecorationLocation) <
|
||||
get_decoration(id2, DecorationLocation);
|
||||
};
|
||||
std::sort(regular_uniforms.begin(), regular_uniforms.end(),
|
||||
compare_locations);
|
||||
std::sort(shader_uniforms.begin(), shader_uniforms.end(), compare_locations);
|
||||
|
||||
for (const auto& id : regular_uniforms) {
|
||||
auto& var = get<SPIRVariable>(id);
|
||||
emit_uniform(var);
|
||||
|
||||
@ -13,6 +13,7 @@ if (enable_unittests) {
|
||||
"functions.frag",
|
||||
"simple.frag",
|
||||
"uniforms.frag",
|
||||
"uniforms_sorted.frag",
|
||||
]
|
||||
|
||||
group("general_shaders") {
|
||||
|
||||
@ -0,0 +1,135 @@
|
||||
#version 320 es
|
||||
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// This shader is a fixture for a test that ensures that the order of the
|
||||
// unifroms is retained. The values of the uniforms in the test are strictly
|
||||
// increasing. If two uniforms are out of order, the output color is red. If
|
||||
// the uniforms are in the right order, the output color is green.
|
||||
|
||||
precision highp float;
|
||||
|
||||
layout(location = 0) uniform vec4 u_color;
|
||||
layout(location = 1) uniform float u_alpha;
|
||||
layout(location = 2) uniform vec4 u_sparkle_color;
|
||||
layout(location = 3) uniform float u_sparkle_alpha;
|
||||
layout(location = 4) uniform float u_blur;
|
||||
layout(location = 5) uniform vec2 u_center;
|
||||
layout(location = 6) uniform float u_radius_scale;
|
||||
layout(location = 7) uniform float u_max_radius;
|
||||
layout(location = 8) uniform vec2 u_resolution_scale;
|
||||
layout(location = 9) uniform vec2 u_noise_scale;
|
||||
layout(location = 10) uniform float u_noise_phase;
|
||||
layout(location = 11) uniform vec2 u_circle1;
|
||||
layout(location = 12) uniform vec2 u_circle2;
|
||||
layout(location = 13) uniform vec2 u_circle3;
|
||||
layout(location = 14) uniform vec2 u_rotation1;
|
||||
layout(location = 15) uniform vec2 u_rotation2;
|
||||
layout(location = 16) uniform vec2 u_rotation3;
|
||||
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
|
||||
const float PI = 3.1415926535897932384626;
|
||||
const float PI_ROTATE_RIGHT = PI * 0.0078125;
|
||||
const float PI_ROTATE_LEFT = PI * -0.0078125;
|
||||
const float ONE_THIRD = 1./3.;
|
||||
const vec2 TURBULENCE_SCALE = vec2(0.8);
|
||||
|
||||
float saturate(float x) {
|
||||
return clamp(x, 0.0, 1.0);
|
||||
}
|
||||
|
||||
float triangle_noise(highp vec2 n) {
|
||||
n = fract(n * vec2(5.3987, 5.4421));
|
||||
n += dot(n.yx, n.xy + vec2(21.5351, 14.3137));
|
||||
float xy = n.x * n.y;
|
||||
return fract(xy * 95.4307) + fract(xy * 75.04961) - 1.0;
|
||||
}
|
||||
|
||||
float threshold(float v, float l, float h) {
|
||||
return step(l, v) * (1.0 - step(h, v));
|
||||
}
|
||||
|
||||
mat2 rotate2d(vec2 rad){
|
||||
return mat2(rad.x, -rad.y, rad.y, rad.x);
|
||||
}
|
||||
|
||||
float soft_circle(vec2 uv, vec2 xy, float radius, float blur) {
|
||||
float blur_half = blur * 0.5;
|
||||
float d = distance(uv, xy);
|
||||
return 1.0 - smoothstep(1.0 - blur_half, 1.0 + blur_half, d / radius);
|
||||
}
|
||||
|
||||
float soft_ring(vec2 uv, vec2 xy, float radius, float thickness, float blur) {
|
||||
float circle_outer = soft_circle(uv, xy, radius + thickness, blur);
|
||||
float circle_inner = soft_circle(uv, xy, max(radius - thickness, 0.0), blur);
|
||||
return saturate(circle_outer - circle_inner);
|
||||
}
|
||||
|
||||
float circle_grid(vec2 resolution, vec2 p, vec2 xy, vec2 rotation, float cell_diameter) {
|
||||
p = rotate2d(rotation) * (xy - p) + xy;
|
||||
p = mod(p, cell_diameter) / resolution;
|
||||
float cell_uv = cell_diameter / resolution.y * 0.5;
|
||||
float r = 0.65 * cell_uv;
|
||||
return soft_circle(p, vec2(cell_uv), r, r * 50.0);
|
||||
}
|
||||
|
||||
float sparkle(vec2 uv, float t) {
|
||||
float n = triangle_noise(uv);
|
||||
float s = threshold(n, 0.0, 0.05);
|
||||
s += threshold(n + sin(PI * (t + 0.35)), 0.1, 0.15);
|
||||
s += threshold(n + sin(PI * (t + 0.7)), 0.2, 0.25);
|
||||
s += threshold(n + sin(PI * (t + 1.05)), 0.3, 0.35);
|
||||
return saturate(s) * 0.55;
|
||||
}
|
||||
|
||||
float turbulence(vec2 uv) {
|
||||
vec2 uv_scale = uv * TURBULENCE_SCALE;
|
||||
float g1 = circle_grid(TURBULENCE_SCALE, uv_scale, u_circle1, u_rotation1, 0.17);
|
||||
float g2 = circle_grid(TURBULENCE_SCALE, uv_scale, u_circle2, u_rotation2, 0.2);
|
||||
float g3 = circle_grid(TURBULENCE_SCALE, uv_scale, u_circle3, u_rotation3, 0.275);
|
||||
float v = (g1 * g1 + g2 - g3) * 0.5;
|
||||
return saturate(0.45 + 0.8 * v);
|
||||
}
|
||||
|
||||
void main() {
|
||||
// This block of code triggers the compiler to emit the uniforms out of order
|
||||
// if they are not explicitly sorted.
|
||||
vec2 p = gl_FragCoord.xy;
|
||||
vec2 uv = p * u_resolution_scale;
|
||||
vec2 density_uv = uv - mod(p, u_noise_scale);
|
||||
float radius = u_max_radius * u_radius_scale;
|
||||
float turbulence = turbulence(uv);
|
||||
float ring = soft_ring(p, u_center, radius, 0.05 * u_max_radius, u_blur);
|
||||
float sparkle = sparkle(density_uv, u_noise_phase) * ring * turbulence * u_sparkle_alpha;
|
||||
float wave_alpha = soft_circle(p, u_center, radius, u_blur) * u_alpha * u_color.a;
|
||||
vec4 wave_color = vec4(u_color.rgb * wave_alpha, wave_alpha);
|
||||
vec4 sparkle_color = vec4(u_sparkle_color.rgb * u_sparkle_color.a, u_sparkle_color.a);
|
||||
fragColor = mix(wave_color, sparkle_color, sparkle);
|
||||
|
||||
vec4 badColor = vec4(1.0, 0, 0, 1.0);
|
||||
vec4 goodColor = vec4(0, 1.0, 0, 1.0);
|
||||
if (u_color.x > u_alpha ||
|
||||
u_alpha > u_sparkle_color.x ||
|
||||
u_sparkle_color.x > u_sparkle_alpha ||
|
||||
u_sparkle_alpha > u_blur ||
|
||||
u_blur > u_center.x ||
|
||||
u_center.x > u_radius_scale ||
|
||||
u_radius_scale > u_max_radius ||
|
||||
u_max_radius > u_resolution_scale.x ||
|
||||
u_resolution_scale.x > u_noise_scale.x ||
|
||||
u_noise_scale.x > u_noise_phase ||
|
||||
u_noise_phase > u_circle1.x ||
|
||||
u_circle1.x > u_circle2.x ||
|
||||
u_circle2.x > u_circle3.x ||
|
||||
u_circle3.x > u_rotation1.x ||
|
||||
u_rotation1.x > u_rotation2.x ||
|
||||
u_rotation2.x > u_rotation3.x) {
|
||||
fragColor = badColor;
|
||||
} else {
|
||||
fragColor = goodColor;
|
||||
}
|
||||
}
|
||||
|
||||
@ -223,6 +223,27 @@ void main() {
|
||||
// produces the correct pixels are in the framework.
|
||||
});
|
||||
|
||||
test('sksl uniforms are sorted correctly', () async {
|
||||
final Uint8List sksl = await shaderFile(
|
||||
path.join('general_shaders', 'sksl'),
|
||||
'uniforms_sorted.frag.sksl',
|
||||
).readAsBytes();
|
||||
final FragmentProgram program = await FragmentProgram.compile(
|
||||
raw: sksl.buffer,
|
||||
uniformFloatCount: 32,
|
||||
);
|
||||
|
||||
// The shader will not render green if the compiler doesn't keep the
|
||||
// uniforms in the right order.
|
||||
final Shader shader = program.shader(
|
||||
floatUniforms: Float32List.fromList(
|
||||
List<double>.generate(32, (int i) => i.toDouble()),
|
||||
),
|
||||
);
|
||||
|
||||
await _expectShaderRendersGreen(shader);
|
||||
});
|
||||
|
||||
// Test all supported GLSL ops. See lib/spirv/lib/src/constants.dart
|
||||
final Map<String, ByteBuffer> supportedGLSLOpShaders = _loadShaders(
|
||||
path.join('supported_glsl_op_shaders', 'spirv'),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user