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