Home | History | Annotate | Download | only in sksl
      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 "SkSLGLSLCodeGenerator.h"
     13 #include "SkSLIRGenerator.h"
     14 #include "SkSLParser.h"
     15 #include "SkSLSPIRVCodeGenerator.h"
     16 #include "ir/SkSLExpression.h"
     17 #include "ir/SkSLIntLiteral.h"
     18 #include "ir/SkSLModifiersDeclaration.h"
     19 #include "ir/SkSLSymbolTable.h"
     20 #include "ir/SkSLUnresolvedFunction.h"
     21 #include "ir/SkSLVarDeclarations.h"
     22 #include "SkMutex.h"
     23 
     24 #ifdef SK_ENABLE_SPIRV_VALIDATION
     25 #include "spirv-tools/libspirv.hpp"
     26 #endif
     27 
     28 #define STRINGIFY(x) #x
     29 
     30 // include the built-in shader symbols as static strings
     31 
     32 static const char* SKSL_INCLUDE =
     33 #include "sksl.include"
     34 ;
     35 
     36 static const char* SKSL_VERT_INCLUDE =
     37 #include "sksl_vert.include"
     38 ;
     39 
     40 static const char* SKSL_FRAG_INCLUDE =
     41 #include "sksl_frag.include"
     42 ;
     43 
     44 static const char* SKSL_GEOM_INCLUDE =
     45 #include "sksl_geom.include"
     46 ;
     47 
     48 namespace SkSL {
     49 
     50 Compiler::Compiler()
     51 : fErrorCount(0) {
     52     auto types = std::shared_ptr<SymbolTable>(new SymbolTable(*this));
     53     auto symbols = std::shared_ptr<SymbolTable>(new SymbolTable(types, *this));
     54     fIRGenerator = new IRGenerator(&fContext, symbols, *this);
     55     fTypes = types;
     56     #define ADD_TYPE(t) types->addWithoutOwnership(fContext.f ## t ## _Type->fName, \
     57                                                    fContext.f ## t ## _Type.get())
     58     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);
     80     types->addWithoutOwnership(SkString("mat2x2"), fContext.fMat2x2_Type.get());
     81     ADD_TYPE(Mat2x3);
     82     ADD_TYPE(Mat2x4);
     83     ADD_TYPE(Mat3x2);
     84     ADD_TYPE(Mat3x3);
     85     types->addWithoutOwnership(SkString("mat3x3"), fContext.fMat3x3_Type.get());
     86     ADD_TYPE(Mat3x4);
     87     ADD_TYPE(Mat4x2);
     88     ADD_TYPE(Mat4x3);
     89     ADD_TYPE(Mat4x4);
     90     types->addWithoutOwnership(SkString("mat4x4"), fContext.fMat4x4_Type.get());
     91     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);
    110     ADD_TYPE(SamplerExternalOES);
    111     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 
    120     ADD_TYPE(ISampler2D);
    121 
    122     ADD_TYPE(Image2D);
    123     ADD_TYPE(IImage2D);
    124 
    125     ADD_TYPE(SubpassInput);
    126     ADD_TYPE(SubpassInputMS);
    127 
    128     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 
    150     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 
    155     Modifiers::Flag ignored1;
    156     std::vector<std::unique_ptr<ProgramElement>> ignored2;
    157     this->internalConvertProgram(SkString(SKSL_INCLUDE), &ignored1, &ignored2);
    158     fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
    159     ASSERT(!fErrorCount);
    160 }
    161 
    162 Compiler::~Compiler() {
    163     delete fIRGenerator;
    164 }
    165 
    166 // add the definition created by assigning to the lvalue to the definition set
    167 void Compiler::addDefinition(const Expression* lvalue, std::unique_ptr<Expression>* expr,
    168                              DefinitionMap* definitions) {
    169     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
    181             // (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
    183             // more complicated whole-program analysis. This is probably good enough.
    184             this->addDefinition(((Swizzle*) lvalue)->fBase.get(),
    185                                 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
    186                                 definitions);
    187             break;
    188         case Expression::kIndex_Kind:
    189             // see comments in Swizzle
    190             this->addDefinition(((IndexExpression*) lvalue)->fBase.get(),
    191                                 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
    192                                 definitions);
    193             break;
    194         case Expression::kFieldAccess_Kind:
    195             // see comments in Swizzle
    196             this->addDefinition(((FieldAccess*) lvalue)->fBase.get(),
    197                                 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
    198                                 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
    207 void Compiler::addDefinitions(const BasicBlock::Node& node,
    208                               DefinitionMap* definitions) {
    209     switch (node.fKind) {
    210         case BasicBlock::Node::kExpression_Kind: {
    211             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;
    226                 }
    227                 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);
    244 
    245                     }
    246                     break;
    247                 }
    248                 default:
    249                     break;
    250             }
    251             break;
    252         }
    253         case BasicBlock::Node::kStatement_Kind: {
    254             const Statement* stmt = (Statement*) node.fStatement;
    255             if (stmt->fKind == Statement::kVarDeclarations_Kind) {
    256                 VarDeclarationsStatement* vd = (VarDeclarationsStatement*) stmt;
    257                 for (VarDeclaration& decl : vd->fDeclaration->fVars) {
    258                     if (decl.fValue) {
    259                         (*definitions)[decl.fVar] = &decl.fValue;
    260                     }
    261                 }
    262             }
    263             break;
    264         }
    265     }
    266 }
    267 
    268 void Compiler::scanCFG(CFG* cfg, BlockId blockId, std::set<BlockId>* workList) {
    269     BasicBlock& block = cfg->fBlocks[blockId];
    270 
    271     // compute definitions after this block
    272     DefinitionMap after = block.fBefore;
    273     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) {
    281             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);
    286                 exit.fBefore[pair.first] = e1;
    287             } else {
    288                 // exit has a (possibly different) value already defined
    289                 std::unique_ptr<Expression>* e2 = exit.fBefore[pair.first];
    290                 if (e1 != e2) {
    291                     // definition has changed, merge and add exit block to worklist
    292                     workList->insert(exitId);
    293                     if (e1 && e2) {
    294                         exit.fBefore[pair.first] =
    295                                        (std::unique_ptr<Expression>*) &fContext.fDefined_Expression;
    296                     } else {
    297                         exit.fBefore[pair.first] = nullptr;
    298                     }
    299                 }
    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
    307 static DefinitionMap compute_start_state(const CFG& cfg) {
    308     DefinitionMap result;
    309     for (const auto& block : cfg.fBlocks) {
    310         for (const auto& node : block.fNodes) {
    311             if (node.fKind == BasicBlock::Node::kStatement_Kind) {
    312                 ASSERT(node.fStatement);
    313                 const Statement* s = node.fStatement;
    314                 if (s->fKind == Statement::kVarDeclarations_Kind) {
    315                     const VarDeclarationsStatement* vd = (const VarDeclarationsStatement*) s;
    316                     for (const VarDeclaration& decl : vd->fDeclaration->fVars) {
    317                         result[decl.fVar] = nullptr;
    318                     }
    319                 }
    320             }
    321         }
    322     }
    323     return result;
    324 }
    325 
    326 void Compiler::scanCFG(const FunctionDefinition& f) {
    327     CFG cfg = CFGGenerator().getCFG(f);
    328 
    329     // compute the data flow
    330     cfg.fBlocks[cfg.fStart].fBefore = compute_start_state(cfg);
    331     std::set<BlockId> workList;
    332     for (BlockId i = 0; i < cfg.fBlocks.size(); i++) {
    333         workList.insert(i);
    334     }
    335     while (workList.size()) {
    336         BlockId next = *workList.begin();
    337         workList.erase(workList.begin());
    338         this->scanCFG(&cfg, next, &workList);
    339     }
    340 
    341     // check for unreachable code
    342     for (size_t i = 0; i < cfg.fBlocks.size(); i++) {
    343         if (i != cfg.fStart && !cfg.fBlocks[i].fEntrances.size() &&
    344             cfg.fBlocks[i].fNodes.size()) {
    345             Position p;
    346             switch (cfg.fBlocks[i].fNodes[0].fKind) {
    347                 case BasicBlock::Node::kStatement_Kind:
    348                     p = cfg.fBlocks[i].fNodes[0].fStatement->fPosition;
    349                     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"));
    355         }
    356     }
    357     if (fErrorCount) {
    358         return;
    359     }
    360 
    361     // 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();
    374                     }
    375                 }
    376                 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                 }
    384             }
    385             this->addDefinitions(n, &definitions);
    386         }
    387     }
    388 
    389     // check for missing return
    390     if (f.fDeclaration.fReturnType != *fContext.fVoid_Type) {
    391         if (cfg.fBlocks[cfg.fExit].fEntrances.size()) {
    392             this->error(f.fPosition, SkString("function can exit without returning a value"));
    393         }
    394     }
    395 }
    396 
    397 void Compiler::internalConvertProgram(SkString text,
    398                                       Modifiers::Flag* defaultPrecision,
    399                                       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     }
    405     *defaultPrecision = Modifiers::kHighp_Flag;
    406     for (size_t i = 0; i < parsed.size(); i++) {
    407         ASTDeclaration& decl = *parsed[i];
    408         switch (decl.fKind) {
    409             case ASTDeclaration::kVar_Kind: {
    410                 std::unique_ptr<VarDeclarations> s = fIRGenerator->convertVarDeclarations(
    411                                                                          (ASTVarDeclarations&) decl,
    412                                                                          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);
    421                 if (!fErrorCount && f) {
    422                     this->scanCFG(*f);
    423                     result->push_back(std::move(f));
    424                 }
    425                 break;
    426             }
    427             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             }
    435             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             }
    450             case ASTDeclaration::kPrecision_Kind: {
    451                 *defaultPrecision = ((ASTPrecision&) decl).fPrecision;
    452                 break;
    453             }
    454             default:
    455                 ABORT("unsupported declaration: %s\n", decl.description().c_str());
    456         }
    457     }
    458 }
    459 
    460 std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, SkString text,
    461                                                   const Program::Settings& settings) {
    462     fErrorText = "";
    463     fErrorCount = 0;
    464     fIRGenerator->start(&settings);
    465     std::vector<std::unique_ptr<ProgramElement>> elements;
    466     Modifiers::Flag ignored;
    467     switch (kind) {
    468         case Program::kVertex_Kind:
    469             this->internalConvertProgram(SkString(SKSL_VERT_INCLUDE), &ignored, &elements);
    470             break;
    471         case Program::kFragment_Kind:
    472             this->internalConvertProgram(SkString(SKSL_FRAG_INCLUDE), &ignored, &elements);
    473             break;
    474         case Program::kGeometry_Kind:
    475             this->internalConvertProgram(SkString(SKSL_GEOM_INCLUDE), &ignored, &elements);
    476             break;
    477     }
    478     fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
    479     Modifiers::Flag defaultPrecision;
    480     this->internalConvertProgram(text, &defaultPrecision, &elements);
    481     auto result = std::unique_ptr<Program>(new Program(kind, settings, defaultPrecision, &fContext,
    482                                                        std::move(elements),
    483                                                        fIRGenerator->fSymbolTable,
    484                                                        fIRGenerator->fInputs));
    485     fIRGenerator->finish();
    486     this->writeErrorCount();
    487     if (fErrorCount) {
    488         return nullptr;
    489     }
    490     return result;
    491 }
    492 
    493 bool Compiler::toSPIRV(const Program& program, SkWStream& out) {
    494 #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
    512     SPIRVCodeGenerator cg(&fContext, &program, this, &out);
    513     bool result = cg.generateCode();
    514 #endif
    515     this->writeErrorCount();
    516     return result;
    517 }
    518 
    519 bool 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 
    529 bool 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 
    536 bool 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 
    547 void Compiler::error(Position position, SkString msg) {
    548     fErrorCount++;
    549     fErrorText += "error: " + position.description() + ": " + msg.c_str() + "\n";
    550 }
    551 
    552 SkString Compiler::errorText() {
    553     SkString result = fErrorText;
    554     return result;
    555 }
    556 
    557 void 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 
    567 } // namespace
    568