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