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