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
15namespace SkSL {
16    class ShaderCapsFactory;
17}
18struct GrContextOptions;
19
20class GrShaderCaps : public SkRefCnt {
21public:
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    bool vertexIDSupport() const { return fVertexIDSupport; }
134
135    AdvBlendEqInteraction advBlendEqInteraction() const { return fAdvBlendEqInteraction; }
136
137    bool mustEnableAdvBlendEqs() const {
138        return fAdvBlendEqInteraction >= kGeneralEnable_AdvBlendEqInteraction;
139    }
140
141    bool mustEnableSpecificAdvBlendEqs() const {
142        return fAdvBlendEqInteraction == kSpecificEnables_AdvBlendEqInteraction;
143    }
144
145    bool mustDeclareFragmentShaderOutput() const {
146        return fGLSLGeneration > k110_GrGLSLGeneration;
147    }
148
149    bool usesPrecisionModifiers() const { return fUsesPrecisionModifiers; }
150
151    // Returns whether we can use the glsl function any() in our shader code.
152    bool canUseAnyFunctionInShader() const { return fCanUseAnyFunctionInShader; }
153
154    bool canUseMinAndAbsTogether() const { return fCanUseMinAndAbsTogether; }
155
156    bool mustForceNegatedAtanParamToFloat() const { return fMustForceNegatedAtanParamToFloat; }
157
158    // Returns whether a device incorrectly implements atan(y,x) as atan(y/x)
159    bool atan2ImplementedAsAtanYOverX() const { return fAtan2ImplementedAsAtanYOverX; }
160
161    bool requiresLocalOutputColorForFBFetch() const { return fRequiresLocalOutputColorForFBFetch; }
162
163    // On MacBook, geometry shaders break if they have more than one invocation.
164    bool mustImplementGSInvocationsWithLoop() const { return fMustImplementGSInvocationsWithLoop; }
165
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.
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.
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.
188    const char* secondaryOutputExtensionString() const {
189        return fSecondaryOutputExtensionString;
190    }
191
192    const char* externalTextureExtensionString() const {
193        SkASSERT(this->externalTextureSupport());
194        return fExternalTextureExtensionString;
195    }
196
197    const char* texelBufferExtensionString() const {
198        SkASSERT(this->texelBufferSupport());
199        return fTexelBufferExtensionString;
200    }
201
202    const char* noperspectiveInterpolationExtensionString() const {
203        SkASSERT(this->noperspectiveInterpolationSupport());
204        return fNoPerspectiveInterpolationExtensionString;
205    }
206
207    const char* multisampleInterpolationExtensionString() const {
208        SkASSERT(this->multisampleInterpolationSupport());
209        return fMultisampleInterpolationExtensionString;
210    }
211
212    const char* sampleVariablesExtensionString() const {
213        SkASSERT(this->sampleVariablesSupport());
214        return fSampleVariablesExtensionString;
215    }
216
217    const char* imageLoadStoreExtensionString() const {
218        SkASSERT(this->imageLoadStoreSupport());
219        return fImageLoadStoreExtensionString;
220    }
221
222    int maxVertexSamplers() const { return fMaxVertexSamplers; }
223
224    int maxGeometrySamplers() const { return fMaxGeometrySamplers; }
225
226    int maxFragmentSamplers() const { return fMaxFragmentSamplers; }
227
228    int maxCombinedSamplers() const { return fMaxCombinedSamplers; }
229
230    int maxVertexImageStorages() const { return fMaxVertexImageStorages; }
231
232    int maxGeometryImageStorages() const { return fMaxGeometryImageStorages; }
233
234    int maxFragmentImageStorages() const { return fMaxFragmentImageStorages; }
235
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     */
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. */
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. */
253    GrSLPrecision samplerPrecision(GrPixelConfig config, GrShaderFlags visibility) const {
254        return static_cast<GrSLPrecision>(fSamplerPrecisions[visibility][config]);
255    }
256
257    GrGLSLGeneration generation() const { return fGLSLGeneration; }
258
259private:
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