diff options
author | Brian Osman <brianosman@google.com> | 2017-11-16 14:02:11 +0000 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-11-16 14:02:23 +0000 |
commit | 24f9c19172e149602551cd6716b3cc264c1d40ef (patch) | |
tree | 48f622c34b80fa9d6595f1050b313033ec8e4104 | |
parent | 554c1f0508a95b5411036a95d1bb62c0d5fdeae8 (diff) |
Revert "Fix precision caps and rrect/ellipse effect precisions"
This reverts commit e42180022720f2fcfd3c634cad855506a7940591.
Reason for revert: Also may be responsible for layout test failures? Playing it safe.
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=egdaniel@google.com,bsalomon@google.com,csmartdalton@google.com,ethannicholas@google.com
Change-Id: Idca2f0390e7a0eb85010255183f2f27332b8d26d
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:7190
Reviewed-on: https://skia-review.googlesource.com/72540
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
-rw-r--r-- | include/gpu/GrShaderCaps.h | 71 | ||||
-rw-r--r-- | include/private/GrTypesPriv.h | 27 | ||||
-rw-r--r-- | src/gpu/GrProgramDesc.cpp | 2 | ||||
-rw-r--r-- | src/gpu/GrShaderCaps.cpp | 104 | ||||
-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 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.cpp | 115 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.h | 4 | ||||
-rw-r--r-- | src/gpu/glsl/GrGLSLProgramBuilder.cpp | 4 | ||||
-rw-r--r-- | src/gpu/mtl/GrMtlCaps.mm | 17 | ||||
-rw-r--r-- | src/gpu/vk/GrVkCaps.cpp | 15 | ||||
-rw-r--r-- | src/sksl/SkSLCPP.h | 2 | ||||
-rw-r--r-- | src/sksl/SkSLIRGenerator.cpp | 2 | ||||
-rw-r--r-- | src/sksl/SkSLUtil.h | 4 | ||||
-rw-r--r-- | tests/ApplyGammaTest.cpp | 2 | ||||
-rw-r--r-- | tests/SRGBReadWritePixelsTest.cpp | 4 |
17 files changed, 359 insertions, 141 deletions
diff --git a/include/gpu/GrShaderCaps.h b/include/gpu/GrShaderCaps.h index 4c847ac8b0..5ecd58ca59 100644 --- a/include/gpu/GrShaderCaps.h +++ b/include/gpu/GrShaderCaps.h @@ -20,6 +20,40 @@ class SkJSONWriter; class GrShaderCaps : public SkRefCnt { public: + /** Info about shader variable precision within a given shader stage. That is, this info + is relevant to a float (or vecNf) variable declared with a GrSLPrecision + in a given GrShaderType. The info here is hoisted from the OpenGL spec. */ + struct PrecisionInfo { + PrecisionInfo() { + fLogRangeLow = 0; + fLogRangeHigh = 0; + fBits = 0; + } + + /** Is this precision level allowed in the shader stage? */ + bool supported() const { return 0 != fBits; } + + bool operator==(const PrecisionInfo& that) const { + return fLogRangeLow == that.fLogRangeLow && fLogRangeHigh == that.fLogRangeHigh && + fBits == that.fBits; + } + bool operator!=(const PrecisionInfo& that) const { return !(*this == that); } + + /** floor(log2(|min_value|)) */ + int fLogRangeLow; + /** floor(log2(|max_value|)) */ + int fLogRangeHigh; + /** Number of bits of precision. As defined in OpenGL (with names modified to reflect this + struct) : + """ + If the smallest representable value greater than 1 is 1 + e, then fBits will + contain floor(log2(e)), and every value in the range [2^fLogRangeLow, + 2^fLogRangeHigh] can be represented to at least one part in 2^fBits. + """ + */ + int fBits; + }; + /** * Indicates how GLSL must interact with advanced blend equations. The KHR extension requires * special layout qualifiers in the fragment shader. @@ -48,6 +82,24 @@ public: int imageLoadStoreSupport() const { return fImageLoadStoreSupport; } /** + * Get the precision info for a variable of type kFloat_GrSLType, kFloat2_GrSLType, etc in a + * given shader type. If the shader type is not supported or the precision level is not + * supported in that shader type then the returned struct will report false when supported() is + * called. + */ + const PrecisionInfo& getFloatShaderPrecisionInfo(GrShaderType shaderType, + GrSLPrecision precision) const { + return fFloatPrecisions[shaderType][precision]; + } + + /** + * Is there any difference between the float shader variable precision types? If this is true + * then unless the shader type is not supported, any call to getFloatShaderPrecisionInfo() would + * report the same info for all precisions in all shader types. + */ + bool floatPrecisionVaries() const { return fShaderPrecisionVaries; } + + /** * Some helper functions for encapsulating various extensions to read FB Buffer on openglES * * TODO(joshualitt) On desktop opengl 4.2+ we can achieve something similar to this effect @@ -84,10 +136,6 @@ public: bool vertexIDSupport() const { return fVertexIDSupport; } - bool floatIs32Bits() const { return fFloatIs32Bits; } - - bool halfIs32Bits() const { return fHalfIs32Bits; } - AdvBlendEqInteraction advBlendEqInteraction() const { return fAdvBlendEqInteraction; } bool mustEnableAdvBlendEqs() const { @@ -212,9 +260,17 @@ public: return fConfigOutputSwizzle[config]; } + /** Precision qualifier that should be used with a sampler, given its config and visibility. */ + GrSLPrecision samplerPrecision(GrPixelConfig config, GrShaderFlags visibility) const { + return static_cast<GrSLPrecision>(fSamplerPrecisions[visibility][config]); + } + GrGLSLGeneration generation() const { return fGLSLGeneration; } private: + /** GrCaps subclasses must call this after filling in the shader precision table. */ + void initSamplerPrecisionTable(); + void applyOptionsOverrides(const GrContextOptions& options); GrGLSLGeneration fGLSLGeneration; @@ -228,6 +284,7 @@ private: bool fIntegerSupport : 1; bool fTexelBufferSupport : 1; bool fImageLoadStoreSupport : 1; + bool fShaderPrecisionVaries : 1; bool fDropsTileOnZeroDivide : 1; bool fFBFetchSupport : 1; bool fFBFetchNeedsCustomOutput : 1; @@ -243,8 +300,6 @@ private: bool fExternalTextureSupport : 1; bool fTexelFetchSupport : 1; bool fVertexIDSupport : 1; - bool fFloatIs32Bits : 1; - bool fHalfIs32Bits : 1; bool fDisableImageMultitexturing : 1; // Used for specific driver bug work arounds @@ -256,6 +311,8 @@ private: bool fMustObfuscateUniformColor : 1; bool fMustGuardDivisionEvenAfterExplicitZeroCheck : 1; + PrecisionInfo fFloatPrecisions[kGrShaderTypeCount][kGrSLPrecisionCount]; + const char* fVersionDeclString; const char* fShaderDerivativeExtensionString; @@ -282,6 +339,8 @@ private: GrSwizzle fConfigTextureSwizzle[kGrPixelConfigCnt]; GrSwizzle fConfigOutputSwizzle[kGrPixelConfigCnt]; + uint8_t fSamplerPrecisions[(1 << kGrShaderTypeCount)][kGrPixelConfigCnt]; + friend class GrGLCaps; // For initialization. friend class GrMockCaps; friend class GrMtlCaps; diff --git a/include/private/GrTypesPriv.h b/include/private/GrTypesPriv.h index cd1c0d4483..a90944064f 100644 --- a/include/private/GrTypesPriv.h +++ b/include/private/GrTypesPriv.h @@ -909,33 +909,6 @@ static inline bool GrPixelConfigIsUnorm(GrPixelConfig config) { return false; } -/** - * Precision qualifier that should be used with a sampler. - */ -static inline GrSLPrecision GrSLSamplerPrecision(GrPixelConfig config) { - switch (config) { - case kUnknown_GrPixelConfig: - case kAlpha_8_GrPixelConfig: - case kGray_8_GrPixelConfig: - case kRGB_565_GrPixelConfig: - case kRGBA_4444_GrPixelConfig: - case kRGBA_8888_GrPixelConfig: - case kBGRA_8888_GrPixelConfig: - case kSRGBA_8888_GrPixelConfig: - case kSBGRA_8888_GrPixelConfig: - case kRGBA_8888_sint_GrPixelConfig: - return kLow_GrSLPrecision; - case kRGBA_float_GrPixelConfig: - case kRG_float_GrPixelConfig: - return kHigh_GrSLPrecision; - case kAlpha_half_GrPixelConfig: - case kRGBA_half_GrPixelConfig: - return kMedium_GrSLPrecision; - } - SK_ABORT("Unexpected type"); - return kHigh_GrSLPrecision; -} - static inline GrPixelConfigIsClamped GrGetPixelConfigIsClamped(GrPixelConfig config) { return GrPixelConfigIsFloatingPoint(config) ? GrPixelConfigIsClamped::kNo : GrPixelConfigIsClamped::kYes; diff --git a/src/gpu/GrProgramDesc.cpp b/src/gpu/GrProgramDesc.cpp index 9c0add66e6..a32e0cc28b 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 | - (GrSLSamplerPrecision(config) << (8 + kSamplerOrImageTypeKeyBits))); + (caps.samplerPrecision(config, visibility) << (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 2d9cd0a39b..124fd4de40 100644 --- a/src/gpu/GrShaderCaps.cpp +++ b/src/gpu/GrShaderCaps.cpp @@ -13,6 +13,32 @@ //////////////////////////////////////////////////////////////////////////////////////////// +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; @@ -24,6 +50,7 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) { fIntegerSupport = false; fTexelBufferSupport = false; fImageLoadStoreSupport = false; + fShaderPrecisionVaries = false; fDropsTileOnZeroDivide = false; fFBFetchSupport = false; fFBFetchNeedsCustomOutput = false; @@ -46,8 +73,6 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) { fExternalTextureSupport = false; fTexelFetchSupport = false; fVertexIDSupport = false; - fFloatIs32Bits = true; - fHalfIs32Bits = false; fVersionDeclString = nullptr; fShaderDerivativeExtensionString = nullptr; @@ -88,6 +113,26 @@ 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", @@ -121,8 +166,6 @@ 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); @@ -135,6 +178,59 @@ 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 6b1a8cc59f..4a0f37665c 100644 --- a/src/gpu/effects/GrEllipseEffect.cpp +++ b/src/gpu/effects/GrEllipseEffect.cpp @@ -28,33 +28,34 @@ public: (void)center; auto radii = _outer.radii(); (void)radii; - prevRadii = float2(-1.0); - useScale = !sk_Caps.floatIs32Bits; + prevRadii = half2(-1.0); + useScale = sk_Caps.floatPrecisionVaries; fEllipseVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kFloat4_GrSLType, kDefault_GrSLPrecision, "ellipse"); if (useScale) { - fScaleVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kFloat2_GrSLType, + fScaleVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType, kDefault_GrSLPrecision, "scale"); } fragBuilder->codeAppendf( - "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 ", + "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.", prevRadii.fX, prevRadii.fY, (useScale ? "true" : "false"), args.fUniformHandler->getUniformCStr(fEllipseVar), - fScaleVar.isValid() ? args.fUniformHandler->getUniformCStr(fScaleVar) : "float2(0)", + fScaleVar.isValid() ? args.fUniformHandler->getUniformCStr(fScaleVar) : "half2(0)", args.fUniformHandler->getUniformCStr(fEllipseVar), - fScaleVar.isValid() ? args.fUniformHandler->getUniformCStr(fScaleVar) : "float2(0)", + fScaleVar.isValid() ? args.fUniformHandler->getUniformCStr(fScaleVar) : "half2(0)", (int)_outer.edgeType()); fragBuilder->codeAppendf( - " 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", + "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", args.fOutputColor, args.fInputColor ? args.fInputColor : "half4(1)"); } diff --git a/src/gpu/effects/GrEllipseEffect.fp b/src/gpu/effects/GrEllipseEffect.fp index 27beb85d2f..54641b72c6 100644 --- a/src/gpu/effects/GrEllipseEffect.fp +++ b/src/gpu/effects/GrEllipseEffect.fp @@ -6,17 +6,17 @@ */ layout(key) in GrClipEdgeType edgeType; -in float2 center; -in float2 radii; +in half2 center; +in half2 radii; -float2 prevCenter; -float2 prevRadii = float2(-1); +half2 prevCenter; +half2 prevRadii = half2(-1); // The ellipse uniform is (center.x, center.y, 1 / rx^2, 1 / ry^2) -// The last two terms can underflow when float != fp32, so we also provide a workaround. +// The last two terms can underflow with halfs, so we use floats. uniform float4 ellipse; -bool useScale = !sk_Caps.floatIs32Bits; -layout(when=useScale) uniform float2 scale; +bool useScale = sk_Caps.floatPrecisionVaries; +layout(when=useScale) uniform half2 scale; @optimizationFlags { kCompatibleWithCoverageAsAlpha_OptimizationFlag } @@ -50,7 +50,7 @@ layout(when=useScale) uniform float2 scale; void main() { // d is the offset to the ellipse center - float2 d = sk_FragCoord.xy - ellipse.xy; + half2 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; } - float2 Z = d * ellipse.zw; + half2 Z = d * ellipse.zw; // implicit is the evaluation of (x/rx)^2 + (y/ry)^2 - 1. - float implicit = dot(Z, d) - 1; + half implicit = dot(Z, d) - 1; // grad_dot is the squared length of the gradient of the implicit. - float grad_dot = 4 * dot(Z, Z); + half grad_dot = 4 * dot(Z, Z); // Avoid calling inversesqrt on zero. grad_dot = max(grad_dot, 1e-4); - float approx_dist = implicit * inversesqrt(grad_dot); + half 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 510a26b425..4b56443b0d 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 where float != fp32 then the length calculation could overflow. + // If we're on a device with a "real" mediump then the length calculation could overflow. SkString clampedCircleDistance; - if (!args.fShaderCaps->floatIs32Bits()) { + if (args.fShaderCaps->floatPrecisionVaries()) { 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("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("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("half alpha = %s;", clampedCircleDistance.c_str()); break; case CircularRRectEffect::kTopLeft_CornerFlag: - fragBuilder->codeAppendf("float2 dxy = max(%s.xy - sk_FragCoord.xy, 0.0);", + fragBuilder->codeAppendf("half2 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("float2 dxy = max(float2(sk_FragCoord.x - %s.z, " - "%s.y - sk_FragCoord.y), 0.0);", + fragBuilder->codeAppendf("half2 dxy = max(half2(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("float2 dxy = max(sk_FragCoord.xy - %s.zw, 0.0);", + fragBuilder->codeAppendf("half2 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("float2 dxy = max(float2(%s.x - sk_FragCoord.x, " - "sk_FragCoord.y - %s.w), 0.0);", + fragBuilder->codeAppendf("half2 dxy = max(half2(%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("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("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("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("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("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("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("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 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("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("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 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("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("float2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName); - fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName); + fragBuilder->codeAppendf("half2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName); + fragBuilder->codeAppendf("half2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName); - // If we're on a device where float != fp32 then we'll do the distance computation in a space + // 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 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->floatIs32Bits()) { + if (args.fShaderCaps->floatPrecisionVaries()) { fScaleUniform = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType, "scale", &scaleName); } @@ -543,12 +543,12 @@ void GLEllipticalRRectEffect::emitCode(EmitArgs& args) { kHalf2_GrSLType, "invRadiiXY", &invRadiiXYSqdName); - fragBuilder->codeAppend("float2 dxy = max(max(dxy0, dxy1), 0.0);"); + fragBuilder->codeAppend("half2 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("float2 Z = dxy * %s.xy;", invRadiiXYSqdName); + fragBuilder->codeAppendf("half2 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("float2 dxy = max(max(dxy0, dxy1), 0.0);"); + fragBuilder->codeAppend("half2 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("float2 Z = max(max(dxy0 * %s.xy, dxy1 * %s.zw), 0.0);", + fragBuilder->codeAppendf("half2 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("float implicit = dot(Z, dxy) - 1.0;"); + fragBuilder->codeAppend("half implicit = dot(Z, dxy) - 1.0;"); // grad_dot is the squared length of the gradient of the implicit. - fragBuilder->codeAppend("float grad_dot = 4.0 * dot(Z, Z);"); + fragBuilder->codeAppend("half grad_dot = 4.0 * dot(Z, Z);"); // avoid calling inversesqrt on zero. fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);"); - fragBuilder->codeAppend("float approx_dist = implicit * inversesqrt(grad_dot);"); + fragBuilder->codeAppend("half 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 0c185e4a78..fe9bce8528 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, gli); + this->initGLSL(ctxInfo); GrShaderCaps* shaderCaps = fShaderCaps.get(); shaderCaps->fPathRenderingSupport = this->hasPathRenderingSupport(ctxInfo, gli); @@ -634,6 +634,8 @@ 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) { @@ -758,27 +760,7 @@ const char* get_glsl_version_decl_string(GrGLStandard standard, GrGLSLGeneration return "<no version>"; } -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) { +void GrGLCaps::initGLSL(const GrGLContextInfo& ctxInfo) { GrGLStandard standard = ctxInfo.standard(); GrGLVersion version = ctxInfo.version(); @@ -955,9 +937,6 @@ void GrGLCaps::initGLSL(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli 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. @@ -1429,6 +1408,92 @@ 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 3a50e8a393..923b3f416d 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&, const GrGLInterface*); + void initGLSL(const GrGLContextInfo&); bool hasPathRenderingSupport(const GrGLContextInfo&, const GrGLInterface*); void onApplyOptionsOverrides(const GrContextOptions& options) override; @@ -441,6 +441,8 @@ 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 118b904540..6f8d1be736 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 = GrSLSamplerPrecision(config); + GrSLPrecision precision = this->shaderCaps()->samplerPrecision(config, visibility); 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 = GrSLSamplerPrecision(config); + GrSLPrecision precision = this->shaderCaps()->samplerPrecision(config, visibility); return this->uniformHandler()->addTexelBuffer(visibility, precision, name); } diff --git a/src/gpu/mtl/GrMtlCaps.mm b/src/gpu/mtl/GrMtlCaps.mm index 2354b85e64..d431f0a1e1 100644 --- a/src/gpu/mtl/GrMtlCaps.mm +++ b/src/gpu/mtl/GrMtlCaps.mm @@ -229,10 +229,21 @@ void GrMtlCaps::initShaderCaps() { shaderCaps->fTexelFetchSupport = false; shaderCaps->fVertexIDSupport = false; shaderCaps->fImageLoadStoreSupport = false; + shaderCaps->fShaderPrecisionVaries = false; // ??? - // Metal uses IEEE float and half floats so assuming those values here. - shaderCaps->fFloatIs32Bits = true; - shaderCaps->fHalfIs32Bits = 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(); shaderCaps->fMaxVertexSamplers = shaderCaps->fMaxFragmentSamplers = 16; diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp index f5c4b342ed..2b24205af8 100644 --- a/src/gpu/vk/GrVkCaps.cpp +++ b/src/gpu/vk/GrVkCaps.cpp @@ -259,8 +259,19 @@ void GrVkCaps::initShaderCaps(const VkPhysicalDeviceProperties& properties, uint shaderCaps->fVertexIDSupport = true; // Assume the minimum precisions mandated by the SPIR-V spec. - shaderCaps->fFloatIs32Bits = true; - shaderCaps->fHalfIs32Bits = false; + 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->fMaxVertexSamplers = shaderCaps->fMaxGeometrySamplers = diff --git a/src/sksl/SkSLCPP.h b/src/sksl/SkSLCPP.h index 612a200f28..d67990820b 100644 --- a/src/sksl/SkSLCPP.h +++ b/src/sksl/SkSLCPP.h @@ -18,7 +18,7 @@ using std::abs; // macros to make sk_Caps.<cap name> work from C++ code #define sk_Caps (*args.fShaderCaps) -#define floatIs32Bits floatIs32Bits() +#define floatPrecisionVaries floatPrecisionVaries() // functions to make GLSL constructors work from C++ code inline SkPoint float2(float xy) { return SkPoint::Make(xy, xy); } diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp index cfa3049a2c..18b36a4b0f 100644 --- a/src/sksl/SkSLIRGenerator.cpp +++ b/src/sksl/SkSLIRGenerator.cpp @@ -140,7 +140,7 @@ static void fill_caps(const SKSL_CAPS_CLASS& caps, CAP(mustEnableSpecificAdvBlendEqs); CAP(mustDeclareFragmentShaderOutput); CAP(canUseAnyFunctionInShader); - CAP(floatIs32Bits); + CAP(floatPrecisionVaries); CAP(integerSupport); #undef CAP } diff --git a/src/sksl/SkSLUtil.h b/src/sksl/SkSLUtil.h index 1d9d53f6e8..a8be7ef72f 100644 --- a/src/sksl/SkSLUtil.h +++ b/src/sksl/SkSLUtil.h @@ -135,8 +135,8 @@ public: return false; } - bool floatIs32Bits() const { - return true; + bool floatPrecisionVaries() const { + return false; } bool integerSupport() const { diff --git a/tests/ApplyGammaTest.cpp b/tests/ApplyGammaTest.cpp index 4147be7f41..f2049e7ccc 100644 --- a/tests/ApplyGammaTest.cpp +++ b/tests/ApplyGammaTest.cpp @@ -105,7 +105,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ApplyGamma, reporter, ctxInfo) { SkAutoTMalloc<uint32_t> read(kW * kH); // We allow more error on GPUs with lower precision shader variables. - float error = context->caps()->shaderCaps()->halfIs32Bits() ? 0.5f : 1.2f; + float error = context->caps()->shaderCaps()->floatPrecisionVaries() ? 1.2f : 0.5f; for (auto toSRGB : { false, true }) { sk_sp<SkSurface> dst(SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii)); diff --git a/tests/SRGBReadWritePixelsTest.cpp b/tests/SRGBReadWritePixelsTest.cpp index b5d61c1850..6ebdcf7c20 100644 --- a/tests/SRGBReadWritePixelsTest.cpp +++ b/tests/SRGBReadWritePixelsTest.cpp @@ -184,14 +184,14 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SRGBReadWritePixels, reporter, ctxInfo) { return; } - float error = context->caps()->shaderCaps()->halfIs32Bits() ? 0.5f : 1.2f; + float error = context->caps()->shaderCaps()->floatPrecisionVaries() ? 1.2f : 0.5f; // Write srgba data and read as srgba and then as rgba if (sContext->writePixels(iiSRGBA, origData, 0, 0, 0)) { // For the all-srgba case, we allow a small error only for devices that have // precision variation because the srgba data gets converted to linear and back in // the shader. - float smallError = context->caps()->shaderCaps()->halfIs32Bits() ? 0.0f : 1.f; + float smallError = context->caps()->shaderCaps()->floatPrecisionVaries() ? 1.f : 0.0f; read_and_check_pixels(reporter, sContext.get(), origData, iiSRGBA, check_srgb_to_linear_to_srgb_conversion, smallError, "write/read srgba to srgba texture"); |