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 "src/sksl/SkSLDefines.h"
16 #include "src/sksl/SkSLLexer.h"
17 
18 #ifndef SKSL_STANDALONE
19 #include "include/core/SkTypes.h"
20 #include "include/private/GrTypesPriv.h"
21 #if SK_SUPPORT_GPU
22 #include "include/gpu/GrContextOptions.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 fGeometryShaderSupport = true;
geometryShaderSupport()74     bool geometryShaderSupport() const {
75         return fGeometryShaderSupport;
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 = true;
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 fInBlendModesFailRandomlyForAllZeroVec = false;
inBlendModesFailRandomlyForAllZeroVec()138     bool inBlendModesFailRandomlyForAllZeroVec() const {
139         return fInBlendModesFailRandomlyForAllZeroVec;
140     }
141 
142     bool fMustEnableAdvBlendEqs = false;
mustEnableAdvBlendEqs()143     bool mustEnableAdvBlendEqs() const {
144         return fMustEnableAdvBlendEqs;
145     }
146 
147     bool fMustEnableSpecificAdvBlendEqs = false;
mustEnableSpecificAdvBlendEqs()148     bool mustEnableSpecificAdvBlendEqs() const {
149         return fMustEnableSpecificAdvBlendEqs;
150     }
151 
152     bool fCanUseAnyFunctionInShader = true;
canUseAnyFunctionInShader()153     bool canUseAnyFunctionInShader() const {
154         return fCanUseAnyFunctionInShader;
155     }
156 
157     bool fNoDefaultPrecisionForExternalSamplers = false;
noDefaultPrecisionForExternalSamplers()158     bool noDefaultPrecisionForExternalSamplers() const {
159         return fNoDefaultPrecisionForExternalSamplers;
160     }
161 
162     bool fFloatIs32Bits = true;
floatIs32Bits()163     bool floatIs32Bits() const {
164         return fFloatIs32Bits;
165     }
166 
167     bool fIntegerSupport = false;
integerSupport()168     bool integerSupport() const {
169         return fIntegerSupport;
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     const char* fShaderDerivativeExtensionString = nullptr;
shaderDerivativeExtensionString()191     const char* shaderDerivativeExtensionString() const {
192         return fShaderDerivativeExtensionString;
193     }
194 
195     const char* fFragCoordConventionsExtensionString = nullptr;
fragCoordConventionsExtensionString()196     const char* fragCoordConventionsExtensionString() const {
197         return fFragCoordConventionsExtensionString;
198     }
199 
200     const char* fGeometryShaderExtensionString = nullptr;
geometryShaderExtensionString()201     const char* geometryShaderExtensionString() const {
202         return fGeometryShaderExtensionString;
203     }
204 
205     const char* fGSInvocationsExtensionString = nullptr;
gsInvocationsExtensionString()206     const char* gsInvocationsExtensionString() const {
207         return fGSInvocationsExtensionString;
208     }
209 
210     const char* fExternalTextureExtensionString = nullptr;
externalTextureExtensionString()211     const char* externalTextureExtensionString() const {
212         return fExternalTextureExtensionString;
213     }
214 
215     const char* fSecondExternalTextureExtensionString = nullptr;
secondExternalTextureExtensionString()216     const char* secondExternalTextureExtensionString() const {
217         return fSecondExternalTextureExtensionString;
218     }
219 
220     const char* fVersionDeclString = "";
versionDeclString()221     const char* versionDeclString() const {
222         return fVersionDeclString;
223     }
224 
225     bool fGSInvocationsSupport = true;
gsInvocationsSupport()226     bool gsInvocationsSupport() const {
227         return fGSInvocationsSupport;
228     }
229 
230     bool fCanUseFractForNegativeValues = true;
canUseFractForNegativeValues()231     bool canUseFractForNegativeValues() const {
232         return fCanUseFractForNegativeValues;
233     }
234 
235     bool fCanUseFragCoord = true;
canUseFragCoord()236     bool canUseFragCoord() const {
237         return fCanUseFragCoord;
238     }
239 
240     bool fIncompleteShortIntPrecision = false;
incompleteShortIntPrecision()241     bool incompleteShortIntPrecision() const {
242         return fIncompleteShortIntPrecision;
243     }
244 
245     bool fAddAndTrueToLoopCondition = false;
addAndTrueToLoopCondition()246     bool addAndTrueToLoopCondition() const {
247         return fAddAndTrueToLoopCondition;
248     }
249 
250     bool fUnfoldShortCircuitAsTernary = false;
unfoldShortCircuitAsTernary()251     bool unfoldShortCircuitAsTernary() const {
252         return fUnfoldShortCircuitAsTernary;
253     }
254 
255     bool fEmulateAbsIntFunction = false;
emulateAbsIntFunction()256     bool emulateAbsIntFunction() const {
257         return fEmulateAbsIntFunction;
258     }
259 
260     bool fRewriteDoWhileLoops = false;
rewriteDoWhileLoops()261     bool rewriteDoWhileLoops() const {
262         return fRewriteDoWhileLoops;
263     }
264 
265     bool fRemovePowWithConstantExponent = false;
removePowWithConstantExponent()266     bool removePowWithConstantExponent() const {
267         return fRemovePowWithConstantExponent;
268     }
269 
270     const char* fFBFetchColorName = nullptr;
fbFetchColorName()271     const char* fbFetchColorName() const {
272         return fFBFetchColorName;
273     }
274 };
275 
276 using ShaderCapsClass = StandaloneShaderCaps;
277 using ShaderCapsPointer = std::shared_ptr<StandaloneShaderCaps>;
278 extern StandaloneShaderCaps standaloneCaps;
279 
280 #else
281 
282 using ShaderCapsClass = GrShaderCaps;
283 using ShaderCapsPointer = sk_sp<GrShaderCaps>;
284 
285 #endif  // defined(SKSL_STANDALONE) || !SK_SUPPORT_GPU
286 
287 // Various sets of caps for use in tests
288 class ShaderCapsFactory {
289 public:
Default()290     static ShaderCapsPointer Default() {
291         ShaderCapsPointer result = MakeShaderCaps();
292         result->fVersionDeclString = "#version 400";
293         result->fShaderDerivativeSupport = true;
294         result->fBuiltinDeterminantSupport = true;
295         result->fCanUseDoLoops = true;
296         return result;
297     }
298 
Standalone()299     static ShaderCapsPointer Standalone() {
300         return MakeShaderCaps();
301     }
302 
AddAndTrueToLoopCondition()303     static ShaderCapsPointer AddAndTrueToLoopCondition() {
304         ShaderCapsPointer result = MakeShaderCaps();
305         result->fVersionDeclString = "#version 400";
306         result->fAddAndTrueToLoopCondition = true;
307         return result;
308     }
309 
BlendModesFailRandomlyForAllZeroVec()310     static ShaderCapsPointer BlendModesFailRandomlyForAllZeroVec() {
311         ShaderCapsPointer result = MakeShaderCaps();
312         result->fInBlendModesFailRandomlyForAllZeroVec = true;
313         return result;
314     }
315 
CannotUseFractForNegativeValues()316     static ShaderCapsPointer CannotUseFractForNegativeValues() {
317         ShaderCapsPointer result = MakeShaderCaps();
318         result->fVersionDeclString = "#version 400";
319         result->fCanUseFractForNegativeValues = false;
320         return result;
321     }
322 
CannotUseFragCoord()323     static ShaderCapsPointer CannotUseFragCoord() {
324         ShaderCapsPointer result = MakeShaderCaps();
325         result->fVersionDeclString = "#version 400";
326         result->fCanUseFragCoord = false;
327         return result;
328     }
329 
CannotUseMinAndAbsTogether()330     static ShaderCapsPointer CannotUseMinAndAbsTogether() {
331         ShaderCapsPointer result = MakeShaderCaps();
332         result->fVersionDeclString = "#version 400";
333         result->fCanUseMinAndAbsTogether = false;
334         return result;
335     }
336 
EmulateAbsIntFunction()337     static ShaderCapsPointer EmulateAbsIntFunction() {
338         ShaderCapsPointer result = MakeShaderCaps();
339         result->fVersionDeclString = "#version 400";
340         result->fEmulateAbsIntFunction = true;
341         return result;
342     }
343 
FragCoordsNew()344     static ShaderCapsPointer FragCoordsNew() {
345         ShaderCapsPointer result = MakeShaderCaps();
346         result->fVersionDeclString = "#version 400";
347         result->fFragCoordConventionsExtensionString = "GL_ARB_fragment_coord_conventions";
348         return result;
349     }
FragCoordsOld()350     static ShaderCapsPointer FragCoordsOld() {
351         ShaderCapsPointer result = MakeShaderCaps();
352         result->fVersionDeclString = "#version 110";
353         result->fGLSLGeneration = GrGLSLGeneration::k110_GrGLSLGeneration;
354         result->fFragCoordConventionsExtensionString = "GL_ARB_fragment_coord_conventions";
355         return result;
356     }
357 
GeometryShaderExtensionString()358     static ShaderCapsPointer GeometryShaderExtensionString() {
359         ShaderCapsPointer result = MakeShaderCaps();
360         result->fVersionDeclString = "#version 310es";
361         result->fGeometryShaderSupport = true;
362         result->fGeometryShaderExtensionString = "GL_EXT_geometry_shader";
363         result->fGSInvocationsSupport = true;
364         return result;
365     }
366 
GeometryShaderSupport()367     static ShaderCapsPointer GeometryShaderSupport() {
368         ShaderCapsPointer result = MakeShaderCaps();
369         result->fVersionDeclString = "#version 400";
370         result->fGeometryShaderSupport = true;
371         result->fGSInvocationsSupport = true;
372         return result;
373     }
374 
GSInvocationsExtensionString()375     static ShaderCapsPointer GSInvocationsExtensionString() {
376         ShaderCapsPointer result = MakeShaderCaps();
377         result->fVersionDeclString = "#version 400";
378         result->fGeometryShaderSupport = true;
379         result->fGSInvocationsSupport = true;
380         result->fGSInvocationsExtensionString = "GL_ARB_gpu_shader5";
381         return result;
382     }
383 
IncompleteShortIntPrecision()384     static ShaderCapsPointer IncompleteShortIntPrecision() {
385         ShaderCapsPointer result = MakeShaderCaps();
386         result->fVersionDeclString = "#version 310es";
387         result->fUsesPrecisionModifiers = true;
388         result->fIncompleteShortIntPrecision = true;
389         return result;
390     }
391 
MustForceNegatedAtanParamToFloat()392     static ShaderCapsPointer MustForceNegatedAtanParamToFloat() {
393         ShaderCapsPointer result = MakeShaderCaps();
394         result->fVersionDeclString = "#version 400";
395         result->fMustForceNegatedAtanParamToFloat = true;
396         return result;
397     }
398 
MustGuardDivisionEvenAfterExplicitZeroCheck()399     static ShaderCapsPointer MustGuardDivisionEvenAfterExplicitZeroCheck() {
400         ShaderCapsPointer result = MakeShaderCaps();
401         result->fMustGuardDivisionEvenAfterExplicitZeroCheck = true;
402         return result;
403     }
404 
NoGSInvocationsSupport()405     static ShaderCapsPointer NoGSInvocationsSupport() {
406         ShaderCapsPointer result = MakeShaderCaps();
407         result->fVersionDeclString = "#version 400";
408         result->fGeometryShaderSupport = true;
409         result->fGSInvocationsSupport = false;
410         return result;
411     }
412 
RemovePowWithConstantExponent()413     static ShaderCapsPointer RemovePowWithConstantExponent() {
414         ShaderCapsPointer result = MakeShaderCaps();
415         result->fVersionDeclString = "#version 400";
416         result->fRemovePowWithConstantExponent = true;
417         return result;
418     }
419 
RewriteDoWhileLoops()420     static ShaderCapsPointer RewriteDoWhileLoops() {
421         ShaderCapsPointer result = MakeShaderCaps();
422         result->fVersionDeclString = "#version 400";
423         result->fRewriteDoWhileLoops = true;
424         return result;
425     }
426 
SampleMaskSupport()427     static ShaderCapsPointer SampleMaskSupport() {
428         ShaderCapsPointer result = Default();
429         result->fSampleMaskSupport = true;
430         return result;
431     }
432 
ShaderDerivativeExtensionString()433     static ShaderCapsPointer ShaderDerivativeExtensionString() {
434         ShaderCapsPointer result = MakeShaderCaps();
435         result->fVersionDeclString = "#version 400";
436         result->fShaderDerivativeSupport = true;
437         result->fShaderDerivativeExtensionString = "GL_OES_standard_derivatives";
438         result->fUsesPrecisionModifiers = true;
439         return result;
440     }
441 
UnfoldShortCircuitAsTernary()442     static ShaderCapsPointer UnfoldShortCircuitAsTernary() {
443         ShaderCapsPointer result = MakeShaderCaps();
444         result->fVersionDeclString = "#version 400";
445         result->fUnfoldShortCircuitAsTernary = true;
446         return result;
447     }
448 
UsesPrecisionModifiers()449     static ShaderCapsPointer UsesPrecisionModifiers() {
450         ShaderCapsPointer result = MakeShaderCaps();
451         result->fVersionDeclString = "#version 400";
452         result->fUsesPrecisionModifiers = true;
453         return result;
454     }
455 
Version110()456     static ShaderCapsPointer Version110() {
457         ShaderCapsPointer result = MakeShaderCaps();
458         result->fVersionDeclString = "#version 110";
459         result->fGLSLGeneration = GrGLSLGeneration::k110_GrGLSLGeneration;
460         return result;
461     }
462 
Version450Core()463     static ShaderCapsPointer Version450Core() {
464         ShaderCapsPointer result = MakeShaderCaps();
465         result->fVersionDeclString = "#version 450 core";
466         return result;
467     }
468 
469 private:
470     static ShaderCapsPointer MakeShaderCaps();
471 };
472 
473 #if !defined(SKSL_STANDALONE)
474 bool type_to_grsltype(const Context& context, const Type& type, GrSLType* outType);
475 #endif
476 
477 void write_stringstream(const StringStream& d, OutputStream& out);
478 
479 NORETURN void sksl_abort();
480 
481 }  // namespace SkSL
482 
483 #endif  // SKSL_UTIL
484