• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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