SkSLCompiler.cpp revision 19671772c1a03bd973fae54dead4defc9ee1d4c3
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#include "SkSLCompiler.h"
9
10#include "ast/SkSLASTPrecision.h"
11#include "SkSLCFGGenerator.h"
12#include "SkSLIRGenerator.h"
13#include "SkSLParser.h"
14#include "SkSLSPIRVCodeGenerator.h"
15#include "ir/SkSLExpression.h"
16#include "ir/SkSLIntLiteral.h"
17#include "ir/SkSLModifiersDeclaration.h"
18#include "ir/SkSLSymbolTable.h"
19#include "ir/SkSLUnresolvedFunction.h"
20#include "ir/SkSLVarDeclarations.h"
21#include "SkMutex.h"
22
23#define STRINGIFY(x) #x
24
25// include the built-in shader symbols as static strings
26
27static const char* SKSL_INCLUDE =
28#include "sksl.include"
29;
30
31static const char* SKSL_VERT_INCLUDE =
32#include "sksl_vert.include"
33;
34
35static const char* SKSL_FRAG_INCLUDE =
36#include "sksl_frag.include"
37;
38
39namespace SkSL {
40
41Compiler::Compiler()
42: fErrorCount(0) {
43    auto types = std::shared_ptr<SymbolTable>(new SymbolTable(*this));
44    auto symbols = std::shared_ptr<SymbolTable>(new SymbolTable(types, *this));
45    fIRGenerator = new IRGenerator(&fContext, symbols, *this);
46    fTypes = types;
47    #define ADD_TYPE(t) types->addWithoutOwnership(fContext.f ## t ## _Type->fName, \
48                                                   fContext.f ## t ## _Type.get())
49    ADD_TYPE(Void);
50    ADD_TYPE(Float);
51    ADD_TYPE(Vec2);
52    ADD_TYPE(Vec3);
53    ADD_TYPE(Vec4);
54    ADD_TYPE(Double);
55    ADD_TYPE(DVec2);
56    ADD_TYPE(DVec3);
57    ADD_TYPE(DVec4);
58    ADD_TYPE(Int);
59    ADD_TYPE(IVec2);
60    ADD_TYPE(IVec3);
61    ADD_TYPE(IVec4);
62    ADD_TYPE(UInt);
63    ADD_TYPE(UVec2);
64    ADD_TYPE(UVec3);
65    ADD_TYPE(UVec4);
66    ADD_TYPE(Bool);
67    ADD_TYPE(BVec2);
68    ADD_TYPE(BVec3);
69    ADD_TYPE(BVec4);
70    ADD_TYPE(Mat2x2);
71    types->addWithoutOwnership(SkString("mat2x2"), fContext.fMat2x2_Type.get());
72    ADD_TYPE(Mat2x3);
73    ADD_TYPE(Mat2x4);
74    ADD_TYPE(Mat3x2);
75    ADD_TYPE(Mat3x3);
76    types->addWithoutOwnership(SkString("mat3x3"), fContext.fMat3x3_Type.get());
77    ADD_TYPE(Mat3x4);
78    ADD_TYPE(Mat4x2);
79    ADD_TYPE(Mat4x3);
80    ADD_TYPE(Mat4x4);
81    types->addWithoutOwnership(SkString("mat4x4"), fContext.fMat4x4_Type.get());
82    ADD_TYPE(GenType);
83    ADD_TYPE(GenDType);
84    ADD_TYPE(GenIType);
85    ADD_TYPE(GenUType);
86    ADD_TYPE(GenBType);
87    ADD_TYPE(Mat);
88    ADD_TYPE(Vec);
89    ADD_TYPE(GVec);
90    ADD_TYPE(GVec2);
91    ADD_TYPE(GVec3);
92    ADD_TYPE(GVec4);
93    ADD_TYPE(DVec);
94    ADD_TYPE(IVec);
95    ADD_TYPE(UVec);
96    ADD_TYPE(BVec);
97
98    ADD_TYPE(Sampler1D);
99    ADD_TYPE(Sampler2D);
100    ADD_TYPE(Sampler3D);
101    ADD_TYPE(SamplerExternalOES);
102    ADD_TYPE(SamplerCube);
103    ADD_TYPE(Sampler2DRect);
104    ADD_TYPE(Sampler1DArray);
105    ADD_TYPE(Sampler2DArray);
106    ADD_TYPE(SamplerCubeArray);
107    ADD_TYPE(SamplerBuffer);
108    ADD_TYPE(Sampler2DMS);
109    ADD_TYPE(Sampler2DMSArray);
110
111    ADD_TYPE(ISampler2D);
112
113    ADD_TYPE(Image2D);
114    ADD_TYPE(IImage2D);
115
116    ADD_TYPE(SubpassInput);
117    ADD_TYPE(SubpassInputMS);
118
119    ADD_TYPE(GSampler1D);
120    ADD_TYPE(GSampler2D);
121    ADD_TYPE(GSampler3D);
122    ADD_TYPE(GSamplerCube);
123    ADD_TYPE(GSampler2DRect);
124    ADD_TYPE(GSampler1DArray);
125    ADD_TYPE(GSampler2DArray);
126    ADD_TYPE(GSamplerCubeArray);
127    ADD_TYPE(GSamplerBuffer);
128    ADD_TYPE(GSampler2DMS);
129    ADD_TYPE(GSampler2DMSArray);
130
131    ADD_TYPE(Sampler1DShadow);
132    ADD_TYPE(Sampler2DShadow);
133    ADD_TYPE(SamplerCubeShadow);
134    ADD_TYPE(Sampler2DRectShadow);
135    ADD_TYPE(Sampler1DArrayShadow);
136    ADD_TYPE(Sampler2DArrayShadow);
137    ADD_TYPE(SamplerCubeArrayShadow);
138    ADD_TYPE(GSampler2DArrayShadow);
139    ADD_TYPE(GSamplerCubeArrayShadow);
140
141    SkString skCapsName("sk_Caps");
142    Variable* skCaps = new Variable(Position(), Modifiers(), skCapsName,
143                                    *fContext.fSkCaps_Type, Variable::kGlobal_Storage);
144    fIRGenerator->fSymbolTable->add(skCapsName, std::unique_ptr<Symbol>(skCaps));
145
146    Modifiers::Flag ignored1;
147    std::vector<std::unique_ptr<ProgramElement>> ignored2;
148    this->internalConvertProgram(SkString(SKSL_INCLUDE), &ignored1, &ignored2);
149    fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
150    ASSERT(!fErrorCount);
151}
152
153Compiler::~Compiler() {
154    delete fIRGenerator;
155}
156
157// add the definition created by assigning to the lvalue to the definition set
158void Compiler::addDefinition(const Expression* lvalue, const Expression* expr,
159                           std::unordered_map<const Variable*, const Expression*>* definitions) {
160    switch (lvalue->fKind) {
161        case Expression::kVariableReference_Kind: {
162            const Variable& var = ((VariableReference*) lvalue)->fVariable;
163            if (var.fStorage == Variable::kLocal_Storage) {
164                (*definitions)[&var] = expr;
165            }
166            break;
167        }
168        case Expression::kSwizzle_Kind:
169            // We consider the variable written to as long as at least some of its components have
170            // been written to. This will lead to some false negatives (we won't catch it if you
171            // write to foo.x and then read foo.y), but being stricter could lead to false positives
172            // (we write to foo.x, and then pass foo to a function which happens to only read foo.x,
173            // but since we pass foo as a whole it is flagged as an error) unless we perform a much
174            // more complicated whole-program analysis. This is probably good enough.
175            this->addDefinition(((Swizzle*) lvalue)->fBase.get(),
176                                fContext.fDefined_Expression.get(),
177                                definitions);
178            break;
179        case Expression::kIndex_Kind:
180            // see comments in Swizzle
181            this->addDefinition(((IndexExpression*) lvalue)->fBase.get(),
182                                fContext.fDefined_Expression.get(),
183                                definitions);
184            break;
185        case Expression::kFieldAccess_Kind:
186            // see comments in Swizzle
187            this->addDefinition(((FieldAccess*) lvalue)->fBase.get(),
188                                fContext.fDefined_Expression.get(),
189                                definitions);
190            break;
191        default:
192            // not an lvalue, can't happen
193            ASSERT(false);
194    }
195}
196
197// add local variables defined by this node to the set
198void Compiler::addDefinitions(const BasicBlock::Node& node,
199                              std::unordered_map<const Variable*, const Expression*>* definitions) {
200    switch (node.fKind) {
201        case BasicBlock::Node::kExpression_Kind: {
202            const Expression* expr = (Expression*) node.fNode;
203            if (expr->fKind == Expression::kBinary_Kind) {
204                const BinaryExpression* b = (BinaryExpression*) expr;
205                if (b->fOperator == Token::EQ) {
206                    this->addDefinition(b->fLeft.get(), b->fRight.get(), definitions);
207                }
208            }
209            break;
210        }
211        case BasicBlock::Node::kStatement_Kind: {
212            const Statement* stmt = (Statement*) node.fNode;
213            if (stmt->fKind == Statement::kVarDeclarations_Kind) {
214                const VarDeclarationsStatement* vd = (VarDeclarationsStatement*) stmt;
215                for (const VarDeclaration& decl : vd->fDeclaration->fVars) {
216                    if (decl.fValue) {
217                        (*definitions)[decl.fVar] = decl.fValue.get();
218                    }
219                }
220            }
221            break;
222        }
223    }
224}
225
226void Compiler::scanCFG(CFG* cfg, BlockId blockId, std::set<BlockId>* workList) {
227    BasicBlock& block = cfg->fBlocks[blockId];
228
229    // compute definitions after this block
230    std::unordered_map<const Variable*, const Expression*> after = block.fBefore;
231    for (const BasicBlock::Node& n : block.fNodes) {
232        this->addDefinitions(n, &after);
233    }
234
235    // propagate definitions to exits
236    for (BlockId exitId : block.fExits) {
237        BasicBlock& exit = cfg->fBlocks[exitId];
238        for (const auto& pair : after) {
239            const Expression* e1 = pair.second;
240            if (exit.fBefore.find(pair.first) == exit.fBefore.end()) {
241                exit.fBefore[pair.first] = e1;
242            } else {
243                const Expression* e2 = exit.fBefore[pair.first];
244                if (e1 != e2) {
245                    // definition has changed, merge and add exit block to worklist
246                    workList->insert(exitId);
247                    if (!e1 || !e2) {
248                        exit.fBefore[pair.first] = nullptr;
249                    } else {
250                        exit.fBefore[pair.first] = fContext.fDefined_Expression.get();
251                    }
252                }
253            }
254        }
255    }
256}
257
258// returns a map which maps all local variables in the function to null, indicating that their value
259// is initially unknown
260static std::unordered_map<const Variable*, const Expression*> compute_start_state(const CFG& cfg) {
261    std::unordered_map<const Variable*, const Expression*> result;
262    for (const auto& block : cfg.fBlocks) {
263        for (const auto& node : block.fNodes) {
264            if (node.fKind == BasicBlock::Node::kStatement_Kind) {
265                const Statement* s = (Statement*) node.fNode;
266                if (s->fKind == Statement::kVarDeclarations_Kind) {
267                    const VarDeclarationsStatement* vd = (const VarDeclarationsStatement*) s;
268                    for (const VarDeclaration& decl : vd->fDeclaration->fVars) {
269                        result[decl.fVar] = nullptr;
270                    }
271                }
272            }
273        }
274    }
275    return result;
276}
277
278void Compiler::scanCFG(const FunctionDefinition& f) {
279    CFG cfg = CFGGenerator().getCFG(f);
280
281    // compute the data flow
282    cfg.fBlocks[cfg.fStart].fBefore = compute_start_state(cfg);
283    std::set<BlockId> workList;
284    for (BlockId i = 0; i < cfg.fBlocks.size(); i++) {
285        workList.insert(i);
286    }
287    while (workList.size()) {
288        BlockId next = *workList.begin();
289        workList.erase(workList.begin());
290        this->scanCFG(&cfg, next, &workList);
291    }
292
293    // check for unreachable code
294    for (size_t i = 0; i < cfg.fBlocks.size(); i++) {
295        if (i != cfg.fStart && !cfg.fBlocks[i].fEntrances.size() &&
296            cfg.fBlocks[i].fNodes.size()) {
297            this->error(cfg.fBlocks[i].fNodes[0].fNode->fPosition, SkString("unreachable"));
298        }
299    }
300    if (fErrorCount) {
301        return;
302    }
303
304    // check for undefined variables
305    for (const BasicBlock& b : cfg.fBlocks) {
306        std::unordered_map<const Variable*, const Expression*> definitions = b.fBefore;
307        for (const BasicBlock::Node& n : b.fNodes) {
308            if (n.fKind == BasicBlock::Node::kExpression_Kind) {
309                const Expression* expr = (const Expression*) n.fNode;
310                if (expr->fKind == Expression::kVariableReference_Kind) {
311                    const Variable& var = ((VariableReference*) expr)->fVariable;
312                    if (var.fStorage == Variable::kLocal_Storage &&
313                        !definitions[&var]) {
314                        this->error(expr->fPosition,
315                                    "'" + var.fName + "' has not been assigned");
316                    }
317                }
318            }
319            this->addDefinitions(n, &definitions);
320        }
321    }
322
323    // check for missing return
324    if (f.fDeclaration.fReturnType != *fContext.fVoid_Type) {
325        if (cfg.fBlocks[cfg.fExit].fEntrances.size()) {
326            this->error(f.fPosition, SkString("function can exit without returning a value"));
327        }
328    }
329}
330
331void Compiler::internalConvertProgram(SkString text,
332                                      Modifiers::Flag* defaultPrecision,
333                                      std::vector<std::unique_ptr<ProgramElement>>* result) {
334    Parser parser(text, *fTypes, *this);
335    std::vector<std::unique_ptr<ASTDeclaration>> parsed = parser.file();
336    if (fErrorCount) {
337        return;
338    }
339    *defaultPrecision = Modifiers::kHighp_Flag;
340    for (size_t i = 0; i < parsed.size(); i++) {
341        ASTDeclaration& decl = *parsed[i];
342        switch (decl.fKind) {
343            case ASTDeclaration::kVar_Kind: {
344                std::unique_ptr<VarDeclarations> s = fIRGenerator->convertVarDeclarations(
345                                                                         (ASTVarDeclarations&) decl,
346                                                                         Variable::kGlobal_Storage);
347                if (s) {
348                    result->push_back(std::move(s));
349                }
350                break;
351            }
352            case ASTDeclaration::kFunction_Kind: {
353                std::unique_ptr<FunctionDefinition> f = fIRGenerator->convertFunction(
354                                                                               (ASTFunction&) decl);
355                if (!fErrorCount && f) {
356                    this->scanCFG(*f);
357                    result->push_back(std::move(f));
358                }
359                break;
360            }
361            case ASTDeclaration::kModifiers_Kind: {
362                std::unique_ptr<ModifiersDeclaration> f = fIRGenerator->convertModifiersDeclaration(
363                                                                   (ASTModifiersDeclaration&) decl);
364                if (f) {
365                    result->push_back(std::move(f));
366                }
367                break;
368            }
369            case ASTDeclaration::kInterfaceBlock_Kind: {
370                std::unique_ptr<InterfaceBlock> i = fIRGenerator->convertInterfaceBlock(
371                                                                         (ASTInterfaceBlock&) decl);
372                if (i) {
373                    result->push_back(std::move(i));
374                }
375                break;
376            }
377            case ASTDeclaration::kExtension_Kind: {
378                std::unique_ptr<Extension> e = fIRGenerator->convertExtension((ASTExtension&) decl);
379                if (e) {
380                    result->push_back(std::move(e));
381                }
382                break;
383            }
384            case ASTDeclaration::kPrecision_Kind: {
385                *defaultPrecision = ((ASTPrecision&) decl).fPrecision;
386                break;
387            }
388            default:
389                ABORT("unsupported declaration: %s\n", decl.description().c_str());
390        }
391    }
392}
393
394std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, SkString text,
395                                                  std::unordered_map<SkString, CapValue> caps) {
396    fErrorText = "";
397    fErrorCount = 0;
398    fIRGenerator->start(&caps);
399    std::vector<std::unique_ptr<ProgramElement>> elements;
400    Modifiers::Flag ignored;
401    switch (kind) {
402        case Program::kVertex_Kind:
403            this->internalConvertProgram(SkString(SKSL_VERT_INCLUDE), &ignored, &elements);
404            break;
405        case Program::kFragment_Kind:
406            this->internalConvertProgram(SkString(SKSL_FRAG_INCLUDE), &ignored, &elements);
407            break;
408    }
409    fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
410    Modifiers::Flag defaultPrecision;
411    this->internalConvertProgram(text, &defaultPrecision, &elements);
412    auto result = std::unique_ptr<Program>(new Program(kind, defaultPrecision, std::move(elements),
413                                                       fIRGenerator->fSymbolTable));
414    fIRGenerator->finish();
415    this->writeErrorCount();
416    return result;
417}
418
419void Compiler::error(Position position, SkString msg) {
420    fErrorCount++;
421    fErrorText += "error: " + position.description() + ": " + msg.c_str() + "\n";
422}
423
424SkString Compiler::errorText() {
425    SkString result = fErrorText;
426    return result;
427}
428
429void Compiler::writeErrorCount() {
430    if (fErrorCount) {
431        fErrorText += to_string(fErrorCount) + " error";
432        if (fErrorCount > 1) {
433            fErrorText += "s";
434        }
435        fErrorText += "\n";
436    }
437}
438
439bool Compiler::toSPIRV(Program::Kind kind, const SkString& text, SkWStream& out) {
440    std::unordered_map<SkString, CapValue> capsMap;
441    auto program = this->convertProgram(kind, text, capsMap);
442    if (fErrorCount == 0) {
443        SkSL::SPIRVCodeGenerator cg(&fContext);
444        cg.generateCode(*program.get(), *this, out);
445        this->writeErrorCount();
446    }
447    return fErrorCount == 0;
448}
449
450bool Compiler::toSPIRV(Program::Kind kind, const SkString& text, SkString* out) {
451    SkDynamicMemoryWStream buffer;
452    bool result = this->toSPIRV(kind, text, buffer);
453    if (result) {
454        sk_sp<SkData> data(buffer.detachAsData());
455        *out = SkString((const char*) data->data(), data->size());
456    }
457    return result;
458}
459
460static void fill_caps(const GrGLSLCaps& caps, std::unordered_map<SkString, CapValue>* capsMap) {
461#define CAP(name) capsMap->insert(std::make_pair(SkString(#name), CapValue(caps.name())));
462    CAP(fbFetchSupport);
463    CAP(fbFetchNeedsCustomOutput);
464    CAP(bindlessTextureSupport);
465    CAP(dropsTileOnZeroDivide);
466    CAP(flatInterpolationSupport);
467    CAP(noperspectiveInterpolationSupport);
468    CAP(multisampleInterpolationSupport);
469    CAP(sampleVariablesSupport);
470    CAP(sampleMaskOverrideCoverageSupport);
471    CAP(externalTextureSupport);
472    CAP(texelFetchSupport);
473    CAP(imageLoadStoreSupport);
474    CAP(mustEnableAdvBlendEqs);
475    CAP(mustEnableSpecificAdvBlendEqs);
476    CAP(mustDeclareFragmentShaderOutput);
477    CAP(canUseAnyFunctionInShader);
478#undef CAP
479}
480
481bool Compiler::toGLSL(Program::Kind kind, const SkString& text, const GrGLSLCaps& caps,
482                      SkWStream& out) {
483    std::unordered_map<SkString, CapValue> capsMap;
484    fill_caps(caps, &capsMap);
485    auto program = this->convertProgram(kind, text, capsMap);
486    if (fErrorCount == 0) {
487        SkSL::GLSLCodeGenerator cg(&fContext, &caps);
488        cg.generateCode(*program.get(), *this, out);
489        this->writeErrorCount();
490    }
491    return fErrorCount == 0;
492}
493
494bool Compiler::toGLSL(Program::Kind kind, const SkString& text, const GrGLSLCaps& caps,
495                      SkString* out) {
496    SkDynamicMemoryWStream buffer;
497    bool result = this->toGLSL(kind, text, caps, buffer);
498    if (result) {
499        sk_sp<SkData> data(buffer.detachAsData());
500        *out = SkString((const char*) data->data(), data->size());
501    }
502    return result;
503}
504
505} // namespace
506