xref: /aosp_15_r20/external/skia/src/sksl/SkSLProgramSettings.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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/sksl/SkSLVersion.h"
12 #include "src/sksl/SkSLDefines.h"
13 #include "src/sksl/SkSLModule.h"
14 #include "src/sksl/SkSLProgramKind.h"
15 
16 #include <optional>
17 #include <vector>
18 
19 namespace SkSL {
20 
21 enum class ModuleType : int8_t;
22 
23 /**
24  * Holds the compiler settings for a program.
25  */
26 struct ProgramSettings {
27     // If true, the destination fragment color can be read from sk_FragColor. It must be declared
28     // inout. This is only supported in GLSL, when framebuffer-fetch is used.
29     bool fFragColorIsInOut = false;
30     // if true, all halfs are forced to be floats
31     bool fForceHighPrecision = false;
32     // if true, add -0.5 bias to LOD of all texture lookups
33     bool fSharpenTextures = false;
34     // If true, sk_FragCoord, the dFdy gradient, and sk_Clockwise won't be modified by the
35     // rtFlip. Additionally, the program interface's 'fRTFlipUniform' value will be left as None,
36     // so no rtFlip uniform will be emitted.
37     bool fForceNoRTFlip = false;
38     // if the program needs to create an RTFlip uniform, this is its offset in the uniform buffer
39     int fRTFlipOffset = -1;
40     // if the program needs to create an RTFlip uniform and is creating SPIR-V, this is the binding
41     // and set number of the uniform buffer.
42     int fRTFlipBinding = -1;
43     int fRTFlipSet = -1;
44     // If layout(set=S, binding=B) is not specified for a uniform, these values will be used.
45     // At present, zero is always used by our backends.
46     int fDefaultUniformSet = 0;
47     int fDefaultUniformBinding = 0;
48     // Enables the SkSL optimizer. Note that we never disable optimizations which are needed to
49     // fully evaluate constant-expressions, like constant folding or constant-intrinsic evaluation.
50     bool fOptimize = true;
51     // (Requires fOptimize = true) Removes any uncalled functions other than main(). Note that a
52     // function which starts out being used may end up being uncalled after optimization.
53     bool fRemoveDeadFunctions = true;
54     // (Requires fOptimize = true) Removes variables which are never used.
55     bool fRemoveDeadVariables = true;
56     // (Requires fOptimize = true) When greater than zero, enables the inliner. The threshold value
57     // sets an upper limit on the acceptable amount of code growth from inlining.
58     int fInlineThreshold = SkSL::kDefaultInlineThreshold;
59     // If true, every function in the generated program will be given the `noinline` modifier.
60     bool fForceNoInline = false;
61     // If true, implicit conversions to lower precision numeric types are allowed (e.g., float to
62     // half). These are always allowed when compiling Runtime Effects.
63     bool fAllowNarrowingConversions = false;
64     // If true, then Debug code will run SPIR-V output through the validator to ensure its
65     // correctness
66     bool fValidateSPIRV = true;
67     // If true, any synthetic uniforms must use push constant syntax
68     bool fUsePushConstants = false;
69     // TODO(skia:11209) - Replace this with a "promised" capabilities?
70     // Sets a maximum SkSL version. Compilation will fail if the program uses features that aren't
71     // allowed at the requested version. For instance, a valid program must have fully-unrollable
72     // `for` loops at version 100, but any loop structure is allowed at version 300.
73     SkSL::Version fMaxVersionAllowed = SkSL::Version::k100;
74     // If true, SkSL will use a memory pool for all IR nodes when compiling a program. This is
75     // usually a significant speed increase, but uses more memory, so it is a good idea for programs
76     // that will be freed shortly after compilation. It can also be useful to disable this flag when
77     // investigating memory corruption. (This controls behavior of the SkSL compiler, not the code
78     // we generate.)
79     bool fUseMemoryPool = true;
80 };
81 
82 /**
83  * All the configuration data for a given program.
84  */
85 struct ProgramConfig {
86     /**
87      * If we are compiling one of the SkSL built-in modules, this field indicates which one.
88      * Contains `ModuleType::program` when not compiling a module at all.
89      */
90     ModuleType fModuleType;
91     ProgramKind fKind;
92     ProgramSettings fSettings;
93 
isBuiltinCodeProgramConfig94     bool isBuiltinCode() {
95         return fModuleType != ModuleType::program;
96     }
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);
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                kind == ProgramKind::kGraphiteFragmentES2;
128     }
129 
IsVertexProgramConfig130     static bool IsVertex(ProgramKind kind) {
131         return kind == ProgramKind::kVertex ||
132                kind == ProgramKind::kGraphiteVertex ||
133                kind == ProgramKind::kGraphiteVertexES2;
134     }
135 
IsComputeProgramConfig136     static bool IsCompute(ProgramKind kind) {
137         return kind == ProgramKind::kCompute;
138     }
139 
IsRuntimeEffectProgramConfig140     static bool IsRuntimeEffect(ProgramKind kind) {
141         return (kind == ProgramKind::kRuntimeColorFilter ||
142                 kind == ProgramKind::kRuntimeShader ||
143                 kind == ProgramKind::kRuntimeBlender ||
144                 kind == ProgramKind::kPrivateRuntimeColorFilter ||
145                 kind == ProgramKind::kPrivateRuntimeShader ||
146                 kind == ProgramKind::kPrivateRuntimeBlender ||
147                 kind == ProgramKind::kMeshVertex ||
148                 kind == ProgramKind::kMeshFragment);
149     }
150 
IsRuntimeShaderProgramConfig151     static bool IsRuntimeShader(ProgramKind kind) {
152         return (kind == ProgramKind::kRuntimeShader ||
153                 kind == ProgramKind::kPrivateRuntimeShader);
154     }
155 
IsRuntimeColorFilterProgramConfig156     static bool IsRuntimeColorFilter(ProgramKind kind) {
157         return (kind == ProgramKind::kRuntimeColorFilter ||
158                 kind == ProgramKind::kPrivateRuntimeColorFilter);
159     }
160 
IsRuntimeBlenderProgramConfig161     static bool IsRuntimeBlender(ProgramKind kind) {
162         return (kind == ProgramKind::kRuntimeBlender ||
163                 kind == ProgramKind::kPrivateRuntimeBlender);
164     }
165 
IsMeshProgramConfig166     static bool IsMesh(ProgramKind kind) {
167         return (kind == ProgramKind::kMeshVertex ||
168                 kind == ProgramKind::kMeshFragment);
169     }
170 
AllowsPrivateIdentifiersProgramConfig171     static bool AllowsPrivateIdentifiers(ProgramKind kind) {
172         return (kind != ProgramKind::kRuntimeColorFilter &&
173                 kind != ProgramKind::kRuntimeShader &&
174                 kind != ProgramKind::kRuntimeBlender &&
175                 kind != ProgramKind::kMeshVertex &&
176                 kind != ProgramKind::kMeshFragment);
177     }
178 };
179 
180 }  // namespace SkSL
181 
182 #endif
183