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 
advBlendEqInteraction()133     AdvBlendEqInteraction advBlendEqInteraction() const { return fAdvBlendEqInteraction; }
134 
mustEnableAdvBlendEqs()135     bool mustEnableAdvBlendEqs() const {
136         return fAdvBlendEqInteraction >= kGeneralEnable_AdvBlendEqInteraction;
137     }
138 
mustEnableSpecificAdvBlendEqs()139     bool mustEnableSpecificAdvBlendEqs() const {
140         return fAdvBlendEqInteraction == kSpecificEnables_AdvBlendEqInteraction;
141     }
142 
mustDeclareFragmentShaderOutput()143     bool mustDeclareFragmentShaderOutput() const {
144         return fGLSLGeneration > k110_GrGLSLGeneration;
145     }
146 
usesPrecisionModifiers()147     bool usesPrecisionModifiers() const { return fUsesPrecisionModifiers; }
148 
149     // Returns whether we can use the glsl function any() in our shader code.
canUseAnyFunctionInShader()150     bool canUseAnyFunctionInShader() const { return fCanUseAnyFunctionInShader; }
151 
canUseMinAndAbsTogether()152     bool canUseMinAndAbsTogether() const { return fCanUseMinAndAbsTogether; }
153 
mustForceNegatedAtanParamToFloat()154     bool mustForceNegatedAtanParamToFloat() const { return fMustForceNegatedAtanParamToFloat; }
155 
156     // Returns whether a device incorrectly implements atan(y,x) as atan(y/x)
atan2ImplementedAsAtanYOverX()157     bool atan2ImplementedAsAtanYOverX() const { return fAtan2ImplementedAsAtanYOverX; }
158 
requiresLocalOutputColorForFBFetch()159     bool requiresLocalOutputColorForFBFetch() const { return fRequiresLocalOutputColorForFBFetch; }
160 
161     // On MacBook, geometry shaders break if they have more than one invocation.
mustImplementGSInvocationsWithLoop()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.
shaderDerivativeExtensionString()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.
fragCoordConventionsExtensionString()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.
secondaryOutputExtensionString()184     const char* secondaryOutputExtensionString() const {
185         return fSecondaryOutputExtensionString;
186     }
187 
externalTextureExtensionString()188     const char* externalTextureExtensionString() const {
189         SkASSERT(this->externalTextureSupport());
190         return fExternalTextureExtensionString;
191     }
192 
texelBufferExtensionString()193     const char* texelBufferExtensionString() const {
194         SkASSERT(this->texelBufferSupport());
195         return fTexelBufferExtensionString;
196     }
197 
noperspectiveInterpolationExtensionString()198     const char* noperspectiveInterpolationExtensionString() const {
199         SkASSERT(this->noperspectiveInterpolationSupport());
200         return fNoPerspectiveInterpolationExtensionString;
201     }
202 
multisampleInterpolationExtensionString()203     const char* multisampleInterpolationExtensionString() const {
204         SkASSERT(this->multisampleInterpolationSupport());
205         return fMultisampleInterpolationExtensionString;
206     }
207 
sampleVariablesExtensionString()208     const char* sampleVariablesExtensionString() const {
209         SkASSERT(this->sampleVariablesSupport());
210         return fSampleVariablesExtensionString;
211     }
212 
imageLoadStoreExtensionString()213     const char* imageLoadStoreExtensionString() const {
214         SkASSERT(this->imageLoadStoreSupport());
215         return fImageLoadStoreExtensionString;
216     }
217 
maxVertexSamplers()218     int maxVertexSamplers() const { return fMaxVertexSamplers; }
219 
maxGeometrySamplers()220     int maxGeometrySamplers() const { return fMaxGeometrySamplers; }
221 
maxFragmentSamplers()222     int maxFragmentSamplers() const { return fMaxFragmentSamplers; }
223 
maxCombinedSamplers()224     int maxCombinedSamplers() const { return fMaxCombinedSamplers; }
225 
maxVertexImageStorages()226     int maxVertexImageStorages() const { return fMaxVertexImageStorages; }
227 
maxGeometryImageStorages()228     int maxGeometryImageStorages() const { return fMaxGeometryImageStorages; }
229 
maxFragmentImageStorages()230     int maxFragmentImageStorages() const { return fMaxFragmentImageStorages; }
231 
maxCombinedImageStorages()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      */
configTextureSwizzle(GrPixelConfig config)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. */
configOutputSwizzle(GrPixelConfig 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. */
samplerPrecision(GrPixelConfig config,GrShaderFlags visibility)249     GrSLPrecision samplerPrecision(GrPixelConfig config, GrShaderFlags visibility) const {
250         return static_cast<GrSLPrecision>(fSamplerPrecisions[visibility][config]);
251     }
252 
generation()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