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

Commit d74489c

Browse files
committed
Test for stroke tesellation in compute
1 parent 3d82bdc commit d74489c

File tree

10 files changed

+874
-10
lines changed

10 files changed

+874
-10
lines changed

impeller/compiler/compiler.cc

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ static CompilerBackend CreateMSLCompiler(const spirv_cross::ParsedIR& ir,
3434
// If this version specification changes, the GN rules that process the
3535
// Metal to AIR must be updated as well.
3636
sl_options.msl_version =
37-
spirv_cross::CompilerMSL::Options::make_msl_version(1, 2);
37+
spirv_cross::CompilerMSL::Options::make_msl_version(2, 1);
3838
sl_options.use_framebuffer_fetch_subpasses = true;
3939
sl_compiler->set_msl_options(sl_options);
4040

@@ -348,7 +348,7 @@ Compiler::Compiler(const fml::Mapping& source_mapping,
348348
shaderc_optimization_level::shaderc_optimization_level_performance);
349349
spirv_options.SetTargetEnvironment(
350350
shaderc_target_env::shaderc_target_env_vulkan,
351-
shaderc_env_version::shaderc_env_version_vulkan_1_1);
351+
shaderc_env_version::shaderc_env_version_vulkan_1_3);
352352
spirv_options.SetTargetSpirv(
353353
shaderc_spirv_version::shaderc_spirv_version_1_3);
354354
break;
@@ -357,9 +357,9 @@ Compiler::Compiler(const fml::Mapping& source_mapping,
357357
shaderc_optimization_level::shaderc_optimization_level_performance);
358358
spirv_options.SetTargetEnvironment(
359359
shaderc_target_env::shaderc_target_env_vulkan,
360-
shaderc_env_version::shaderc_env_version_vulkan_1_0);
360+
shaderc_env_version::shaderc_env_version_vulkan_1_3);
361361
spirv_options.SetTargetSpirv(
362-
shaderc_spirv_version::shaderc_spirv_version_1_0);
362+
shaderc_spirv_version::shaderc_spirv_version_1_3);
363363
break;
364364
case TargetPlatform::kRuntimeStageMetal:
365365
case TargetPlatform::kRuntimeStageGLES:
@@ -383,7 +383,7 @@ Compiler::Compiler(const fml::Mapping& source_mapping,
383383
shaderc_target_env::shaderc_target_env_opengl,
384384
shaderc_env_version::shaderc_env_version_opengl_4_5);
385385
spirv_options.SetTargetSpirv(
386-
shaderc_spirv_version::shaderc_spirv_version_1_0);
386+
shaderc_spirv_version::shaderc_spirv_version_1_3);
387387
spirv_options.AddMacroDefinition("SKIA_GRAPHICS_BACKEND");
388388
break;
389389
case TargetPlatform::kUnknown:
@@ -437,9 +437,10 @@ Compiler::Compiler(const fml::Mapping& source_mapping,
437437
<< ShaderCErrorToString(spv_result_->GetCompilationStatus())
438438
<< ". " << spv_result_->GetNumErrors() << " error(s) and "
439439
<< spv_result_->GetNumWarnings() << " warning(s).";
440-
if (spv_result_->GetNumErrors() > 0 || spv_result_->GetNumWarnings() > 0) {
441-
COMPILER_ERROR_NO_PREFIX << spv_result_->GetErrorMessage();
442-
}
440+
// if (spv_result_->GetNumErrors() > 0 || spv_result_->GetNumWarnings() > 0)
441+
// {
442+
COMPILER_ERROR_NO_PREFIX << spv_result_->GetErrorMessage();
443+
// }
443444
return;
444445
} else {
445446
included_file_names_ = std::move(included_file_names);

impeller/compiler/shader_lib/impeller/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ copy("impeller") {
1010
"constants.glsl",
1111
"gaussian.glsl",
1212
"gradient.glsl",
13+
"path.glsl",
1314
"texture.glsl",
1415
"transform.glsl",
1516
"types.glsl",
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#ifndef PATH_GLSL_
6+
#define PATH_GLSL_
7+
8+
#define MOVE 0
9+
#define LINE 1
10+
#define QUAD 2
11+
#define CUBIC 3
12+
13+
struct LineData {
14+
vec2 p1;
15+
vec2 p2;
16+
};
17+
18+
struct QuadData {
19+
vec2 p1;
20+
vec2 cp;
21+
vec2 p2;
22+
};
23+
24+
struct CubicData {
25+
vec2 p1;
26+
vec2 cp1;
27+
vec2 cp2;
28+
vec2 p2;
29+
};
30+
31+
struct Position {
32+
uint index;
33+
uint count;
34+
};
35+
36+
/// Solve for point on a quadratic Bezier curve defined by starting point `p1`,
37+
/// control point `cp`, and end point `p2` at time `t`.
38+
vec2 QuadraticSolve(QuadData quad, float t) {
39+
return (1.0 - t) * (1.0 - t) * quad.p1 + //
40+
2.0 * (1.0 - t) * t * quad.cp + //
41+
t * t * quad.p2;
42+
}
43+
44+
vec2 CubicSolve(CubicData cubic, float t) {
45+
return (1. - t) * (1. - t) * (1. - t) * cubic.p1 + //
46+
3 * (1. - t) * (1. - t) * t * cubic.cp1 + //
47+
3 * (1. - t) * t * t * cubic.cp2 + //
48+
t * t * t * cubic.p2;
49+
}
50+
51+
/// Used to approximate quadratic curves using parabola.
52+
///
53+
/// See
54+
/// https://raphlinus.github.io/graphics/curves/2019/12/23/flatten-quadbez.html
55+
float ApproximateParabolaIntegral(float x) {
56+
float d = 0.67;
57+
return x / (1.0 - d + sqrt(sqrt(pow(d, 4) + 0.25 * x * x)));
58+
}
59+
60+
bool isfinite(float f) {
61+
return !isnan(f) && !isinf(f);
62+
}
63+
64+
float Cross(vec2 p1, vec2 p2) {
65+
return p1.x * p2.y - p1.y * p2.x;
66+
}
67+
68+
#endif

impeller/fixtures/BUILD.gn

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ impeller_shaders("shader_fixtures") {
1818
"box_fade.vert",
1919
"colors.vert",
2020
"colors.frag",
21+
"cubic_to_quads.comp",
2122
"impeller.frag",
2223
"impeller.vert",
2324
"inactive_uniforms.frag",
@@ -26,19 +27,24 @@ impeller_shaders("shader_fixtures") {
2627
"instanced_draw.vert",
2728
"mipmaps.frag",
2829
"mipmaps.vert",
30+
"quad_polyline.comp",
2931
"sample.comp",
3032
"stage1.comp",
3133
"stage2.comp",
3234
"simple.vert",
35+
"stroke.comp",
3336
"test_texture.frag",
3437
"test_texture.vert",
3538
]
3639

3740
if (impeller_enable_opengles) {
3841
gles_exclusions = [
42+
"cubic_to_quads.comp",
43+
"quad_polyline.comp",
3944
"sample.comp",
4045
"stage1.comp",
4146
"stage2.comp",
47+
"stroke.comp",
4248
]
4349
}
4450
}
@@ -70,10 +76,12 @@ test_fixtures("file_fixtures") {
7076
"bay_bridge.jpg",
7177
"blue_noise.png",
7278
"boston.jpg",
79+
"cubic_to_quads.comp",
7380
"embarcadero.jpg",
7481
"flutter_logo_baked.glb",
7582
"kalimba.jpg",
7683
"multiple_stages.hlsl",
84+
"quad_polyline.comp",
7785
"resources_limit.vert",
7886
"sample.comp",
7987
"sample.frag",
@@ -85,6 +93,7 @@ test_fixtures("file_fixtures") {
8593
"sa%m#ple.vert",
8694
"stage1.comp",
8795
"stage2.comp",
96+
"stroke.comp",
8897
"struct_def_bug.vert",
8998
"table_mountain_nx.png",
9099
"table_mountain_ny.png",
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
#extension GL_KHR_shader_subgroup_arithmetic : enable
5+
6+
layout(local_size_x = 512, local_size_y = 1) in;
7+
layout(std430) buffer;
8+
9+
#include <impeller/path.glsl>
10+
11+
layout(binding = 0) readonly buffer Cubics {
12+
uint count;
13+
CubicData data[];
14+
}
15+
cubics;
16+
17+
layout(binding = 1) buffer Quads {
18+
uint count;
19+
QuadData data[];
20+
}
21+
quads;
22+
23+
uniform Config {
24+
float accuracy;
25+
}
26+
config;
27+
28+
shared uint quad_counts[512];
29+
shared uint count_sums[512];
30+
31+
void main() {
32+
uint ident = gl_GlobalInvocationID.x;
33+
if (ident >= cubics.count) {
34+
return;
35+
}
36+
37+
// The maximum error, as a vector from the cubic to the best approximating
38+
// quadratic, is proportional to the third derivative, which is constant
39+
// across the segment. Thus, the error scales down as the third power of
40+
// the number of subdivisions. Our strategy then is to subdivide `t` evenly.
41+
//
42+
// This is an overestimate of the error because only the component
43+
// perpendicular to the first derivative is important. But the simplicity is
44+
// appealing.
45+
46+
// This magic number is the square of 36 / sqrt(3).
47+
// See: http://caffeineowl.com/graphics/2d/vectorial/cubic2quad01.html
48+
float max_hypot2 = 432.0 * config.accuracy * config.accuracy;
49+
50+
CubicData cubic = cubics.data[ident];
51+
52+
vec2 err_v = 3.0 * (cubic.cp2 - cubic.cp1) + cubic.p1 - cubic.p2;
53+
float err = dot(err_v, err_v);
54+
float quad_count = max(1., ceil(pow(err * (1.0 / max_hypot2), 1. / 6.0)));
55+
56+
quad_counts[ident] = uint(quad_count);
57+
58+
barrier();
59+
count_sums[ident] = subgroupInclusiveAdd(quad_counts[ident]);
60+
61+
quads.count = count_sums[cubics.count - 1];
62+
for (uint i = 0; i < quad_count; i++) {
63+
float t0 = i / quad_count;
64+
float t1 = (i + 1) / quad_count;
65+
66+
// calculate the subsegment
67+
vec2 sub_p1 = CubicSolve(cubic, t0);
68+
vec2 sub_p2 = CubicSolve(cubic, t1);
69+
QuadData quad = QuadData(3.0 * (cubic.cp1 - cubic.p1), //
70+
3.0 * (cubic.cp2 - cubic.cp1), //
71+
3.0 * (cubic.p2 - cubic.cp2));
72+
float sub_scale = (t1 - t0) * (1.0 / 3.0);
73+
vec2 sub_cp1 = sub_p1 + sub_scale * QuadraticSolve(quad, t0);
74+
vec2 sub_cp2 = sub_p2 - sub_scale * QuadraticSolve(quad, t1);
75+
76+
vec2 quad_p1x2 = 3.0 * sub_cp1 - sub_p1;
77+
vec2 quad_p2x2 = 3.0 * sub_cp2 - sub_p2;
78+
uint offset = count_sums[ident] - uint(quad_count);
79+
quads.data[offset + i] = QuadData(sub_p1, //
80+
((quad_p1x2 + quad_p2x2) / 4.0), //
81+
sub_p2);
82+
}
83+
}

0 commit comments

Comments
 (0)