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 } 19 20 struct GrContextOptions; 21 class SkJSONWriter; 22 23 class GrShaderCaps : public SkRefCnt { 24 public: 25 /** 26 * Indicates how GLSL must interact with advanced blend equations. The KHR extension requires 27 * special layout qualifiers in the fragment shader. 28 */ 29 enum AdvBlendEqInteraction { 30 kNotSupported_AdvBlendEqInteraction, //<! No _blend_equation_advanced extension 31 kAutomatic_AdvBlendEqInteraction, //<! No interaction required 32 kGeneralEnable_AdvBlendEqInteraction, //<! layout(blend_support_all_equations) out 33 kSpecificEnables_AdvBlendEqInteraction, //<! Specific layout qualifiers per equation 34 35 kLast_AdvBlendEqInteraction = kSpecificEnables_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; } pathRenderingSupport()47 bool pathRenderingSupport() const { return fPathRenderingSupport; } dstReadInShaderSupport()48 bool dstReadInShaderSupport() const { return fDstReadInShaderSupport; } dualSourceBlendingSupport()49 bool dualSourceBlendingSupport() const { return fDualSourceBlendingSupport; } integerSupport()50 bool integerSupport() const { return fIntegerSupport; } 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 tessellationSupport()75 bool tessellationSupport() const { return fTessellationSupport; } 76 externalTextureSupport()77 bool externalTextureSupport() const { return fExternalTextureSupport; } 78 vertexIDSupport()79 bool vertexIDSupport() const { return fVertexIDSupport; } 80 81 // frexp, ldexp, etc. fpManipulationSupport()82 bool fpManipulationSupport() const { return fFPManipulationSupport; } 83 floatIs32Bits()84 bool floatIs32Bits() const { return fFloatIs32Bits; } 85 halfIs32Bits()86 bool halfIs32Bits() const { return fHalfIs32Bits; } 87 hasLowFragmentPrecision()88 bool hasLowFragmentPrecision() const { return fHasLowFragmentPrecision; } 89 90 // SkSL only. builtinFMASupport()91 bool builtinFMASupport() const { return fBuiltinFMASupport; } 92 advBlendEqInteraction()93 AdvBlendEqInteraction advBlendEqInteraction() const { return fAdvBlendEqInteraction; } 94 mustEnableAdvBlendEqs()95 bool mustEnableAdvBlendEqs() const { 96 return fAdvBlendEqInteraction >= kGeneralEnable_AdvBlendEqInteraction; 97 } 98 mustEnableSpecificAdvBlendEqs()99 bool mustEnableSpecificAdvBlendEqs() const { 100 return fAdvBlendEqInteraction == kSpecificEnables_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 131 // If true, then conditions in for loops need "&& true" to work around driver bugs. addAndTrueToLoopCondition()132 bool addAndTrueToLoopCondition() const { return fAddAndTrueToLoopCondition; } 133 134 // If true, then expressions such as "x && y" or "x || y" are rewritten as 135 // ternary to work around driver bugs. unfoldShortCircuitAsTernary()136 bool unfoldShortCircuitAsTernary() const { return fUnfoldShortCircuitAsTernary; } 137 emulateAbsIntFunction()138 bool emulateAbsIntFunction() const { return fEmulateAbsIntFunction; } 139 rewriteDoWhileLoops()140 bool rewriteDoWhileLoops() const { return fRewriteDoWhileLoops; } 141 removePowWithConstantExponent()142 bool removePowWithConstantExponent() const { return fRemovePowWithConstantExponent; } 143 requiresLocalOutputColorForFBFetch()144 bool requiresLocalOutputColorForFBFetch() const { return fRequiresLocalOutputColorForFBFetch; } 145 mustObfuscateUniformColor()146 bool mustObfuscateUniformColor() const { return fMustObfuscateUniformColor; } 147 148 // The D3D shader compiler, when targeting PS 3.0 (ie within ANGLE) fails to compile certain 149 // constructs. See detailed comments in GrGLCaps.cpp. mustGuardDivisionEvenAfterExplicitZeroCheck()150 bool mustGuardDivisionEvenAfterExplicitZeroCheck() const { 151 return fMustGuardDivisionEvenAfterExplicitZeroCheck; 152 } 153 154 // On Pixel 3, 3a, and 4 devices we've noticed that the simple function: 155 // half4 blend(half4 a, half4 b) { return a.a * b; } 156 // may return (0, 0, 0, 1) when b is (0, 0, 0, 0). inBlendModesFailRandomlyForAllZeroVec()157 bool inBlendModesFailRandomlyForAllZeroVec() const { 158 return fInBlendModesFailRandomlyForAllZeroVec; 159 } 160 161 // On Nexus 6, the GL context can get lost if a shader does not write a value to gl_FragColor. 162 // https://bugs.chromium.org/p/chromium/issues/detail?id=445377 mustWriteToFragColor()163 bool mustWriteToFragColor() const { return fMustWriteToFragColor; } 164 165 // The Android emulator claims samplerExternalOES is an unknown type if a default precision 166 // statement is made for the type. noDefaultPrecisionForExternalSamplers()167 bool noDefaultPrecisionForExternalSamplers() const { 168 return fNoDefaultPrecisionForExternalSamplers; 169 } 170 171 // The sample mask round rect op draws nothing on several Adreno and Radeon bots. Other ops that 172 // use sample mask while rendering to stencil seem to work fine. 173 // http://skbug.com/8921 canOnlyUseSampleMaskWithStencil()174 bool canOnlyUseSampleMaskWithStencil() const { return fCanOnlyUseSampleMaskWithStencil; } 175 176 // Returns the string of an extension that must be enabled in the shader to support 177 // derivatives. If nullptr is returned then no extension needs to be enabled. Before calling 178 // this function, the caller should check that shaderDerivativeSupport exists. shaderDerivativeExtensionString()179 const char* shaderDerivativeExtensionString() const { 180 SkASSERT(this->shaderDerivativeSupport()); 181 return fShaderDerivativeExtensionString; 182 } 183 184 // Returns the string of an extension that must be enabled in the shader to support geometry 185 // shaders. If nullptr is returned then no extension needs to be enabled. Before calling this 186 // function, the caller must verify that geometryShaderSupport exists. geometryShaderExtensionString()187 const char* geometryShaderExtensionString() const { 188 SkASSERT(this->geometryShaderSupport()); 189 return fGeometryShaderExtensionString; 190 } 191 192 // Returns the string of an extension that must be enabled in the shader to support 193 // geometry shader invocations. If nullptr is returned then no extension needs to be enabled. 194 // Before calling this function, the caller must verify that gsInvocationsSupport exists. gsInvocationsExtensionString()195 const char* gsInvocationsExtensionString() const { 196 SkASSERT(this->gsInvocationsSupport()); 197 return fGSInvocationsExtensionString; 198 } 199 200 // Returns the string of an extension that will do all necessary coord transfomations needed 201 // when reading the fragment position. If such an extension does not exisits, this function 202 // returns a nullptr, and all transforms of the frag position must be done manually in the 203 // shader. fragCoordConventionsExtensionString()204 const char* fragCoordConventionsExtensionString() const { 205 return fFragCoordConventionsExtensionString; 206 } 207 208 // This returns the name of an extension that must be enabled in the shader, if such a thing is 209 // required in order to use a secondary output in the shader. This returns a nullptr if no such 210 // extension is required. However, the return value of this function does not say whether dual 211 // source blending is supported. secondaryOutputExtensionString()212 const char* secondaryOutputExtensionString() const { return fSecondaryOutputExtensionString; } 213 214 // This returns the name of an extension that must be enabled in the shader to support external 215 // textures. In some cases, two extensions must be enabled - the second extension is returned 216 // by secondExternalTextureExtensionString(). If that function returns nullptr, then only one 217 // extension is required. externalTextureExtensionString()218 const char* externalTextureExtensionString() const { 219 SkASSERT(this->externalTextureSupport()); 220 return fExternalTextureExtensionString; 221 } 222 secondExternalTextureExtensionString()223 const char* secondExternalTextureExtensionString() const { 224 SkASSERT(this->externalTextureSupport()); 225 return fSecondExternalTextureExtensionString; 226 } 227 noperspectiveInterpolationExtensionString()228 const char* noperspectiveInterpolationExtensionString() const { 229 SkASSERT(this->noperspectiveInterpolationSupport()); 230 return fNoPerspectiveInterpolationExtensionString; 231 } 232 sampleVariablesExtensionString()233 const char* sampleVariablesExtensionString() const { 234 SkASSERT(this->sampleMaskSupport()); 235 return fSampleVariablesExtensionString; 236 } 237 tessellationExtensionString()238 const char* tessellationExtensionString() const { 239 SkASSERT(this->tessellationSupport()); 240 return fTessellationExtensionString; 241 } 242 maxFragmentSamplers()243 int maxFragmentSamplers() const { return fMaxFragmentSamplers; } 244 textureSwizzleAppliedInShader()245 bool textureSwizzleAppliedInShader() const { return fTextureSwizzleAppliedInShader; } 246 generation()247 GrGLSLGeneration generation() const { return fGLSLGeneration; } 248 249 private: 250 void applyOptionsOverrides(const GrContextOptions& options); 251 252 GrGLSLGeneration fGLSLGeneration; 253 254 bool fShaderDerivativeSupport : 1; 255 bool fGeometryShaderSupport : 1; 256 bool fGSInvocationsSupport : 1; 257 bool fPathRenderingSupport : 1; 258 bool fDstReadInShaderSupport : 1; 259 bool fDualSourceBlendingSupport : 1; 260 bool fIntegerSupport : 1; 261 bool fFBFetchSupport : 1; 262 bool fFBFetchNeedsCustomOutput : 1; 263 bool fUsesPrecisionModifiers : 1; 264 bool fFlatInterpolationSupport : 1; 265 bool fPreferFlatInterpolation : 1; 266 bool fNoPerspectiveInterpolationSupport : 1; 267 bool fSampleMaskSupport : 1; 268 bool fTessellationSupport : 1; 269 bool fExternalTextureSupport : 1; 270 bool fVertexIDSupport : 1; 271 bool fFPManipulationSupport : 1; 272 bool fFloatIs32Bits : 1; 273 bool fHalfIs32Bits : 1; 274 bool fHasLowFragmentPrecision : 1; 275 bool fTextureSwizzleAppliedInShader : 1; 276 277 // Used by SkSL to know when to generate polyfills. 278 bool fBuiltinFMASupport : 1; 279 280 // Used for specific driver bug work arounds 281 bool fCanUseAnyFunctionInShader : 1; 282 bool fCanUseMinAndAbsTogether : 1; 283 bool fCanUseFractForNegativeValues : 1; 284 bool fMustForceNegatedAtanParamToFloat : 1; 285 bool fAtan2ImplementedAsAtanYOverX : 1; 286 bool fMustDoOpBetweenFloorAndAbs : 1; 287 bool fRequiresLocalOutputColorForFBFetch : 1; 288 bool fMustObfuscateUniformColor : 1; 289 bool fMustGuardDivisionEvenAfterExplicitZeroCheck : 1; 290 bool fInBlendModesFailRandomlyForAllZeroVec : 1; 291 bool fCanUseFragCoord : 1; 292 bool fIncompleteShortIntPrecision : 1; 293 bool fAddAndTrueToLoopCondition : 1; 294 bool fUnfoldShortCircuitAsTernary : 1; 295 bool fEmulateAbsIntFunction : 1; 296 bool fRewriteDoWhileLoops : 1; 297 bool fRemovePowWithConstantExponent : 1; 298 bool fMustWriteToFragColor : 1; 299 bool fNoDefaultPrecisionForExternalSamplers : 1; 300 bool fCanOnlyUseSampleMaskWithStencil : 1; 301 302 const char* fVersionDeclString; 303 304 const char* fShaderDerivativeExtensionString; 305 const char* fGeometryShaderExtensionString; 306 const char* fGSInvocationsExtensionString; 307 const char* fFragCoordConventionsExtensionString; 308 const char* fSecondaryOutputExtensionString; 309 const char* fExternalTextureExtensionString; 310 const char* fSecondExternalTextureExtensionString; 311 const char* fNoPerspectiveInterpolationExtensionString; 312 const char* fSampleVariablesExtensionString; 313 const char* fTessellationExtensionString; 314 315 const char* fFBFetchColorName; 316 const char* fFBFetchExtensionString; 317 318 int fMaxFragmentSamplers; 319 320 AdvBlendEqInteraction fAdvBlendEqInteraction; 321 322 friend class GrCaps; // For initialization. 323 friend class GrDawnCaps; 324 friend class GrGLCaps; 325 friend class GrMockCaps; 326 friend class GrMtlCaps; 327 friend class GrVkCaps; 328 friend class SkSL::ShaderCapsFactory; 329 }; 330 331 #endif 332