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