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 9 #ifndef GrShaderCaps_DEFINED 10 #define GrShaderCaps_DEFINED 11 12 #include "../private/GrSwizzle.h" 13 #include "../private/GrGLSL.h" 14 15 namespace SkSL { 16 class ShaderCapsFactory; 17 } 18 struct GrContextOptions; 19 20 class GrShaderCaps : public SkRefCnt { 21 public: 22 /** Info about shader variable precision within a given shader stage. That is, this info 23 is relevant to a float (or vecNf) variable declared with a GrSLPrecision 24 in a given GrShaderType. The info here is hoisted from the OpenGL spec. */ 25 struct PrecisionInfo { PrecisionInfoPrecisionInfo26 PrecisionInfo() { 27 fLogRangeLow = 0; 28 fLogRangeHigh = 0; 29 fBits = 0; 30 } 31 32 /** Is this precision level allowed in the shader stage? */ supportedPrecisionInfo33 bool supported() const { return 0 != fBits; } 34 35 bool operator==(const PrecisionInfo& that) const { 36 return fLogRangeLow == that.fLogRangeLow && fLogRangeHigh == that.fLogRangeHigh && 37 fBits == that.fBits; 38 } 39 bool operator!=(const PrecisionInfo& that) const { return !(*this == that); } 40 41 /** floor(log2(|min_value|)) */ 42 int fLogRangeLow; 43 /** floor(log2(|max_value|)) */ 44 int fLogRangeHigh; 45 /** Number of bits of precision. As defined in OpenGL (with names modified to reflect this 46 struct) : 47 """ 48 If the smallest representable value greater than 1 is 1 + e, then fBits will 49 contain floor(log2(e)), and every value in the range [2^fLogRangeLow, 50 2^fLogRangeHigh] can be represented to at least one part in 2^fBits. 51 """ 52 */ 53 int fBits; 54 }; 55 56 /** 57 * Indicates how GLSL must interact with advanced blend equations. The KHR extension requires 58 * special layout qualifiers in the fragment shader. 59 */ 60 enum AdvBlendEqInteraction { 61 kNotSupported_AdvBlendEqInteraction, //<! No _blend_equation_advanced extension 62 kAutomatic_AdvBlendEqInteraction, //<! No interaction required 63 kGeneralEnable_AdvBlendEqInteraction, //<! layout(blend_support_all_equations) out 64 kSpecificEnables_AdvBlendEqInteraction, //<! Specific layout qualifiers per equation 65 66 kLast_AdvBlendEqInteraction = kSpecificEnables_AdvBlendEqInteraction 67 }; 68 69 GrShaderCaps(const GrContextOptions&); 70 71 SkString dump() const; 72 shaderDerivativeSupport()73 bool shaderDerivativeSupport() const { return fShaderDerivativeSupport; } geometryShaderSupport()74 bool geometryShaderSupport() const { return fGeometryShaderSupport; } pathRenderingSupport()75 bool pathRenderingSupport() const { return fPathRenderingSupport; } dstReadInShaderSupport()76 bool dstReadInShaderSupport() const { return fDstReadInShaderSupport; } dualSourceBlendingSupport()77 bool dualSourceBlendingSupport() const { return fDualSourceBlendingSupport; } integerSupport()78 bool integerSupport() const { return fIntegerSupport; } texelBufferSupport()79 bool texelBufferSupport() const { return fTexelBufferSupport; } imageLoadStoreSupport()80 int imageLoadStoreSupport() const { return fImageLoadStoreSupport; } 81 82 /** 83 * Get the precision info for a variable of type kFloat_GrSLType, kVec2f_GrSLType, etc in a 84 * given shader type. If the shader type is not supported or the precision level is not 85 * supported in that shader type then the returned struct will report false when supported() is 86 * called. 87 */ getFloatShaderPrecisionInfo(GrShaderType shaderType,GrSLPrecision precision)88 const PrecisionInfo& getFloatShaderPrecisionInfo(GrShaderType shaderType, 89 GrSLPrecision precision) const { 90 return fFloatPrecisions[shaderType][precision]; 91 } 92 93 /** 94 * Is there any difference between the float shader variable precision types? If this is true 95 * then unless the shader type is not supported, any call to getFloatShaderPrecisionInfo() would 96 * report the same info for all precisions in all shader types. 97 */ floatPrecisionVaries()98 bool floatPrecisionVaries() const { return fShaderPrecisionVaries; } 99 100 /** 101 * Some helper functions for encapsulating various extensions to read FB Buffer on openglES 102 * 103 * TODO(joshualitt) On desktop opengl 4.2+ we can achieve something similar to this effect 104 */ fbFetchSupport()105 bool fbFetchSupport() const { return fFBFetchSupport; } 106 fbFetchNeedsCustomOutput()107 bool fbFetchNeedsCustomOutput() const { return fFBFetchNeedsCustomOutput; } 108 bindlessTextureSupport()109 bool bindlessTextureSupport() const { return fBindlessTextureSupport; } 110 versionDeclString()111 const char* versionDeclString() const { return fVersionDeclString; } 112 fbFetchColorName()113 const char* fbFetchColorName() const { return fFBFetchColorName; } 114 fbFetchExtensionString()115 const char* fbFetchExtensionString() const { return fFBFetchExtensionString; } 116 dropsTileOnZeroDivide()117 bool dropsTileOnZeroDivide() const { return fDropsTileOnZeroDivide; } 118 flatInterpolationSupport()119 bool flatInterpolationSupport() const { return fFlatInterpolationSupport; } 120 noperspectiveInterpolationSupport()121 bool noperspectiveInterpolationSupport() const { return fNoPerspectiveInterpolationSupport; } 122 multisampleInterpolationSupport()123 bool multisampleInterpolationSupport() const { return fMultisampleInterpolationSupport; } 124 sampleVariablesSupport()125 bool sampleVariablesSupport() const { return fSampleVariablesSupport; } 126 sampleMaskOverrideCoverageSupport()127 bool sampleMaskOverrideCoverageSupport() const { return fSampleMaskOverrideCoverageSupport; } 128 externalTextureSupport()129 bool externalTextureSupport() const { return fExternalTextureSupport; } 130 texelFetchSupport()131 bool texelFetchSupport() const { return fTexelFetchSupport; } 132 vertexIDSupport()133 bool vertexIDSupport() const { return fVertexIDSupport; } 134 advBlendEqInteraction()135 AdvBlendEqInteraction advBlendEqInteraction() const { return fAdvBlendEqInteraction; } 136 mustEnableAdvBlendEqs()137 bool mustEnableAdvBlendEqs() const { 138 return fAdvBlendEqInteraction >= kGeneralEnable_AdvBlendEqInteraction; 139 } 140 mustEnableSpecificAdvBlendEqs()141 bool mustEnableSpecificAdvBlendEqs() const { 142 return fAdvBlendEqInteraction == kSpecificEnables_AdvBlendEqInteraction; 143 } 144 mustDeclareFragmentShaderOutput()145 bool mustDeclareFragmentShaderOutput() const { 146 return fGLSLGeneration > k110_GrGLSLGeneration; 147 } 148 usesPrecisionModifiers()149 bool usesPrecisionModifiers() const { return fUsesPrecisionModifiers; } 150 151 // Returns whether we can use the glsl function any() in our shader code. canUseAnyFunctionInShader()152 bool canUseAnyFunctionInShader() const { return fCanUseAnyFunctionInShader; } 153 canUseMinAndAbsTogether()154 bool canUseMinAndAbsTogether() const { return fCanUseMinAndAbsTogether; } 155 mustForceNegatedAtanParamToFloat()156 bool mustForceNegatedAtanParamToFloat() const { return fMustForceNegatedAtanParamToFloat; } 157 158 // Returns whether a device incorrectly implements atan(y,x) as atan(y/x) atan2ImplementedAsAtanYOverX()159 bool atan2ImplementedAsAtanYOverX() const { return fAtan2ImplementedAsAtanYOverX; } 160 requiresLocalOutputColorForFBFetch()161 bool requiresLocalOutputColorForFBFetch() const { return fRequiresLocalOutputColorForFBFetch; } 162 163 // On MacBook, geometry shaders break if they have more than one invocation. mustImplementGSInvocationsWithLoop()164 bool mustImplementGSInvocationsWithLoop() const { return fMustImplementGSInvocationsWithLoop; } 165 mustObfuscateUniformColor()166 bool mustObfuscateUniformColor() const { return fMustObfuscateUniformColor; } 167 168 // Returns the string of an extension that must be enabled in the shader to support 169 // derivatives. If nullptr is returned then no extension needs to be enabled. Before calling 170 // this function, the caller should check that shaderDerivativeSupport exists. shaderDerivativeExtensionString()171 const char* shaderDerivativeExtensionString() const { 172 SkASSERT(this->shaderDerivativeSupport()); 173 return fShaderDerivativeExtensionString; 174 } 175 176 // Returns the string of an extension that will do all necessary coord transfomations needed 177 // when reading the fragment position. If such an extension does not exisits, this function 178 // returns a nullptr, and all transforms of the frag position must be done manually in the 179 // shader. fragCoordConventionsExtensionString()180 const char* fragCoordConventionsExtensionString() const { 181 return fFragCoordConventionsExtensionString; 182 } 183 184 // This returns the name of an extension that must be enabled in the shader, if such a thing is 185 // required in order to use a secondary output in the shader. This returns a nullptr if no such 186 // extension is required. However, the return value of this function does not say whether dual 187 // source blending is supported. secondaryOutputExtensionString()188 const char* secondaryOutputExtensionString() const { 189 return fSecondaryOutputExtensionString; 190 } 191 externalTextureExtensionString()192 const char* externalTextureExtensionString() const { 193 SkASSERT(this->externalTextureSupport()); 194 return fExternalTextureExtensionString; 195 } 196 texelBufferExtensionString()197 const char* texelBufferExtensionString() const { 198 SkASSERT(this->texelBufferSupport()); 199 return fTexelBufferExtensionString; 200 } 201 noperspectiveInterpolationExtensionString()202 const char* noperspectiveInterpolationExtensionString() const { 203 SkASSERT(this->noperspectiveInterpolationSupport()); 204 return fNoPerspectiveInterpolationExtensionString; 205 } 206 multisampleInterpolationExtensionString()207 const char* multisampleInterpolationExtensionString() const { 208 SkASSERT(this->multisampleInterpolationSupport()); 209 return fMultisampleInterpolationExtensionString; 210 } 211 sampleVariablesExtensionString()212 const char* sampleVariablesExtensionString() const { 213 SkASSERT(this->sampleVariablesSupport()); 214 return fSampleVariablesExtensionString; 215 } 216 imageLoadStoreExtensionString()217 const char* imageLoadStoreExtensionString() const { 218 SkASSERT(this->imageLoadStoreSupport()); 219 return fImageLoadStoreExtensionString; 220 } 221 maxVertexSamplers()222 int maxVertexSamplers() const { return fMaxVertexSamplers; } 223 maxGeometrySamplers()224 int maxGeometrySamplers() const { return fMaxGeometrySamplers; } 225 maxFragmentSamplers()226 int maxFragmentSamplers() const { return fMaxFragmentSamplers; } 227 maxCombinedSamplers()228 int maxCombinedSamplers() const { return fMaxCombinedSamplers; } 229 maxVertexImageStorages()230 int maxVertexImageStorages() const { return fMaxVertexImageStorages; } 231 maxGeometryImageStorages()232 int maxGeometryImageStorages() const { return fMaxGeometryImageStorages; } 233 maxFragmentImageStorages()234 int maxFragmentImageStorages() const { return fMaxFragmentImageStorages; } 235 maxCombinedImageStorages()236 int maxCombinedImageStorages() const { return fMaxCombinedImageStorages; } 237 238 /** 239 * Given a texture's config, this determines what swizzle must be appended to accesses to the 240 * texture in generated shader code. Swizzling may be implemented in texture parameters or a 241 * sampler rather than in the shader. In this case the returned swizzle will always be "rgba". 242 */ configTextureSwizzle(GrPixelConfig config)243 const GrSwizzle& configTextureSwizzle(GrPixelConfig config) const { 244 return fConfigTextureSwizzle[config]; 245 } 246 247 /** Swizzle that should occur on the fragment shader outputs for a given config. */ configOutputSwizzle(GrPixelConfig config)248 const GrSwizzle& configOutputSwizzle(GrPixelConfig config) const { 249 return fConfigOutputSwizzle[config]; 250 } 251 252 /** Precision qualifier that should be used with a sampler, given its config and visibility. */ samplerPrecision(GrPixelConfig config,GrShaderFlags visibility)253 GrSLPrecision samplerPrecision(GrPixelConfig config, GrShaderFlags visibility) const { 254 return static_cast<GrSLPrecision>(fSamplerPrecisions[visibility][config]); 255 } 256 generation()257 GrGLSLGeneration generation() const { return fGLSLGeneration; } 258 259 private: 260 /** GrCaps subclasses must call this after filling in the shader precision table. */ 261 void initSamplerPrecisionTable(); 262 263 void applyOptionsOverrides(const GrContextOptions& options); 264 265 GrGLSLGeneration fGLSLGeneration; 266 267 bool fShaderDerivativeSupport : 1; 268 bool fGeometryShaderSupport : 1; 269 bool fPathRenderingSupport : 1; 270 bool fDstReadInShaderSupport : 1; 271 bool fDualSourceBlendingSupport : 1; 272 bool fIntegerSupport : 1; 273 bool fTexelBufferSupport : 1; 274 bool fImageLoadStoreSupport : 1; 275 bool fShaderPrecisionVaries : 1; 276 bool fDropsTileOnZeroDivide : 1; 277 bool fFBFetchSupport : 1; 278 bool fFBFetchNeedsCustomOutput : 1; 279 bool fBindlessTextureSupport : 1; 280 bool fUsesPrecisionModifiers : 1; 281 bool fCanUseAnyFunctionInShader : 1; 282 bool fFlatInterpolationSupport : 1; 283 bool fNoPerspectiveInterpolationSupport : 1; 284 bool fMultisampleInterpolationSupport : 1; 285 bool fSampleVariablesSupport : 1; 286 bool fSampleMaskOverrideCoverageSupport : 1; 287 bool fExternalTextureSupport : 1; 288 bool fTexelFetchSupport : 1; 289 bool fVertexIDSupport : 1; 290 291 // Used for specific driver bug work arounds 292 bool fCanUseMinAndAbsTogether : 1; 293 bool fMustForceNegatedAtanParamToFloat : 1; 294 bool fAtan2ImplementedAsAtanYOverX : 1; 295 bool fRequiresLocalOutputColorForFBFetch : 1; 296 bool fMustImplementGSInvocationsWithLoop : 1; 297 bool fMustObfuscateUniformColor : 1; 298 299 PrecisionInfo fFloatPrecisions[kGrShaderTypeCount][kGrSLPrecisionCount]; 300 301 const char* fVersionDeclString; 302 303 const char* fShaderDerivativeExtensionString; 304 const char* fFragCoordConventionsExtensionString; 305 const char* fSecondaryOutputExtensionString; 306 const char* fExternalTextureExtensionString; 307 const char* fTexelBufferExtensionString; 308 const char* fNoPerspectiveInterpolationExtensionString; 309 const char* fMultisampleInterpolationExtensionString; 310 const char* fSampleVariablesExtensionString; 311 const char* fImageLoadStoreExtensionString; 312 313 const char* fFBFetchColorName; 314 const char* fFBFetchExtensionString; 315 316 int fMaxVertexSamplers; 317 int fMaxGeometrySamplers; 318 int fMaxFragmentSamplers; 319 int fMaxCombinedSamplers; 320 321 int fMaxVertexImageStorages; 322 int fMaxGeometryImageStorages; 323 int fMaxFragmentImageStorages; 324 int fMaxCombinedImageStorages; 325 326 AdvBlendEqInteraction fAdvBlendEqInteraction; 327 328 GrSwizzle fConfigTextureSwizzle[kGrPixelConfigCnt]; 329 GrSwizzle fConfigOutputSwizzle[kGrPixelConfigCnt]; 330 331 uint8_t fSamplerPrecisions[(1 << kGrShaderTypeCount)][kGrPixelConfigCnt]; 332 333 friend class GrGLCaps; // For initialization. 334 friend class GrVkCaps; 335 friend class SkSL::ShaderCapsFactory; 336 }; 337 338 #endif 339