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 73 // Can we use sample variables everywhere? sampleVariablesSupport()74 bool sampleVariablesSupport() const { return fSampleVariablesSupport; } 75 76 // Can we use sample variables when rendering to stencil? (This is a workaround for platforms 77 // where sample variables are broken in general, but seem to work when rendering to stencil.) sampleVariablesStencilSupport()78 bool sampleVariablesStencilSupport() const { return fSampleVariablesStencilSupport; } 79 externalTextureSupport()80 bool externalTextureSupport() const { return fExternalTextureSupport; } 81 vertexIDSupport()82 bool vertexIDSupport() const { return fVertexIDSupport; } 83 84 // frexp, ldexp, etc. fpManipulationSupport()85 bool fpManipulationSupport() const { return fFPManipulationSupport; } 86 floatIs32Bits()87 bool floatIs32Bits() const { return fFloatIs32Bits; } 88 halfIs32Bits()89 bool halfIs32Bits() const { return fHalfIs32Bits; } 90 hasLowFragmentPrecision()91 bool hasLowFragmentPrecision() const { return fHasLowFragmentPrecision; } 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 // On Nexus 6, the GL context can get lost if a shader does not write a value to gl_FragColor. 158 // https://bugs.chromium.org/p/chromium/issues/detail?id=445377 mustWriteToFragColor()159 bool mustWriteToFragColor() const { return fMustWriteToFragColor; } 160 161 // The Android emulator claims samplerExternalOES is an unknown type if a default precision 162 // statement is made for the type. noDefaultPrecisionForExternalSamplers()163 bool noDefaultPrecisionForExternalSamplers() const { 164 return fNoDefaultPrecisionForExternalSamplers; 165 } 166 167 // Returns the string of an extension that must be enabled in the shader to support 168 // derivatives. If nullptr is returned then no extension needs to be enabled. Before calling 169 // this function, the caller should check that shaderDerivativeSupport exists. shaderDerivativeExtensionString()170 const char* shaderDerivativeExtensionString() const { 171 SkASSERT(this->shaderDerivativeSupport()); 172 return fShaderDerivativeExtensionString; 173 } 174 175 // Returns the string of an extension that must be enabled in the shader to support geometry 176 // shaders. If nullptr is returned then no extension needs to be enabled. Before calling this 177 // function, the caller must verify that geometryShaderSupport exists. geometryShaderExtensionString()178 const char* geometryShaderExtensionString() const { 179 SkASSERT(this->geometryShaderSupport()); 180 return fGeometryShaderExtensionString; 181 } 182 183 // Returns the string of an extension that must be enabled in the shader to support 184 // geometry shader invocations. If nullptr is returned then no extension needs to be enabled. 185 // Before calling this function, the caller must verify that gsInvocationsSupport exists. gsInvocationsExtensionString()186 const char* gsInvocationsExtensionString() const { 187 SkASSERT(this->gsInvocationsSupport()); 188 return fGSInvocationsExtensionString; 189 } 190 191 // Returns the string of an extension that will do all necessary coord transfomations needed 192 // when reading the fragment position. If such an extension does not exisits, this function 193 // returns a nullptr, and all transforms of the frag position must be done manually in the 194 // shader. fragCoordConventionsExtensionString()195 const char* fragCoordConventionsExtensionString() const { 196 return fFragCoordConventionsExtensionString; 197 } 198 199 // This returns the name of an extension that must be enabled in the shader, if such a thing is 200 // required in order to use a secondary output in the shader. This returns a nullptr if no such 201 // extension is required. However, the return value of this function does not say whether dual 202 // source blending is supported. secondaryOutputExtensionString()203 const char* secondaryOutputExtensionString() const { return fSecondaryOutputExtensionString; } 204 205 // This returns the name of an extension that must be enabled in the shader to support external 206 // textures. In some cases, two extensions must be enabled - the second extension is returned 207 // by secondExternalTextureExtensionString(). If that function returns nullptr, then only one 208 // extension is required. externalTextureExtensionString()209 const char* externalTextureExtensionString() const { 210 SkASSERT(this->externalTextureSupport()); 211 return fExternalTextureExtensionString; 212 } 213 secondExternalTextureExtensionString()214 const char* secondExternalTextureExtensionString() const { 215 SkASSERT(this->externalTextureSupport()); 216 return fSecondExternalTextureExtensionString; 217 } 218 noperspectiveInterpolationExtensionString()219 const char* noperspectiveInterpolationExtensionString() const { 220 SkASSERT(this->noperspectiveInterpolationSupport()); 221 return fNoPerspectiveInterpolationExtensionString; 222 } 223 sampleVariablesExtensionString()224 const char* sampleVariablesExtensionString() const { 225 SkASSERT(this->sampleVariablesSupport() || this->sampleVariablesStencilSupport()); 226 return fSampleVariablesExtensionString; 227 } 228 maxFragmentSamplers()229 int maxFragmentSamplers() const { return fMaxFragmentSamplers; } 230 textureSwizzleAppliedInShader()231 bool textureSwizzleAppliedInShader() const { return fTextureSwizzleAppliedInShader; } 232 generation()233 GrGLSLGeneration generation() const { return fGLSLGeneration; } 234 235 private: 236 void applyOptionsOverrides(const GrContextOptions& options); 237 238 GrGLSLGeneration fGLSLGeneration; 239 240 bool fShaderDerivativeSupport : 1; 241 bool fGeometryShaderSupport : 1; 242 bool fGSInvocationsSupport : 1; 243 bool fPathRenderingSupport : 1; 244 bool fDstReadInShaderSupport : 1; 245 bool fDualSourceBlendingSupport : 1; 246 bool fIntegerSupport : 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 fSampleVariablesSupport : 1; 254 bool fSampleVariablesStencilSupport : 1; 255 bool fExternalTextureSupport : 1; 256 bool fVertexIDSupport : 1; 257 bool fFPManipulationSupport : 1; 258 bool fFloatIs32Bits : 1; 259 bool fHalfIs32Bits : 1; 260 bool fHasLowFragmentPrecision : 1; 261 bool fTextureSwizzleAppliedInShader : 1; 262 263 // Used by SkSL to know when to generate polyfills. 264 bool fBuiltinFMASupport : 1; 265 266 // Used for specific driver bug work arounds 267 bool fCanUseAnyFunctionInShader : 1; 268 bool fCanUseMinAndAbsTogether : 1; 269 bool fCanUseFractForNegativeValues : 1; 270 bool fMustForceNegatedAtanParamToFloat : 1; 271 bool fAtan2ImplementedAsAtanYOverX : 1; 272 bool fMustDoOpBetweenFloorAndAbs : 1; 273 bool fRequiresLocalOutputColorForFBFetch : 1; 274 bool fMustObfuscateUniformColor : 1; 275 bool fMustGuardDivisionEvenAfterExplicitZeroCheck : 1; 276 bool fCanUseFragCoord : 1; 277 bool fIncompleteShortIntPrecision : 1; 278 bool fAddAndTrueToLoopCondition : 1; 279 bool fUnfoldShortCircuitAsTernary : 1; 280 bool fEmulateAbsIntFunction : 1; 281 bool fRewriteDoWhileLoops : 1; 282 bool fRemovePowWithConstantExponent : 1; 283 bool fMustWriteToFragColor : 1; 284 bool fNoDefaultPrecisionForExternalSamplers : 1; 285 286 const char* fVersionDeclString; 287 288 const char* fShaderDerivativeExtensionString; 289 const char* fGeometryShaderExtensionString; 290 const char* fGSInvocationsExtensionString; 291 const char* fFragCoordConventionsExtensionString; 292 const char* fSecondaryOutputExtensionString; 293 const char* fExternalTextureExtensionString; 294 const char* fSecondExternalTextureExtensionString; 295 const char* fNoPerspectiveInterpolationExtensionString; 296 const char* fSampleVariablesExtensionString; 297 298 const char* fFBFetchColorName; 299 const char* fFBFetchExtensionString; 300 301 int fMaxFragmentSamplers; 302 303 AdvBlendEqInteraction fAdvBlendEqInteraction; 304 305 friend class GrCaps; // For initialization. 306 friend class GrDawnCaps; 307 friend class GrGLCaps; 308 friend class GrMockCaps; 309 friend class GrMtlCaps; 310 friend class GrVkCaps; 311 friend class SkSL::ShaderCapsFactory; 312 }; 313 314 #endif 315