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