• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 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 SKSL_UTIL
9 #define SKSL_UTIL
10 
11 #include <cstdarg>
12 #include <memory>
13 #include <stdlib.h>
14 #include <string.h>
15 #include "include/private/SkSLDefines.h"
16 #include "src/core/SkSLTypeShared.h"
17 #include "src/sksl/SkSLGLSL.h"
18 #include "src/sksl/SkSLLexer.h"
19 
20 #ifndef SKSL_STANDALONE
21 #include "include/core/SkTypes.h"
22 #if SK_SUPPORT_GPU
23 #include "include/gpu/GrContextOptions.h"
24 #include "include/private/GrTypesPriv.h"
25 #endif // SK_SUPPORT_GPU
26 #endif // SKSL_STANDALONE
27 
28 namespace SkSL {
29 
30 class Context;
31 class OutputStream;
32 class ShaderCapsFactory;
33 class StringStream;
34 class Type;
35 
36 struct ShaderCaps {
37     /**
38      * Indicates how GLSL must interact with advanced blend equations. The KHR extension requires
39      * special layout qualifiers in the fragment shader.
40      */
41     enum AdvBlendEqInteraction {
42         kNotSupported_AdvBlendEqInteraction,     //<! No _blend_equation_advanced extension
43         kAutomatic_AdvBlendEqInteraction,        //<! No interaction required
44         kGeneralEnable_AdvBlendEqInteraction,    //<! layout(blend_support_all_equations) out
45 
46         kLast_AdvBlendEqInteraction = kGeneralEnable_AdvBlendEqInteraction
47     };
48 
49     //
50     // TODO: Remove these accessors
51     //
shaderDerivativeSupportShaderCaps52     bool shaderDerivativeSupport() const { return fShaderDerivativeSupport; }
nonsquareMatrixSupportShaderCaps53     bool nonsquareMatrixSupport() const { return fNonsquareMatrixSupport; }
54 
55     /** Indicates true 32-bit integer support, with unsigned types and bitwise operations */
integerSupportShaderCaps56     bool integerSupport() const { return fIntegerSupport; }
57 
58     /** asinh(), acosh(), atanh() */
inverseHyperbolicSupportShaderCaps59     bool inverseHyperbolicSupport() const { return fInverseHyperbolicSupport; }
60 
61     /**
62      * Some helper functions for encapsulating various extensions to read FB Buffer on openglES
63      *
64      * TODO: On desktop opengl 4.2+ we can achieve something similar to this effect
65      */
fbFetchSupportShaderCaps66     bool fbFetchSupport() const { return fFBFetchSupport; }
67 
fbFetchNeedsCustomOutputShaderCaps68     bool fbFetchNeedsCustomOutput() const { return fFBFetchNeedsCustomOutput; }
69 
versionDeclStringShaderCaps70     const char* versionDeclString() const { return fVersionDeclString; }
71 
fbFetchColorNameShaderCaps72     const char* fbFetchColorName() const { return fFBFetchColorName; }
73 
flatInterpolationSupportShaderCaps74     bool flatInterpolationSupport() const { return fFlatInterpolationSupport; }
75 
noperspectiveInterpolationSupportShaderCaps76     bool noperspectiveInterpolationSupport() const { return fNoPerspectiveInterpolationSupport; }
77 
sampleMaskSupportShaderCaps78     bool sampleMaskSupport() const { return fSampleMaskSupport; }
79 
externalTextureSupportShaderCaps80     bool externalTextureSupport() const { return fExternalTextureSupport; }
81 
floatIs32BitsShaderCaps82     bool floatIs32Bits() const { return fFloatIs32Bits; }
83 
84     // SkSL only.
builtinFMASupportShaderCaps85     bool builtinFMASupport() const { return fBuiltinFMASupport; }
86 
builtinDeterminantSupportShaderCaps87     bool builtinDeterminantSupport() const { return fBuiltinDeterminantSupport; }
88 
advBlendEqInteractionShaderCaps89     AdvBlendEqInteraction advBlendEqInteraction() const { return fAdvBlendEqInteraction; }
90 
mustEnableAdvBlendEqsShaderCaps91     bool mustEnableAdvBlendEqs() const {
92         return fAdvBlendEqInteraction >= kGeneralEnable_AdvBlendEqInteraction;
93     }
94 
mustDeclareFragmentShaderOutputShaderCaps95     bool mustDeclareFragmentShaderOutput() const {
96         return fGLSLGeneration > SkSL::GLSLGeneration::k110;
97     }
98 
usesPrecisionModifiersShaderCaps99     bool usesPrecisionModifiers() const { return fUsesPrecisionModifiers; }
100 
101     // Returns whether we can use the glsl function any() in our shader code.
canUseAnyFunctionInShaderShaderCaps102     bool canUseAnyFunctionInShader() const { return fCanUseAnyFunctionInShader; }
103 
canUseMinAndAbsTogetherShaderCaps104     bool canUseMinAndAbsTogether() const { return fCanUseMinAndAbsTogether; }
105 
canUseFractForNegativeValuesShaderCaps106     bool canUseFractForNegativeValues() const { return fCanUseFractForNegativeValues; }
107 
mustForceNegatedAtanParamToFloatShaderCaps108     bool mustForceNegatedAtanParamToFloat() const { return fMustForceNegatedAtanParamToFloat; }
109 
110     // http://skbug.com/12076
mustForceNegatedLdexpParamToMultiplyShaderCaps111     bool mustForceNegatedLdexpParamToMultiply() const {
112         return fMustForceNegatedLdexpParamToMultiply;
113     }
114 
115     // Returns whether a device incorrectly implements atan(y,x) as atan(y/x)
atan2ImplementedAsAtanYOverXShaderCaps116     bool atan2ImplementedAsAtanYOverX() const { return fAtan2ImplementedAsAtanYOverX; }
117 
118     // If this returns true some operation (could be a no op) must be called between floor and abs
119     // to make sure the driver compiler doesn't inline them together which can cause a driver bug in
120     // the shader.
mustDoOpBetweenFloorAndAbsShaderCaps121     bool mustDoOpBetweenFloorAndAbs() const { return fMustDoOpBetweenFloorAndAbs; }
122 
123     // If false, SkSL uses a workaround so that sk_FragCoord doesn't actually query gl_FragCoord
canUseFragCoordShaderCaps124     bool canUseFragCoord() const { return fCanUseFragCoord; }
125 
126     // If true, short ints can't represent every integer in the 16-bit two's complement range as
127     // required by the spec. SKSL will always emit full ints.
incompleteShortIntPrecisionShaderCaps128     bool incompleteShortIntPrecision() const { return fIncompleteShortIntPrecision; }
129 
130     // If true, then conditions in for loops need "&& true" to work around driver bugs.
addAndTrueToLoopConditionShaderCaps131     bool addAndTrueToLoopCondition() const { return fAddAndTrueToLoopCondition; }
132 
133     // If true, then expressions such as "x && y" or "x || y" are rewritten as
134     // ternary to work around driver bugs.
unfoldShortCircuitAsTernaryShaderCaps135     bool unfoldShortCircuitAsTernary() const { return fUnfoldShortCircuitAsTernary; }
136 
emulateAbsIntFunctionShaderCaps137     bool emulateAbsIntFunction() const { return fEmulateAbsIntFunction; }
138 
rewriteDoWhileLoopsShaderCaps139     bool rewriteDoWhileLoops() const { return fRewriteDoWhileLoops; }
140 
rewriteSwitchStatementsShaderCaps141     bool rewriteSwitchStatements() const { return fRewriteSwitchStatements; }
142 
removePowWithConstantExponentShaderCaps143     bool removePowWithConstantExponent() const { return fRemovePowWithConstantExponent; }
144 
145     // The D3D shader compiler, when targeting PS 3.0 (ie within ANGLE) fails to compile certain
146     // constructs. See detailed comments in GrGLCaps.cpp.
mustGuardDivisionEvenAfterExplicitZeroCheckShaderCaps147     bool mustGuardDivisionEvenAfterExplicitZeroCheck() const {
148         return fMustGuardDivisionEvenAfterExplicitZeroCheck;
149     }
150 
151     // The Android emulator claims samplerExternalOES is an unknown type if a default precision
152     // statement is made for the type.
noDefaultPrecisionForExternalSamplersShaderCaps153     bool noDefaultPrecisionForExternalSamplers() const {
154         return fNoDefaultPrecisionForExternalSamplers;
155     }
156 
157     // ARM GPUs calculate `matrix * vector` in SPIR-V at full precision, even when the inputs are
158     // RelaxedPrecision. Rewriting the multiply as a sum of vector*scalar fixes this. (skia:11769)
rewriteMatrixVectorMultiplyShaderCaps159     bool rewriteMatrixVectorMultiply() const {
160         return fRewriteMatrixVectorMultiply;
161     }
162 
163     // Rewrites matrix equality comparisons to avoid an Adreno driver bug. (skia:11308)
rewriteMatrixComparisonsShaderCaps164     bool rewriteMatrixComparisons() const { return fRewriteMatrixComparisons; }
165 
166     // By default, SkSL pools IR nodes per-program. To debug memory corruption, it is sometimes
167     // helpful to disable that feature.
useNodePoolsShaderCaps168     bool useNodePools() const { return fUseNodePools; }
169 
170     // Returns the string of an extension that must be enabled in the shader to support
171     // derivatives. If nullptr is returned then no extension needs to be enabled. Before calling
172     // this function, the caller should check that shaderDerivativeSupport exists.
shaderDerivativeExtensionStringShaderCaps173     const char* shaderDerivativeExtensionString() const {
174         SkASSERT(this->shaderDerivativeSupport());
175         return fShaderDerivativeExtensionString;
176     }
177 
178     // This returns the name of an extension that must be enabled in the shader to support external
179     // textures. In some cases, two extensions must be enabled - the second extension is returned
180     // by secondExternalTextureExtensionString(). If that function returns nullptr, then only one
181     // extension is required.
externalTextureExtensionStringShaderCaps182     const char* externalTextureExtensionString() const {
183         SkASSERT(this->externalTextureSupport());
184         return fExternalTextureExtensionString;
185     }
186 
secondExternalTextureExtensionStringShaderCaps187     const char* secondExternalTextureExtensionString() const {
188         SkASSERT(this->externalTextureSupport());
189         return fSecondExternalTextureExtensionString;
190     }
191 
generationShaderCaps192     SkSL::GLSLGeneration generation() const { return fGLSLGeneration; }
193 
194     SkSL::GLSLGeneration fGLSLGeneration = SkSL::GLSLGeneration::k330;
195 
196     bool fShaderDerivativeSupport = false;
197     bool fIntegerSupport = false;
198     bool fNonsquareMatrixSupport = false;
199     bool fInverseHyperbolicSupport = false;
200     bool fFBFetchSupport = false;
201     bool fFBFetchNeedsCustomOutput = false;
202     bool fUsesPrecisionModifiers = false;
203     bool fFlatInterpolationSupport = false;
204     bool fNoPerspectiveInterpolationSupport = false;
205     bool fSampleMaskSupport = false;
206     bool fExternalTextureSupport = false;
207     bool fFloatIs32Bits = true;
208 
209     // Used by SkSL to know when to generate polyfills.
210     bool fBuiltinFMASupport = false;
211     bool fBuiltinDeterminantSupport = false;
212 
213     // Used for specific driver bug work arounds
214     bool fCanUseAnyFunctionInShader = true;
215     bool fCanUseMinAndAbsTogether = true;
216     bool fCanUseFractForNegativeValues = true;
217     bool fMustForceNegatedAtanParamToFloat = false;
218     bool fMustForceNegatedLdexpParamToMultiply = false;
219     bool fAtan2ImplementedAsAtanYOverX = false;
220     bool fMustDoOpBetweenFloorAndAbs = false;
221     bool fMustGuardDivisionEvenAfterExplicitZeroCheck = false;
222     bool fCanUseFragCoord = true;
223     bool fIncompleteShortIntPrecision = false;
224     bool fAddAndTrueToLoopCondition = false;
225     bool fUnfoldShortCircuitAsTernary = false;
226     bool fEmulateAbsIntFunction = false;
227     bool fRewriteDoWhileLoops = false;
228     bool fRewriteSwitchStatements = false;
229     bool fRemovePowWithConstantExponent = false;
230     bool fNoDefaultPrecisionForExternalSamplers = false;
231     bool fRewriteMatrixVectorMultiply = false;
232     bool fRewriteMatrixComparisons = false;
233 
234     // This controls behavior of the SkSL compiler, not the code we generate
235     bool fUseNodePools = true;
236 
237     const char* fVersionDeclString = "";
238 
239     const char* fShaderDerivativeExtensionString = nullptr;
240     const char* fExternalTextureExtensionString = nullptr;
241     const char* fSecondExternalTextureExtensionString = nullptr;
242     const char* fFBFetchColorName = nullptr;
243 
244     AdvBlendEqInteraction fAdvBlendEqInteraction = kNotSupported_AdvBlendEqInteraction;
245 };
246 
247 // Various sets of caps for use in tests
248 class ShaderCapsFactory {
249 public:
Default()250     static std::unique_ptr<ShaderCaps> Default() {
251         std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
252         result->fVersionDeclString = "#version 400";
253         result->fShaderDerivativeSupport = true;
254         result->fBuiltinDeterminantSupport = true;
255         return result;
256     }
257 
Standalone()258     static std::unique_ptr<ShaderCaps> Standalone() {
259         return MakeShaderCaps();
260     }
261 
AddAndTrueToLoopCondition()262     static std::unique_ptr<ShaderCaps> AddAndTrueToLoopCondition() {
263         std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
264         result->fVersionDeclString = "#version 400";
265         result->fAddAndTrueToLoopCondition = true;
266         return result;
267     }
268 
CannotUseFractForNegativeValues()269     static std::unique_ptr<ShaderCaps> CannotUseFractForNegativeValues() {
270         std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
271         result->fVersionDeclString = "#version 400";
272         result->fCanUseFractForNegativeValues = false;
273         return result;
274     }
275 
CannotUseFragCoord()276     static std::unique_ptr<ShaderCaps> CannotUseFragCoord() {
277         std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
278         result->fVersionDeclString = "#version 400";
279         result->fCanUseFragCoord = false;
280         return result;
281     }
282 
CannotUseMinAndAbsTogether()283     static std::unique_ptr<ShaderCaps> CannotUseMinAndAbsTogether() {
284         std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
285         result->fVersionDeclString = "#version 400";
286         result->fCanUseMinAndAbsTogether = false;
287         return result;
288     }
289 
EmulateAbsIntFunction()290     static std::unique_ptr<ShaderCaps> EmulateAbsIntFunction() {
291         std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
292         result->fVersionDeclString = "#version 400";
293         result->fEmulateAbsIntFunction = true;
294         return result;
295     }
296 
FramebufferFetchSupport()297     static std::unique_ptr<ShaderCaps> FramebufferFetchSupport() {
298         std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
299         result->fFBFetchSupport = true;
300         result->fFBFetchColorName = "gl_LastFragData[0]";
301         return result;
302     }
303 
IncompleteShortIntPrecision()304     static std::unique_ptr<ShaderCaps> IncompleteShortIntPrecision() {
305         std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
306         result->fVersionDeclString = "#version 310es";
307         result->fUsesPrecisionModifiers = true;
308         result->fIncompleteShortIntPrecision = true;
309         return result;
310     }
311 
MustForceNegatedAtanParamToFloat()312     static std::unique_ptr<ShaderCaps> MustForceNegatedAtanParamToFloat() {
313         std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
314         result->fVersionDeclString = "#version 400";
315         result->fMustForceNegatedAtanParamToFloat = true;
316         return result;
317     }
318 
MustForceNegatedLdexpParamToMultiply()319     static std::unique_ptr<ShaderCaps> MustForceNegatedLdexpParamToMultiply() {
320         std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
321         result->fVersionDeclString = "#version 400";
322         result->fMustForceNegatedLdexpParamToMultiply = true;
323         return result;
324     }
325 
MustGuardDivisionEvenAfterExplicitZeroCheck()326     static std::unique_ptr<ShaderCaps> MustGuardDivisionEvenAfterExplicitZeroCheck() {
327         std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
328         result->fMustGuardDivisionEvenAfterExplicitZeroCheck = true;
329         return result;
330     }
331 
RemovePowWithConstantExponent()332     static std::unique_ptr<ShaderCaps> RemovePowWithConstantExponent() {
333         std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
334         result->fVersionDeclString = "#version 400";
335         result->fRemovePowWithConstantExponent = true;
336         return result;
337     }
338 
RewriteDoWhileLoops()339     static std::unique_ptr<ShaderCaps> RewriteDoWhileLoops() {
340         std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
341         result->fVersionDeclString = "#version 400";
342         result->fRewriteDoWhileLoops = true;
343         return result;
344     }
345 
RewriteMatrixComparisons()346     static std::unique_ptr<ShaderCaps> RewriteMatrixComparisons() {
347         std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
348         result->fRewriteMatrixComparisons = true;
349         result->fUsesPrecisionModifiers = true;
350         return result;
351     }
352 
RewriteMatrixVectorMultiply()353     static std::unique_ptr<ShaderCaps> RewriteMatrixVectorMultiply() {
354         std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
355         result->fVersionDeclString = "#version 400";
356         result->fRewriteMatrixVectorMultiply = true;
357         return result;
358     }
359 
RewriteSwitchStatements()360     static std::unique_ptr<ShaderCaps> RewriteSwitchStatements() {
361         std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
362         result->fVersionDeclString = "#version 400";
363         result->fRewriteSwitchStatements = true;
364         return result;
365     }
366 
SampleMaskSupport()367     static std::unique_ptr<ShaderCaps> SampleMaskSupport() {
368         std::unique_ptr<ShaderCaps> result = Default();
369         result->fSampleMaskSupport = true;
370         return result;
371     }
372 
ShaderDerivativeExtensionString()373     static std::unique_ptr<ShaderCaps> ShaderDerivativeExtensionString() {
374         std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
375         result->fVersionDeclString = "#version 400";
376         result->fShaderDerivativeSupport = true;
377         result->fShaderDerivativeExtensionString = "GL_OES_standard_derivatives";
378         result->fUsesPrecisionModifiers = true;
379         return result;
380     }
381 
UnfoldShortCircuitAsTernary()382     static std::unique_ptr<ShaderCaps> UnfoldShortCircuitAsTernary() {
383         std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
384         result->fVersionDeclString = "#version 400";
385         result->fUnfoldShortCircuitAsTernary = true;
386         return result;
387     }
388 
UsesPrecisionModifiers()389     static std::unique_ptr<ShaderCaps> UsesPrecisionModifiers() {
390         std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
391         result->fVersionDeclString = "#version 400";
392         result->fUsesPrecisionModifiers = true;
393         return result;
394     }
395 
Version110()396     static std::unique_ptr<ShaderCaps> Version110() {
397         std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
398         result->fVersionDeclString = "#version 110";
399         result->fGLSLGeneration = SkSL::GLSLGeneration::k110;
400         return result;
401     }
402 
Version450Core()403     static std::unique_ptr<ShaderCaps> Version450Core() {
404         std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
405         result->fVersionDeclString = "#version 450 core";
406         return result;
407     }
408 
409 private:
410     static std::unique_ptr<ShaderCaps> MakeShaderCaps();
411 };
412 
413 #if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
414 bool type_to_sksltype(const Context& context, const Type& type, SkSLType* outType);
415 #endif
416 
417 void write_stringstream(const StringStream& d, OutputStream& out);
418 
419 }  // namespace SkSL
420 
421 #endif  // SKSL_UTIL
422