• 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_PROGRAMSETTINGS
9 #define SKSL_PROGRAMSETTINGS
10 
11 #include "include/private/SkSLDefines.h"
12 #include "include/private/SkSLProgramKind.h"
13 #include "include/sksl/SkSLVersion.h"
14 
15 #include <vector>
16 
17 namespace SkSL {
18 
19 /**
20  * Holds the compiler settings for a program.
21  */
22 struct ProgramSettings {
23     // If true, the destination fragment color can be read from sk_FragColor. It must be declared
24     // inout. This is only supported in GLSL, when framebuffer-fetch is used.
25     bool fFragColorIsInOut = false;
26     // if true, all halfs are forced to be floats
27     bool fForceHighPrecision = false;
28     // if true, add -0.5 bias to LOD of all texture lookups
29     bool fSharpenTextures = false;
30     // If true, sk_FragCoord, the dFdy gradient, and sk_Clockwise won't be modified by the
31     // rtFlip. Additionally, the 'fUseFlipRTUniform' boolean will be forced to false so no rtFlip
32     // uniform will be emitted.
33     bool fForceNoRTFlip = false;
34     // if the program needs to create an RTFlip uniform, this is its offset in the uniform buffer
35     int fRTFlipOffset = -1;
36     // if the program needs to create an RTFlip uniform and is creating SPIR-V, this is the binding
37     // and set number of the uniform buffer.
38     int fRTFlipBinding = -1;
39     int fRTFlipSet = -1;
40     // If layout(set=S, binding=B) is not specified for a uniform, these values will be used.
41     // At present, zero is always used by our backends.
42     int fDefaultUniformSet = 0;
43     int fDefaultUniformBinding = 0;
44     // Enables the SkSL optimizer. Note that we never disable optimizations which are needed to
45     // fully evaluate constant-expressions, like constant folding or constant-intrinsic evaluation.
46     bool fOptimize = true;
47     // (Requires fOptimize = true) Removes any uncalled functions other than main(). Note that a
48     // function which starts out being used may end up being uncalled after optimization.
49     bool fRemoveDeadFunctions = true;
50     // (Requires fOptimize = true) Removes variables which are never used.
51     bool fRemoveDeadVariables = true;
52     // (Requires fOptimize = true) When greater than zero, enables the inliner. The threshold value
53     // sets an upper limit on the acceptable amount of code growth from inlining.
54     int fInlineThreshold = SkSL::kDefaultInlineThreshold;
55     // If true, every function in the generated program will be given the `noinline` modifier.
56     bool fForceNoInline = false;
57     // If true, implicit conversions to lower precision numeric types are allowed (e.g., float to
58     // half). These are always allowed when compiling Runtime Effects.
59     bool fAllowNarrowingConversions = false;
60     // If true, then Debug code will run SPIR-V output through the validator to ensure its
61     // correctness
62     bool fValidateSPIRV = true;
63     // If true, any synthetic uniforms must use push constant syntax
64     bool fUsePushConstants = false;
65     // TODO(skia:11209) - Replace this with a "promised" capabilities?
66     // Sets a maximum SkSL version. Compilation will fail if the program uses features that aren't
67     // allowed at the requested version. For instance, a valid program must have fully-unrollable
68     // `for` loops at version 100, but any loop structure is allowed at version 300.
69     SkSL::Version fMaxVersionAllowed = SkSL::Version::k100;
70     // If true, SkVM debug traces will contain the `trace_var` opcode. This opcode can cause the
71     // generated code to contain a lot of extra computations, because we need to explicitly compute
72     // every temporary value, even ones that would otherwise be optimized away entirely. The other
73     // debug opcodes are much less invasive on the generated code.
74     bool fAllowTraceVarInSkVMDebugTrace = true;
75     // If true, SkSL will use a memory pool for all IR nodes when compiling a program. This is
76     // usually a significant speed increase, but uses more memory, so it is a good idea for programs
77     // that will be freed shortly after compilation. It can also be useful to disable this flag when
78     // investigating memory corruption. (This controls behavior of the SkSL compiler, not the code
79     // we generate.)
80     bool fUseMemoryPool = true;
81     // If true, VarDeclaration can be cloned for testing purposes. See VarDeclaration::clone for
82     // more information.
83     bool fAllowVarDeclarationCloneForTesting = false;
84     // If true, SPIR-V codegen restricted to a subset supported by Dawn.
85     // TODO(skia:13840, skia:14023): Remove this setting when Skia can use WGSL on Dawn.
86     bool fSPIRVDawnCompatMode = false;
87 };
88 
89 /**
90  * All the configuration data for a given program.
91  */
92 struct ProgramConfig {
93     /** True if we are currently processing one of the built-in SkSL include modules. */
94     bool fIsBuiltinCode;
95     ProgramKind fKind;
96     ProgramSettings fSettings;
97 
98     // When enforcesSkSLVersion() is true, this determines the available feature set that will be
99     // enforced. This is set automatically when the `#version` directive is parsed.
100     SkSL::Version fRequiredSkSLVersion = SkSL::Version::k100;
101 
enforcesSkSLVersionProgramConfig102     bool enforcesSkSLVersion() const {
103         return IsRuntimeEffect(fKind) || fKind == ProgramKind::kGeneric;
104     }
105 
strictES2ModeProgramConfig106     bool strictES2Mode() const {
107         // TODO(skia:11209): Remove the first condition - so this is just based on #version.
108         //                   Make it more generic (eg, isVersionLT) checking.
109         return fSettings.fMaxVersionAllowed == Version::k100 &&
110                fRequiredSkSLVersion == Version::k100 &&
111                this->enforcesSkSLVersion();
112     }
113 
versionDescriptionProgramConfig114     const char* versionDescription() const {
115         if (this->enforcesSkSLVersion()) {
116             switch (fRequiredSkSLVersion) {
117                 case Version::k100: return "#version 100\n";
118                 case Version::k300: return "#version 300\n";
119             }
120         }
121         return "";
122     }
123 
IsFragmentProgramConfig124     static bool IsFragment(ProgramKind kind) {
125         return kind == ProgramKind::kFragment ||
126                kind == ProgramKind::kGraphiteFragment;
127     }
128 
IsVertexProgramConfig129     static bool IsVertex(ProgramKind kind) {
130         return kind == ProgramKind::kVertex ||
131                kind == ProgramKind::kGraphiteVertex;
132     }
133 
IsComputeProgramConfig134     static bool IsCompute(ProgramKind kind) {
135         return kind == ProgramKind::kCompute;
136     }
137 
IsRuntimeEffectProgramConfig138     static bool IsRuntimeEffect(ProgramKind kind) {
139         return (kind == ProgramKind::kRuntimeColorFilter ||
140                 kind == ProgramKind::kRuntimeShader ||
141                 kind == ProgramKind::kRuntimeBlender ||
142                 kind == ProgramKind::kPrivateRuntimeColorFilter ||
143                 kind == ProgramKind::kPrivateRuntimeShader ||
144                 kind == ProgramKind::kPrivateRuntimeBlender ||
145                 kind == ProgramKind::kMeshVertex ||
146                 kind == ProgramKind::kMeshFragment);
147     }
148 
AllowsPrivateIdentifiersProgramConfig149     static bool AllowsPrivateIdentifiers(ProgramKind kind) {
150         return (kind != ProgramKind::kRuntimeColorFilter &&
151                 kind != ProgramKind::kRuntimeShader &&
152                 kind != ProgramKind::kRuntimeBlender &&
153                 kind != ProgramKind::kMeshVertex &&
154                 kind != ProgramKind::kMeshFragment);
155     }
156 };
157 
158 }  // namespace SkSL
159 
160 #endif
161