aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu
diff options
context:
space:
mode:
authorGravatar Chris Dalton <csmartdalton@google.com>2017-11-15 18:27:09 -0700
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-11-16 03:31:45 +0000
commite42180022720f2fcfd3c634cad855506a7940591 (patch)
tree76fb7187cd7dd509da717a221b3c309f9b703d3b /src/gpu
parentae9d6189ec03c4a188e67b42d755c42024397f44 (diff)
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>
Diffstat (limited to 'src/gpu')
-rw-r--r--src/gpu/GrProgramDesc.cpp2
-rw-r--r--src/gpu/GrShaderCaps.cpp104
-rw-r--r--src/gpu/effects/GrEllipseEffect.cpp33
-rw-r--r--src/gpu/effects/GrEllipseEffect.fp26
-rw-r--r--src/gpu/effects/GrRRectEffect.cpp68
-rw-r--r--src/gpu/gl/GrGLCaps.cpp115
-rw-r--r--src/gpu/gl/GrGLCaps.h4
-rw-r--r--src/gpu/glsl/GrGLSLProgramBuilder.cpp4
-rw-r--r--src/gpu/mtl/GrMtlCaps.mm17
-rw-r--r--src/gpu/vk/GrVkCaps.cpp15
10 files changed, 101 insertions, 287 deletions
diff --git a/src/gpu/GrProgramDesc.cpp b/src/gpu/GrProgramDesc.cpp
index a32e0cc28b..9c0add66e6 100644
--- a/src/gpu/GrProgramDesc.cpp
+++ b/src/gpu/GrProgramDesc.cpp
@@ -52,7 +52,7 @@ static uint16_t sampler_key(GrSLType samplerType, GrPixelConfig config, GrShader
GR_STATIC_ASSERT(1 == sizeof(caps.configTextureSwizzle(config).asKey()));
return SkToU16(samplerTypeKey |
caps.configTextureSwizzle(config).asKey() << kSamplerOrImageTypeKeyBits |
- (caps.samplerPrecision(config, visibility) << (8 + kSamplerOrImageTypeKeyBits)));
+ (GrSLSamplerPrecision(config) << (8 + kSamplerOrImageTypeKeyBits)));
}
static void add_sampler_and_image_keys(GrProcessorKeyBuilder* b, const GrResourceIOProcessor& proc,
diff --git a/src/gpu/GrShaderCaps.cpp b/src/gpu/GrShaderCaps.cpp
index 124fd4de40..2d9cd0a39b 100644
--- a/src/gpu/GrShaderCaps.cpp
+++ b/src/gpu/GrShaderCaps.cpp
@@ -13,32 +13,6 @@
////////////////////////////////////////////////////////////////////////////////////////////
-static const char* shader_type_to_string(GrShaderType type) {
- switch (type) {
- case kVertex_GrShaderType:
- return "vertex";
- case kGeometry_GrShaderType:
- return "geometry";
- case kFragment_GrShaderType:
- return "fragment";
- }
- return "";
-}
-
-static const char* precision_to_string(GrSLPrecision p) {
- switch (p) {
- case kLow_GrSLPrecision:
- return "low";
- case kMedium_GrSLPrecision:
- return "medium";
- case kHigh_GrSLPrecision:
- return "high";
- default:
- SK_ABORT("Unexpected precision type.");
- return "";
- }
-}
-
GrShaderCaps::GrShaderCaps(const GrContextOptions& options) {
fGLSLGeneration = k330_GrGLSLGeneration;
fShaderDerivativeSupport = false;
@@ -50,7 +24,6 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) {
fIntegerSupport = false;
fTexelBufferSupport = false;
fImageLoadStoreSupport = false;
- fShaderPrecisionVaries = false;
fDropsTileOnZeroDivide = false;
fFBFetchSupport = false;
fFBFetchNeedsCustomOutput = false;
@@ -73,6 +46,8 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) {
fExternalTextureSupport = false;
fTexelFetchSupport = false;
fVertexIDSupport = false;
+ fFloatIs32Bits = true;
+ fHalfIs32Bits = false;
fVersionDeclString = nullptr;
fShaderDerivativeExtensionString = nullptr;
@@ -113,26 +88,6 @@ void GrShaderCaps::dumpJSON(SkJSONWriter* writer) const {
writer->appendBool("Texel Buffer Support", fTexelBufferSupport);
writer->appendBool("Image Load Store Support", fImageLoadStoreSupport);
- writer->appendBool("Variable Precision", fShaderPrecisionVaries);
-
- for (int s = 0; s < kGrShaderTypeCount; ++s) {
- GrShaderType shaderType = static_cast<GrShaderType>(s);
- writer->beginArray(SkStringPrintf("%s precisions",
- shader_type_to_string(shaderType)).c_str());
- for (int p = 0; p < kGrSLPrecisionCount; ++p) {
- if (fFloatPrecisions[s][p].supported()) {
- GrSLPrecision precision = static_cast<GrSLPrecision>(p);
- writer->beginObject(nullptr, false);
- writer->appendString("precision", precision_to_string(precision));
- writer->appendS32("log_low", fFloatPrecisions[s][p].fLogRangeLow);
- writer->appendS32("log_high", fFloatPrecisions[s][p].fLogRangeHigh);
- writer->appendS32("bits", fFloatPrecisions[s][p].fBits);
- writer->endObject();
- }
- }
- writer->endArray();
- }
-
static const char* kAdvBlendEqInteractionStr[] = {
"Not Supported",
"Automatic",
@@ -166,6 +121,8 @@ void GrShaderCaps::dumpJSON(SkJSONWriter* writer) const {
writer->appendBool("External texture support", fExternalTextureSupport);
writer->appendBool("texelFetch support", fTexelFetchSupport);
writer->appendBool("sk_VertexID support", fVertexIDSupport);
+ writer->appendBool("float == fp32", fFloatIs32Bits);
+ writer->appendBool("half == fp32", fHalfIs32Bits);
writer->appendS32("Max VS Samplers", fMaxVertexSamplers);
writer->appendS32("Max GS Samplers", fMaxGeometrySamplers);
@@ -178,59 +135,6 @@ void GrShaderCaps::dumpJSON(SkJSONWriter* writer) const {
writer->endObject();
}
-void GrShaderCaps::initSamplerPrecisionTable() {
- // Determine the largest precision qualifiers that are effectively the same as lowp/mediump.
- // e.g. if lowp == mediump, then use mediump instead of lowp.
- GrSLPrecision effectiveMediumP[kGrShaderTypeCount];
- GrSLPrecision effectiveLowP[kGrShaderTypeCount];
- for (int s = 0; s < kGrShaderTypeCount; ++s) {
- const PrecisionInfo* info = fFloatPrecisions[s];
- effectiveMediumP[s] = info[kHigh_GrSLPrecision] == info[kMedium_GrSLPrecision] ?
- kHigh_GrSLPrecision : kMedium_GrSLPrecision;
- effectiveLowP[s] = info[kMedium_GrSLPrecision] == info[kLow_GrSLPrecision] ?
- effectiveMediumP[s] : kLow_GrSLPrecision;
- }
-
- // Determine which precision qualifiers should be used with samplers.
- for (int visibility = 0; visibility < (1 << kGrShaderTypeCount); ++visibility) {
- GrSLPrecision mediump = kHigh_GrSLPrecision;
- GrSLPrecision lowp = kHigh_GrSLPrecision;
- for (int s = 0; s < kGrShaderTypeCount; ++s) {
- if (visibility & (1 << s)) {
- mediump = SkTMin(mediump, effectiveMediumP[s]);
- lowp = SkTMin(lowp, effectiveLowP[s]);
- }
-
- GR_STATIC_ASSERT(0 == kLow_GrSLPrecision);
- GR_STATIC_ASSERT(1 == kMedium_GrSLPrecision);
- GR_STATIC_ASSERT(2 == kHigh_GrSLPrecision);
-
- GR_STATIC_ASSERT((1 << kVertex_GrShaderType) == kVertex_GrShaderFlag);
- GR_STATIC_ASSERT((1 << kGeometry_GrShaderType) == kGeometry_GrShaderFlag);
- GR_STATIC_ASSERT((1 << kFragment_GrShaderType) == kFragment_GrShaderFlag);
- GR_STATIC_ASSERT(3 == kGrShaderTypeCount);
- }
-
- uint8_t* table = fSamplerPrecisions[visibility];
- table[kUnknown_GrPixelConfig] = lowp;
- table[kAlpha_8_GrPixelConfig] = lowp;
- table[kGray_8_GrPixelConfig] = lowp;
- table[kRGB_565_GrPixelConfig] = lowp;
- table[kRGBA_4444_GrPixelConfig] = lowp;
- table[kRGBA_8888_GrPixelConfig] = lowp;
- table[kBGRA_8888_GrPixelConfig] = lowp;
- table[kSRGBA_8888_GrPixelConfig] = lowp;
- table[kSBGRA_8888_GrPixelConfig] = lowp;
- table[kRGBA_8888_sint_GrPixelConfig] = lowp;
- table[kRGBA_float_GrPixelConfig] = kHigh_GrSLPrecision;
- table[kRG_float_GrPixelConfig] = kHigh_GrSLPrecision;
- table[kAlpha_half_GrPixelConfig] = mediump;
- table[kRGBA_half_GrPixelConfig] = mediump;
-
- GR_STATIC_ASSERT(14 == kGrPixelConfigCnt);
- }
-}
-
void GrShaderCaps::applyOptionsOverrides(const GrContextOptions& options) {
#if GR_TEST_UTILS
fDualSourceBlendingSupport = fDualSourceBlendingSupport && !options.fSuppressDualSourceBlending;
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);
}
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index fe9bce8528..0c185e4a78 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -291,7 +291,7 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
**************************************************************************/
// This must be called after fCoreProfile is set on the GrGLCaps
- this->initGLSL(ctxInfo);
+ this->initGLSL(ctxInfo, gli);
GrShaderCaps* shaderCaps = fShaderCaps.get();
shaderCaps->fPathRenderingSupport = this->hasPathRenderingSupport(ctxInfo, gli);
@@ -634,8 +634,6 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
fDrawRangeElementsSupport = version >= GR_GL_VER(3,0);
}
- this->initShaderPrecisionTable(ctxInfo, gli, shaderCaps);
-
if (kGL_GrGLStandard == standard) {
if ((version >= GR_GL_VER(4, 0) || ctxInfo.hasExtension("GL_ARB_sample_shading")) &&
ctxInfo.vendor() != kIntel_GrGLVendor) {
@@ -760,7 +758,27 @@ const char* get_glsl_version_decl_string(GrGLStandard standard, GrGLSLGeneration
return "<no version>";
}
-void GrGLCaps::initGLSL(const GrGLContextInfo& ctxInfo) {
+bool is_float_fp32(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli, GrGLenum precision) {
+ if (kGLES_GrGLStandard != ctxInfo.standard() &&
+ ctxInfo.version() < GR_GL_VER(4,1) &&
+ !ctxInfo.hasExtension("GL_ARB_ES2_compatibility")) {
+ // We're on a desktop GL that doesn't have precision info. Assume they're all 32bit float.
+ return true;
+ }
+ // glGetShaderPrecisionFormat doesn't accept GL_GEOMETRY_SHADER as a shader type. Hopefully the
+ // geometry shaders don't have lower precision than vertex and fragment.
+ for (GrGLenum shader : {GR_GL_FRAGMENT_SHADER, GR_GL_VERTEX_SHADER}) {
+ GrGLint range[2];
+ GrGLint bits;
+ GR_GL_GetShaderPrecisionFormat(gli, shader, precision, range, &bits);
+ if (range[0] < 127 || range[1] < 127 || bits < 23) {
+ return false;
+ }
+ }
+ return true;
+}
+
+void GrGLCaps::initGLSL(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
GrGLStandard standard = ctxInfo.standard();
GrGLVersion version = ctxInfo.version();
@@ -937,6 +955,9 @@ void GrGLCaps::initGLSL(const GrGLContextInfo& ctxInfo) {
shaderCaps->fVertexIDSupport = ctxInfo.glslGeneration() >= k330_GrGLSLGeneration;
}
+ shaderCaps->fFloatIs32Bits = is_float_fp32(ctxInfo, gli, GR_GL_HIGH_FLOAT);
+ shaderCaps->fHalfIs32Bits = is_float_fp32(ctxInfo, gli, GR_GL_MEDIUM_FLOAT);
+
if (kTegra3_GrGLRenderer == ctxInfo.renderer()) {
// The Tegra3 compiler will sometimes never return if we have min(abs(x), 1.0),
// so we must do the abs first in a separate expression.
@@ -1408,92 +1429,6 @@ void GrGLCaps::onDumpJSON(SkJSONWriter* writer) const {
writer->endObject();
}
-static GrGLenum precision_to_gl_float_type(GrSLPrecision p) {
- switch (p) {
- case kLow_GrSLPrecision:
- return GR_GL_LOW_FLOAT;
- case kMedium_GrSLPrecision:
- return GR_GL_MEDIUM_FLOAT;
- case kHigh_GrSLPrecision:
- return GR_GL_HIGH_FLOAT;
- default:
- SK_ABORT("Unexpected precision type.");
- return -1;
- }
-}
-
-static GrGLenum shader_type_to_gl_shader(GrShaderType type) {
- switch (type) {
- case kVertex_GrShaderType:
- return GR_GL_VERTEX_SHADER;
- case kGeometry_GrShaderType:
- return GR_GL_GEOMETRY_SHADER;
- case kFragment_GrShaderType:
- return GR_GL_FRAGMENT_SHADER;
- }
- SK_ABORT("Unknown shader type.");
- return -1;
-}
-
-void GrGLCaps::initShaderPrecisionTable(const GrGLContextInfo& ctxInfo,
- const GrGLInterface* intf,
- GrShaderCaps* shaderCaps) {
- if (kGLES_GrGLStandard == ctxInfo.standard() || ctxInfo.version() >= GR_GL_VER(4, 1) ||
- ctxInfo.hasExtension("GL_ARB_ES2_compatibility")) {
- for (int s = 0; s < kGrShaderTypeCount; ++s) {
- if (kGeometry_GrShaderType != s) {
- GrShaderType shaderType = static_cast<GrShaderType>(s);
- GrGLenum glShader = shader_type_to_gl_shader(shaderType);
- GrShaderCaps::PrecisionInfo* first = nullptr;
- shaderCaps->fShaderPrecisionVaries = false;
- for (int p = 0; p < kGrSLPrecisionCount; ++p) {
- GrSLPrecision precision = static_cast<GrSLPrecision>(p);
- GrGLenum glPrecision = precision_to_gl_float_type(precision);
- GrGLint range[2];
- GrGLint bits;
- GR_GL_GetShaderPrecisionFormat(intf, glShader, glPrecision, range, &bits);
- if (bits) {
- shaderCaps->fFloatPrecisions[s][p].fLogRangeLow = range[0];
- shaderCaps->fFloatPrecisions[s][p].fLogRangeHigh = range[1];
- shaderCaps->fFloatPrecisions[s][p].fBits = bits;
- if (!first) {
- first = &shaderCaps->fFloatPrecisions[s][p];
- }
- else if (!shaderCaps->fShaderPrecisionVaries) {
- shaderCaps->fShaderPrecisionVaries =
- (*first != shaderCaps->fFloatPrecisions[s][p]);
- }
- }
- }
- }
- }
- }
- else {
- // We're on a desktop GL that doesn't have precision info. Assume they're all 32bit float.
- shaderCaps->fShaderPrecisionVaries = false;
- for (int s = 0; s < kGrShaderTypeCount; ++s) {
- if (kGeometry_GrShaderType != s) {
- for (int p = 0; p < kGrSLPrecisionCount; ++p) {
- shaderCaps->fFloatPrecisions[s][p].fLogRangeLow = 127;
- shaderCaps->fFloatPrecisions[s][p].fLogRangeHigh = 127;
- shaderCaps->fFloatPrecisions[s][p].fBits = 23;
- }
- }
- }
- }
- // GetShaderPrecisionFormat doesn't accept GL_GEOMETRY_SHADER as a shader type. Assume they're
- // the same as the vertex shader. Only fragment shaders were ever allowed to omit support for
- // highp. GS was added after GetShaderPrecisionFormat was added to the list of features that
- // are recommended against.
- if (shaderCaps->fGeometryShaderSupport) {
- for (int p = 0; p < kGrSLPrecisionCount; ++p) {
- shaderCaps->fFloatPrecisions[kGeometry_GrShaderType][p] =
- shaderCaps->fFloatPrecisions[kVertex_GrShaderType][p];
- }
- }
- shaderCaps->initSamplerPrecisionTable();
-}
-
bool GrGLCaps::bgraIsInternalFormat() const {
return fConfigTable[kBGRA_8888_GrPixelConfig].fFormats.fBaseInternalFormat == GR_GL_BGRA;
}
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index 923b3f416d..3a50e8a393 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -428,7 +428,7 @@ private:
GrGLenum* externalType) const;
void init(const GrContextOptions&, const GrGLContextInfo&, const GrGLInterface*);
- void initGLSL(const GrGLContextInfo&);
+ void initGLSL(const GrGLContextInfo&, const GrGLInterface*);
bool hasPathRenderingSupport(const GrGLContextInfo&, const GrGLInterface*);
void onApplyOptionsOverrides(const GrContextOptions& options) override;
@@ -441,8 +441,6 @@ private:
void initConfigTable(const GrContextOptions&, const GrGLContextInfo&, const GrGLInterface*,
GrShaderCaps*);
- void initShaderPrecisionTable(const GrGLContextInfo&, const GrGLInterface*, GrShaderCaps*);
-
GrGLStandard fStandard;
SkTArray<StencilFormat, true> fStencilFormats;
diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.cpp b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
index 6f8d1be736..118b904540 100644
--- a/src/gpu/glsl/GrGLSLProgramBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
@@ -303,7 +303,7 @@ GrGLSLProgramBuilder::SamplerHandle GrGLSLProgramBuilder::emitSampler(GrSLType s
const char* name,
GrShaderFlags visibility) {
this->updateSamplerCounts(visibility);
- GrSLPrecision precision = this->shaderCaps()->samplerPrecision(config, visibility);
+ GrSLPrecision precision = GrSLSamplerPrecision(config);
GrSwizzle swizzle = this->shaderCaps()->configTextureSwizzle(config);
return this->uniformHandler()->addSampler(visibility, swizzle, samplerType, precision, name);
}
@@ -311,7 +311,7 @@ GrGLSLProgramBuilder::SamplerHandle GrGLSLProgramBuilder::emitSampler(GrSLType s
GrGLSLProgramBuilder::TexelBufferHandle GrGLSLProgramBuilder::emitTexelBuffer(
GrPixelConfig config, const char* name, GrShaderFlags visibility) {
this->updateSamplerCounts(visibility);
- GrSLPrecision precision = this->shaderCaps()->samplerPrecision(config, visibility);
+ GrSLPrecision precision = GrSLSamplerPrecision(config);
return this->uniformHandler()->addTexelBuffer(visibility, precision, name);
}
diff --git a/src/gpu/mtl/GrMtlCaps.mm b/src/gpu/mtl/GrMtlCaps.mm
index d431f0a1e1..2354b85e64 100644
--- a/src/gpu/mtl/GrMtlCaps.mm
+++ b/src/gpu/mtl/GrMtlCaps.mm
@@ -229,21 +229,10 @@ void GrMtlCaps::initShaderCaps() {
shaderCaps->fTexelFetchSupport = false;
shaderCaps->fVertexIDSupport = false;
shaderCaps->fImageLoadStoreSupport = false;
- shaderCaps->fShaderPrecisionVaries = false; // ???
- // Metal uses IEEE float and half floats so using those values here.
- for (int s = 0; s < kGrShaderTypeCount; ++s) {
- auto& highp = shaderCaps->fFloatPrecisions[s][kHigh_GrSLPrecision];
- highp.fLogRangeLow = highp.fLogRangeHigh = 127;
- highp.fBits = 23;
-
- auto& mediump = shaderCaps->fFloatPrecisions[s][kMedium_GrSLPrecision];
- mediump.fLogRangeLow = mediump.fLogRangeHigh = 15;
- mediump.fBits = 10;
-
- shaderCaps->fFloatPrecisions[s][kLow_GrSLPrecision] = mediump;
- }
- shaderCaps->initSamplerPrecisionTable();
+ // Metal uses IEEE float and half floats so assuming those values here.
+ shaderCaps->fFloatIs32Bits = true;
+ shaderCaps->fHalfIs32Bits = false;
shaderCaps->fMaxVertexSamplers =
shaderCaps->fMaxFragmentSamplers = 16;
diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp
index 2b24205af8..f5c4b342ed 100644
--- a/src/gpu/vk/GrVkCaps.cpp
+++ b/src/gpu/vk/GrVkCaps.cpp
@@ -259,19 +259,8 @@ void GrVkCaps::initShaderCaps(const VkPhysicalDeviceProperties& properties, uint
shaderCaps->fVertexIDSupport = true;
// Assume the minimum precisions mandated by the SPIR-V spec.
- shaderCaps->fShaderPrecisionVaries = true;
- for (int s = 0; s < kGrShaderTypeCount; ++s) {
- auto& highp = shaderCaps->fFloatPrecisions[s][kHigh_GrSLPrecision];
- highp.fLogRangeLow = highp.fLogRangeHigh = 127;
- highp.fBits = 23;
-
- auto& mediump = shaderCaps->fFloatPrecisions[s][kMedium_GrSLPrecision];
- mediump.fLogRangeLow = mediump.fLogRangeHigh = 14;
- mediump.fBits = 10;
-
- shaderCaps->fFloatPrecisions[s][kLow_GrSLPrecision] = mediump;
- }
- shaderCaps->initSamplerPrecisionTable();
+ shaderCaps->fFloatIs32Bits = true;
+ shaderCaps->fHalfIs32Bits = false;
shaderCaps->fMaxVertexSamplers =
shaderCaps->fMaxGeometrySamplers =