diff options
author | 2017-11-15 18:27:09 -0700 | |
---|---|---|
committer | 2017-11-16 19:29:56 +0000 | |
commit | 47c8ed3c064f5176750f370b88119735163c0e8a (patch) | |
tree | 576fa3f0d64463f1d5c3b3b5e4872438c70688fc /src/gpu/effects | |
parent | 3bc00fe8100948e99deb3dea3f833fd026d39bd5 (diff) |
Reland "Fix precision caps and rrect/ellipse effect precisions"
This is a reland of e42180022720f2fcfd3c634cad855506a7940591
Original change's description:
> Fix precision caps and rrect/ellipse effect precisions
>
> Replaces all the complex precision caps with a single flag that says
> whether "float" == fp32. Updates the ellipse and rrect effects to
> use float coords, and use the scale workaround when float != fp32.
>
> Bug: skia:7190
> Change-Id: Ieccff9f38acd05e5cec78fe90d01a5da901a9307
> Reviewed-on: https://skia-review.googlesource.com/70961
> Commit-Queue: Chris Dalton <csmartdalton@google.com>
> Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
> Reviewed-by: Brian Salomon <bsalomon@google.com>
TBR=bsalomon@google.com
Bug: skia:7190
Change-Id: I7ced37a64164b83d86f6a957c35e10ce9085aba0
Reviewed-on: https://skia-review.googlesource.com/72760
Reviewed-by: Chris Dalton <csmartdalton@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Diffstat (limited to 'src/gpu/effects')
-rw-r--r-- | src/gpu/effects/GrEllipseEffect.cpp | 33 | ||||
-rw-r--r-- | src/gpu/effects/GrEllipseEffect.fp | 26 | ||||
-rw-r--r-- | src/gpu/effects/GrRRectEffect.cpp | 68 |
3 files changed, 63 insertions, 64 deletions
diff --git a/src/gpu/effects/GrEllipseEffect.cpp b/src/gpu/effects/GrEllipseEffect.cpp index 4a0f37665c..6b1a8cc59f 100644 --- a/src/gpu/effects/GrEllipseEffect.cpp +++ b/src/gpu/effects/GrEllipseEffect.cpp @@ -28,34 +28,33 @@ public: (void)center; auto radii = _outer.radii(); (void)radii; - prevRadii = half2(-1.0); - useScale = sk_Caps.floatPrecisionVaries; + prevRadii = float2(-1.0); + useScale = !sk_Caps.floatIs32Bits; fEllipseVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kFloat4_GrSLType, kDefault_GrSLPrecision, "ellipse"); if (useScale) { - fScaleVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType, + fScaleVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kFloat2_GrSLType, kDefault_GrSLPrecision, "scale"); } fragBuilder->codeAppendf( - "half2 prevCenter;\nhalf2 prevRadii = half2(%f, %f);\nbool useScale = %s;\nhalf2 d " - "= half2(sk_FragCoord.xy - %s.xy);\n@if (useScale) {\n d *= %s.y;\n}\nhalf2 Z = " - "d * half2(%s.zw);\nhalf implicit = dot(Z, d) - 1.0;\nhalf grad_dot = 4.0 * dot(Z, " - "Z);\ngrad_dot = half(max(float(grad_dot), 0.0001));\nhalf approx_dist = " - "float(implicit) * inversesqrt(float(grad_dot));\n@if (useScale) {\n " - "approx_dist *= %s.x;\n}\nhalf alpha;\n@switch (%d) {\n case 0:\n alpha " - "= half(float(approx_dist) > 0.0 ? 0.0 : 1.", + "float2 prevCenter;\nfloat2 prevRadii = float2(%f, %f);\nbool useScale = " + "%s;\nfloat2 d = sk_FragCoord.xy - %s.xy;\n@if (useScale) {\n d *= " + "%s.y;\n}\nfloat2 Z = d * %s.zw;\nfloat implicit = dot(Z, d) - 1.0;\nfloat " + "grad_dot = 4.0 * dot(Z, Z);\ngrad_dot = max(grad_dot, 0.0001);\nfloat approx_dist " + "= implicit * inversesqrt(grad_dot);\n@if (useScale) {\n approx_dist *= " + "%s.x;\n}\nhalf alpha;\n@switch (%d) {\n case 0:\n alpha = " + "half(approx_dist > 0.0 ? 0.0 : 1.0);\n break;\n case 1:\n ", prevRadii.fX, prevRadii.fY, (useScale ? "true" : "false"), args.fUniformHandler->getUniformCStr(fEllipseVar), - fScaleVar.isValid() ? args.fUniformHandler->getUniformCStr(fScaleVar) : "half2(0)", + fScaleVar.isValid() ? args.fUniformHandler->getUniformCStr(fScaleVar) : "float2(0)", args.fUniformHandler->getUniformCStr(fEllipseVar), - fScaleVar.isValid() ? args.fUniformHandler->getUniformCStr(fScaleVar) : "half2(0)", + fScaleVar.isValid() ? args.fUniformHandler->getUniformCStr(fScaleVar) : "float2(0)", (int)_outer.edgeType()); fragBuilder->codeAppendf( - "0);\n break;\n case 1:\n alpha = half(clamp(0.5 - " - "float(approx_dist), 0.0, 1.0));\n break;\n case 2:\n alpha = " - "half(float(approx_dist) > 0.0 ? 1.0 : 0.0);\n break;\n case 3:\n " - "alpha = half(clamp(0.5 + float(approx_dist), 0.0, 1.0));\n break;\n " - "default:\n discard;\n}\n%s = %s * alpha;\n", + " alpha = half(clamp(0.5 - approx_dist, 0.0, 1.0));\n break;\n case " + "2:\n alpha = half(approx_dist > 0.0 ? 1.0 : 0.0);\n break;\n " + "case 3:\n alpha = half(clamp(0.5 + approx_dist, 0.0, 1.0));\n " + "break;\n default:\n discard;\n}\n%s = %s * alpha;\n", args.fOutputColor, args.fInputColor ? args.fInputColor : "half4(1)"); } diff --git a/src/gpu/effects/GrEllipseEffect.fp b/src/gpu/effects/GrEllipseEffect.fp index 54641b72c6..27beb85d2f 100644 --- a/src/gpu/effects/GrEllipseEffect.fp +++ b/src/gpu/effects/GrEllipseEffect.fp @@ -6,17 +6,17 @@ */ layout(key) in GrClipEdgeType edgeType; -in half2 center; -in half2 radii; +in float2 center; +in float2 radii; -half2 prevCenter; -half2 prevRadii = half2(-1); +float2 prevCenter; +float2 prevRadii = float2(-1); // The ellipse uniform is (center.x, center.y, 1 / rx^2, 1 / ry^2) -// The last two terms can underflow with halfs, so we use floats. +// The last two terms can underflow when float != fp32, so we also provide a workaround. uniform float4 ellipse; -bool useScale = sk_Caps.floatPrecisionVaries; -layout(when=useScale) uniform half2 scale; +bool useScale = !sk_Caps.floatIs32Bits; +layout(when=useScale) uniform float2 scale; @optimizationFlags { kCompatibleWithCoverageAsAlpha_OptimizationFlag } @@ -50,7 +50,7 @@ layout(when=useScale) uniform half2 scale; void main() { // d is the offset to the ellipse center - half2 d = sk_FragCoord.xy - ellipse.xy; + float2 d = sk_FragCoord.xy - ellipse.xy; // If we're on a device with a "real" mediump then we'll do the distance computation in a space // that is normalized by the larger radius. The scale uniform will be scale, 1/scale. The // inverse squared radii uniform values are already in this normalized space. The center is @@ -58,14 +58,14 @@ void main() { @if (useScale) { d *= scale.y; } - half2 Z = d * ellipse.zw; + float2 Z = d * ellipse.zw; // implicit is the evaluation of (x/rx)^2 + (y/ry)^2 - 1. - half implicit = dot(Z, d) - 1; + float implicit = dot(Z, d) - 1; // grad_dot is the squared length of the gradient of the implicit. - half grad_dot = 4 * dot(Z, Z); + float grad_dot = 4 * dot(Z, Z); // Avoid calling inversesqrt on zero. grad_dot = max(grad_dot, 1e-4); - half approx_dist = implicit * inversesqrt(grad_dot); + float approx_dist = implicit * inversesqrt(grad_dot); @if (useScale) { approx_dist *= scale.x; } @@ -102,4 +102,4 @@ void main() { et = (GrClipEdgeType) testData->fRandom->nextULessThan(kGrClipEdgeTypeCnt); } while (GrClipEdgeType::kHairlineAA == et); return GrEllipseEffect::Make(et, center, SkPoint::Make(rx, ry)); -}
\ No newline at end of file +} diff --git a/src/gpu/effects/GrRRectEffect.cpp b/src/gpu/effects/GrRRectEffect.cpp index 4b56443b0d..510a26b425 100644 --- a/src/gpu/effects/GrRRectEffect.cpp +++ b/src/gpu/effects/GrRRectEffect.cpp @@ -165,9 +165,9 @@ void GLCircularRRectEffect::emitCode(EmitArgs& args) { fRadiusPlusHalfUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType, "radiusPlusHalf", &radiusPlusHalfName); - // If we're on a device with a "real" mediump then the length calculation could overflow. + // If we're on a device where float != fp32 then the length calculation could overflow. SkString clampedCircleDistance; - if (args.fShaderCaps->floatPrecisionVaries()) { + if (!args.fShaderCaps->floatIs32Bits()) { clampedCircleDistance.printf("clamp(%s.x * (1.0 - length(dxy * %s.y)), 0.0, 1.0);", radiusPlusHalfName, radiusPlusHalfName); } else { @@ -192,13 +192,13 @@ void GLCircularRRectEffect::emitCode(EmitArgs& args) { // alphas together. switch (crre.getCircularCornerFlags()) { case CircularRRectEffect::kAll_CornerFlags: - fragBuilder->codeAppendf("half2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName); - fragBuilder->codeAppendf("half2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName); - fragBuilder->codeAppend("half2 dxy = max(max(dxy0, dxy1), 0.0);"); + fragBuilder->codeAppendf("float2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName); + fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName); + fragBuilder->codeAppend("float2 dxy = max(max(dxy0, dxy1), 0.0);"); fragBuilder->codeAppendf("half alpha = %s;", clampedCircleDistance.c_str()); break; case CircularRRectEffect::kTopLeft_CornerFlag: - fragBuilder->codeAppendf("half2 dxy = max(%s.xy - sk_FragCoord.xy, 0.0);", + fragBuilder->codeAppendf("float2 dxy = max(%s.xy - sk_FragCoord.xy, 0.0);", rectName); fragBuilder->codeAppendf("half rightAlpha = clamp(%s.z - sk_FragCoord.x, 0.0, 1.0);", rectName); @@ -208,8 +208,8 @@ void GLCircularRRectEffect::emitCode(EmitArgs& args) { clampedCircleDistance.c_str()); break; case CircularRRectEffect::kTopRight_CornerFlag: - fragBuilder->codeAppendf("half2 dxy = max(half2(sk_FragCoord.x - %s.z, " - "%s.y - sk_FragCoord.y), 0.0);", + fragBuilder->codeAppendf("float2 dxy = max(float2(sk_FragCoord.x - %s.z, " + "%s.y - sk_FragCoord.y), 0.0);", rectName, rectName); fragBuilder->codeAppendf("half leftAlpha = clamp(sk_FragCoord.x - %s.x, 0.0, 1.0);", rectName); @@ -219,7 +219,7 @@ void GLCircularRRectEffect::emitCode(EmitArgs& args) { clampedCircleDistance.c_str()); break; case CircularRRectEffect::kBottomRight_CornerFlag: - fragBuilder->codeAppendf("half2 dxy = max(sk_FragCoord.xy - %s.zw, 0.0);", + fragBuilder->codeAppendf("float2 dxy = max(sk_FragCoord.xy - %s.zw, 0.0);", rectName); fragBuilder->codeAppendf("half leftAlpha = clamp(sk_FragCoord.x - %s.x, 0.0, 1.0);", rectName); @@ -229,8 +229,8 @@ void GLCircularRRectEffect::emitCode(EmitArgs& args) { clampedCircleDistance.c_str()); break; case CircularRRectEffect::kBottomLeft_CornerFlag: - fragBuilder->codeAppendf("half2 dxy = max(half2(%s.x - sk_FragCoord.x, sk_FragCoord.y - " - "%s.w), 0.0);", + fragBuilder->codeAppendf("float2 dxy = max(float2(%s.x - sk_FragCoord.x, " + "sk_FragCoord.y - %s.w), 0.0);", rectName, rectName); fragBuilder->codeAppendf("half rightAlpha = clamp(%s.z - sk_FragCoord.x, 0.0, 1.0);", rectName); @@ -240,36 +240,36 @@ void GLCircularRRectEffect::emitCode(EmitArgs& args) { clampedCircleDistance.c_str()); break; case CircularRRectEffect::kLeft_CornerFlags: - fragBuilder->codeAppendf("half2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName); - fragBuilder->codeAppendf("half dy1 = sk_FragCoord.y - %s.w;", rectName); - fragBuilder->codeAppend("half2 dxy = max(half2(dxy0.x, max(dxy0.y, dy1)), 0.0);"); + fragBuilder->codeAppendf("float2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName); + fragBuilder->codeAppendf("float dy1 = sk_FragCoord.y - %s.w;", rectName); + fragBuilder->codeAppend("float2 dxy = max(float2(dxy0.x, max(dxy0.y, dy1)), 0.0);"); fragBuilder->codeAppendf("half rightAlpha = clamp(%s.z - sk_FragCoord.x, 0.0, 1.0);", rectName); fragBuilder->codeAppendf("half alpha = rightAlpha * %s;", clampedCircleDistance.c_str()); break; case CircularRRectEffect::kTop_CornerFlags: - fragBuilder->codeAppendf("half2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName); - fragBuilder->codeAppendf("half dx1 = sk_FragCoord.x - %s.z;", rectName); - fragBuilder->codeAppend("half2 dxy = max(half2(max(dxy0.x, dx1), dxy0.y), 0.0);"); + fragBuilder->codeAppendf("float2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName); + fragBuilder->codeAppendf("float dx1 = sk_FragCoord.x - %s.z;", rectName); + fragBuilder->codeAppend("float2 dxy = max(float2(max(dxy0.x, dx1), dxy0.y), 0.0);"); fragBuilder->codeAppendf("half bottomAlpha = clamp(%s.w - sk_FragCoord.y, 0.0, 1.0);", rectName); fragBuilder->codeAppendf("half alpha = bottomAlpha * %s;", clampedCircleDistance.c_str()); break; case CircularRRectEffect::kRight_CornerFlags: - fragBuilder->codeAppendf("half dy0 = %s.y - sk_FragCoord.y;", rectName); - fragBuilder->codeAppendf("half2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName); - fragBuilder->codeAppend("half2 dxy = max(half2(dxy1.x, max(dy0, dxy1.y)), 0.0);"); + fragBuilder->codeAppendf("float dy0 = %s.y - sk_FragCoord.y;", rectName); + fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName); + fragBuilder->codeAppend("float2 dxy = max(float2(dxy1.x, max(dy0, dxy1.y)), 0.0);"); fragBuilder->codeAppendf("half leftAlpha = clamp(sk_FragCoord.x - %s.x, 0.0, 1.0);", rectName); fragBuilder->codeAppendf("half alpha = leftAlpha * %s;", clampedCircleDistance.c_str()); break; case CircularRRectEffect::kBottom_CornerFlags: - fragBuilder->codeAppendf("half dx0 = %s.x - sk_FragCoord.x;", rectName); - fragBuilder->codeAppendf("half2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName); - fragBuilder->codeAppend("half2 dxy = max(half2(max(dx0, dxy1.x), dxy1.y), 0.0);"); + fragBuilder->codeAppendf("float dx0 = %s.x - sk_FragCoord.x;", rectName); + fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName); + fragBuilder->codeAppend("float2 dxy = max(float2(max(dx0, dxy1.x), dxy1.y), 0.0);"); fragBuilder->codeAppendf("half topAlpha = clamp(sk_FragCoord.y - %s.y, 0.0, 1.0);", rectName); fragBuilder->codeAppendf("half alpha = topAlpha * %s;", @@ -523,14 +523,14 @@ void GLEllipticalRRectEffect::emitCode(EmitArgs& args) { // The code below is a simplified version of the above that performs maxs on the vector // components before computing distances and alpha values so that only one distance computation // need be computed to determine the min alpha. - fragBuilder->codeAppendf("half2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName); - fragBuilder->codeAppendf("half2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName); + fragBuilder->codeAppendf("float2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName); + fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName); - // If we're on a device with a "real" mediump then we'll do the distance computation in a space + // If we're on a device where float != fp32 then we'll do the distance computation in a space // that is normalized by the largest radius. The scale uniform will be scale, 1/scale. The // radii uniform values are already in this normalized space. const char* scaleName = nullptr; - if (args.fShaderCaps->floatPrecisionVaries()) { + if (!args.fShaderCaps->floatIs32Bits()) { fScaleUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType, "scale", &scaleName); } @@ -543,12 +543,12 @@ void GLEllipticalRRectEffect::emitCode(EmitArgs& args) { kHalf2_GrSLType, "invRadiiXY", &invRadiiXYSqdName); - fragBuilder->codeAppend("half2 dxy = max(max(dxy0, dxy1), 0.0);"); + fragBuilder->codeAppend("float2 dxy = max(max(dxy0, dxy1), 0.0);"); if (scaleName) { fragBuilder->codeAppendf("dxy *= %s.y;", scaleName); } // Z is the x/y offsets divided by squared radii. - fragBuilder->codeAppendf("half2 Z = dxy * %s.xy;", invRadiiXYSqdName); + fragBuilder->codeAppendf("float2 Z = dxy * %s.xy;", invRadiiXYSqdName); break; } case SkRRect::kNinePatch_Type: { @@ -561,11 +561,11 @@ void GLEllipticalRRectEffect::emitCode(EmitArgs& args) { fragBuilder->codeAppendf("dxy0 *= %s.y;", scaleName); fragBuilder->codeAppendf("dxy1 *= %s.y;", scaleName); } - fragBuilder->codeAppend("half2 dxy = max(max(dxy0, dxy1), 0.0);"); + fragBuilder->codeAppend("float2 dxy = max(max(dxy0, dxy1), 0.0);"); // Z is the x/y offsets divided by squared radii. We only care about the (at most) one // corner where both the x and y offsets are positive, hence the maxes. (The inverse // squared radii will always be positive.) - fragBuilder->codeAppendf("half2 Z = max(max(dxy0 * %s.xy, dxy1 * %s.zw), 0.0);", + fragBuilder->codeAppendf("float2 Z = max(max(dxy0 * %s.xy, dxy1 * %s.zw), 0.0);", invRadiiLTRBSqdName, invRadiiLTRBSqdName); break; @@ -574,12 +574,12 @@ void GLEllipticalRRectEffect::emitCode(EmitArgs& args) { SK_ABORT("RRect should always be simple or nine-patch."); } // implicit is the evaluation of (x/a)^2 + (y/b)^2 - 1. - fragBuilder->codeAppend("half implicit = dot(Z, dxy) - 1.0;"); + fragBuilder->codeAppend("float implicit = dot(Z, dxy) - 1.0;"); // grad_dot is the squared length of the gradient of the implicit. - fragBuilder->codeAppend("half grad_dot = 4.0 * dot(Z, Z);"); + fragBuilder->codeAppend("float grad_dot = 4.0 * dot(Z, Z);"); // avoid calling inversesqrt on zero. fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);"); - fragBuilder->codeAppend("half approx_dist = implicit * inversesqrt(grad_dot);"); + fragBuilder->codeAppend("float approx_dist = implicit * inversesqrt(grad_dot);"); if (scaleName) { fragBuilder->codeAppendf("approx_dist *= %s.x;", scaleName); } |