• 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 #ifndef GrShaderCaps_DEFINED
9 #define GrShaderCaps_DEFINED
10 
11 #include "include/core/SkRefCnt.h"
12 #include "src/gpu/glsl/GrGLSL.h"
13 
14 namespace SkSL {
15 class ShaderCapsFactory;
16 class SharedCompiler;
17 }  // namespace SkSL
18 
19 struct GrContextOptions;
20 class SkJSONWriter;
21 
22 class GrShaderCaps {
23 public:
24     /**
25      * Indicates how GLSL must interact with advanced blend equations. The KHR extension requires
26      * special layout qualifiers in the fragment shader.
27      */
28     enum AdvBlendEqInteraction {
29         kNotSupported_AdvBlendEqInteraction,     //<! No _blend_equation_advanced extension
30         kAutomatic_AdvBlendEqInteraction,        //<! No interaction required
31         kGeneralEnable_AdvBlendEqInteraction,    //<! layout(blend_support_all_equations) out
32 
33         kLast_AdvBlendEqInteraction = kGeneralEnable_AdvBlendEqInteraction
34     };
35 
36     GrShaderCaps();
37 
38     void dumpJSON(SkJSONWriter*) const;
39 
supportsDistanceFieldText()40     bool supportsDistanceFieldText() const { return fShaderDerivativeSupport; }
41 
shaderDerivativeSupport()42     bool shaderDerivativeSupport() const { return fShaderDerivativeSupport; }
dstReadInShaderSupport()43     bool dstReadInShaderSupport() const { return fDstReadInShaderSupport; }
dualSourceBlendingSupport()44     bool dualSourceBlendingSupport() const { return fDualSourceBlendingSupport; }
nonsquareMatrixSupport()45     bool nonsquareMatrixSupport() const { return fNonsquareMatrixSupport; }
46 
47     /** Indicates true 32-bit integer support, with unsigned types and bitwise operations */
integerSupport()48     bool integerSupport() const { return fIntegerSupport; }
49 
50     /** asinh(), acosh(), atanh() */
inverseHyperbolicSupport()51     bool inverseHyperbolicSupport() const { return fInverseHyperbolicSupport; }
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 
flatInterpolationSupport()68     bool flatInterpolationSupport() const { return fFlatInterpolationSupport; }
69 
preferFlatInterpolation()70     bool preferFlatInterpolation() const { return fPreferFlatInterpolation; }
71 
noperspectiveInterpolationSupport()72     bool noperspectiveInterpolationSupport() const { return fNoPerspectiveInterpolationSupport; }
73 
sampleMaskSupport()74     bool sampleMaskSupport() const { return fSampleMaskSupport; }
75 
externalTextureSupport()76     bool externalTextureSupport() const { return fExternalTextureSupport; }
77 
vertexIDSupport()78     bool vertexIDSupport() const { return fVertexIDSupport; }
79 
80     // isinf() is defined, and floating point infinities are handled according to IEEE standards.
infinitySupport()81     bool infinitySupport() const { return fInfinitySupport; }
82 
83     // Returns true if `expr` in `myArray[expr]` can be any integer expression. If false, `expr`
84     // must be a constant-index-expression as defined in the OpenGL ES2 specification, Appendix A.5.
nonconstantArrayIndexSupport()85     bool nonconstantArrayIndexSupport() const {
86         return fNonconstantArrayIndexSupport;
87     }
88 
89     // frexp(), ldexp(), findMSB(), findLSB().
bitManipulationSupport()90     bool bitManipulationSupport() const { return fBitManipulationSupport; }
91 
floatIs32Bits()92     bool floatIs32Bits() const { return fFloatIs32Bits; }
93 
halfIs32Bits()94     bool halfIs32Bits() const { return fHalfIs32Bits; }
95 
hasLowFragmentPrecision()96     bool hasLowFragmentPrecision() const { return fHasLowFragmentPrecision; }
97 
98     // Use a reduced set of rendering algorithms or less optimal effects in order to
99     // reduce the number of unique shaders generated.
reducedShaderMode()100     bool reducedShaderMode() const { return fReducedShaderMode; }
101 
102     /**
103      * SkSL ES3 requires support for derivatives, nonsquare matrices and bitwise integer operations.
104      */
supportsSkSLES3()105     bool supportsSkSLES3() const {
106         return fShaderDerivativeSupport && fNonsquareMatrixSupport && fIntegerSupport &&
107                fGLSLGeneration >= k330_GrGLSLGeneration;
108     }
109 
110     // SkSL only.
builtinFMASupport()111     bool builtinFMASupport() const { return fBuiltinFMASupport; }
112 
builtinDeterminantSupport()113     bool builtinDeterminantSupport() const { return fBuiltinDeterminantSupport; }
114 
advBlendEqInteraction()115     AdvBlendEqInteraction advBlendEqInteraction() const { return fAdvBlendEqInteraction; }
116 
mustEnableAdvBlendEqs()117     bool mustEnableAdvBlendEqs() const {
118         return fAdvBlendEqInteraction >= kGeneralEnable_AdvBlendEqInteraction;
119     }
120 
mustDeclareFragmentShaderOutput()121     bool mustDeclareFragmentShaderOutput() const { return fGLSLGeneration > k110_GrGLSLGeneration; }
122 
usesPrecisionModifiers()123     bool usesPrecisionModifiers() const { return fUsesPrecisionModifiers; }
124 
125     // Returns whether we can use the glsl function any() in our shader code.
canUseAnyFunctionInShader()126     bool canUseAnyFunctionInShader() const { return fCanUseAnyFunctionInShader; }
127 
canUseMinAndAbsTogether()128     bool canUseMinAndAbsTogether() const { return fCanUseMinAndAbsTogether; }
129 
canUseFractForNegativeValues()130     bool canUseFractForNegativeValues() const { return fCanUseFractForNegativeValues; }
131 
mustForceNegatedAtanParamToFloat()132     bool mustForceNegatedAtanParamToFloat() const { return fMustForceNegatedAtanParamToFloat; }
133 
134     // http://skbug.com/12076
mustForceNegatedLdexpParamToMultiply()135     bool mustForceNegatedLdexpParamToMultiply() const {
136         return fMustForceNegatedLdexpParamToMultiply;
137     }
138 
139     // Returns whether a device incorrectly implements atan(y,x) as atan(y/x)
atan2ImplementedAsAtanYOverX()140     bool atan2ImplementedAsAtanYOverX() const { return fAtan2ImplementedAsAtanYOverX; }
141 
142     // If this returns true some operation (could be a no op) must be called between floor and abs
143     // to make sure the driver compiler doesn't inline them together which can cause a driver bug in
144     // the shader.
mustDoOpBetweenFloorAndAbs()145     bool mustDoOpBetweenFloorAndAbs() const { return fMustDoOpBetweenFloorAndAbs; }
146 
147     // If false, SkSL uses a workaround so that sk_FragCoord doesn't actually query gl_FragCoord
canUseFragCoord()148     bool canUseFragCoord() const { return fCanUseFragCoord; }
149 
150     // If true, short ints can't represent every integer in the 16-bit two's complement range as
151     // required by the spec. SKSL will always emit full ints.
incompleteShortIntPrecision()152     bool incompleteShortIntPrecision() const { return fIncompleteShortIntPrecision; }
153 
colorSpaceMathNeedsFloat()154     bool colorSpaceMathNeedsFloat() const { return fColorSpaceMathNeedsFloat; }
155 
156     // If true, then conditions in for loops need "&& true" to work around driver bugs.
addAndTrueToLoopCondition()157     bool addAndTrueToLoopCondition() const { return fAddAndTrueToLoopCondition; }
158 
159     // If true, then expressions such as "x && y" or "x || y" are rewritten as
160     // ternary to work around driver bugs.
unfoldShortCircuitAsTernary()161     bool unfoldShortCircuitAsTernary() const { return fUnfoldShortCircuitAsTernary; }
162 
emulateAbsIntFunction()163     bool emulateAbsIntFunction() const { return fEmulateAbsIntFunction; }
164 
rewriteDoWhileLoops()165     bool rewriteDoWhileLoops() const { return fRewriteDoWhileLoops; }
166 
rewriteSwitchStatements()167     bool rewriteSwitchStatements() const { return fRewriteSwitchStatements; }
168 
removePowWithConstantExponent()169     bool removePowWithConstantExponent() const { return fRemovePowWithConstantExponent; }
170 
requiresLocalOutputColorForFBFetch()171     bool requiresLocalOutputColorForFBFetch() const { return fRequiresLocalOutputColorForFBFetch; }
172 
mustObfuscateUniformColor()173     bool mustObfuscateUniformColor() const { return fMustObfuscateUniformColor; }
174 
175     // The D3D shader compiler, when targeting PS 3.0 (ie within ANGLE) fails to compile certain
176     // constructs. See detailed comments in GrGLCaps.cpp.
mustGuardDivisionEvenAfterExplicitZeroCheck()177     bool mustGuardDivisionEvenAfterExplicitZeroCheck() const {
178         return fMustGuardDivisionEvenAfterExplicitZeroCheck;
179     }
180 
181     // On Nexus 6, the GL context can get lost if a shader does not write a value to gl_FragColor.
182     // https://bugs.chromium.org/p/chromium/issues/detail?id=445377
mustWriteToFragColor()183     bool mustWriteToFragColor() const { return fMustWriteToFragColor; }
184 
185     // The Android emulator claims samplerExternalOES is an unknown type if a default precision
186     // statement is made for the type.
noDefaultPrecisionForExternalSamplers()187     bool noDefaultPrecisionForExternalSamplers() const {
188         return fNoDefaultPrecisionForExternalSamplers;
189     }
190 
191     // ARM GPUs calculate `matrix * vector` in SPIR-V at full precision, even when the inputs are
192     // RelaxedPrecision. Rewriting the multiply as a sum of vector*scalar fixes this. (skia:11769)
rewriteMatrixVectorMultiply()193     bool rewriteMatrixVectorMultiply() const {
194         return fRewriteMatrixVectorMultiply;
195     }
196 
197     // Rewrites matrix equality comparisons to avoid an Adreno driver bug. (skia:11308)
rewriteMatrixComparisons()198     bool rewriteMatrixComparisons() const { return fRewriteMatrixComparisons; }
199 
200     // ANGLE disallows do loops altogether, and we're seeing crashes on Tegra3 with do loops in at
201     // least some cases.
canUseDoLoops()202     bool canUseDoLoops() const { return fCanUseDoLoops; }
203 
204     // Some GPUs produce poor results when enabling Metal's fastmath option
canUseFastMath()205     bool canUseFastMath() const { return fCanUseFastMath; }
206 
207     // By default, SkSL pools IR nodes per-program. To debug memory corruption, it is sometimes
208     // helpful to disable that feature.
useNodePools()209     bool useNodePools() const { return fUseNodePools; }
210 
211     // When we have the option of using either dFdx or dfDy in a shader, this returns whether we
212     // should avoid using dFdx. We have found some drivers have bugs or lower precision when using
213     // dFdx.
avoidDfDxForGradientsWhenPossible()214     bool avoidDfDxForGradientsWhenPossible() const { return fAvoidDfDxForGradientsWhenPossible; }
215 
216     // Returns the string of an extension that must be enabled in the shader to support
217     // derivatives. If nullptr is returned then no extension needs to be enabled. Before calling
218     // this function, the caller should check that shaderDerivativeSupport exists.
shaderDerivativeExtensionString()219     const char* shaderDerivativeExtensionString() const {
220         SkASSERT(this->shaderDerivativeSupport());
221         return fShaderDerivativeExtensionString;
222     }
223 
224     // This returns the name of an extension that must be enabled in the shader, if such a thing is
225     // required in order to use a secondary output in the shader. This returns a nullptr if no such
226     // extension is required. However, the return value of this function does not say whether dual
227     // source blending is supported.
secondaryOutputExtensionString()228     const char* secondaryOutputExtensionString() const { return fSecondaryOutputExtensionString; }
229 
230     // This returns the name of an extension that must be enabled in the shader to support external
231     // textures. In some cases, two extensions must be enabled - the second extension is returned
232     // by secondExternalTextureExtensionString(). If that function returns nullptr, then only one
233     // extension is required.
externalTextureExtensionString()234     const char* externalTextureExtensionString() const {
235         SkASSERT(this->externalTextureSupport());
236         return fExternalTextureExtensionString;
237     }
238 
secondExternalTextureExtensionString()239     const char* secondExternalTextureExtensionString() const {
240         SkASSERT(this->externalTextureSupport());
241         return fSecondExternalTextureExtensionString;
242     }
243 
noperspectiveInterpolationExtensionString()244     const char* noperspectiveInterpolationExtensionString() const {
245         SkASSERT(this->noperspectiveInterpolationSupport());
246         return fNoPerspectiveInterpolationExtensionString;
247     }
248 
sampleVariablesExtensionString()249     const char* sampleVariablesExtensionString() const {
250         SkASSERT(this->sampleMaskSupport());
251         return fSampleVariablesExtensionString;
252     }
253 
tessellationExtensionString()254     const char* tessellationExtensionString() const {
255         SkASSERT(this->tessellationSupport());
256         return fTessellationExtensionString;
257     }
258 
maxFragmentSamplers()259     int maxFragmentSamplers() const { return fMaxFragmentSamplers; }
260 
261     // Maximum number of segments a tessellation edge can be divided into.
maxTessellationSegments()262     int maxTessellationSegments() const { return fMaxTessellationSegments; }
263 
tessellationSupport()264     bool tessellationSupport() const { return SkToBool(fMaxTessellationSegments);}
265 
generation()266     GrGLSLGeneration generation() const { return fGLSLGeneration; }
267 
268 private:
269     void applyOptionsOverrides(const GrContextOptions& options);
270 
271     GrGLSLGeneration fGLSLGeneration;
272 
273     bool fShaderDerivativeSupport           : 1;
274     bool fDstReadInShaderSupport            : 1;
275     bool fDualSourceBlendingSupport         : 1;
276     bool fIntegerSupport                    : 1;
277     bool fNonsquareMatrixSupport            : 1;
278     bool fInverseHyperbolicSupport          : 1;
279     bool fFBFetchSupport                    : 1;
280     bool fFBFetchNeedsCustomOutput          : 1;
281     bool fUsesPrecisionModifiers            : 1;
282     bool fFlatInterpolationSupport          : 1;
283     bool fPreferFlatInterpolation           : 1;
284     bool fNoPerspectiveInterpolationSupport : 1;
285     bool fSampleMaskSupport                 : 1;
286     bool fExternalTextureSupport            : 1;
287     bool fVertexIDSupport                   : 1;
288     bool fInfinitySupport                   : 1;
289     bool fNonconstantArrayIndexSupport      : 1;
290     bool fBitManipulationSupport            : 1;
291     bool fFloatIs32Bits                     : 1;
292     bool fHalfIs32Bits                      : 1;
293     bool fHasLowFragmentPrecision           : 1;
294     bool fReducedShaderMode                 : 1;
295 
296     // Used by SkSL to know when to generate polyfills.
297     bool fBuiltinFMASupport : 1;
298     bool fBuiltinDeterminantSupport : 1;
299 
300     // Used for specific driver bug work arounds
301     bool fCanUseAnyFunctionInShader                   : 1;
302     bool fCanUseMinAndAbsTogether                     : 1;
303     bool fCanUseFractForNegativeValues                : 1;
304     bool fMustForceNegatedAtanParamToFloat            : 1;
305     bool fMustForceNegatedLdexpParamToMultiply        : 1;
306     bool fAtan2ImplementedAsAtanYOverX                : 1;
307     bool fMustDoOpBetweenFloorAndAbs                  : 1;
308     bool fRequiresLocalOutputColorForFBFetch          : 1;
309     bool fMustObfuscateUniformColor                   : 1;
310     bool fMustGuardDivisionEvenAfterExplicitZeroCheck : 1;
311     bool fCanUseFragCoord                             : 1;
312     bool fIncompleteShortIntPrecision                 : 1;
313     bool fAddAndTrueToLoopCondition                   : 1;
314     bool fUnfoldShortCircuitAsTernary                 : 1;
315     bool fEmulateAbsIntFunction                       : 1;
316     bool fRewriteDoWhileLoops                         : 1;
317     bool fRewriteSwitchStatements                     : 1;
318     bool fRemovePowWithConstantExponent               : 1;
319     bool fMustWriteToFragColor                        : 1;
320     bool fNoDefaultPrecisionForExternalSamplers       : 1;
321     bool fRewriteMatrixVectorMultiply                 : 1;
322     bool fRewriteMatrixComparisons                    : 1;
323     bool fColorSpaceMathNeedsFloat                    : 1;
324     bool fCanUseDoLoops                               : 1;
325     bool fCanUseFastMath                              : 1;
326     bool fAvoidDfDxForGradientsWhenPossible           : 1;
327 
328     // This controls behavior of the SkSL compiler, not the code we generate
329     bool fUseNodePools : 1;
330 
331     const char* fVersionDeclString;
332 
333     const char* fShaderDerivativeExtensionString;
334     const char* fSecondaryOutputExtensionString;
335     const char* fExternalTextureExtensionString;
336     const char* fSecondExternalTextureExtensionString;
337     const char* fNoPerspectiveInterpolationExtensionString;
338     const char* fSampleVariablesExtensionString;
339     const char* fTessellationExtensionString;
340 
341     const char* fFBFetchColorName;
342     const char* fFBFetchExtensionString;
343 
344     int fMaxFragmentSamplers;
345     int fMaxTessellationSegments;
346 
347     AdvBlendEqInteraction fAdvBlendEqInteraction;
348 
349     friend class GrCaps;  // For initialization.
350     friend class GrDawnCaps;
351     friend class GrD3DCaps;
352     friend class GrGLCaps;
353     friend class GrMockCaps;
354     friend class GrMtlCaps;
355     friend class GrVkCaps;
356     friend class SkSL::ShaderCapsFactory;
357     friend class SkSL::SharedCompiler;
358 };
359 
360 #endif
361