blob: 1cbc4410b5db08b53ccfbbafa4962fe058d17b05 [file] [log] [blame]
ethannicholasb3058bd2016-07-01 08:22:01 -07001/*
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 */
Mike Klein6ad99092016-10-26 10:35:22 -04007
ethannicholasb3058bd2016-07-01 08:22:01 -07008#include "SkSLCompiler.h"
9
ethannicholas5961bc92016-10-12 06:39:56 -070010#include "ast/SkSLASTPrecision.h"
ethannicholas22f939e2016-10-13 13:25:34 -070011#include "SkSLCFGGenerator.h"
Ethan Nicholas941e7e22016-12-12 15:33:30 -050012#include "SkSLGLSLCodeGenerator.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070013#include "SkSLIRGenerator.h"
14#include "SkSLParser.h"
15#include "SkSLSPIRVCodeGenerator.h"
16#include "ir/SkSLExpression.h"
17#include "ir/SkSLIntLiteral.h"
ethannicholas5961bc92016-10-12 06:39:56 -070018#include "ir/SkSLModifiersDeclaration.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070019#include "ir/SkSLSymbolTable.h"
ethannicholasddb37d62016-10-20 09:54:00 -070020#include "ir/SkSLUnresolvedFunction.h"
ethannicholas22f939e2016-10-13 13:25:34 -070021#include "ir/SkSLVarDeclarations.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070022#include "SkMutex.h"
23
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -040024#ifdef SK_ENABLE_SPIRV_VALIDATION
25#include "spirv-tools/libspirv.hpp"
26#endif
27
ethannicholasb3058bd2016-07-01 08:22:01 -070028#define STRINGIFY(x) #x
29
30// include the built-in shader symbols as static strings
31
ethannicholas5961bc92016-10-12 06:39:56 -070032static const char* SKSL_INCLUDE =
ethannicholasb3058bd2016-07-01 08:22:01 -070033#include "sksl.include"
34;
35
ethannicholas5961bc92016-10-12 06:39:56 -070036static const char* SKSL_VERT_INCLUDE =
ethannicholasb3058bd2016-07-01 08:22:01 -070037#include "sksl_vert.include"
38;
39
ethannicholas5961bc92016-10-12 06:39:56 -070040static const char* SKSL_FRAG_INCLUDE =
ethannicholasb3058bd2016-07-01 08:22:01 -070041#include "sksl_frag.include"
42;
43
Ethan Nicholas52cad152017-02-16 16:37:32 -050044static const char* SKSL_GEOM_INCLUDE =
45#include "sksl_geom.include"
46;
47
ethannicholasb3058bd2016-07-01 08:22:01 -070048namespace SkSL {
49
Mike Klein6ad99092016-10-26 10:35:22 -040050Compiler::Compiler()
ethannicholasb3058bd2016-07-01 08:22:01 -070051: fErrorCount(0) {
52 auto types = std::shared_ptr<SymbolTable>(new SymbolTable(*this));
53 auto symbols = std::shared_ptr<SymbolTable>(new SymbolTable(types, *this));
ethannicholasd598f792016-07-25 10:08:54 -070054 fIRGenerator = new IRGenerator(&fContext, symbols, *this);
ethannicholasb3058bd2016-07-01 08:22:01 -070055 fTypes = types;
ethannicholasd598f792016-07-25 10:08:54 -070056 #define ADD_TYPE(t) types->addWithoutOwnership(fContext.f ## t ## _Type->fName, \
57 fContext.f ## t ## _Type.get())
ethannicholasb3058bd2016-07-01 08:22:01 -070058 ADD_TYPE(Void);
59 ADD_TYPE(Float);
60 ADD_TYPE(Vec2);
61 ADD_TYPE(Vec3);
62 ADD_TYPE(Vec4);
63 ADD_TYPE(Double);
64 ADD_TYPE(DVec2);
65 ADD_TYPE(DVec3);
66 ADD_TYPE(DVec4);
67 ADD_TYPE(Int);
68 ADD_TYPE(IVec2);
69 ADD_TYPE(IVec3);
70 ADD_TYPE(IVec4);
71 ADD_TYPE(UInt);
72 ADD_TYPE(UVec2);
73 ADD_TYPE(UVec3);
74 ADD_TYPE(UVec4);
75 ADD_TYPE(Bool);
76 ADD_TYPE(BVec2);
77 ADD_TYPE(BVec3);
78 ADD_TYPE(BVec4);
79 ADD_TYPE(Mat2x2);
Ethan Nicholas9e1138d2016-11-21 10:39:35 -050080 types->addWithoutOwnership(SkString("mat2x2"), fContext.fMat2x2_Type.get());
ethannicholasb3058bd2016-07-01 08:22:01 -070081 ADD_TYPE(Mat2x3);
82 ADD_TYPE(Mat2x4);
83 ADD_TYPE(Mat3x2);
84 ADD_TYPE(Mat3x3);
Ethan Nicholas9e1138d2016-11-21 10:39:35 -050085 types->addWithoutOwnership(SkString("mat3x3"), fContext.fMat3x3_Type.get());
ethannicholasb3058bd2016-07-01 08:22:01 -070086 ADD_TYPE(Mat3x4);
87 ADD_TYPE(Mat4x2);
88 ADD_TYPE(Mat4x3);
89 ADD_TYPE(Mat4x4);
Ethan Nicholas9e1138d2016-11-21 10:39:35 -050090 types->addWithoutOwnership(SkString("mat4x4"), fContext.fMat4x4_Type.get());
ethannicholasb3058bd2016-07-01 08:22:01 -070091 ADD_TYPE(GenType);
92 ADD_TYPE(GenDType);
93 ADD_TYPE(GenIType);
94 ADD_TYPE(GenUType);
95 ADD_TYPE(GenBType);
96 ADD_TYPE(Mat);
97 ADD_TYPE(Vec);
98 ADD_TYPE(GVec);
99 ADD_TYPE(GVec2);
100 ADD_TYPE(GVec3);
101 ADD_TYPE(GVec4);
102 ADD_TYPE(DVec);
103 ADD_TYPE(IVec);
104 ADD_TYPE(UVec);
105 ADD_TYPE(BVec);
106
107 ADD_TYPE(Sampler1D);
108 ADD_TYPE(Sampler2D);
109 ADD_TYPE(Sampler3D);
ethannicholas5961bc92016-10-12 06:39:56 -0700110 ADD_TYPE(SamplerExternalOES);
ethannicholasb3058bd2016-07-01 08:22:01 -0700111 ADD_TYPE(SamplerCube);
112 ADD_TYPE(Sampler2DRect);
113 ADD_TYPE(Sampler1DArray);
114 ADD_TYPE(Sampler2DArray);
115 ADD_TYPE(SamplerCubeArray);
116 ADD_TYPE(SamplerBuffer);
117 ADD_TYPE(Sampler2DMS);
118 ADD_TYPE(Sampler2DMSArray);
119
Brian Salomonbf7b6202016-11-11 16:08:03 -0500120 ADD_TYPE(ISampler2D);
121
Brian Salomon2a51de82016-11-16 12:06:01 -0500122 ADD_TYPE(Image2D);
123 ADD_TYPE(IImage2D);
124
Greg Daniel64773e62016-11-22 09:44:03 -0500125 ADD_TYPE(SubpassInput);
126 ADD_TYPE(SubpassInputMS);
127
ethannicholasb3058bd2016-07-01 08:22:01 -0700128 ADD_TYPE(GSampler1D);
129 ADD_TYPE(GSampler2D);
130 ADD_TYPE(GSampler3D);
131 ADD_TYPE(GSamplerCube);
132 ADD_TYPE(GSampler2DRect);
133 ADD_TYPE(GSampler1DArray);
134 ADD_TYPE(GSampler2DArray);
135 ADD_TYPE(GSamplerCubeArray);
136 ADD_TYPE(GSamplerBuffer);
137 ADD_TYPE(GSampler2DMS);
138 ADD_TYPE(GSampler2DMSArray);
139
140 ADD_TYPE(Sampler1DShadow);
141 ADD_TYPE(Sampler2DShadow);
142 ADD_TYPE(SamplerCubeShadow);
143 ADD_TYPE(Sampler2DRectShadow);
144 ADD_TYPE(Sampler1DArrayShadow);
145 ADD_TYPE(Sampler2DArrayShadow);
146 ADD_TYPE(SamplerCubeArrayShadow);
147 ADD_TYPE(GSampler2DArrayShadow);
148 ADD_TYPE(GSamplerCubeArrayShadow);
149
Ethan Nicholas3605ace2016-11-21 15:59:48 -0500150 SkString skCapsName("sk_Caps");
151 Variable* skCaps = new Variable(Position(), Modifiers(), skCapsName,
152 *fContext.fSkCaps_Type, Variable::kGlobal_Storage);
153 fIRGenerator->fSymbolTable->add(skCapsName, std::unique_ptr<Symbol>(skCaps));
154
ethannicholas5961bc92016-10-12 06:39:56 -0700155 Modifiers::Flag ignored1;
156 std::vector<std::unique_ptr<ProgramElement>> ignored2;
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500157 this->internalConvertProgram(SkString(SKSL_INCLUDE), &ignored1, &ignored2);
ethannicholasddb37d62016-10-20 09:54:00 -0700158 fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
ethannicholasb3058bd2016-07-01 08:22:01 -0700159 ASSERT(!fErrorCount);
160}
161
162Compiler::~Compiler() {
163 delete fIRGenerator;
164}
165
ethannicholas22f939e2016-10-13 13:25:34 -0700166// add the definition created by assigning to the lvalue to the definition set
Ethan Nicholas86a43402017-01-19 13:32:00 -0500167void Compiler::addDefinition(const Expression* lvalue, std::unique_ptr<Expression>* expr,
168 DefinitionMap* definitions) {
ethannicholas22f939e2016-10-13 13:25:34 -0700169 switch (lvalue->fKind) {
170 case Expression::kVariableReference_Kind: {
171 const Variable& var = ((VariableReference*) lvalue)->fVariable;
172 if (var.fStorage == Variable::kLocal_Storage) {
173 (*definitions)[&var] = expr;
174 }
175 break;
176 }
177 case Expression::kSwizzle_Kind:
178 // We consider the variable written to as long as at least some of its components have
179 // been written to. This will lead to some false negatives (we won't catch it if you
180 // write to foo.x and then read foo.y), but being stricter could lead to false positives
Mike Klein6ad99092016-10-26 10:35:22 -0400181 // (we write to foo.x, and then pass foo to a function which happens to only read foo.x,
182 // but since we pass foo as a whole it is flagged as an error) unless we perform a much
ethannicholas22f939e2016-10-13 13:25:34 -0700183 // more complicated whole-program analysis. This is probably good enough.
Mike Klein6ad99092016-10-26 10:35:22 -0400184 this->addDefinition(((Swizzle*) lvalue)->fBase.get(),
Ethan Nicholas86a43402017-01-19 13:32:00 -0500185 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
ethannicholas22f939e2016-10-13 13:25:34 -0700186 definitions);
187 break;
188 case Expression::kIndex_Kind:
189 // see comments in Swizzle
Mike Klein6ad99092016-10-26 10:35:22 -0400190 this->addDefinition(((IndexExpression*) lvalue)->fBase.get(),
Ethan Nicholas86a43402017-01-19 13:32:00 -0500191 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
ethannicholas22f939e2016-10-13 13:25:34 -0700192 definitions);
193 break;
194 case Expression::kFieldAccess_Kind:
195 // see comments in Swizzle
Mike Klein6ad99092016-10-26 10:35:22 -0400196 this->addDefinition(((FieldAccess*) lvalue)->fBase.get(),
Ethan Nicholas86a43402017-01-19 13:32:00 -0500197 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
ethannicholas22f939e2016-10-13 13:25:34 -0700198 definitions);
199 break;
200 default:
201 // not an lvalue, can't happen
202 ASSERT(false);
203 }
204}
205
206// add local variables defined by this node to the set
Mike Klein6ad99092016-10-26 10:35:22 -0400207void Compiler::addDefinitions(const BasicBlock::Node& node,
Ethan Nicholas86a43402017-01-19 13:32:00 -0500208 DefinitionMap* definitions) {
ethannicholas22f939e2016-10-13 13:25:34 -0700209 switch (node.fKind) {
210 case BasicBlock::Node::kExpression_Kind: {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500211 ASSERT(node.fExpression);
212 const Expression* expr = (Expression*) node.fExpression->get();
213 switch (expr->fKind) {
214 case Expression::kBinary_Kind: {
215 BinaryExpression* b = (BinaryExpression*) expr;
216 if (b->fOperator == Token::EQ) {
217 this->addDefinition(b->fLeft.get(), &b->fRight, definitions);
218 } else if (Token::IsAssignment(b->fOperator)) {
219 this->addDefinition(
220 b->fLeft.get(),
221 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
222 definitions);
223
224 }
225 break;
ethannicholas22f939e2016-10-13 13:25:34 -0700226 }
Ethan Nicholas86a43402017-01-19 13:32:00 -0500227 case Expression::kPrefix_Kind: {
228 const PrefixExpression* p = (PrefixExpression*) expr;
229 if (p->fOperator == Token::MINUSMINUS || p->fOperator == Token::PLUSPLUS) {
230 this->addDefinition(
231 p->fOperand.get(),
232 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
233 definitions);
234 }
235 break;
236 }
237 case Expression::kPostfix_Kind: {
238 const PostfixExpression* p = (PostfixExpression*) expr;
239 if (p->fOperator == Token::MINUSMINUS || p->fOperator == Token::PLUSPLUS) {
240 this->addDefinition(
241 p->fOperand.get(),
242 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
243 definitions);
Ethan Nicholase1d9cb82017-02-06 18:53:07 +0000244
Ethan Nicholas86a43402017-01-19 13:32:00 -0500245 }
246 break;
247 }
248 default:
249 break;
ethannicholas22f939e2016-10-13 13:25:34 -0700250 }
251 break;
252 }
253 case BasicBlock::Node::kStatement_Kind: {
Ethan Nicholase1d9cb82017-02-06 18:53:07 +0000254 const Statement* stmt = (Statement*) node.fStatement;
ethannicholas22f939e2016-10-13 13:25:34 -0700255 if (stmt->fKind == Statement::kVarDeclarations_Kind) {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500256 VarDeclarationsStatement* vd = (VarDeclarationsStatement*) stmt;
Ethan Nicholase1d9cb82017-02-06 18:53:07 +0000257 for (VarDeclaration& decl : vd->fDeclaration->fVars) {
258 if (decl.fValue) {
259 (*definitions)[decl.fVar] = &decl.fValue;
ethannicholas22f939e2016-10-13 13:25:34 -0700260 }
261 }
262 }
263 break;
264 }
265 }
266}
267
268void Compiler::scanCFG(CFG* cfg, BlockId blockId, std::set<BlockId>* workList) {
269 BasicBlock& block = cfg->fBlocks[blockId];
270
271 // compute definitions after this block
Ethan Nicholas86a43402017-01-19 13:32:00 -0500272 DefinitionMap after = block.fBefore;
ethannicholas22f939e2016-10-13 13:25:34 -0700273 for (const BasicBlock::Node& n : block.fNodes) {
274 this->addDefinitions(n, &after);
275 }
276
277 // propagate definitions to exits
278 for (BlockId exitId : block.fExits) {
279 BasicBlock& exit = cfg->fBlocks[exitId];
280 for (const auto& pair : after) {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500281 std::unique_ptr<Expression>* e1 = pair.second;
282 auto found = exit.fBefore.find(pair.first);
283 if (found == exit.fBefore.end()) {
284 // exit has no definition for it, just copy it
285 workList->insert(exitId);
ethannicholas22f939e2016-10-13 13:25:34 -0700286 exit.fBefore[pair.first] = e1;
287 } else {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500288 // exit has a (possibly different) value already defined
289 std::unique_ptr<Expression>* e2 = exit.fBefore[pair.first];
ethannicholas22f939e2016-10-13 13:25:34 -0700290 if (e1 != e2) {
291 // definition has changed, merge and add exit block to worklist
292 workList->insert(exitId);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500293 if (e1 && e2) {
294 exit.fBefore[pair.first] =
Ethan Nicholas86a43402017-01-19 13:32:00 -0500295 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression;
Ethan Nicholasaf197692017-02-27 13:26:45 -0500296 } else {
297 exit.fBefore[pair.first] = nullptr;
298 }
ethannicholas22f939e2016-10-13 13:25:34 -0700299 }
300 }
301 }
302 }
303}
304
305// returns a map which maps all local variables in the function to null, indicating that their value
306// is initially unknown
Ethan Nicholas86a43402017-01-19 13:32:00 -0500307static DefinitionMap compute_start_state(const CFG& cfg) {
308 DefinitionMap result;
Mike Klein6ad99092016-10-26 10:35:22 -0400309 for (const auto& block : cfg.fBlocks) {
310 for (const auto& node : block.fNodes) {
ethannicholas22f939e2016-10-13 13:25:34 -0700311 if (node.fKind == BasicBlock::Node::kStatement_Kind) {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500312 ASSERT(node.fStatement);
Ethan Nicholase1d9cb82017-02-06 18:53:07 +0000313 const Statement* s = node.fStatement;
ethannicholas22f939e2016-10-13 13:25:34 -0700314 if (s->fKind == Statement::kVarDeclarations_Kind) {
315 const VarDeclarationsStatement* vd = (const VarDeclarationsStatement*) s;
Ethan Nicholase1d9cb82017-02-06 18:53:07 +0000316 for (const VarDeclaration& decl : vd->fDeclaration->fVars) {
317 result[decl.fVar] = nullptr;
Mike Klein6ad99092016-10-26 10:35:22 -0400318 }
ethannicholas22f939e2016-10-13 13:25:34 -0700319 }
320 }
321 }
322 }
323 return result;
324}
325
Ethan Nicholase1d9cb82017-02-06 18:53:07 +0000326void Compiler::scanCFG(const FunctionDefinition& f) {
327 CFG cfg = CFGGenerator().getCFG(f);
ethannicholas22f939e2016-10-13 13:25:34 -0700328
Ethan Nicholase1d9cb82017-02-06 18:53:07 +0000329 // compute the data flow
330 cfg.fBlocks[cfg.fStart].fBefore = compute_start_state(cfg);
ethannicholas22f939e2016-10-13 13:25:34 -0700331 std::set<BlockId> workList;
Ethan Nicholase1d9cb82017-02-06 18:53:07 +0000332 for (BlockId i = 0; i < cfg.fBlocks.size(); i++) {
ethannicholas22f939e2016-10-13 13:25:34 -0700333 workList.insert(i);
334 }
335 while (workList.size()) {
336 BlockId next = *workList.begin();
337 workList.erase(workList.begin());
Ethan Nicholase1d9cb82017-02-06 18:53:07 +0000338 this->scanCFG(&cfg, next, &workList);
ethannicholas22f939e2016-10-13 13:25:34 -0700339 }
340
341 // check for unreachable code
342 for (size_t i = 0; i < cfg.fBlocks.size(); i++) {
Mike Klein6ad99092016-10-26 10:35:22 -0400343 if (i != cfg.fStart && !cfg.fBlocks[i].fEntrances.size() &&
ethannicholas22f939e2016-10-13 13:25:34 -0700344 cfg.fBlocks[i].fNodes.size()) {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500345 Position p;
346 switch (cfg.fBlocks[i].fNodes[0].fKind) {
347 case BasicBlock::Node::kStatement_Kind:
Ethan Nicholase1d9cb82017-02-06 18:53:07 +0000348 p = cfg.fBlocks[i].fNodes[0].fStatement->fPosition;
Ethan Nicholas86a43402017-01-19 13:32:00 -0500349 break;
350 case BasicBlock::Node::kExpression_Kind:
351 p = (*cfg.fBlocks[i].fNodes[0].fExpression)->fPosition;
352 break;
353 }
354 this->error(p, SkString("unreachable"));
ethannicholas22f939e2016-10-13 13:25:34 -0700355 }
356 }
357 if (fErrorCount) {
358 return;
359 }
360
Ethan Nicholase1d9cb82017-02-06 18:53:07 +0000361 // check for undefined variables, perform constant propagation
362 for (BasicBlock& b : cfg.fBlocks) {
363 DefinitionMap definitions = b.fBefore;
364 for (BasicBlock::Node& n : b.fNodes) {
365 if (n.fKind == BasicBlock::Node::kExpression_Kind) {
366 ASSERT(n.fExpression);
367 Expression* expr = n.fExpression->get();
368 if (n.fConstantPropagation) {
369 std::unique_ptr<Expression> optimized = expr->constantPropagate(*fIRGenerator,
370 definitions);
371 if (optimized) {
372 n.fExpression->reset(optimized.release());
373 expr = n.fExpression->get();
Ethan Nicholas113628d2017-02-02 16:11:39 -0500374 }
375 }
Ethan Nicholase1d9cb82017-02-06 18:53:07 +0000376 if (expr->fKind == Expression::kVariableReference_Kind) {
377 const Variable& var = ((VariableReference*) expr)->fVariable;
378 if (var.fStorage == Variable::kLocal_Storage &&
379 !definitions[&var]) {
380 this->error(expr->fPosition,
381 "'" + var.fName + "' has not been assigned");
382 }
383 }
Ethan Nicholas113628d2017-02-02 16:11:39 -0500384 }
Ethan Nicholase1d9cb82017-02-06 18:53:07 +0000385 this->addDefinitions(n, &definitions);
Ethan Nicholas113628d2017-02-02 16:11:39 -0500386 }
Ethan Nicholase1d9cb82017-02-06 18:53:07 +0000387 }
ethannicholas22f939e2016-10-13 13:25:34 -0700388
389 // check for missing return
390 if (f.fDeclaration.fReturnType != *fContext.fVoid_Type) {
391 if (cfg.fBlocks[cfg.fExit].fEntrances.size()) {
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500392 this->error(f.fPosition, SkString("function can exit without returning a value"));
ethannicholas22f939e2016-10-13 13:25:34 -0700393 }
394 }
395}
396
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500397void Compiler::internalConvertProgram(SkString text,
ethannicholas5961bc92016-10-12 06:39:56 -0700398 Modifiers::Flag* defaultPrecision,
ethannicholasb3058bd2016-07-01 08:22:01 -0700399 std::vector<std::unique_ptr<ProgramElement>>* result) {
400 Parser parser(text, *fTypes, *this);
401 std::vector<std::unique_ptr<ASTDeclaration>> parsed = parser.file();
402 if (fErrorCount) {
403 return;
404 }
ethannicholas5961bc92016-10-12 06:39:56 -0700405 *defaultPrecision = Modifiers::kHighp_Flag;
ethannicholasb3058bd2016-07-01 08:22:01 -0700406 for (size_t i = 0; i < parsed.size(); i++) {
407 ASTDeclaration& decl = *parsed[i];
408 switch (decl.fKind) {
409 case ASTDeclaration::kVar_Kind: {
ethannicholas14fe8cc2016-09-07 13:37:16 -0700410 std::unique_ptr<VarDeclarations> s = fIRGenerator->convertVarDeclarations(
Mike Klein6ad99092016-10-26 10:35:22 -0400411 (ASTVarDeclarations&) decl,
ethannicholasb3058bd2016-07-01 08:22:01 -0700412 Variable::kGlobal_Storage);
413 if (s) {
414 result->push_back(std::move(s));
415 }
416 break;
417 }
418 case ASTDeclaration::kFunction_Kind: {
419 std::unique_ptr<FunctionDefinition> f = fIRGenerator->convertFunction(
420 (ASTFunction&) decl);
ethannicholas22f939e2016-10-13 13:25:34 -0700421 if (!fErrorCount && f) {
422 this->scanCFG(*f);
ethannicholasb3058bd2016-07-01 08:22:01 -0700423 result->push_back(std::move(f));
424 }
425 break;
426 }
ethannicholas5961bc92016-10-12 06:39:56 -0700427 case ASTDeclaration::kModifiers_Kind: {
428 std::unique_ptr<ModifiersDeclaration> f = fIRGenerator->convertModifiersDeclaration(
429 (ASTModifiersDeclaration&) decl);
430 if (f) {
431 result->push_back(std::move(f));
432 }
433 break;
434 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700435 case ASTDeclaration::kInterfaceBlock_Kind: {
436 std::unique_ptr<InterfaceBlock> i = fIRGenerator->convertInterfaceBlock(
437 (ASTInterfaceBlock&) decl);
438 if (i) {
439 result->push_back(std::move(i));
440 }
441 break;
442 }
443 case ASTDeclaration::kExtension_Kind: {
444 std::unique_ptr<Extension> e = fIRGenerator->convertExtension((ASTExtension&) decl);
445 if (e) {
446 result->push_back(std::move(e));
447 }
448 break;
449 }
ethannicholas5961bc92016-10-12 06:39:56 -0700450 case ASTDeclaration::kPrecision_Kind: {
451 *defaultPrecision = ((ASTPrecision&) decl).fPrecision;
452 break;
453 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700454 default:
455 ABORT("unsupported declaration: %s\n", decl.description().c_str());
456 }
457 }
458}
459
Ethan Nicholas3605ace2016-11-21 15:59:48 -0500460std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, SkString text,
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500461 const Program::Settings& settings) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700462 fErrorText = "";
463 fErrorCount = 0;
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500464 fIRGenerator->start(&settings);
ethannicholasd598f792016-07-25 10:08:54 -0700465 std::vector<std::unique_ptr<ProgramElement>> elements;
ethannicholas5961bc92016-10-12 06:39:56 -0700466 Modifiers::Flag ignored;
ethannicholasb3058bd2016-07-01 08:22:01 -0700467 switch (kind) {
468 case Program::kVertex_Kind:
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500469 this->internalConvertProgram(SkString(SKSL_VERT_INCLUDE), &ignored, &elements);
ethannicholasb3058bd2016-07-01 08:22:01 -0700470 break;
471 case Program::kFragment_Kind:
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500472 this->internalConvertProgram(SkString(SKSL_FRAG_INCLUDE), &ignored, &elements);
ethannicholasb3058bd2016-07-01 08:22:01 -0700473 break;
Ethan Nicholas52cad152017-02-16 16:37:32 -0500474 case Program::kGeometry_Kind:
475 this->internalConvertProgram(SkString(SKSL_GEOM_INCLUDE), &ignored, &elements);
476 break;
ethannicholasb3058bd2016-07-01 08:22:01 -0700477 }
ethannicholasddb37d62016-10-20 09:54:00 -0700478 fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
ethannicholas5961bc92016-10-12 06:39:56 -0700479 Modifiers::Flag defaultPrecision;
480 this->internalConvertProgram(text, &defaultPrecision, &elements);
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500481 auto result = std::unique_ptr<Program>(new Program(kind, settings, defaultPrecision, &fContext,
482 std::move(elements),
483 fIRGenerator->fSymbolTable,
484 fIRGenerator->fInputs));
Ethan Nicholas3605ace2016-11-21 15:59:48 -0500485 fIRGenerator->finish();
ethannicholasb3058bd2016-07-01 08:22:01 -0700486 this->writeErrorCount();
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500487 if (fErrorCount) {
488 return nullptr;
489 }
490 return result;
491}
492
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500493bool Compiler::toSPIRV(const Program& program, SkWStream& out) {
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -0400494#ifdef SK_ENABLE_SPIRV_VALIDATION
495 SkDynamicMemoryWStream buffer;
496 SPIRVCodeGenerator cg(&fContext, &program, this, &buffer);
497 bool result = cg.generateCode();
498 if (result) {
499 sk_sp<SkData> data(buffer.detachAsData());
500 spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_0);
501 SkASSERT(0 == data->size() % 4);
502 auto dumpmsg = [](spv_message_level_t, const char*, const spv_position_t&, const char* m) {
503 SkDebugf("SPIR-V validation error: %s\n", m);
504 };
505 tools.SetMessageConsumer(dumpmsg);
506 // Verify that the SPIR-V we produced is valid. If this assert fails, check the logs prior
507 // to the failure to see the validation errors.
508 SkAssertResult(tools.Validate((const uint32_t*) data->data(), data->size() / 4));
509 out.write(data->data(), data->size());
510 }
511#else
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500512 SPIRVCodeGenerator cg(&fContext, &program, this, &out);
513 bool result = cg.generateCode();
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -0400514#endif
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500515 this->writeErrorCount();
Ethan Nicholasce33f102016-12-09 17:22:59 -0500516 return result;
517}
518
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500519bool Compiler::toSPIRV(const Program& program, SkString* out) {
520 SkDynamicMemoryWStream buffer;
521 bool result = this->toSPIRV(program, buffer);
522 if (result) {
523 sk_sp<SkData> data(buffer.detachAsData());
524 *out = SkString((const char*) data->data(), data->size());
525 }
526 return result;
527}
528
529bool Compiler::toGLSL(const Program& program, SkWStream& out) {
530 GLSLCodeGenerator cg(&fContext, &program, this, &out);
531 bool result = cg.generateCode();
532 this->writeErrorCount();
533 return result;
534}
535
536bool Compiler::toGLSL(const Program& program, SkString* out) {
537 SkDynamicMemoryWStream buffer;
538 bool result = this->toGLSL(program, buffer);
539 if (result) {
540 sk_sp<SkData> data(buffer.detachAsData());
541 *out = SkString((const char*) data->data(), data->size());
542 }
543 return result;
544}
545
546
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500547void Compiler::error(Position position, SkString msg) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700548 fErrorCount++;
549 fErrorText += "error: " + position.description() + ": " + msg.c_str() + "\n";
550}
551
Ethan Nicholas9e1138d2016-11-21 10:39:35 -0500552SkString Compiler::errorText() {
553 SkString result = fErrorText;
ethannicholasb3058bd2016-07-01 08:22:01 -0700554 return result;
555}
556
557void Compiler::writeErrorCount() {
558 if (fErrorCount) {
559 fErrorText += to_string(fErrorCount) + " error";
560 if (fErrorCount > 1) {
561 fErrorText += "s";
562 }
563 fErrorText += "\n";
564 }
565}
566
ethannicholasb3058bd2016-07-01 08:22:01 -0700567} // namespace