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 { 26 PrecisionInfo() { 27 fLogRangeLow = 0; 28 fLogRangeHigh = 0; 29 fBits = 0; 30 } 31 32 /** Is this precision level allowed in the shader stage? */ 33 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 73 bool shaderDerivativeSupport() const { return fShaderDerivativeSupport; } 74 bool geometryShaderSupport() const { return fGeometryShaderSupport; } 75 bool pathRenderingSupport() const { return fPathRenderingSupport; } 76 bool dstReadInShaderSupport() const { return fDstReadInShaderSupport; } 77 bool dualSourceBlendingSupport() const { return fDualSourceBlendingSupport; } 78 bool integerSupport() const { return fIntegerSupport; } 79 bool texelBufferSupport() const { return fTexelBufferSupport; } 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 */ 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 */ 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 */ 105 bool fbFetchSupport() const { return fFBFetchSupport; } 106 107 bool fbFetchNeedsCustomOutput() const { return fFBFetchNeedsCustomOutput; } 108 109 bool bindlessTextureSupport() const { return fBindlessTextureSupport; } 110 111 const char* versionDeclString() const { return fVersionDeclString; } 112 113 const char* fbFetchColorName() const { return fFBFetchColorName; } 114 115 const char* fbFetchExtensionString() const { return fFBFetchExtensionString; } 116 117 bool dropsTileOnZeroDivide() const { return fDropsTileOnZeroDivide; } 118 119 bool flatInterpolationSupport() const { return fFlatInterpolationSupport; } 120 121 bool noperspectiveInterpolationSupport() const { return fNoPerspectiveInterpolationSupport; } 122 123 bool multisampleInterpolationSupport() const { return fMultisampleInterpolationSupport; } 124 125 bool sampleVariablesSupport() const { return fSampleVariablesSupport; } 126 127 bool sampleMaskOverrideCoverageSupport() const { return fSampleMaskOverrideCoverageSupport; } 128 129 bool externalTextureSupport() const { return fExternalTextureSupport; } 130 131 bool texelFetchSupport() const { return fTexelFetchSupport; } 132 133 AdvBlendEqInteraction advBlendEqInteraction() const { return fAdvBlendEqInteraction; } 134 135 bool mustEnableAdvBlendEqs() const { 136 return fAdvBlendEqInteraction >= kGeneralEnable_AdvBlendEqInteraction; 137 } 138 139 bool mustEnableSpecificAdvBlendEqs() const { 140 return fAdvBlendEqInteraction == kSpecificEnables_AdvBlendEqInteraction; 141 } 142 143 bool mustDeclareFragmentShaderOutput() const { 144 return fGLSLGeneration > k110_GrGLSLGeneration; 145 } 146 147 bool usesPrecisionModifiers() const { return fUsesPrecisionModifiers; } 148 149 // Returns whether we can use the glsl function any() in our shader code. 150 bool canUseAnyFunctionInShader() const { return fCanUseAnyFunctionInShader; } 151 152 bool canUseMinAndAbsTogether() const { return fCanUseMinAndAbsTogether; } 153 154 bool mustForceNegatedAtanParamToFloat() const { return fMustForceNegatedAtanParamToFloat; } 155 156 // Returns whether a device incorrectly implements atan(y,x) as atan(y/x) 157 bool atan2ImplementedAsAtanYOverX() const { return fAtan2ImplementedAsAtanYOverX; } 158 159 bool requiresLocalOutputColorForFBFetch() const { return fRequiresLocalOutputColorForFBFetch; } 160 161 // On MacBook, geometry shaders break if they have more than one invocation. 162 bool mustImplementGSInvocationsWithLoop() const { return fMustImplementGSInvocationsWithLoop; } 163 164 // Returns the string of an extension that must be enabled in the shader to support 165 // derivatives. If nullptr is returned then no extension needs to be enabled. Before calling 166 // this function, the caller should check that shaderDerivativeSupport exists. 167 const char* shaderDerivativeExtensionString() const { 168 SkASSERT(this->shaderDerivativeSupport()); 169 return fShaderDerivativeExtensionString; 170 } 171 172 // Returns the string of an extension that will do all necessary coord transfomations needed 173 // when reading the fragment position. If such an extension does not exisits, this function 174 // returns a nullptr, and all transforms of the frag position must be done manually in the 175 // shader. 176 const char* fragCoordConventionsExtensionString() const { 177 return fFragCoordConventionsExtensionString; 178 } 179 180 // This returns the name of an extension that must be enabled in the shader, if such a thing is 181 // required in order to use a secondary output in the shader. This returns a nullptr if no such 182 // extension is required. However, the return value of this function does not say whether dual 183 // source blending is supported. 184 const char* secondaryOutputExtensionString() const { 185 return fSecondaryOutputExtensionString; 186 } 187 188 const char* externalTextureExtensionString() const { 189 SkASSERT(this->externalTextureSupport()); 190 return fExternalTextureExtensionString; 191 } 192 193 const char* texelBufferExtensionString() const { 194 SkASSERT(this->texelBufferSupport()); 195 return fTexelBufferExtensionString; 196 } 197 198 const char* noperspectiveInterpolationExtensionString() const { 199 SkASSERT(this->noperspectiveInterpolationSupport()); 200 return fNoPerspectiveInterpolationExtensionString; 201 } 202 203 const char* multisampleInterpolationExtensionString() const { 204 SkASSERT(this->multisampleInterpolationSupport()); 205 return fMultisampleInterpolationExtensionString; 206 } 207 208 const char* sampleVariablesExtensionString() const { 209 SkASSERT(this->sampleVariablesSupport()); 210 return fSampleVariablesExtensionString; 211 } 212 213 const char* imageLoadStoreExtensionString() const { 214 SkASSERT(this->imageLoadStoreSupport()); 215 return fImageLoadStoreExtensionString; 216 } 217 218 int maxVertexSamplers() const { return fMaxVertexSamplers; } 219 220 int maxGeometrySamplers() const { return fMaxGeometrySamplers; } 221 222 int maxFragmentSamplers() const { return fMaxFragmentSamplers; } 223 224 int maxCombinedSamplers() const { return fMaxCombinedSamplers; } 225 226 int maxVertexImageStorages() const { return fMaxVertexImageStorages; } 227 228 int maxGeometryImageStorages() const { return fMaxGeometryImageStorages; } 229 230 int maxFragmentImageStorages() const { return fMaxFragmentImageStorages; } 231 232 int maxCombinedImageStorages() const { return fMaxCombinedImageStorages; } 233 234 /** 235 * Given a texture's config, this determines what swizzle must be appended to accesses to the 236 * texture in generated shader code. Swizzling may be implemented in texture parameters or a 237 * sampler rather than in the shader. In this case the returned swizzle will always be "rgba". 238 */ 239 const GrSwizzle& configTextureSwizzle(GrPixelConfig config) const { 240 return fConfigTextureSwizzle[config]; 241 } 242 243 /** Swizzle that should occur on the fragment shader outputs for a given config. */ 244 const GrSwizzle& configOutputSwizzle(GrPixelConfig config) const { 245 return fConfigOutputSwizzle[config]; 246 } 247 248 /** Precision qualifier that should be used with a sampler, given its config and visibility. */ 249 GrSLPrecision samplerPrecision(GrPixelConfig config, GrShaderFlags visibility) const { 250 return static_cast<GrSLPrecision>(fSamplerPrecisions[visibility][config]); 251 } 252 253 GrGLSLGeneration generation() const { return fGLSLGeneration; } 254 255 private: 256 /** GrCaps subclasses must call this after filling in the shader precision table. */ 257 void initSamplerPrecisionTable(); 258 259 void applyOptionsOverrides(const GrContextOptions& options); 260 261 GrGLSLGeneration fGLSLGeneration; 262 263 bool fShaderDerivativeSupport : 1; 264 bool fGeometryShaderSupport : 1; 265 bool fPathRenderingSupport : 1; 266 bool fDstReadInShaderSupport : 1; 267 bool fDualSourceBlendingSupport : 1; 268 bool fIntegerSupport : 1; 269 bool fTexelBufferSupport : 1; 270 bool fImageLoadStoreSupport : 1; 271 bool fShaderPrecisionVaries : 1; 272 bool fDropsTileOnZeroDivide : 1; 273 bool fFBFetchSupport : 1; 274 bool fFBFetchNeedsCustomOutput : 1; 275 bool fBindlessTextureSupport : 1; 276 bool fUsesPrecisionModifiers : 1; 277 bool fCanUseAnyFunctionInShader : 1; 278 bool fFlatInterpolationSupport : 1; 279 bool fNoPerspectiveInterpolationSupport : 1; 280 bool fMultisampleInterpolationSupport : 1; 281 bool fSampleVariablesSupport : 1; 282 bool fSampleMaskOverrideCoverageSupport : 1; 283 bool fExternalTextureSupport : 1; 284 bool fTexelFetchSupport : 1; 285 286 // Used for specific driver bug work arounds 287 bool fCanUseMinAndAbsTogether : 1; 288 bool fMustForceNegatedAtanParamToFloat : 1; 289 bool fAtan2ImplementedAsAtanYOverX : 1; 290 bool fRequiresLocalOutputColorForFBFetch : 1; 291 bool fMustImplementGSInvocationsWithLoop : 1; 292 293 PrecisionInfo fFloatPrecisions[kGrShaderTypeCount][kGrSLPrecisionCount]; 294 295 const char* fVersionDeclString; 296 297 const char* fShaderDerivativeExtensionString; 298 const char* fFragCoordConventionsExtensionString; 299 const char* fSecondaryOutputExtensionString; 300 const char* fExternalTextureExtensionString; 301 const char* fTexelBufferExtensionString; 302 const char* fNoPerspectiveInterpolationExtensionString; 303 const char* fMultisampleInterpolationExtensionString; 304 const char* fSampleVariablesExtensionString; 305 const char* fImageLoadStoreExtensionString; 306 307 const char* fFBFetchColorName; 308 const char* fFBFetchExtensionString; 309 310 int fMaxVertexSamplers; 311 int fMaxGeometrySamplers; 312 int fMaxFragmentSamplers; 313 int fMaxCombinedSamplers; 314 315 int fMaxVertexImageStorages; 316 int fMaxGeometryImageStorages; 317 int fMaxFragmentImageStorages; 318 int fMaxCombinedImageStorages; 319 320 AdvBlendEqInteraction fAdvBlendEqInteraction; 321 322 GrSwizzle fConfigTextureSwizzle[kGrPixelConfigCnt]; 323 GrSwizzle fConfigOutputSwizzle[kGrPixelConfigCnt]; 324 325 uint8_t fSamplerPrecisions[(1 << kGrShaderTypeCount)][kGrPixelConfigCnt]; 326 327 friend class GrGLCaps; // For initialization. 328 friend class GrVkCaps; 329 friend class SkSL::ShaderCapsFactory; 330 }; 331 332 #endif 333