This repository was archived by the owner on Feb 25, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6k
[Impeller] Start stroke tessellation in compute #39543
Merged
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
d74489c
Test for stroke tesellation in compute
dnfield b03d0dc
Clean up WIP-ness: parameterize MSL version, fix commented code, move…
dnfield 0c99cda
Ignore metal_version on platforms that do not use it
dnfield 6e79986
..
dnfield 9ec14ce
format
dnfield 1aefa6b
Merge branch 'main' into polyline
dnfield 84aff5b
Plumb metal_version through for vulkan
dnfield 2930673
appease license bot, fix windows build?
dnfield 3543ea4
Merge branch 'main' into polyline
dnfield 0319bb8
try another for windows
dnfield 1328bb7
Make windows build
dnfield bedbe1e
missing character
dnfield a227092
Keep going
dnfield File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,7 +7,9 @@ | |
#include <array> | ||
#include <filesystem> | ||
#include <memory> | ||
#include <optional> | ||
#include <sstream> | ||
#include <string> | ||
#include <utility> | ||
|
||
#include "flutter/fml/paths.h" | ||
|
@@ -25,16 +27,36 @@ const uint32_t kFragBindingBase = 128; | |
const size_t kNumUniformKinds = | ||
static_cast<int>(shaderc_uniform_kind::shaderc_uniform_kind_buffer) + 1; | ||
|
||
static uint32_t ParseMSLVersion(const std::string& msl_version) { | ||
std::stringstream sstream(msl_version); | ||
std::string version_part; | ||
uint32_t major = 1; | ||
uint32_t minor = 2; | ||
uint32_t patch = 0; | ||
if (std::getline(sstream, version_part, '.')) { | ||
major = std::stoi(version_part); | ||
if (std::getline(sstream, version_part, '.')) { | ||
minor = std::stoi(version_part); | ||
if (std::getline(sstream, version_part, '.')) { | ||
patch = std::stoi(version_part); | ||
} | ||
} | ||
} | ||
if (major < 1 || minor < 2) { | ||
std::cerr << "--metal-version version must be at least 1.2. Have " | ||
<< msl_version << std::endl; | ||
} | ||
return spirv_cross::CompilerMSL::Options::make_msl_version(major, minor, | ||
patch); | ||
} | ||
|
||
static CompilerBackend CreateMSLCompiler(const spirv_cross::ParsedIR& ir, | ||
const SourceOptions& source_options) { | ||
auto sl_compiler = std::make_shared<spirv_cross::CompilerMSL>(ir); | ||
spirv_cross::CompilerMSL::Options sl_options; | ||
sl_options.platform = | ||
TargetPlatformToMSLPlatform(source_options.target_platform); | ||
// If this version specification changes, the GN rules that process the | ||
// Metal to AIR must be updated as well. | ||
sl_options.msl_version = | ||
spirv_cross::CompilerMSL::Options::make_msl_version(1, 2); | ||
sl_options.msl_version = ParseMSLVersion(source_options.metal_version); | ||
sl_options.use_framebuffer_fetch_subpasses = true; | ||
sl_compiler->set_msl_options(sl_options); | ||
|
||
|
@@ -357,9 +379,9 @@ Compiler::Compiler(const fml::Mapping& source_mapping, | |
shaderc_optimization_level::shaderc_optimization_level_performance); | ||
spirv_options.SetTargetEnvironment( | ||
shaderc_target_env::shaderc_target_env_vulkan, | ||
shaderc_env_version::shaderc_env_version_vulkan_1_0); | ||
shaderc_env_version::shaderc_env_version_vulkan_1_1); | ||
spirv_options.SetTargetSpirv( | ||
shaderc_spirv_version::shaderc_spirv_version_1_0); | ||
shaderc_spirv_version::shaderc_spirv_version_1_3); | ||
break; | ||
case TargetPlatform::kRuntimeStageMetal: | ||
case TargetPlatform::kRuntimeStageGLES: | ||
|
@@ -437,7 +459,11 @@ Compiler::Compiler(const fml::Mapping& source_mapping, | |
<< ShaderCErrorToString(spv_result_->GetCompilationStatus()) | ||
<< ". " << spv_result_->GetNumErrors() << " error(s) and " | ||
<< spv_result_->GetNumWarnings() << " warning(s)."; | ||
if (spv_result_->GetNumErrors() > 0 || spv_result_->GetNumWarnings() > 0) { | ||
// It should normally be enough to check that there are errors or warnings, | ||
// but some cases result in no errors or warnings and still have an error | ||
// message. If there's a message we should print it. | ||
if (spv_result_->GetNumErrors() > 0 || spv_result_->GetNumWarnings() > 0 || | ||
!spv_result_->GetErrorMessage().empty()) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the part that fixes flutter/flutter#120241 |
||
COMPILER_ERROR_NO_PREFIX << spv_result_->GetErrorMessage(); | ||
} | ||
return; | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
// 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. | ||
|
||
#ifndef PATH_GLSL_ | ||
#define PATH_GLSL_ | ||
|
||
#define MOVE 0 | ||
#define LINE 1 | ||
#define QUAD 2 | ||
#define CUBIC 3 | ||
|
||
struct LineData { | ||
vec2 p1; | ||
vec2 p2; | ||
}; | ||
|
||
struct QuadData { | ||
vec2 p1; | ||
vec2 cp; | ||
vec2 p2; | ||
}; | ||
|
||
struct CubicData { | ||
vec2 p1; | ||
vec2 cp1; | ||
vec2 cp2; | ||
vec2 p2; | ||
}; | ||
|
||
struct Position { | ||
uint index; | ||
uint count; | ||
}; | ||
|
||
/// Solve for point on a quadratic Bezier curve defined by starting point `p1`, | ||
/// control point `cp`, and end point `p2` at time `t`. | ||
vec2 QuadraticSolve(QuadData quad, float t) { | ||
return (1.0 - t) * (1.0 - t) * quad.p1 + // | ||
2.0 * (1.0 - t) * t * quad.cp + // | ||
t * t * quad.p2; | ||
} | ||
|
||
vec2 CubicSolve(CubicData cubic, float t) { | ||
return (1. - t) * (1. - t) * (1. - t) * cubic.p1 + // | ||
3 * (1. - t) * (1. - t) * t * cubic.cp1 + // | ||
3 * (1. - t) * t * t * cubic.cp2 + // | ||
t * t * t * cubic.p2; | ||
} | ||
|
||
/// Used to approximate quadratic curves using parabola. | ||
/// | ||
/// See | ||
/// https://raphlinus.github.io/graphics/curves/2019/12/23/flatten-quadbez.html | ||
float ApproximateParabolaIntegral(float x) { | ||
float d = 0.67; | ||
return x / (1.0 - d + sqrt(sqrt(pow(d, 4) + 0.25 * x * x))); | ||
} | ||
|
||
bool isfinite(float f) { | ||
return !isnan(f) && !isinf(f); | ||
} | ||
|
||
float Cross(vec2 p1, vec2 p2) { | ||
return p1.x * p2.y - p1.y * p2.x; | ||
} | ||
|
||
#endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
// 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. | ||
#extension GL_KHR_shader_subgroup_arithmetic : enable | ||
|
||
layout(local_size_x = 512, local_size_y = 1) in; | ||
layout(std430) buffer; | ||
|
||
#include <impeller/path.glsl> | ||
|
||
layout(binding = 0) readonly buffer Cubics { | ||
uint count; | ||
CubicData data[]; | ||
} | ||
cubics; | ||
|
||
layout(binding = 1) buffer Quads { | ||
uint count; | ||
QuadData data[]; | ||
} | ||
quads; | ||
|
||
uniform Config { | ||
float accuracy; | ||
} | ||
config; | ||
|
||
shared uint quad_counts[512]; | ||
shared uint count_sums[512]; | ||
|
||
void main() { | ||
uint ident = gl_GlobalInvocationID.x; | ||
if (ident >= cubics.count) { | ||
return; | ||
} | ||
|
||
// The maximum error, as a vector from the cubic to the best approximating | ||
// quadratic, is proportional to the third derivative, which is constant | ||
// across the segment. Thus, the error scales down as the third power of | ||
// the number of subdivisions. Our strategy then is to subdivide `t` evenly. | ||
// | ||
// This is an overestimate of the error because only the component | ||
// perpendicular to the first derivative is important. But the simplicity is | ||
// appealing. | ||
|
||
// This magic number is the square of 36 / sqrt(3). | ||
// See: http://caffeineowl.com/graphics/2d/vectorial/cubic2quad01.html | ||
float max_hypot2 = 432.0 * config.accuracy * config.accuracy; | ||
|
||
CubicData cubic = cubics.data[ident]; | ||
|
||
vec2 err_v = 3.0 * (cubic.cp2 - cubic.cp1) + cubic.p1 - cubic.p2; | ||
float err = dot(err_v, err_v); | ||
float quad_count = max(1., ceil(pow(err * (1.0 / max_hypot2), 1. / 6.0))); | ||
|
||
quad_counts[ident] = uint(quad_count); | ||
|
||
barrier(); | ||
count_sums[ident] = subgroupInclusiveAdd(quad_counts[ident]); | ||
|
||
quads.count = count_sums[cubics.count - 1]; | ||
for (uint i = 0; i < quad_count; i++) { | ||
float t0 = i / quad_count; | ||
float t1 = (i + 1) / quad_count; | ||
|
||
// calculate the subsegment | ||
vec2 sub_p1 = CubicSolve(cubic, t0); | ||
vec2 sub_p2 = CubicSolve(cubic, t1); | ||
QuadData quad = QuadData(3.0 * (cubic.cp1 - cubic.p1), // | ||
3.0 * (cubic.cp2 - cubic.cp1), // | ||
3.0 * (cubic.p2 - cubic.cp2)); | ||
float sub_scale = (t1 - t0) * (1.0 / 3.0); | ||
vec2 sub_cp1 = sub_p1 + sub_scale * QuadraticSolve(quad, t0); | ||
vec2 sub_cp2 = sub_p2 - sub_scale * QuadraticSolve(quad, t1); | ||
|
||
vec2 quad_p1x2 = 3.0 * sub_cp1 - sub_p1; | ||
vec2 quad_p2x2 = 3.0 * sub_cp2 - sub_p2; | ||
uint offset = count_sums[ident] - uint(quad_count); | ||
quads.data[offset + i] = QuadData(sub_p1, // | ||
((quad_p1x2 + quad_p2x2) / 4.0), // | ||
sub_p2); | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@chinmaygarde or @iskakaushik - is this ok?
I'm not sure why we'd be targetting Vulkan 1.0 here but Vulkan 1.1 above.
I'm also not sure I understand the implications of using SPIR-V version 1.0 here. I need 1.3 for subgroups. I think it's probably ok but don't know where to look it up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it's not ok all the time, I can parameterize this the way I did with the MSL version above.