1 /* 2 * Copyright 2012 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef GrShaderCaps_DEFINED 9 #define GrShaderCaps_DEFINED 10 11 #include "include/core/SkRefCnt.h" 12 #include "src/gpu/glsl/GrGLSL.h" 13 14 namespace SkSL { 15 class ShaderCapsFactory; 16 class SharedCompiler; 17 } // namespace SkSL 18 19 struct GrContextOptions; 20 class SkJSONWriter; 21 22 class GrShaderCaps { 23 public: 24 /** 25 * Indicates how GLSL must interact with advanced blend equations. The KHR extension requires 26 * special layout qualifiers in the fragment shader. 27 */ 28 enum AdvBlendEqInteraction { 29 kNotSupported_AdvBlendEqInteraction, //<! No _blend_equation_advanced extension 30 kAutomatic_AdvBlendEqInteraction, //<! No interaction required 31 kGeneralEnable_AdvBlendEqInteraction, //<! layout(blend_support_all_equations) out 32 33 kLast_AdvBlendEqInteraction = kGeneralEnable_AdvBlendEqInteraction 34 }; 35 36 GrShaderCaps(); 37 38 void dumpJSON(SkJSONWriter*) const; 39 supportsDistanceFieldText()40 bool supportsDistanceFieldText() const { return fShaderDerivativeSupport; } 41 shaderDerivativeSupport()42 bool shaderDerivativeSupport() const { return fShaderDerivativeSupport; } dstReadInShaderSupport()43 bool dstReadInShaderSupport() const { return fDstReadInShaderSupport; } dualSourceBlendingSupport()44 bool dualSourceBlendingSupport() const { return fDualSourceBlendingSupport; } nonsquareMatrixSupport()45 bool nonsquareMatrixSupport() const { return fNonsquareMatrixSupport; } 46 47 /** Indicates true 32-bit integer support, with unsigned types and bitwise operations */ integerSupport()48 bool integerSupport() const { return fIntegerSupport; } 49 50 /** asinh(), acosh(), atanh() */ inverseHyperbolicSupport()51 bool inverseHyperbolicSupport() const { return fInverseHyperbolicSupport; } 52 53 /** 54 * Some helper functions for encapsulating various extensions to read FB Buffer on openglES 55 * 56 * TODO(joshualitt) On desktop opengl 4.2+ we can achieve something similar to this effect 57 */ fbFetchSupport()58 bool fbFetchSupport() const { return fFBFetchSupport; } 59 fbFetchNeedsCustomOutput()60 bool fbFetchNeedsCustomOutput() const { return fFBFetchNeedsCustomOutput; } 61 versionDeclString()62 const char* versionDeclString() const { return fVersionDeclString; } 63 fbFetchColorName()64 const char* fbFetchColorName() const { return fFBFetchColorName; } 65 fbFetchExtensionString()66 const char* fbFetchExtensionString() const { return fFBFetchExtensionString; } 67 flatInterpolationSupport()68 bool flatInterpolationSupport() const { return fFlatInterpolationSupport; } 69 preferFlatInterpolation()70 bool preferFlatInterpolation() const { return fPreferFlatInterpolation; } 71 noperspectiveInterpolationSupport()72 bool noperspectiveInterpolationSupport() const { return fNoPerspectiveInterpolationSupport; } 73 sampleMaskSupport()74 bool sampleMaskSupport() const { return fSampleMaskSupport; } 75 externalTextureSupport()76 bool externalTextureSupport() const { return fExternalTextureSupport; } 77 vertexIDSupport()78 bool vertexIDSupport() const { return fVertexIDSupport; } 79 80 // isinf() is defined, and floating point infinities are handled according to IEEE standards. infinitySupport()81 bool infinitySupport() const { return fInfinitySupport; } 82 83 // Returns true if `expr` in `myArray[expr]` can be any integer expression. If false, `expr` 84 // must be a constant-index-expression as defined in the OpenGL ES2 specification, Appendix A.5. nonconstantArrayIndexSupport()85 bool nonconstantArrayIndexSupport() const { 86 return fNonconstantArrayIndexSupport; 87 } 88 89 // frexp(), ldexp(), findMSB(), findLSB(). bitManipulationSupport()90 bool bitManipulationSupport() const { return fBitManipulationSupport; } 91 floatIs32Bits()92 bool floatIs32Bits() const { return fFloatIs32Bits; } 93 halfIs32Bits()94 bool halfIs32Bits() const { return fHalfIs32Bits; } 95 hasLowFragmentPrecision()96 bool hasLowFragmentPrecision() const { return fHasLowFragmentPrecision; } 97 98 // Use a reduced set of rendering algorithms or less optimal effects in order to 99 // reduce the number of unique shaders generated. reducedShaderMode()100 bool reducedShaderMode() const { return fReducedShaderMode; } 101 102 /** 103 * SkSL ES3 requires support for derivatives, nonsquare matrices and bitwise integer operations. 104 */ supportsSkSLES3()105 bool supportsSkSLES3() const { 106 return fShaderDerivativeSupport && fNonsquareMatrixSupport && fIntegerSupport && 107 fGLSLGeneration >= k330_GrGLSLGeneration; 108 } 109 110 // SkSL only. builtinFMASupport()111 bool builtinFMASupport() const { return fBuiltinFMASupport; } 112 builtinDeterminantSupport()113 bool builtinDeterminantSupport() const { return fBuiltinDeterminantSupport; } 114 advBlendEqInteraction()115 AdvBlendEqInteraction advBlendEqInteraction() const { return fAdvBlendEqInteraction; } 116 mustEnableAdvBlendEqs()117 bool mustEnableAdvBlendEqs() const { 118 return fAdvBlendEqInteraction >= kGeneralEnable_AdvBlendEqInteraction; 119 } 120 mustDeclareFragmentShaderOutput()121 bool mustDeclareFragmentShaderOutput() const { return fGLSLGeneration > k110_GrGLSLGeneration; } 122 usesPrecisionModifiers()123 bool usesPrecisionModifiers() const { return fUsesPrecisionModifiers; } 124 125 // Returns whether we can use the glsl function any() in our shader code. canUseAnyFunctionInShader()126 bool canUseAnyFunctionInShader() const { return fCanUseAnyFunctionInShader; } 127 canUseMinAndAbsTogether()128 bool canUseMinAndAbsTogether() const { return fCanUseMinAndAbsTogether; } 129 canUseFractForNegativeValues()130 bool canUseFractForNegativeValues() const { return fCanUseFractForNegativeValues; } 131 mustForceNegatedAtanParamToFloat()132 bool mustForceNegatedAtanParamToFloat() const { return fMustForceNegatedAtanParamToFloat; } 133 134 // http://skbug.com/12076 mustForceNegatedLdexpParamToMultiply()135 bool mustForceNegatedLdexpParamToMultiply() const { 136 return fMustForceNegatedLdexpParamToMultiply; 137 } 138 139 // Returns whether a device incorrectly implements atan(y,x) as atan(y/x) atan2ImplementedAsAtanYOverX()140 bool atan2ImplementedAsAtanYOverX() const { return fAtan2ImplementedAsAtanYOverX; } 141 142 // If this returns true some operation (could be a no op) must be called between floor and abs 143 // to make sure the driver compiler doesn't inline them together which can cause a driver bug in 144 // the shader. mustDoOpBetweenFloorAndAbs()145 bool mustDoOpBetweenFloorAndAbs() const { return fMustDoOpBetweenFloorAndAbs; } 146 147 // If false, SkSL uses a workaround so that sk_FragCoord doesn't actually query gl_FragCoord canUseFragCoord()148 bool canUseFragCoord() const { return fCanUseFragCoord; } 149 150 // If true, short ints can't represent every integer in the 16-bit two's complement range as 151 // required by the spec. SKSL will always emit full ints. incompleteShortIntPrecision()152 bool incompleteShortIntPrecision() const { return fIncompleteShortIntPrecision; } 153 colorSpaceMathNeedsFloat()154 bool colorSpaceMathNeedsFloat() const { return fColorSpaceMathNeedsFloat; } 155 156 // If true, then conditions in for loops need "&& true" to work around driver bugs. addAndTrueToLoopCondition()157 bool addAndTrueToLoopCondition() const { return fAddAndTrueToLoopCondition; } 158 159 // If true, then expressions such as "x && y" or "x || y" are rewritten as 160 // ternary to work around driver bugs. unfoldShortCircuitAsTernary()161 bool unfoldShortCircuitAsTernary() const { return fUnfoldShortCircuitAsTernary; } 162 emulateAbsIntFunction()163 bool emulateAbsIntFunction() const { return fEmulateAbsIntFunction; } 164 rewriteDoWhileLoops()165 bool rewriteDoWhileLoops() const { return fRewriteDoWhileLoops; } 166 rewriteSwitchStatements()167 bool rewriteSwitchStatements() const { return fRewriteSwitchStatements; } 168 removePowWithConstantExponent()169 bool removePowWithConstantExponent() const { return fRemovePowWithConstantExponent; } 170 requiresLocalOutputColorForFBFetch()171 bool requiresLocalOutputColorForFBFetch() const { return fRequiresLocalOutputColorForFBFetch; } 172 mustObfuscateUniformColor()173 bool mustObfuscateUniformColor() const { return fMustObfuscateUniformColor; } 174 175 // The D3D shader compiler, when targeting PS 3.0 (ie within ANGLE) fails to compile certain 176 // constructs. See detailed comments in GrGLCaps.cpp. mustGuardDivisionEvenAfterExplicitZeroCheck()177 bool mustGuardDivisionEvenAfterExplicitZeroCheck() const { 178 return fMustGuardDivisionEvenAfterExplicitZeroCheck; 179 } 180 181 // On Nexus 6, the GL context can get lost if a shader does not write a value to gl_FragColor. 182 // https://bugs.chromium.org/p/chromium/issues/detail?id=445377 mustWriteToFragColor()183 bool mustWriteToFragColor() const { return fMustWriteToFragColor; } 184 185 // The Android emulator claims samplerExternalOES is an unknown type if a default precision 186 // statement is made for the type. noDefaultPrecisionForExternalSamplers()187 bool noDefaultPrecisionForExternalSamplers() const { 188 return fNoDefaultPrecisionForExternalSamplers; 189 } 190 191 // ARM GPUs calculate `matrix * vector` in SPIR-V at full precision, even when the inputs are 192 // RelaxedPrecision. Rewriting the multiply as a sum of vector*scalar fixes this. (skia:11769) rewriteMatrixVectorMultiply()193 bool rewriteMatrixVectorMultiply() const { 194 return fRewriteMatrixVectorMultiply; 195 } 196 197 // Rewrites matrix equality comparisons to avoid an Adreno driver bug. (skia:11308) rewriteMatrixComparisons()198 bool rewriteMatrixComparisons() const { return fRewriteMatrixComparisons; } 199 200 // ANGLE disallows do loops altogether, and we're seeing crashes on Tegra3 with do loops in at 201 // least some cases. canUseDoLoops()202 bool canUseDoLoops() const { return fCanUseDoLoops; } 203 204 // Some GPUs produce poor results when enabling Metal's fastmath option canUseFastMath()205 bool canUseFastMath() const { return fCanUseFastMath; } 206 207 // By default, SkSL pools IR nodes per-program. To debug memory corruption, it is sometimes 208 // helpful to disable that feature. useNodePools()209 bool useNodePools() const { return fUseNodePools; } 210 211 // When we have the option of using either dFdx or dfDy in a shader, this returns whether we 212 // should avoid using dFdx. We have found some drivers have bugs or lower precision when using 213 // dFdx. avoidDfDxForGradientsWhenPossible()214 bool avoidDfDxForGradientsWhenPossible() const { return fAvoidDfDxForGradientsWhenPossible; } 215 216 // Returns the string of an extension that must be enabled in the shader to support 217 // derivatives. If nullptr is returned then no extension needs to be enabled. Before calling 218 // this function, the caller should check that shaderDerivativeSupport exists. shaderDerivativeExtensionString()219 const char* shaderDerivativeExtensionString() const { 220 SkASSERT(this->shaderDerivativeSupport()); 221 return fShaderDerivativeExtensionString; 222 } 223 224 // This returns the name of an extension that must be enabled in the shader, if such a thing is 225 // required in order to use a secondary output in the shader. This returns a nullptr if no such 226 // extension is required. However, the return value of this function does not say whether dual 227 // source blending is supported. secondaryOutputExtensionString()228 const char* secondaryOutputExtensionString() const { return fSecondaryOutputExtensionString; } 229 230 // This returns the name of an extension that must be enabled in the shader to support external 231 // textures. In some cases, two extensions must be enabled - the second extension is returned 232 // by secondExternalTextureExtensionString(). If that function returns nullptr, then only one 233 // extension is required. externalTextureExtensionString()234 const char* externalTextureExtensionString() const { 235 SkASSERT(this->externalTextureSupport()); 236 return fExternalTextureExtensionString; 237 } 238 secondExternalTextureExtensionString()239 const char* secondExternalTextureExtensionString() const { 240 SkASSERT(this->externalTextureSupport()); 241 return fSecondExternalTextureExtensionString; 242 } 243 noperspectiveInterpolationExtensionString()244 const char* noperspectiveInterpolationExtensionString() const { 245 SkASSERT(this->noperspectiveInterpolationSupport()); 246 return fNoPerspectiveInterpolationExtensionString; 247 } 248 sampleVariablesExtensionString()249 const char* sampleVariablesExtensionString() const { 250 SkASSERT(this->sampleMaskSupport()); 251 return fSampleVariablesExtensionString; 252 } 253 tessellationExtensionString()254 const char* tessellationExtensionString() const { 255 SkASSERT(this->tessellationSupport()); 256 return fTessellationExtensionString; 257 } 258 maxFragmentSamplers()259 int maxFragmentSamplers() const { return fMaxFragmentSamplers; } 260 261 // Maximum number of segments a tessellation edge can be divided into. maxTessellationSegments()262 int maxTessellationSegments() const { return fMaxTessellationSegments; } 263 tessellationSupport()264 bool tessellationSupport() const { return SkToBool(fMaxTessellationSegments);} 265 generation()266 GrGLSLGeneration generation() const { return fGLSLGeneration; } 267 268 private: 269 void applyOptionsOverrides(const GrContextOptions& options); 270 271 GrGLSLGeneration fGLSLGeneration; 272 273 bool fShaderDerivativeSupport : 1; 274 bool fDstReadInShaderSupport : 1; 275 bool fDualSourceBlendingSupport : 1; 276 bool fIntegerSupport : 1; 277 bool fNonsquareMatrixSupport : 1; 278 bool fInverseHyperbolicSupport : 1; 279 bool fFBFetchSupport : 1; 280 bool fFBFetchNeedsCustomOutput : 1; 281 bool fUsesPrecisionModifiers : 1; 282 bool fFlatInterpolationSupport : 1; 283 bool fPreferFlatInterpolation : 1; 284 bool fNoPerspectiveInterpolationSupport : 1; 285 bool fSampleMaskSupport : 1; 286 bool fExternalTextureSupport : 1; 287 bool fVertexIDSupport : 1; 288 bool fInfinitySupport : 1; 289 bool fNonconstantArrayIndexSupport : 1; 290 bool fBitManipulationSupport : 1; 291 bool fFloatIs32Bits : 1; 292 bool fHalfIs32Bits : 1; 293 bool fHasLowFragmentPrecision : 1; 294 bool fReducedShaderMode : 1; 295 296 // Used by SkSL to know when to generate polyfills. 297 bool fBuiltinFMASupport : 1; 298 bool fBuiltinDeterminantSupport : 1; 299 300 // Used for specific driver bug work arounds 301 bool fCanUseAnyFunctionInShader : 1; 302 bool fCanUseMinAndAbsTogether : 1; 303 bool fCanUseFractForNegativeValues : 1; 304 bool fMustForceNegatedAtanParamToFloat : 1; 305 bool fMustForceNegatedLdexpParamToMultiply : 1; 306 bool fAtan2ImplementedAsAtanYOverX : 1; 307 bool fMustDoOpBetweenFloorAndAbs : 1; 308 bool fRequiresLocalOutputColorForFBFetch : 1; 309 bool fMustObfuscateUniformColor : 1; 310 bool fMustGuardDivisionEvenAfterExplicitZeroCheck : 1; 311 bool fCanUseFragCoord : 1; 312 bool fIncompleteShortIntPrecision : 1; 313 bool fAddAndTrueToLoopCondition : 1; 314 bool fUnfoldShortCircuitAsTernary : 1; 315 bool fEmulateAbsIntFunction : 1; 316 bool fRewriteDoWhileLoops : 1; 317 bool fRewriteSwitchStatements : 1; 318 bool fRemovePowWithConstantExponent : 1; 319 bool fMustWriteToFragColor : 1; 320 bool fNoDefaultPrecisionForExternalSamplers : 1; 321 bool fRewriteMatrixVectorMultiply : 1; 322 bool fRewriteMatrixComparisons : 1; 323 bool fColorSpaceMathNeedsFloat : 1; 324 bool fCanUseDoLoops : 1; 325 bool fCanUseFastMath : 1; 326 bool fAvoidDfDxForGradientsWhenPossible : 1; 327 328 // This controls behavior of the SkSL compiler, not the code we generate 329 bool fUseNodePools : 1; 330 331 const char* fVersionDeclString; 332 333 const char* fShaderDerivativeExtensionString; 334 const char* fSecondaryOutputExtensionString; 335 const char* fExternalTextureExtensionString; 336 const char* fSecondExternalTextureExtensionString; 337 const char* fNoPerspectiveInterpolationExtensionString; 338 const char* fSampleVariablesExtensionString; 339 const char* fTessellationExtensionString; 340 341 const char* fFBFetchColorName; 342 const char* fFBFetchExtensionString; 343 344 int fMaxFragmentSamplers; 345 int fMaxTessellationSegments; 346 347 AdvBlendEqInteraction fAdvBlendEqInteraction; 348 349 friend class GrCaps; // For initialization. 350 friend class GrDawnCaps; 351 friend class GrD3DCaps; 352 friend class GrGLCaps; 353 friend class GrMockCaps; 354 friend class GrMtlCaps; 355 friend class GrVkCaps; 356 friend class SkSL::ShaderCapsFactory; 357 friend class SkSL::SharedCompiler; 358 }; 359 360 #endif 361