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 "GrSwizzle.h" 12 #include "GrTypesPriv.h" 13 #include "SkRefCnt.h" 14 #include "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; } imageLoadStoreSupport()51 int imageLoadStoreSupport() const { return fImageLoadStoreSupport; } 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 dropsTileOnZeroDivide()68 bool dropsTileOnZeroDivide() const { return fDropsTileOnZeroDivide; } 69 flatInterpolationSupport()70 bool flatInterpolationSupport() const { return fFlatInterpolationSupport; } 71 preferFlatInterpolation()72 bool preferFlatInterpolation() const { return fPreferFlatInterpolation; } 73 noperspectiveInterpolationSupport()74 bool noperspectiveInterpolationSupport() const { return fNoPerspectiveInterpolationSupport; } 75 sampleVariablesSupport()76 bool sampleVariablesSupport() const { return fSampleVariablesSupport; } 77 externalTextureSupport()78 bool externalTextureSupport() const { return fExternalTextureSupport; } 79 vertexIDSupport()80 bool vertexIDSupport() const { return fVertexIDSupport; } 81 82 // frexp, ldexp, etc. fpManipulationSupport()83 bool fpManipulationSupport() const { return fFPManipulationSupport; } 84 floatIs32Bits()85 bool floatIs32Bits() const { return fFloatIs32Bits; } 86 halfIs32Bits()87 bool halfIs32Bits() const { return fHalfIs32Bits; } 88 hasLowFragmentPrecision()89 bool hasLowFragmentPrecision() const { return fHasLowFragmentPrecision; } 90 unsignedSupport()91 bool unsignedSupport() const { return fUnsignedSupport; } 92 93 // SkSL only. builtinFMASupport()94 bool builtinFMASupport() const { return fBuiltinFMASupport; } 95 advBlendEqInteraction()96 AdvBlendEqInteraction advBlendEqInteraction() const { return fAdvBlendEqInteraction; } 97 mustEnableAdvBlendEqs()98 bool mustEnableAdvBlendEqs() const { 99 return fAdvBlendEqInteraction >= kGeneralEnable_AdvBlendEqInteraction; 100 } 101 mustEnableSpecificAdvBlendEqs()102 bool mustEnableSpecificAdvBlendEqs() const { 103 return fAdvBlendEqInteraction == kSpecificEnables_AdvBlendEqInteraction; 104 } 105 mustDeclareFragmentShaderOutput()106 bool mustDeclareFragmentShaderOutput() const { return fGLSLGeneration > k110_GrGLSLGeneration; } 107 usesPrecisionModifiers()108 bool usesPrecisionModifiers() const { return fUsesPrecisionModifiers; } 109 110 // Returns whether we can use the glsl function any() in our shader code. canUseAnyFunctionInShader()111 bool canUseAnyFunctionInShader() const { return fCanUseAnyFunctionInShader; } 112 canUseMinAndAbsTogether()113 bool canUseMinAndAbsTogether() const { return fCanUseMinAndAbsTogether; } 114 canUseFractForNegativeValues()115 bool canUseFractForNegativeValues() const { return fCanUseFractForNegativeValues; } 116 mustForceNegatedAtanParamToFloat()117 bool mustForceNegatedAtanParamToFloat() const { return fMustForceNegatedAtanParamToFloat; } 118 119 // Returns whether a device incorrectly implements atan(y,x) as atan(y/x) atan2ImplementedAsAtanYOverX()120 bool atan2ImplementedAsAtanYOverX() const { return fAtan2ImplementedAsAtanYOverX; } 121 122 // If this returns true some operation (could be a no op) must be called between floor and abs 123 // to make sure the driver compiler doesn't inline them together which can cause a driver bug in 124 // the shader. mustDoOpBetweenFloorAndAbs()125 bool mustDoOpBetweenFloorAndAbs() const { return fMustDoOpBetweenFloorAndAbs; } 126 127 // If false, SkSL uses a workaround so that sk_FragCoord doesn't actually query gl_FragCoord canUseFragCoord()128 bool canUseFragCoord() const { return fCanUseFragCoord; } 129 130 // If true, short ints can't represent every integer in the 16-bit two's complement range as 131 // required by the spec. SKSL will always emit full ints. incompleteShortIntPrecision()132 bool incompleteShortIntPrecision() const { return fIncompleteShortIntPrecision; } 133 134 // If true, then conditions in for loops need "&& true" to work around driver bugs. addAndTrueToLoopCondition()135 bool addAndTrueToLoopCondition() const { return fAddAndTrueToLoopCondition; } 136 137 // If true, then expressions such as "x && y" or "x || y" are rewritten as 138 // ternary to work around driver bugs. unfoldShortCircuitAsTernary()139 bool unfoldShortCircuitAsTernary() const { return fUnfoldShortCircuitAsTernary; } 140 emulateAbsIntFunction()141 bool emulateAbsIntFunction() const { return fEmulateAbsIntFunction; } 142 rewriteDoWhileLoops()143 bool rewriteDoWhileLoops() const { return fRewriteDoWhileLoops; } 144 removePowWithConstantExponent()145 bool removePowWithConstantExponent() const { return fRemovePowWithConstantExponent; } 146 requiresLocalOutputColorForFBFetch()147 bool requiresLocalOutputColorForFBFetch() const { return fRequiresLocalOutputColorForFBFetch; } 148 mustObfuscateUniformColor()149 bool mustObfuscateUniformColor() const { return fMustObfuscateUniformColor; } 150 151 // The D3D shader compiler, when targeting PS 3.0 (ie within ANGLE) fails to compile certain 152 // constructs. See detailed comments in GrGLCaps.cpp. mustGuardDivisionEvenAfterExplicitZeroCheck()153 bool mustGuardDivisionEvenAfterExplicitZeroCheck() const { 154 return fMustGuardDivisionEvenAfterExplicitZeroCheck; 155 } 156 157 // Returns the string of an extension that must be enabled in the shader to support 158 // derivatives. If nullptr is returned then no extension needs to be enabled. Before calling 159 // this function, the caller should check that shaderDerivativeSupport exists. shaderDerivativeExtensionString()160 const char* shaderDerivativeExtensionString() const { 161 SkASSERT(this->shaderDerivativeSupport()); 162 return fShaderDerivativeExtensionString; 163 } 164 165 // Returns the string of an extension that must be enabled in the shader to support geometry 166 // shaders. If nullptr is returned then no extension needs to be enabled. Before calling this 167 // function, the caller must verify that geometryShaderSupport exists. geometryShaderExtensionString()168 const char* geometryShaderExtensionString() const { 169 SkASSERT(this->geometryShaderSupport()); 170 return fGeometryShaderExtensionString; 171 } 172 173 // Returns the string of an extension that must be enabled in the shader to support 174 // geometry shader invocations. If nullptr is returned then no extension needs to be enabled. 175 // Before calling this function, the caller must verify that gsInvocationsSupport exists. gsInvocationsExtensionString()176 const char* gsInvocationsExtensionString() const { 177 SkASSERT(this->gsInvocationsSupport()); 178 return fGSInvocationsExtensionString; 179 } 180 181 // Returns the string of an extension that will do all necessary coord transfomations needed 182 // when reading the fragment position. If such an extension does not exisits, this function 183 // returns a nullptr, and all transforms of the frag position must be done manually in the 184 // shader. fragCoordConventionsExtensionString()185 const char* fragCoordConventionsExtensionString() const { 186 return fFragCoordConventionsExtensionString; 187 } 188 189 // This returns the name of an extension that must be enabled in the shader, if such a thing is 190 // required in order to use a secondary output in the shader. This returns a nullptr if no such 191 // extension is required. However, the return value of this function does not say whether dual 192 // source blending is supported. secondaryOutputExtensionString()193 const char* secondaryOutputExtensionString() const { return fSecondaryOutputExtensionString; } 194 195 // This returns the name of an extension that must be enabled in the shader to support external 196 // textures. In some cases, two extensions must be enabled - the second extension is returned 197 // by secondExternalTextureExtensionString(). If that function returns nullptr, then only one 198 // extension is required. externalTextureExtensionString()199 const char* externalTextureExtensionString() const { 200 SkASSERT(this->externalTextureSupport()); 201 return fExternalTextureExtensionString; 202 } 203 secondExternalTextureExtensionString()204 const char* secondExternalTextureExtensionString() const { 205 SkASSERT(this->externalTextureSupport()); 206 return fSecondExternalTextureExtensionString; 207 } 208 noperspectiveInterpolationExtensionString()209 const char* noperspectiveInterpolationExtensionString() const { 210 SkASSERT(this->noperspectiveInterpolationSupport()); 211 return fNoPerspectiveInterpolationExtensionString; 212 } 213 sampleVariablesExtensionString()214 const char* sampleVariablesExtensionString() const { 215 SkASSERT(this->sampleVariablesSupport()); 216 return fSampleVariablesExtensionString; 217 } 218 imageLoadStoreExtensionString()219 const char* imageLoadStoreExtensionString() const { 220 SkASSERT(this->imageLoadStoreSupport()); 221 return fImageLoadStoreExtensionString; 222 } 223 maxFragmentSamplers()224 int maxFragmentSamplers() const { return fMaxFragmentSamplers; } 225 226 /** 227 * Given a texture's config, this determines what swizzle must be appended to accesses to the 228 * texture in generated shader code. Swizzling may be implemented in texture parameters or a 229 * sampler rather than in the shader. In this case the returned swizzle will always be "rgba". 230 */ configTextureSwizzle(GrPixelConfig config)231 const GrSwizzle& configTextureSwizzle(GrPixelConfig config) const { 232 return fConfigTextureSwizzle[config]; 233 } 234 235 /** Swizzle that should occur on the fragment shader outputs for a given config. */ configOutputSwizzle(GrPixelConfig config)236 const GrSwizzle& configOutputSwizzle(GrPixelConfig config) const { 237 return fConfigOutputSwizzle[config]; 238 } 239 generation()240 GrGLSLGeneration generation() const { return fGLSLGeneration; } 241 242 private: 243 void applyOptionsOverrides(const GrContextOptions& options); 244 245 GrGLSLGeneration fGLSLGeneration; 246 247 bool fShaderDerivativeSupport : 1; 248 bool fGeometryShaderSupport : 1; 249 bool fGSInvocationsSupport : 1; 250 bool fPathRenderingSupport : 1; 251 bool fDstReadInShaderSupport : 1; 252 bool fDualSourceBlendingSupport : 1; 253 bool fIntegerSupport : 1; 254 bool fImageLoadStoreSupport : 1; 255 bool fDropsTileOnZeroDivide : 1; 256 bool fFBFetchSupport : 1; 257 bool fFBFetchNeedsCustomOutput : 1; 258 bool fUsesPrecisionModifiers : 1; 259 bool fFlatInterpolationSupport : 1; 260 bool fPreferFlatInterpolation : 1; 261 bool fNoPerspectiveInterpolationSupport : 1; 262 bool fSampleVariablesSupport : 1; 263 bool fExternalTextureSupport : 1; 264 bool fVertexIDSupport : 1; 265 bool fFPManipulationSupport : 1; 266 bool fFloatIs32Bits : 1; 267 bool fHalfIs32Bits : 1; 268 bool fHasLowFragmentPrecision : 1; 269 bool fUnsignedSupport : 1; 270 271 // Used by SkSL to know when to generate polyfills. 272 bool fBuiltinFMASupport : 1; 273 274 // Used for specific driver bug work arounds 275 bool fCanUseAnyFunctionInShader : 1; 276 bool fCanUseMinAndAbsTogether : 1; 277 bool fCanUseFractForNegativeValues : 1; 278 bool fMustForceNegatedAtanParamToFloat : 1; 279 bool fAtan2ImplementedAsAtanYOverX : 1; 280 bool fMustDoOpBetweenFloorAndAbs : 1; 281 bool fRequiresLocalOutputColorForFBFetch : 1; 282 bool fMustObfuscateUniformColor : 1; 283 bool fMustGuardDivisionEvenAfterExplicitZeroCheck : 1; 284 bool fCanUseFragCoord : 1; 285 bool fIncompleteShortIntPrecision : 1; 286 bool fAddAndTrueToLoopCondition : 1; 287 bool fUnfoldShortCircuitAsTernary : 1; 288 bool fEmulateAbsIntFunction : 1; 289 bool fRewriteDoWhileLoops : 1; 290 bool fRemovePowWithConstantExponent : 1; 291 292 const char* fVersionDeclString; 293 294 const char* fShaderDerivativeExtensionString; 295 const char* fGeometryShaderExtensionString; 296 const char* fGSInvocationsExtensionString; 297 const char* fFragCoordConventionsExtensionString; 298 const char* fSecondaryOutputExtensionString; 299 const char* fExternalTextureExtensionString; 300 const char* fSecondExternalTextureExtensionString; 301 const char* fNoPerspectiveInterpolationExtensionString; 302 const char* fSampleVariablesExtensionString; 303 const char* fImageLoadStoreExtensionString; 304 305 const char* fFBFetchColorName; 306 const char* fFBFetchExtensionString; 307 308 int fMaxFragmentSamplers; 309 310 AdvBlendEqInteraction fAdvBlendEqInteraction; 311 312 GrSwizzle fConfigTextureSwizzle[kGrPixelConfigCnt]; 313 GrSwizzle fConfigOutputSwizzle[kGrPixelConfigCnt]; 314 315 friend class GrCaps; // For initialization. 316 friend class GrGLCaps; 317 friend class GrMockCaps; 318 friend class GrMtlCaps; 319 friend class GrVkCaps; 320 friend class SkSL::ShaderCapsFactory; 321 }; 322 323 #endif 324