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