Migrate as_sksl out of skgpu::wangs_formula.

This is only referenced by tessellation code now, so it's been moved to
GrTessellationShader.cpp. (In the near future, we may remove this code
entirely, since it is not very impactful for performance.)

Change-Id: Id0f176220efb3eeed63e08c2c1faa48df07cd124
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/533676
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
This commit is contained in:
John Stiles 2022-04-25 13:42:34 -04:00 committed by SkCQ
parent 3f8fc145ba
commit 4f33f5bef8
8 changed files with 67 additions and 64 deletions

View File

@ -119,5 +119,8 @@ generated_cc_atom(
name = "GrTessellationShader_src",
srcs = ["GrTessellationShader.cpp"],
visibility = ["//:__subpackages__"],
deps = [":GrTessellationShader_hdr"],
deps = [
":GrTessellationShader_hdr",
"//src/gpu/tessellate:WangsFormula_hdr",
],
)

View File

@ -77,7 +77,7 @@ std::unique_ptr<GrGeometryProcessor::ProgramImpl> HardwareWedgeShader::makeProgr
code.appendf(R"(
#define PRECISION %f)", skgpu::kTessellationPrecision);
code.append(kSkSLTypeDefs);
code.append(skgpu::wangs_formula::as_sksl());
code.append(GrTessellationShader::WangsFormulaSkSL());
code.append(R"(
layout(vertices = 1) out;
@ -221,7 +221,7 @@ std::unique_ptr<GrGeometryProcessor::ProgramImpl> HardwareCurveShader::makeProgr
code.appendf(R"(
#define PRECISION %f)", skgpu::kTessellationPrecision);
code.append(kSkSLTypeDefs);
code.append(skgpu::wangs_formula::as_sksl());
code.append(GrTessellationShader::WangsFormulaSkSL());
code.append(R"(
layout(vertices = 1) out;

View File

@ -101,7 +101,7 @@ std::unique_ptr<GrGeometryProcessor::ProgramImpl> MiddleOutShader::makeProgramIm
(float)skgpu::kMaxFixedResolveLevel);
v->defineConstant("MAX_FIXED_SEGMENTS",
(float)(skgpu::kMaxParametricSegments));
v->insertFunction(skgpu::wangs_formula::as_sksl().c_str());
v->insertFunction(GrTessellationShader::WangsFormulaSkSL());
if (middleOutShader.fAttribs & PatchAttribs::kExplicitCurveType) {
v->insertFunction(SkStringPrintf(R"(
bool is_conic_curve() {

View File

@ -350,7 +350,7 @@ SkString GrStrokeTessellationShader::HardwareImpl::getTessControlShaderGLSL(
code.appendf("#define NUM_RADIAL_SEGMENTS_PER_RADIAN vsStrokeArgs[0].x\n");
}
code.append(skgpu::wangs_formula::as_sksl());
code.append(GrTessellationShader::WangsFormulaSkSL());
code.append(kCosineBetweenVectorsFn);
code.append(kMiterExtentFn);
code.append(R"(

View File

@ -29,7 +29,7 @@ void GrStrokeTessellationShader::InstancedImpl::onEmitCode(EmitArgs& args, GrGPA
args.fVertBuilder->insertFunction(kCosineBetweenVectorsFn);
args.fVertBuilder->insertFunction(kMiterExtentFn);
args.fVertBuilder->insertFunction(kUncheckedMixFn);
args.fVertBuilder->insertFunction(skgpu::wangs_formula::as_sksl().c_str());
args.fVertBuilder->insertFunction(GrTessellationShader::WangsFormulaSkSL());
// Tessellation control uniforms and/or dynamic attributes.
if (!shader.hasDynamicStroke()) {

View File

@ -6,6 +6,7 @@
*/
#include "src/gpu/ganesh/tessellate/shaders/GrTessellationShader.h"
#include "src/gpu/tessellate/WangsFormula.h"
const GrPipeline* GrTessellationShader::MakePipeline(const ProgramArgs& args,
GrAAType aaType,
@ -21,3 +22,57 @@ const GrPipeline* GrTessellationShader::MakePipeline(const ProgramArgs& args,
std::move(processors),
std::move(appliedClip));
}
const char* GrTessellationShader::WangsFormulaSkSL() {
static_assert(skgpu::wangs_formula::length_term<3>(1) == 0.75);
static_assert(skgpu::wangs_formula::length_term_pow2<3>(1) == 0.5625);
return R"(
// Returns the length squared of the largest forward difference from Wang's cubic formula.
float wangs_formula_max_fdiff_pow2(float2 p0, float2 p1, float2 p2, float2 p3,
float2x2 matrix) {
float2 d0 = matrix * (fma(float2(-2), p1, p2) + p0);
float2 d1 = matrix * (fma(float2(-2), p2, p3) + p1);
return max(dot(d0,d0), dot(d1,d1));
}
float wangs_formula_cubic(float _precision_, float2 p0, float2 p1, float2 p2, float2 p3,
float2x2 matrix) {
float m = wangs_formula_max_fdiff_pow2(p0, p1, p2, p3, matrix);
return max(ceil(sqrt(0.75 * _precision_ * sqrt(m))), 1.0);
}
float wangs_formula_cubic_log2(float _precision_, float2 p0, float2 p1, float2 p2, float2 p3,
float2x2 matrix) {
float m = wangs_formula_max_fdiff_pow2(p0, p1, p2, p3, matrix);
return ceil(log2(max(0.5625 * _precision_ * _precision_ * m, 1.0)) * .25);
}
float wangs_formula_conic_pow2(float _precision_, float2 p0, float2 p1, float2 p2, float w) {
// Translate the bounding box center to the origin.
float2 C = (min(min(p0, p1), p2) + max(max(p0, p1), p2)) * 0.5;
p0 -= C;
p1 -= C;
p2 -= C;
// Compute max length.
float m = sqrt(max(max(dot(p0,p0), dot(p1,p1)), dot(p2,p2)));
// Compute forward differences.
float2 dp = fma(float2(-2.0 * w), p1, p0) + p2;
float dw = abs(fma(-2.0, w, 2.0));
// Compute numerator and denominator for parametric step size of linearization. Here, the
// epsilon referenced from the cited paper is 1/precision.
float rp_minus_1 = max(0.0, fma(m, _precision_, -1.0));
float numer = length(dp) * _precision_ + rp_minus_1 * dw;
float denom = 4 * min(w, 1.0);
return numer/denom;
}
float wangs_formula_conic(float _precision_, float2 p0, float2 p1, float2 p2, float w) {
float n2 = wangs_formula_conic_pow2(_precision_, p0, p1, p2, w);
return max(ceil(sqrt(n2)), 1.0);
}
float wangs_formula_conic_log2(float _precision_, float2 p0, float2 p1, float2 p2, float w) {
float n2 = wangs_formula_conic_pow2(_precision_, p0, p1, p2, w);
return ceil(log2(max(n2, 1.0)) * .5);
})";
}

View File

@ -70,6 +70,9 @@ public:
args.fXferBarrierFlags, args.fColorLoadOp);
}
// SkSL functions that calculate Wang's formula for cubics or conics.
static const char* WangsFormulaSkSL();
private:
const GrPrimitiveType fPrimitiveType;
const int fTessellationPatchVertexCount;

View File

@ -281,64 +281,6 @@ AI int conic_log2(float tolerance,
return nextlog4(conic_pow2(tolerance, pts, w, vectorXform));
}
// Emits an SKSL function that calculates Wang's formula for the given set of 4 points. The points
// represent a cubic if w < 0, or if w >= 0, a conic defined by the first 3 points.
SK_MAYBE_UNUSED inline static SkString as_sksl() {
SkString code;
code.appendf(R"(
// Returns the length squared of the largest forward difference from Wang's cubic formula.
float wangs_formula_max_fdiff_pow2(float2 p0, float2 p1, float2 p2, float2 p3,
float2x2 matrix) {
float2 d0 = matrix * (fma(float2(-2), p1, p2) + p0);
float2 d1 = matrix * (fma(float2(-2), p2, p3) + p1);
return max(dot(d0,d0), dot(d1,d1));
}
float wangs_formula_cubic(float _precision_, float2 p0, float2 p1, float2 p2, float2 p3,
float2x2 matrix) {
float m = wangs_formula_max_fdiff_pow2(p0, p1, p2, p3, matrix);
return max(ceil(sqrt(%f * _precision_ * sqrt(m))), 1.0);
}
float wangs_formula_cubic_log2(float _precision_, float2 p0, float2 p1, float2 p2, float2 p3,
float2x2 matrix) {
float m = wangs_formula_max_fdiff_pow2(p0, p1, p2, p3, matrix);
return ceil(log2(max(%f * _precision_ * _precision_ * m, 1.0)) * .25);
})", length_term<3>(1), length_term_pow2<3>(1));
code.appendf(R"(
float wangs_formula_conic_pow2(float _precision_, float2 p0, float2 p1, float2 p2, float w) {
// Translate the bounding box center to the origin.
float2 C = (min(min(p0, p1), p2) + max(max(p0, p1), p2)) * 0.5;
p0 -= C;
p1 -= C;
p2 -= C;
// Compute max length.
float m = sqrt(max(max(dot(p0,p0), dot(p1,p1)), dot(p2,p2)));
// Compute forward differences.
float2 dp = fma(float2(-2.0 * w), p1, p0) + p2;
float dw = abs(fma(-2.0, w, 2.0));
// Compute numerator and denominator for parametric step size of linearization. Here, the
// epsilon referenced from the cited paper is 1/precision.
float rp_minus_1 = max(0.0, fma(m, _precision_, -1.0));
float numer = length(dp) * _precision_ + rp_minus_1 * dw;
float denom = 4 * min(w, 1.0);
return numer/denom;
}
float wangs_formula_conic(float _precision_, float2 p0, float2 p1, float2 p2, float w) {
float n2 = wangs_formula_conic_pow2(_precision_, p0, p1, p2, w);
return max(ceil(sqrt(n2)), 1.0);
}
float wangs_formula_conic_log2(float _precision_, float2 p0, float2 p1, float2 p2, float w) {
float n2 = wangs_formula_conic_pow2(_precision_, p0, p1, p2, w);
return ceil(log2(max(n2, 1.0)) * .5);
})");
return code;
}
} // namespace skgpu::wangs_formula
#undef AI