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