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