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 class SkJSONWriter; 20 21 class GrShaderCaps : public SkRefCnt { 22 public: 23 /** 24 * Indicates how GLSL must interact with advanced blend equations. The KHR extension requires 25 * special layout qualifiers in the fragment shader. 26 */ 27 enum AdvBlendEqInteraction { 28 kNotSupported_AdvBlendEqInteraction, //<! No _blend_equation_advanced extension 29 kAutomatic_AdvBlendEqInteraction, //<! No interaction required 30 kGeneralEnable_AdvBlendEqInteraction, //<! layout(blend_support_all_equations) out 31 kSpecificEnables_AdvBlendEqInteraction, //<! Specific layout qualifiers per equation 32 33 kLast_AdvBlendEqInteraction = kSpecificEnables_AdvBlendEqInteraction 34 }; 35 36 GrShaderCaps(const GrContextOptions&); 37 38 void dumpJSON(SkJSONWriter*) const; 39 shaderDerivativeSupport()40 bool shaderDerivativeSupport() const { return fShaderDerivativeSupport; } geometryShaderSupport()41 bool geometryShaderSupport() const { return fGeometryShaderSupport; } gsInvocationsSupport()42 bool gsInvocationsSupport() const { return fGSInvocationsSupport; } pathRenderingSupport()43 bool pathRenderingSupport() const { return fPathRenderingSupport; } dstReadInShaderSupport()44 bool dstReadInShaderSupport() const { return fDstReadInShaderSupport; } dualSourceBlendingSupport()45 bool dualSourceBlendingSupport() const { return fDualSourceBlendingSupport; } integerSupport()46 bool integerSupport() const { return fIntegerSupport; } texelBufferSupport()47 bool texelBufferSupport() const { return fTexelBufferSupport; } imageLoadStoreSupport()48 int imageLoadStoreSupport() const { return fImageLoadStoreSupport; } 49 50 /** 51 * Some helper functions for encapsulating various extensions to read FB Buffer on openglES 52 * 53 * TODO(joshualitt) On desktop opengl 4.2+ we can achieve something similar to this effect 54 */ fbFetchSupport()55 bool fbFetchSupport() const { return fFBFetchSupport; } 56 fbFetchNeedsCustomOutput()57 bool fbFetchNeedsCustomOutput() const { return fFBFetchNeedsCustomOutput; } 58 versionDeclString()59 const char* versionDeclString() const { return fVersionDeclString; } 60 fbFetchColorName()61 const char* fbFetchColorName() const { return fFBFetchColorName; } 62 fbFetchExtensionString()63 const char* fbFetchExtensionString() const { return fFBFetchExtensionString; } 64 dropsTileOnZeroDivide()65 bool dropsTileOnZeroDivide() const { return fDropsTileOnZeroDivide; } 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 externalTextureSupport()73 bool externalTextureSupport() const { return fExternalTextureSupport; } 74 texelFetchSupport()75 bool texelFetchSupport() const { return fTexelFetchSupport; } 76 vertexIDSupport()77 bool vertexIDSupport() const { return fVertexIDSupport; } 78 floatIs32Bits()79 bool floatIs32Bits() const { return fFloatIs32Bits; } 80 halfIs32Bits()81 bool halfIs32Bits() const { return fHalfIs32Bits; } 82 advBlendEqInteraction()83 AdvBlendEqInteraction advBlendEqInteraction() const { return fAdvBlendEqInteraction; } 84 mustEnableAdvBlendEqs()85 bool mustEnableAdvBlendEqs() const { 86 return fAdvBlendEqInteraction >= kGeneralEnable_AdvBlendEqInteraction; 87 } 88 mustEnableSpecificAdvBlendEqs()89 bool mustEnableSpecificAdvBlendEqs() const { 90 return fAdvBlendEqInteraction == kSpecificEnables_AdvBlendEqInteraction; 91 } 92 mustDeclareFragmentShaderOutput()93 bool mustDeclareFragmentShaderOutput() const { 94 return fGLSLGeneration > k110_GrGLSLGeneration; 95 } 96 usesPrecisionModifiers()97 bool usesPrecisionModifiers() const { return fUsesPrecisionModifiers; } 98 99 // Returns whether we can use the glsl function any() in our shader code. canUseAnyFunctionInShader()100 bool canUseAnyFunctionInShader() const { return fCanUseAnyFunctionInShader; } 101 canUseMinAndAbsTogether()102 bool canUseMinAndAbsTogether() const { return fCanUseMinAndAbsTogether; } 103 canUseFractForNegativeValues()104 bool canUseFractForNegativeValues() const { return fCanUseFractForNegativeValues; } 105 mustForceNegatedAtanParamToFloat()106 bool mustForceNegatedAtanParamToFloat() const { return fMustForceNegatedAtanParamToFloat; } 107 108 // Returns whether a device incorrectly implements atan(y,x) as atan(y/x) atan2ImplementedAsAtanYOverX()109 bool atan2ImplementedAsAtanYOverX() const { return fAtan2ImplementedAsAtanYOverX; } 110 111 // If this returns true some operation (could be a no op) must be called between floor and abs 112 // to make sure the driver compiler doesn't inline them together which can cause a driver bug in 113 // the shader. mustDoOpBetweenFloorAndAbs()114 bool mustDoOpBetweenFloorAndAbs() const { return fMustDoOpBetweenFloorAndAbs; } 115 116 // If false, SkSL uses a workaround so that sk_FragCoord doesn't actually query gl_FragCoord canUseFragCoord()117 bool canUseFragCoord() const { return fCanUseFragCoord; } 118 119 // If true interpolated vertex shader outputs are inaccurate. interpolantsAreInaccurate()120 bool interpolantsAreInaccurate() const { return fInterpolantsAreInaccurate; } 121 requiresLocalOutputColorForFBFetch()122 bool requiresLocalOutputColorForFBFetch() const { return fRequiresLocalOutputColorForFBFetch; } 123 mustObfuscateUniformColor()124 bool mustObfuscateUniformColor() const { return fMustObfuscateUniformColor; } 125 126 // The D3D shader compiler, when targeting PS 3.0 (ie within ANGLE) fails to compile certain 127 // constructs. See detailed comments in GrGLCaps.cpp. mustGuardDivisionEvenAfterExplicitZeroCheck()128 bool mustGuardDivisionEvenAfterExplicitZeroCheck() const { 129 return fMustGuardDivisionEvenAfterExplicitZeroCheck; 130 } 131 132 // Returns the string of an extension that must be enabled in the shader to support 133 // derivatives. If nullptr is returned then no extension needs to be enabled. Before calling 134 // this function, the caller should check that shaderDerivativeSupport exists. shaderDerivativeExtensionString()135 const char* shaderDerivativeExtensionString() const { 136 SkASSERT(this->shaderDerivativeSupport()); 137 return fShaderDerivativeExtensionString; 138 } 139 140 // Returns the string of an extension that must be enabled in the shader to support geometry 141 // shaders. If nullptr is returned then no extension needs to be enabled. Before calling this 142 // function, the caller must verify that geometryShaderSupport exists. geometryShaderExtensionString()143 const char* geometryShaderExtensionString() const { 144 SkASSERT(this->geometryShaderSupport()); 145 return fGeometryShaderExtensionString; 146 } 147 148 // Returns the string of an extension that must be enabled in the shader to support 149 // geometry shader invocations. If nullptr is returned then no extension needs to be enabled. 150 // Before calling this function, the caller must verify that gsInvocationsSupport exists. gsInvocationsExtensionString()151 const char* gsInvocationsExtensionString() const { 152 SkASSERT(this->gsInvocationsSupport()); 153 return fGSInvocationsExtensionString; 154 } 155 156 // Returns the string of an extension that will do all necessary coord transfomations needed 157 // when reading the fragment position. If such an extension does not exisits, this function 158 // returns a nullptr, and all transforms of the frag position must be done manually in the 159 // shader. fragCoordConventionsExtensionString()160 const char* fragCoordConventionsExtensionString() const { 161 return fFragCoordConventionsExtensionString; 162 } 163 164 // This returns the name of an extension that must be enabled in the shader, if such a thing is 165 // required in order to use a secondary output in the shader. This returns a nullptr if no such 166 // extension is required. However, the return value of this function does not say whether dual 167 // source blending is supported. secondaryOutputExtensionString()168 const char* secondaryOutputExtensionString() const { 169 return fSecondaryOutputExtensionString; 170 } 171 externalTextureExtensionString()172 const char* externalTextureExtensionString() const { 173 SkASSERT(this->externalTextureSupport()); 174 return fExternalTextureExtensionString; 175 } 176 texelBufferExtensionString()177 const char* texelBufferExtensionString() const { 178 SkASSERT(this->texelBufferSupport()); 179 return fTexelBufferExtensionString; 180 } 181 noperspectiveInterpolationExtensionString()182 const char* noperspectiveInterpolationExtensionString() const { 183 SkASSERT(this->noperspectiveInterpolationSupport()); 184 return fNoPerspectiveInterpolationExtensionString; 185 } 186 imageLoadStoreExtensionString()187 const char* imageLoadStoreExtensionString() const { 188 SkASSERT(this->imageLoadStoreSupport()); 189 return fImageLoadStoreExtensionString; 190 } 191 maxVertexSamplers()192 int maxVertexSamplers() const { return fMaxVertexSamplers; } 193 maxGeometrySamplers()194 int maxGeometrySamplers() const { return fMaxGeometrySamplers; } 195 maxFragmentSamplers()196 int maxFragmentSamplers() const { return fMaxFragmentSamplers; } 197 maxCombinedSamplers()198 int maxCombinedSamplers() const { return fMaxCombinedSamplers; } 199 200 /** 201 * In general using multiple texture units for image rendering seems to be a win at smaller 202 * sizes of dst rects and a loss at larger sizes. Dst rects above this pixel area threshold will 203 * not use multitexturing. 204 */ disableImageMultitexturingDstRectAreaThreshold()205 size_t disableImageMultitexturingDstRectAreaThreshold() const { 206 return fDisableImageMultitexturingDstRectAreaThreshold; 207 } 208 209 /** 210 * Given a texture's config, this determines what swizzle must be appended to accesses to the 211 * texture in generated shader code. Swizzling may be implemented in texture parameters or a 212 * sampler rather than in the shader. In this case the returned swizzle will always be "rgba". 213 */ configTextureSwizzle(GrPixelConfig config)214 const GrSwizzle& configTextureSwizzle(GrPixelConfig config) const { 215 return fConfigTextureSwizzle[config]; 216 } 217 218 /** Swizzle that should occur on the fragment shader outputs for a given config. */ configOutputSwizzle(GrPixelConfig config)219 const GrSwizzle& configOutputSwizzle(GrPixelConfig config) const { 220 return fConfigOutputSwizzle[config]; 221 } 222 generation()223 GrGLSLGeneration generation() const { return fGLSLGeneration; } 224 225 private: 226 void applyOptionsOverrides(const GrContextOptions& options); 227 228 GrGLSLGeneration fGLSLGeneration; 229 230 bool fShaderDerivativeSupport : 1; 231 bool fGeometryShaderSupport : 1; 232 bool fGSInvocationsSupport : 1; 233 bool fPathRenderingSupport : 1; 234 bool fDstReadInShaderSupport : 1; 235 bool fDualSourceBlendingSupport : 1; 236 bool fIntegerSupport : 1; 237 bool fTexelBufferSupport : 1; 238 bool fImageLoadStoreSupport : 1; 239 bool fDropsTileOnZeroDivide : 1; 240 bool fFBFetchSupport : 1; 241 bool fFBFetchNeedsCustomOutput : 1; 242 bool fUsesPrecisionModifiers : 1; 243 bool fFlatInterpolationSupport : 1; 244 bool fPreferFlatInterpolation : 1; 245 bool fNoPerspectiveInterpolationSupport : 1; 246 bool fExternalTextureSupport : 1; 247 bool fTexelFetchSupport : 1; 248 bool fVertexIDSupport : 1; 249 bool fFloatIs32Bits : 1; 250 bool fHalfIs32Bits : 1; 251 252 // Used for specific driver bug work arounds 253 bool fCanUseAnyFunctionInShader : 1; 254 bool fCanUseMinAndAbsTogether : 1; 255 bool fCanUseFractForNegativeValues : 1; 256 bool fMustForceNegatedAtanParamToFloat : 1; 257 bool fAtan2ImplementedAsAtanYOverX : 1; 258 bool fMustDoOpBetweenFloorAndAbs : 1; 259 bool fRequiresLocalOutputColorForFBFetch : 1; 260 bool fMustObfuscateUniformColor : 1; 261 bool fMustGuardDivisionEvenAfterExplicitZeroCheck : 1; 262 bool fCanUseFragCoord : 1; 263 bool fInterpolantsAreInaccurate : 1; 264 265 const char* fVersionDeclString; 266 267 const char* fShaderDerivativeExtensionString; 268 const char* fGeometryShaderExtensionString; 269 const char* fGSInvocationsExtensionString; 270 const char* fFragCoordConventionsExtensionString; 271 const char* fSecondaryOutputExtensionString; 272 const char* fExternalTextureExtensionString; 273 const char* fTexelBufferExtensionString; 274 const char* fNoPerspectiveInterpolationExtensionString; 275 const char* fImageLoadStoreExtensionString; 276 277 const char* fFBFetchColorName; 278 const char* fFBFetchExtensionString; 279 280 int fMaxVertexSamplers; 281 int fMaxGeometrySamplers; 282 int fMaxFragmentSamplers; 283 int fMaxCombinedSamplers; 284 285 size_t fDisableImageMultitexturingDstRectAreaThreshold; 286 287 AdvBlendEqInteraction fAdvBlendEqInteraction; 288 289 GrSwizzle fConfigTextureSwizzle[kGrPixelConfigCnt]; 290 GrSwizzle fConfigOutputSwizzle[kGrPixelConfigCnt]; 291 292 friend class GrCaps; // For initialization. 293 friend class GrGLCaps; 294 friend class GrMockCaps; 295 friend class GrMtlCaps; 296 friend class GrVkCaps; 297 friend class SkSL::ShaderCapsFactory; 298 }; 299 300 #endif 301