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