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 <map> |
12 | #include <set> |
13 | #include <unordered_set> |
14 | #include <vector> |
15 | #include "src/sksl/SkSLASTFile.h" |
16 | #include "src/sksl/SkSLCFGGenerator.h" |
17 | #include "src/sksl/SkSLContext.h" |
18 | #include "src/sksl/SkSLErrorReporter.h" |
19 | #include "src/sksl/SkSLLexer.h" |
20 | #include "src/sksl/ir/SkSLProgram.h" |
21 | #include "src/sksl/ir/SkSLSymbolTable.h" |
22 | |
23 | #if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU |
24 | #include "src/gpu/GrShaderVar.h" |
25 | #endif |
26 | |
27 | #define SK_FRAGCOLOR_BUILTIN 10001 |
28 | #define SK_IN_BUILTIN 10002 |
29 | #define SK_INCOLOR_BUILTIN 10003 |
30 | #define SK_OUTCOLOR_BUILTIN 10004 |
31 | #define SK_TRANSFORMEDCOORDS2D_BUILTIN 10005 |
32 | #define SK_TEXTURESAMPLERS_BUILTIN 10006 |
33 | #define SK_OUT_BUILTIN 10007 |
34 | #define SK_LASTFRAGCOLOR_BUILTIN 10008 |
35 | #define SK_MAIN_COORDS_BUILTIN 10009 |
36 | #define SK_WIDTH_BUILTIN 10011 |
37 | #define SK_HEIGHT_BUILTIN 10012 |
38 | #define SK_FRAGCOORD_BUILTIN 15 |
39 | #define SK_CLOCKWISE_BUILTIN 17 |
40 | #define SK_SAMPLEMASK_BUILTIN 20 |
41 | #define SK_VERTEXID_BUILTIN 42 |
42 | #define SK_INSTANCEID_BUILTIN 43 |
43 | #define SK_CLIPDISTANCE_BUILTIN 3 |
44 | #define SK_INVOCATIONID_BUILTIN 8 |
45 | #define SK_POSITION_BUILTIN 0 |
46 | |
47 | namespace SkSL { |
48 | |
49 | class ByteCode; |
50 | class ExternalValue; |
51 | class IRGenerator; |
52 | struct PipelineStageArgs; |
53 | |
54 | /** |
55 | * Main compiler entry point. This is a traditional compiler design which first parses the .sksl |
56 | * file into an abstract syntax tree (a tree of ASTNodes), then performs semantic analysis to |
57 | * produce a Program (a tree of IRNodes), then feeds the Program into a CodeGenerator to produce |
58 | * compiled output. |
59 | * |
60 | * See the README for information about SkSL. |
61 | */ |
62 | class SK_API Compiler : public ErrorReporter { |
63 | public: |
64 | static constexpr const char* RTADJUST_NAME = "sk_RTAdjust" ; |
65 | static constexpr const char* PERVERTEX_NAME = "sk_PerVertex" ; |
66 | |
67 | enum Flags { |
68 | kNone_Flags = 0, |
69 | // permits static if/switch statements to be used with non-constant tests. This is used when |
70 | // producing H and CPP code; the static tests don't have to have constant values *yet*, but |
71 | // the generated code will contain a static test which then does have to be a constant. |
72 | kPermitInvalidStaticTests_Flag = 1, |
73 | }; |
74 | |
75 | struct FormatArg { |
76 | enum class Kind { |
77 | kInput, |
78 | kOutput, |
79 | kCoords, |
80 | kUniform, |
81 | kChildProcessor, |
82 | kFunctionName |
83 | }; |
84 | |
85 | FormatArg(Kind kind) |
86 | : fKind(kind) {} |
87 | |
88 | FormatArg(Kind kind, int index) |
89 | : fKind(kind) |
90 | , fIndex(index) {} |
91 | |
92 | Kind fKind; |
93 | int fIndex; |
94 | String fCoords; |
95 | }; |
96 | |
97 | #if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU |
98 | /** |
99 | * Represents the arguments to GrGLSLShaderBuilder::emitFunction. |
100 | */ |
101 | struct GLSLFunction { |
102 | GrSLType fReturnType; |
103 | SkString fName; |
104 | std::vector<GrShaderVar> fParameters; |
105 | SkString fBody; |
106 | std::vector<Compiler::FormatArg> fFormatArgs; |
107 | }; |
108 | #endif |
109 | |
110 | Compiler(Flags flags = kNone_Flags); |
111 | |
112 | ~Compiler() override; |
113 | |
114 | Compiler(const Compiler&) = delete; |
115 | Compiler& operator=(const Compiler&) = delete; |
116 | |
117 | /** |
118 | * Registers an ExternalValue as a top-level symbol which is visible in the global namespace. |
119 | */ |
120 | void registerExternalValue(ExternalValue* value); |
121 | |
122 | std::unique_ptr<Program> convertProgram(Program::Kind kind, String text, |
123 | const Program::Settings& settings); |
124 | |
125 | bool optimize(Program& program); |
126 | |
127 | std::unique_ptr<Program> specialize(Program& program, |
128 | const std::unordered_map<SkSL::String, SkSL::Program::Settings::Value>& inputs); |
129 | |
130 | bool toSPIRV(Program& program, OutputStream& out); |
131 | |
132 | bool toSPIRV(Program& program, String* out); |
133 | |
134 | bool toGLSL(Program& program, OutputStream& out); |
135 | |
136 | bool toGLSL(Program& program, String* out); |
137 | |
138 | bool toHLSL(Program& program, String* out); |
139 | |
140 | bool toMetal(Program& program, OutputStream& out); |
141 | |
142 | bool toMetal(Program& program, String* out); |
143 | |
144 | bool toCPP(Program& program, String name, OutputStream& out); |
145 | |
146 | bool toH(Program& program, String name, OutputStream& out); |
147 | |
148 | std::unique_ptr<ByteCode> toByteCode(Program& program); |
149 | |
150 | #if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU |
151 | bool toPipelineStage(const Program& program, PipelineStageArgs* outArgs); |
152 | #endif |
153 | |
154 | /** |
155 | * Takes ownership of the given symbol. It will be destroyed when the compiler is destroyed. |
156 | */ |
157 | Symbol* takeOwnership(std::unique_ptr<Symbol> symbol); |
158 | |
159 | void error(int offset, String msg) override; |
160 | |
161 | String errorText(); |
162 | |
163 | void writeErrorCount(); |
164 | |
165 | int errorCount() override { |
166 | return fErrorCount; |
167 | } |
168 | |
169 | Context& context() { |
170 | return *fContext; |
171 | } |
172 | |
173 | static const char* OperatorName(Token::Kind token); |
174 | |
175 | static bool IsAssignment(Token::Kind token); |
176 | |
177 | private: |
178 | void processIncludeFile(Program::Kind kind, const char* src, size_t length, |
179 | std::shared_ptr<SymbolTable> base, |
180 | std::vector<std::unique_ptr<ProgramElement>>* outElements, |
181 | std::shared_ptr<SymbolTable>* outSymbolTable); |
182 | |
183 | void addDefinition(const Expression* lvalue, std::unique_ptr<Expression>* expr, |
184 | DefinitionMap* definitions); |
185 | |
186 | void addDefinitions(const BasicBlock::Node& node, DefinitionMap* definitions); |
187 | |
188 | void scanCFG(CFG* cfg, BlockId block, std::set<BlockId>* workList); |
189 | |
190 | void computeDataFlow(CFG* cfg); |
191 | |
192 | /** |
193 | * Simplifies the expression pointed to by iter (in both the IR and CFG structures), if |
194 | * possible. |
195 | */ |
196 | void simplifyExpression(DefinitionMap& definitions, |
197 | BasicBlock& b, |
198 | std::vector<BasicBlock::Node>::iterator* iter, |
199 | std::unordered_set<const Variable*>* undefinedVariables, |
200 | bool* outUpdated, |
201 | bool* outNeedsRescan); |
202 | |
203 | /** |
204 | * Simplifies the statement pointed to by iter (in both the IR and CFG structures), if |
205 | * possible. |
206 | */ |
207 | void simplifyStatement(DefinitionMap& definitions, |
208 | BasicBlock& b, |
209 | std::vector<BasicBlock::Node>::iterator* iter, |
210 | std::unordered_set<const Variable*>* undefinedVariables, |
211 | bool* outUpdated, |
212 | bool* outNeedsRescan); |
213 | |
214 | void scanCFG(FunctionDefinition& f); |
215 | |
216 | Position position(int offset); |
217 | |
218 | std::map<StringFragment, std::pair<std::unique_ptr<ProgramElement>, bool>> fGPUIntrinsics; |
219 | std::map<StringFragment, std::pair<std::unique_ptr<ProgramElement>, bool>> fInterpreterIntrinsics; |
220 | std::unique_ptr<ASTFile> fGpuIncludeSource; |
221 | std::shared_ptr<SymbolTable> fGpuSymbolTable; |
222 | std::vector<std::unique_ptr<ProgramElement>> fVertexInclude; |
223 | std::shared_ptr<SymbolTable> fVertexSymbolTable; |
224 | std::vector<std::unique_ptr<ProgramElement>> fFragmentInclude; |
225 | std::shared_ptr<SymbolTable> fFragmentSymbolTable; |
226 | std::vector<std::unique_ptr<ProgramElement>> fGeometryInclude; |
227 | std::shared_ptr<SymbolTable> fGeometrySymbolTable; |
228 | std::vector<std::unique_ptr<ProgramElement>> fPipelineInclude; |
229 | std::shared_ptr<SymbolTable> fPipelineSymbolTable; |
230 | std::vector<std::unique_ptr<ProgramElement>> fInterpreterInclude; |
231 | std::shared_ptr<SymbolTable> fInterpreterSymbolTable; |
232 | |
233 | std::shared_ptr<SymbolTable> fTypes; |
234 | IRGenerator* fIRGenerator; |
235 | int fFlags; |
236 | |
237 | const String* fSource; |
238 | std::shared_ptr<Context> fContext; |
239 | int fErrorCount; |
240 | String fErrorText; |
241 | }; |
242 | |
243 | #if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU |
244 | struct PipelineStageArgs { |
245 | String fCode; |
246 | std::vector<Compiler::FormatArg> fFormatArgs; |
247 | std::vector<Compiler::GLSLFunction> fFunctions; |
248 | }; |
249 | #endif |
250 | |
251 | } // namespace |
252 | |
253 | #endif |
254 | |