xref: /aosp_15_r20/external/skia/src/sksl/SkSLCompiler.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_COMPILER
9 #define SKSL_COMPILER
10 
11 #include "include/core/SkSize.h"
12 #include "include/core/SkTypes.h"
13 #include "src/sksl/SkSLContext.h"  // IWYU pragma: keep
14 #include "src/sksl/SkSLErrorReporter.h"
15 #include "src/sksl/SkSLPosition.h"
16 
17 #include <array>
18 #include <cstdint>
19 #include <memory>
20 #include <string>
21 #include <string_view>
22 #include <type_traits>
23 #include <vector>
24 
25 constexpr int SK_FRAGCOLOR_BUILTIN =           10001;
26 constexpr int SK_LASTFRAGCOLOR_BUILTIN =       10008;
27 constexpr int SK_SECONDARYFRAGCOLOR_BUILTIN =  10012;
28 constexpr int SK_FRAGCOORD_BUILTIN =              15;
29 constexpr int SK_CLOCKWISE_BUILTIN =              17;
30 constexpr int SK_SAMPLEMASKIN_BUILTIN =           20;
31 constexpr int SK_SAMPLEMASK_BUILTIN =          10020;
32 
33 constexpr int SK_VERTEXID_BUILTIN =               42;
34 constexpr int SK_INSTANCEID_BUILTIN =             43;
35 constexpr int SK_POSITION_BUILTIN =                0;
36 constexpr int SK_POINTSIZE_BUILTIN =               1;
37 
38 constexpr int SK_NUMWORKGROUPS_BUILTIN =          24;
39 constexpr int SK_WORKGROUPID_BUILTIN =            26;
40 constexpr int SK_LOCALINVOCATIONID_BUILTIN =      27;
41 constexpr int SK_GLOBALINVOCATIONID_BUILTIN =     28;
42 constexpr int SK_LOCALINVOCATIONINDEX_BUILTIN =   29;
43 
44 namespace SkSL {
45 
46 class Inliner;
47 struct Module;
48 enum class ModuleType : int8_t;
49 class Pool;
50 struct ProgramConfig;
51 class ProgramUsage;
52 enum class ProgramKind : int8_t;
53 struct Program;
54 class ProgramElement;
55 struct ProgramSettings;
56 class SymbolTable;
57 
58 /**
59  * Main compiler entry point. The compiler parses the SkSL text directly into a tree of IRNodes,
60  * while performing basic optimizations such as constant-folding and dead-code elimination. Then the
61  * Program is passed into a CodeGenerator to produce compiled output.
62  *
63  * See the README for information about SkSL.
64  */
65 class SK_API Compiler {
66 public:
67     inline static constexpr const char FRAGCOLOR_NAME[] = "sk_FragColor";
68     inline static constexpr const char RTADJUST_NAME[]  = "sk_RTAdjust";
69     inline static constexpr const char POSITION_NAME[]  = "sk_Position";
70     inline static constexpr const char POISON_TAG[]     = "<POISON>";
71 
72     /**
73      * Gets a float4 that adjusts the position from Skia device coords to normalized device coords,
74      * used to populate sk_RTAdjust.  Assuming the transformed position, pos, is a homogeneous
75      * float4, the vec, v, is applied as such:
76      * float4((pos.xy * v.xz) + sk_Position.ww * v.yw, 0, pos.w);
77      */
GetRTAdjustVector(SkISize rtDims,bool flipY)78     static std::array<float, 4> GetRTAdjustVector(SkISize rtDims, bool flipY) {
79         std::array<float, 4> result;
80         result[0] = 2.f/rtDims.width();
81         result[2] = 2.f/rtDims.height();
82         result[1] = -1.f;
83         result[3] = -1.f;
84         if (flipY) {
85             result[2] = -result[2];
86             result[3] = -result[3];
87         }
88         return result;
89     }
90 
91     /**
92      * Uniform values used by the compiler to implement origin-neutral dFdy, sk_Clockwise, and
93      * sk_FragCoord.
94      */
GetRTFlipVector(int rtHeight,bool flipY)95     static std::array<float, 2> GetRTFlipVector(int rtHeight, bool flipY) {
96         std::array<float, 2> result;
97         result[0] = flipY ? rtHeight : 0.f;
98         result[1] = flipY ?     -1.f : 1.f;
99         return result;
100     }
101 
102     Compiler();
103     ~Compiler();
104 
105     Compiler(const Compiler&) = delete;
106     Compiler& operator=(const Compiler&) = delete;
107 
108     /**
109      * Allows optimization settings to be unilaterally overridden. This is meant to allow tools like
110      * Viewer or Nanobench to override the compiler's ProgramSettings and ShaderCaps for debugging.
111      */
112     enum class OverrideFlag {
113         kDefault,
114         kOff,
115         kOn,
116     };
EnableOptimizer(OverrideFlag flag)117     static void EnableOptimizer(OverrideFlag flag) { sOptimizer = flag; }
EnableInliner(OverrideFlag flag)118     static void EnableInliner(OverrideFlag flag) { sInliner = flag; }
119 
120     std::unique_ptr<Program> convertProgram(ProgramKind kind,
121                                             std::string programSource,
122                                             const ProgramSettings& settings);
123 
124     void handleError(std::string_view msg, Position pos);
125 
126     std::string errorText(bool showCount = true);
127 
errorReporter()128     ErrorReporter& errorReporter() { return *fContext->fErrors; }
129 
errorCount()130     int errorCount() const { return fContext->fErrors->errorCount(); }
131 
132     void writeErrorCount();
133 
resetErrors()134     void resetErrors() {
135         fErrorText.clear();
136         this->errorReporter().resetErrorCount();
137     }
138 
context()139     Context& context() const {
140         return *fContext;
141     }
142 
globalSymbols()143     SymbolTable* globalSymbols() {
144         return fGlobalSymbols.get();
145     }
146 
symbolTable()147     SymbolTable* symbolTable() {
148         return fContext->fSymbolTable;
149     }
150 
151     std::unique_ptr<Module> compileModule(ProgramKind kind,
152                                           ModuleType moduleType,
153                                           std::string moduleSource,
154                                           const Module* parentModule,
155                                           bool shouldInline);
156 
157     /** Optimize a module at minification time, before writing it out. */
158     bool optimizeModuleBeforeMinifying(ProgramKind kind, Module& module, bool shrinkSymbols);
159 
160     const Module* moduleForProgramKind(ProgramKind kind);
161 
162     /** Run the inliner on a program which was compiled earlier (with inlining turned off). */
163     void runInliner(Program& program);
164 
165 private:
166     class CompilerErrorReporter : public ErrorReporter {
167     public:
CompilerErrorReporter(Compiler * compiler)168         CompilerErrorReporter(Compiler* compiler)
169             : fCompiler(*compiler) {}
170 
handleError(std::string_view msg,Position pos)171         void handleError(std::string_view msg, Position pos) override {
172             fCompiler.handleError(msg, pos);
173         }
174 
175     private:
176         Compiler& fCompiler;
177     };
178 
179     /** Updates ProgramSettings to eliminate contradictions and to honor the ProgramKind. */
180     static void FinalizeSettings(ProgramSettings* settings, ProgramKind kind);
181 
182     /** Prepares the Context for compilation of a program or module. */
183     void initializeContext(const SkSL::Module* module,
184                            ProgramKind kind,
185                            ProgramSettings settings,
186                            std::string_view source,
187                            ModuleType moduleType);
188 
189     /** Cleans up the Context post-compilation. */
190     void cleanupContext();
191 
192     /**
193      * Returns all global elements (functions and global variables) as a self-contained Program.
194      * The optional source string is retained as the program's source.
195      */
196     std::unique_ptr<SkSL::Program> releaseProgram(
197             std::unique_ptr<std::string> source,
198             std::vector<std::unique_ptr<SkSL::ProgramElement>> programElements);
199 
200     /** Optimize every function in the program. */
201     bool optimize(Program& program);
202 
203     /** Performs final checks to confirm that a fully-assembled/optimized is valid. */
204     bool finalize(Program& program);
205 
206     /** Optimize a module at Skia runtime, after loading it. */
207     bool optimizeModuleAfterLoading(ProgramKind kind, Module& module);
208 
209     /** Flattens out function calls when it is safe to do so. */
210     bool runInliner(Inliner* inliner,
211                     const std::vector<std::unique_ptr<ProgramElement>>& elements,
212                     SymbolTable* symbols,
213                     ProgramUsage* usage);
214 
215     CompilerErrorReporter fErrorReporter;
216     std::shared_ptr<Context> fContext;
217     std::unique_ptr<SymbolTable> fGlobalSymbols;
218     std::unique_ptr<ProgramConfig> fConfig;
219     std::unique_ptr<Pool> fPool;
220 
221     std::string fErrorText;
222 
223     static OverrideFlag sOptimizer;
224     static OverrideFlag sInliner;
225 
226     friend class Parser;
227     friend class ThreadContext;
228 };
229 
230 }  // namespace SkSL
231 
232 #endif
233