• 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/sksl/SkSLLexer.h"
17 
18 #ifndef SKSL_STANDALONE
19 #include "include/core/SkTypes.h"
20 #if SK_SUPPORT_GPU
21 #include "include/gpu/GrContextOptions.h"
22 #include "include/private/GrTypesPriv.h"
23 #include "src/gpu/GrShaderCaps.h"
24 #endif // SK_SUPPORT_GPU
25 #endif // SKSL_STANDALONE
26 
27 class GrShaderCaps;
28 
29 namespace SkSL {
30 
31 class Context;
32 class OutputStream;
33 class StringStream;
34 class Type;
35 
36 #if defined(SKSL_STANDALONE) || !SK_SUPPORT_GPU
37 
38 // we're being compiled standalone, so we don't have access to caps...
39 enum GrGLSLGeneration {
40     k110_GrGLSLGeneration,
41     k130_GrGLSLGeneration,
42     k140_GrGLSLGeneration,
43     k150_GrGLSLGeneration,
44     k330_GrGLSLGeneration,
45     k400_GrGLSLGeneration,
46     k420_GrGLSLGeneration,
47     k310es_GrGLSLGeneration,
48     k320es_GrGLSLGeneration,
49 };
50 
51 class StandaloneShaderCaps {
52 public:
53     GrGLSLGeneration fGLSLGeneration = k400_GrGLSLGeneration;
generation()54     GrGLSLGeneration generation() const {
55         return fGLSLGeneration;
56     }
57 
58     bool fAtan2ImplementedAsAtanYOverX = false;
atan2ImplementedAsAtanYOverX()59     bool atan2ImplementedAsAtanYOverX() const {
60         return fAtan2ImplementedAsAtanYOverX;
61     }
62 
63     bool fCanUseMinAndAbsTogether = true;
canUseMinAndAbsTogether()64     bool canUseMinAndAbsTogether() const {
65         return fCanUseMinAndAbsTogether;
66     }
67 
68     bool fMustForceNegatedAtanParamToFloat = false;
mustForceNegatedAtanParamToFloat()69     bool mustForceNegatedAtanParamToFloat() const {
70         return fMustForceNegatedAtanParamToFloat;
71     }
72 
73     bool fMustForceNegatedLdexpParamToMultiply = false;
mustForceNegatedLdexpParamToMultiply()74     bool mustForceNegatedLdexpParamToMultiply() const {
75         return fMustForceNegatedLdexpParamToMultiply;
76     }
77 
78     bool fShaderDerivativeSupport = true;
shaderDerivativeSupport()79     bool shaderDerivativeSupport() const {
80         return fShaderDerivativeSupport;
81     }
82 
83     bool fUsesPrecisionModifiers = false;
usesPrecisionModifiers()84     bool usesPrecisionModifiers() const {
85         return fUsesPrecisionModifiers;
86     }
87 
mustDeclareFragmentShaderOutput()88     bool mustDeclareFragmentShaderOutput() const {
89         return fGLSLGeneration > k110_GrGLSLGeneration;
90     }
91 
92     bool fFBFetchSupport = false;
fbFetchSupport()93     bool fbFetchSupport() const {
94         return fFBFetchSupport;
95     }
96 
97     bool fFBFetchNeedsCustomOutput = false;
fbFetchNeedsCustomOutput()98     bool fbFetchNeedsCustomOutput() const {
99         return fFBFetchNeedsCustomOutput;
100     }
101 
102     bool fFlatInterpolationSupport = true;
flatInterpolationSupport()103     bool flatInterpolationSupport() const {
104         return fFlatInterpolationSupport;
105     }
106 
107     bool fNoperspectiveInterpolationSupport = true;
noperspectiveInterpolationSupport()108     bool noperspectiveInterpolationSupport() const {
109         return fNoperspectiveInterpolationSupport;
110     }
111 
112     bool fMultisampleInterpolationSupport = true;
multisampleInterpolationSupport()113     bool multisampleInterpolationSupport() const {
114         return fMultisampleInterpolationSupport;
115     }
116 
117     bool fSampleMaskSupport = true;
sampleMaskSupport()118     bool sampleMaskSupport() const {
119         return fSampleMaskSupport;
120     }
121 
122     bool fExternalTextureSupport = true;
externalTextureSupport()123     bool externalTextureSupport() const {
124         return fExternalTextureSupport;
125     }
126 
127     bool fMustDoOpBetweenFloorAndAbs = false;
mustDoOpBetweenFloorAndAbs()128     bool mustDoOpBetweenFloorAndAbs() const {
129         return fMustDoOpBetweenFloorAndAbs;
130     }
131 
132     bool fMustGuardDivisionEvenAfterExplicitZeroCheck = false;
mustGuardDivisionEvenAfterExplicitZeroCheck()133     bool mustGuardDivisionEvenAfterExplicitZeroCheck() const {
134         return fMustGuardDivisionEvenAfterExplicitZeroCheck;
135     }
136 
137     bool fMustEnableAdvBlendEqs = false;
mustEnableAdvBlendEqs()138     bool mustEnableAdvBlendEqs() const {
139         return fMustEnableAdvBlendEqs;
140     }
141 
142     bool fCanUseAnyFunctionInShader = true;
canUseAnyFunctionInShader()143     bool canUseAnyFunctionInShader() const {
144         return fCanUseAnyFunctionInShader;
145     }
146 
147     bool fNoDefaultPrecisionForExternalSamplers = false;
noDefaultPrecisionForExternalSamplers()148     bool noDefaultPrecisionForExternalSamplers() const {
149         return fNoDefaultPrecisionForExternalSamplers;
150     }
151 
152     bool fFloatIs32Bits = true;
floatIs32Bits()153     bool floatIs32Bits() const {
154         return fFloatIs32Bits;
155     }
156 
157     bool fIntegerSupport = false;
integerSupport()158     bool integerSupport() const {
159         return fIntegerSupport;
160     }
161 
162     bool fNonsquareMatrixSupport = false;
nonsquareMatrixSupport()163     bool nonsquareMatrixSupport() const {
164         return fNonsquareMatrixSupport;
165     }
166 
167     bool fInverseHyperbolicSupport = false;
inverseHyperbolicSupport()168     bool inverseHyperbolicSupport() const {
169         return fInverseHyperbolicSupport;
170     }
171 
172     bool fBuiltinFMASupport = false;
builtinFMASupport()173     bool builtinFMASupport() const {
174         return fBuiltinFMASupport;
175     }
176 
177     bool fBuiltinDeterminantSupport = false;
builtinDeterminantSupport()178     bool builtinDeterminantSupport() const {
179         return fBuiltinDeterminantSupport;
180     }
181 
182     bool fCanUseDoLoops = false;
canUseDoLoops()183     bool canUseDoLoops() const {
184         // we define this to false in standalone so we don't use do loops while inlining in FP files
185         // (which would then, being baked in, end up being used even in contexts where do loops are
186         // not allowed)
187         return fCanUseDoLoops;
188     }
189 
190     bool fUseNodePools = true;
useNodePools()191     bool useNodePools() const {
192         return fUseNodePools;
193     }
194 
195     const char* fShaderDerivativeExtensionString = nullptr;
shaderDerivativeExtensionString()196     const char* shaderDerivativeExtensionString() const {
197         return fShaderDerivativeExtensionString;
198     }
199 
200     const char* fFragCoordConventionsExtensionString = nullptr;
fragCoordConventionsExtensionString()201     const char* fragCoordConventionsExtensionString() const {
202         return fFragCoordConventionsExtensionString;
203     }
204 
205     const char* fExternalTextureExtensionString = nullptr;
externalTextureExtensionString()206     const char* externalTextureExtensionString() const {
207         return fExternalTextureExtensionString;
208     }
209 
210     const char* fSecondExternalTextureExtensionString = nullptr;
secondExternalTextureExtensionString()211     const char* secondExternalTextureExtensionString() const {
212         return fSecondExternalTextureExtensionString;
213     }
214 
215     const char* fVersionDeclString = "";
versionDeclString()216     const char* versionDeclString() const {
217         return fVersionDeclString;
218     }
219 
220     bool fCanUseFractForNegativeValues = true;
canUseFractForNegativeValues()221     bool canUseFractForNegativeValues() const {
222         return fCanUseFractForNegativeValues;
223     }
224 
225     bool fCanUseFragCoord = true;
canUseFragCoord()226     bool canUseFragCoord() const {
227         return fCanUseFragCoord;
228     }
229 
230     bool fIncompleteShortIntPrecision = false;
incompleteShortIntPrecision()231     bool incompleteShortIntPrecision() const {
232         return fIncompleteShortIntPrecision;
233     }
234 
235     bool fAddAndTrueToLoopCondition = false;
addAndTrueToLoopCondition()236     bool addAndTrueToLoopCondition() const {
237         return fAddAndTrueToLoopCondition;
238     }
239 
240     bool fUnfoldShortCircuitAsTernary = false;
unfoldShortCircuitAsTernary()241     bool unfoldShortCircuitAsTernary() const {
242         return fUnfoldShortCircuitAsTernary;
243     }
244 
245     bool fEmulateAbsIntFunction = false;
emulateAbsIntFunction()246     bool emulateAbsIntFunction() const {
247         return fEmulateAbsIntFunction;
248     }
249 
250     bool fRewriteDoWhileLoops = false;
rewriteDoWhileLoops()251     bool rewriteDoWhileLoops() const {
252         return fRewriteDoWhileLoops;
253     }
254 
255     bool fRewriteSwitchStatements = false;
rewriteSwitchStatements()256     bool rewriteSwitchStatements() const {
257         return fRewriteSwitchStatements;
258     }
259 
260     bool fRemovePowWithConstantExponent = false;
removePowWithConstantExponent()261     bool removePowWithConstantExponent() const {
262         return fRemovePowWithConstantExponent;
263     }
264 
265     const char* fFBFetchColorName = nullptr;
fbFetchColorName()266     const char* fbFetchColorName() const {
267         return fFBFetchColorName;
268     }
269 
270     bool fRewriteMatrixVectorMultiply = false;
rewriteMatrixVectorMultiply()271     bool rewriteMatrixVectorMultiply() const {
272         return fRewriteMatrixVectorMultiply;
273     }
274 
275     bool fRewriteMatrixComparisons = false;
rewriteMatrixComparisons()276     bool rewriteMatrixComparisons() const {
277         return fRewriteMatrixComparisons;
278     }
279 };
280 
281 using ShaderCapsClass = StandaloneShaderCaps;
282 using ShaderCapsPointer = std::unique_ptr<StandaloneShaderCaps>;
283 
284 #else
285 
286 using ShaderCapsClass = GrShaderCaps;
287 using ShaderCapsPointer = std::unique_ptr<GrShaderCaps>;
288 
289 #endif  // defined(SKSL_STANDALONE) || !SK_SUPPORT_GPU
290 
291 // Various sets of caps for use in tests
292 class ShaderCapsFactory {
293 public:
Default()294     static ShaderCapsPointer Default() {
295         ShaderCapsPointer result = MakeShaderCaps();
296         result->fVersionDeclString = "#version 400";
297         result->fShaderDerivativeSupport = true;
298         result->fBuiltinDeterminantSupport = true;
299         result->fCanUseDoLoops = true;
300         return result;
301     }
302 
Standalone()303     static ShaderCapsPointer Standalone() {
304         return MakeShaderCaps();
305     }
306 
AddAndTrueToLoopCondition()307     static ShaderCapsPointer AddAndTrueToLoopCondition() {
308         ShaderCapsPointer result = MakeShaderCaps();
309         result->fVersionDeclString = "#version 400";
310         result->fAddAndTrueToLoopCondition = true;
311         return result;
312     }
313 
CannotUseFractForNegativeValues()314     static ShaderCapsPointer CannotUseFractForNegativeValues() {
315         ShaderCapsPointer result = MakeShaderCaps();
316         result->fVersionDeclString = "#version 400";
317         result->fCanUseFractForNegativeValues = false;
318         return result;
319     }
320 
CannotUseFragCoord()321     static ShaderCapsPointer CannotUseFragCoord() {
322         ShaderCapsPointer result = MakeShaderCaps();
323         result->fVersionDeclString = "#version 400";
324         result->fCanUseFragCoord = false;
325         return result;
326     }
327 
CannotUseMinAndAbsTogether()328     static ShaderCapsPointer CannotUseMinAndAbsTogether() {
329         ShaderCapsPointer result = MakeShaderCaps();
330         result->fVersionDeclString = "#version 400";
331         result->fCanUseMinAndAbsTogether = false;
332         return result;
333     }
334 
EmulateAbsIntFunction()335     static ShaderCapsPointer EmulateAbsIntFunction() {
336         ShaderCapsPointer result = MakeShaderCaps();
337         result->fVersionDeclString = "#version 400";
338         result->fEmulateAbsIntFunction = true;
339         return result;
340     }
341 
FramebufferFetchSupport()342     static ShaderCapsPointer FramebufferFetchSupport() {
343         ShaderCapsPointer result = MakeShaderCaps();
344         result->fFBFetchSupport = true;
345         result->fFBFetchColorName = "gl_LastFragData[0]";
346         return result;
347     }
348 
IncompleteShortIntPrecision()349     static ShaderCapsPointer IncompleteShortIntPrecision() {
350         ShaderCapsPointer result = MakeShaderCaps();
351         result->fVersionDeclString = "#version 310es";
352         result->fUsesPrecisionModifiers = true;
353         result->fIncompleteShortIntPrecision = true;
354         return result;
355     }
356 
MustForceNegatedAtanParamToFloat()357     static ShaderCapsPointer MustForceNegatedAtanParamToFloat() {
358         ShaderCapsPointer result = MakeShaderCaps();
359         result->fVersionDeclString = "#version 400";
360         result->fMustForceNegatedAtanParamToFloat = true;
361         return result;
362     }
363 
MustForceNegatedLdexpParamToMultiply()364     static ShaderCapsPointer MustForceNegatedLdexpParamToMultiply() {
365         ShaderCapsPointer result = MakeShaderCaps();
366         result->fVersionDeclString = "#version 400";
367         result->fMustForceNegatedLdexpParamToMultiply = true;
368         return result;
369     }
370 
MustGuardDivisionEvenAfterExplicitZeroCheck()371     static ShaderCapsPointer MustGuardDivisionEvenAfterExplicitZeroCheck() {
372         ShaderCapsPointer result = MakeShaderCaps();
373         result->fMustGuardDivisionEvenAfterExplicitZeroCheck = true;
374         return result;
375     }
376 
RemovePowWithConstantExponent()377     static ShaderCapsPointer RemovePowWithConstantExponent() {
378         ShaderCapsPointer result = MakeShaderCaps();
379         result->fVersionDeclString = "#version 400";
380         result->fRemovePowWithConstantExponent = true;
381         return result;
382     }
383 
RewriteDoWhileLoops()384     static ShaderCapsPointer RewriteDoWhileLoops() {
385         ShaderCapsPointer result = MakeShaderCaps();
386         result->fVersionDeclString = "#version 400";
387         result->fRewriteDoWhileLoops = true;
388         return result;
389     }
390 
RewriteMatrixComparisons()391     static ShaderCapsPointer RewriteMatrixComparisons() {
392         ShaderCapsPointer result = MakeShaderCaps();
393         result->fRewriteMatrixComparisons = true;
394         result->fUsesPrecisionModifiers = true;
395         return result;
396     }
397 
RewriteMatrixVectorMultiply()398     static ShaderCapsPointer RewriteMatrixVectorMultiply() {
399         ShaderCapsPointer result = MakeShaderCaps();
400         result->fVersionDeclString = "#version 400";
401         result->fRewriteMatrixVectorMultiply = true;
402         return result;
403     }
404 
RewriteSwitchStatements()405     static ShaderCapsPointer RewriteSwitchStatements() {
406         ShaderCapsPointer result = MakeShaderCaps();
407         result->fVersionDeclString = "#version 400";
408         result->fRewriteSwitchStatements = true;
409         return result;
410     }
411 
SampleMaskSupport()412     static ShaderCapsPointer SampleMaskSupport() {
413         ShaderCapsPointer result = Default();
414         result->fSampleMaskSupport = true;
415         return result;
416     }
417 
ShaderDerivativeExtensionString()418     static ShaderCapsPointer ShaderDerivativeExtensionString() {
419         ShaderCapsPointer result = MakeShaderCaps();
420         result->fVersionDeclString = "#version 400";
421         result->fShaderDerivativeSupport = true;
422         result->fShaderDerivativeExtensionString = "GL_OES_standard_derivatives";
423         result->fUsesPrecisionModifiers = true;
424         return result;
425     }
426 
UnfoldShortCircuitAsTernary()427     static ShaderCapsPointer UnfoldShortCircuitAsTernary() {
428         ShaderCapsPointer result = MakeShaderCaps();
429         result->fVersionDeclString = "#version 400";
430         result->fUnfoldShortCircuitAsTernary = true;
431         return result;
432     }
433 
UsesPrecisionModifiers()434     static ShaderCapsPointer UsesPrecisionModifiers() {
435         ShaderCapsPointer result = MakeShaderCaps();
436         result->fVersionDeclString = "#version 400";
437         result->fUsesPrecisionModifiers = true;
438         return result;
439     }
440 
Version110()441     static ShaderCapsPointer Version110() {
442         ShaderCapsPointer result = MakeShaderCaps();
443         result->fVersionDeclString = "#version 110";
444         result->fGLSLGeneration = GrGLSLGeneration::k110_GrGLSLGeneration;
445         return result;
446     }
447 
Version450Core()448     static ShaderCapsPointer Version450Core() {
449         ShaderCapsPointer result = MakeShaderCaps();
450         result->fVersionDeclString = "#version 450 core";
451         return result;
452     }
453 
454 private:
455     static ShaderCapsPointer MakeShaderCaps();
456 };
457 
458 #if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
459 bool type_to_grsltype(const Context& context, const Type& type, GrSLType* outType);
460 #endif
461 
462 void write_stringstream(const StringStream& d, OutputStream& out);
463 
464 }  // namespace SkSL
465 
466 #endif  // SKSL_UTIL
467