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 "SkSLGLSLCodeGenerator.h" 9 10#include "string.h" 11 12#include "GLSL.std.450.h" 13 14#include "SkSLCompiler.h" 15#include "ir/SkSLExpressionStatement.h" 16#include "ir/SkSLExtension.h" 17#include "ir/SkSLIndexExpression.h" 18#include "ir/SkSLModifiersDeclaration.h" 19#include "ir/SkSLVariableReference.h" 20 21namespace SkSL { 22 23void GLSLCodeGenerator::write(const char* s) { 24 if (s[0] == 0) { 25 return; 26 } 27 if (fAtLineStart) { 28 for (int i = 0; i < fIndentation; i++) { 29 fOut->writeText(" "); 30 } 31 } 32 fOut->writeText(s); 33 fAtLineStart = false; 34} 35 36void GLSLCodeGenerator::writeLine(const char* s) { 37 this->write(s); 38 fOut->writeText("\n"); 39 fAtLineStart = true; 40} 41 42void GLSLCodeGenerator::write(const SkString& s) { 43 this->write(s.c_str()); 44} 45 46void GLSLCodeGenerator::writeLine(const SkString& s) { 47 this->writeLine(s.c_str()); 48} 49 50void GLSLCodeGenerator::writeLine() { 51 this->writeLine(""); 52} 53 54void GLSLCodeGenerator::writeExtension(const Extension& ext) { 55 this->writeLine("#extension " + ext.fName + " : enable"); 56} 57 58void GLSLCodeGenerator::writeType(const Type& type) { 59 if (type.kind() == Type::kStruct_Kind) { 60 for (const Type* search : fWrittenStructs) { 61 if (*search == type) { 62 // already written 63 this->write(type.name()); 64 return; 65 } 66 } 67 fWrittenStructs.push_back(&type); 68 this->writeLine("struct " + type.name() + " {"); 69 fIndentation++; 70 for (const auto& f : type.fields()) { 71 this->writeModifiers(f.fModifiers, false); 72 // sizes (which must be static in structs) are part of the type name here 73 this->writeType(*f.fType); 74 this->writeLine(" " + f.fName + ";"); 75 } 76 fIndentation--; 77 this->write("}"); 78 } else { 79 this->write(type.name()); 80 } 81} 82 83void GLSLCodeGenerator::writeExpression(const Expression& expr, Precedence parentPrecedence) { 84 switch (expr.fKind) { 85 case Expression::kBinary_Kind: 86 this->writeBinaryExpression((BinaryExpression&) expr, parentPrecedence); 87 break; 88 case Expression::kBoolLiteral_Kind: 89 this->writeBoolLiteral((BoolLiteral&) expr); 90 break; 91 case Expression::kConstructor_Kind: 92 this->writeConstructor((Constructor&) expr); 93 break; 94 case Expression::kIntLiteral_Kind: 95 this->writeIntLiteral((IntLiteral&) expr); 96 break; 97 case Expression::kFieldAccess_Kind: 98 this->writeFieldAccess(((FieldAccess&) expr)); 99 break; 100 case Expression::kFloatLiteral_Kind: 101 this->writeFloatLiteral(((FloatLiteral&) expr)); 102 break; 103 case Expression::kFunctionCall_Kind: 104 this->writeFunctionCall((FunctionCall&) expr); 105 break; 106 case Expression::kPrefix_Kind: 107 this->writePrefixExpression((PrefixExpression&) expr, parentPrecedence); 108 break; 109 case Expression::kPostfix_Kind: 110 this->writePostfixExpression((PostfixExpression&) expr, parentPrecedence); 111 break; 112 case Expression::kSwizzle_Kind: 113 this->writeSwizzle((Swizzle&) expr); 114 break; 115 case Expression::kVariableReference_Kind: 116 this->writeVariableReference((VariableReference&) expr); 117 break; 118 case Expression::kTernary_Kind: 119 this->writeTernaryExpression((TernaryExpression&) expr, parentPrecedence); 120 break; 121 case Expression::kIndex_Kind: 122 this->writeIndexExpression((IndexExpression&) expr); 123 break; 124 default: 125 ABORT("unsupported expression: %s", expr.description().c_str()); 126 } 127} 128 129static bool is_abs(Expression& expr) { 130 if (expr.fKind != Expression::kFunctionCall_Kind) { 131 return false; 132 } 133 return ((FunctionCall&) expr).fFunction.fName == "abs"; 134} 135 136// turns min(abs(x), y) into ((tmpVar1 = abs(x)) < (tmpVar2 = y) ? tmpVar1 : tmpVar2) to avoid a 137// Tegra3 compiler bug. 138void GLSLCodeGenerator::writeMinAbsHack(Expression& absExpr, Expression& otherExpr) { 139 ASSERT(!fProgram.fSettings.fCaps->canUseMinAndAbsTogether()); 140 SkString tmpVar1 = "minAbsHackVar" + to_string(fVarCount++); 141 SkString tmpVar2 = "minAbsHackVar" + to_string(fVarCount++); 142 this->fFunctionHeader += " " + absExpr.fType.name() + " " + tmpVar1 + ";\n"; 143 this->fFunctionHeader += " " + otherExpr.fType.name() + " " + tmpVar2 + ";\n"; 144 this->write("((" + tmpVar1 + " = "); 145 this->writeExpression(absExpr, kTopLevel_Precedence); 146 this->write(") < (" + tmpVar2 + " = "); 147 this->writeExpression(otherExpr, kAssignment_Precedence); 148 this->write(") ? " + tmpVar1 + " : " + tmpVar2 + ")"); 149} 150 151void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) { 152 if (!fProgram.fSettings.fCaps->canUseMinAndAbsTogether() && c.fFunction.fName == "min" && 153 c.fFunction.fBuiltin) { 154 ASSERT(c.fArguments.size() == 2); 155 if (is_abs(*c.fArguments[0])) { 156 this->writeMinAbsHack(*c.fArguments[0], *c.fArguments[1]); 157 return; 158 } 159 if (is_abs(*c.fArguments[1])) { 160 // note that this violates the GLSL left-to-right evaluation semantics. I doubt it will 161 // ever end up mattering, but it's worth calling out. 162 this->writeMinAbsHack(*c.fArguments[1], *c.fArguments[0]); 163 return; 164 } 165 } 166 if (fProgram.fSettings.fCaps->mustForceNegatedAtanParamToFloat() && 167 c.fFunction.fName == "atan" && 168 c.fFunction.fBuiltin && c.fArguments.size() == 2 && 169 c.fArguments[1]->fKind == Expression::kPrefix_Kind) { 170 const PrefixExpression& p = (PrefixExpression&) *c.fArguments[1]; 171 if (p.fOperator == Token::MINUS) { 172 this->write("atan("); 173 this->writeExpression(*c.fArguments[0], kSequence_Precedence); 174 this->write(", -1.0 * "); 175 this->writeExpression(*p.fOperand, kMultiplicative_Precedence); 176 this->write(")"); 177 return; 178 } 179 } 180 if (!fFoundDerivatives && (c.fFunction.fName == "dFdx" || c.fFunction.fName == "dFdy") && 181 c.fFunction.fBuiltin && fProgram.fSettings.fCaps->shaderDerivativeExtensionString()) { 182 ASSERT(fProgram.fSettings.fCaps->shaderDerivativeSupport()); 183 fHeader.writeText("#extension "); 184 fHeader.writeText(fProgram.fSettings.fCaps->shaderDerivativeExtensionString()); 185 fHeader.writeText(" : require\n"); 186 fFoundDerivatives = true; 187 } 188 if (c.fFunction.fName == "texture" && c.fFunction.fBuiltin) { 189 const char* dim = ""; 190 bool proj = false; 191 switch (c.fArguments[0]->fType.dimensions()) { 192 case SpvDim1D: 193 dim = "1D"; 194 if (c.fArguments[1]->fType == *fContext.fFloat_Type) { 195 proj = false; 196 } else { 197 ASSERT(c.fArguments[1]->fType == *fContext.fVec2_Type); 198 proj = true; 199 } 200 break; 201 case SpvDim2D: 202 dim = "2D"; 203 if (c.fArguments[1]->fType == *fContext.fVec2_Type) { 204 proj = false; 205 } else { 206 ASSERT(c.fArguments[1]->fType == *fContext.fVec3_Type); 207 proj = true; 208 } 209 break; 210 case SpvDim3D: 211 dim = "3D"; 212 if (c.fArguments[1]->fType == *fContext.fVec3_Type) { 213 proj = false; 214 } else { 215 ASSERT(c.fArguments[1]->fType == *fContext.fVec4_Type); 216 proj = true; 217 } 218 break; 219 case SpvDimCube: 220 dim = "Cube"; 221 proj = false; 222 break; 223 case SpvDimRect: 224 dim = "Rect"; 225 proj = false; 226 break; 227 case SpvDimBuffer: 228 ASSERT(false); // doesn't exist 229 dim = "Buffer"; 230 proj = false; 231 break; 232 case SpvDimSubpassData: 233 ASSERT(false); // doesn't exist 234 dim = "SubpassData"; 235 proj = false; 236 break; 237 } 238 this->write("texture"); 239 if (fProgram.fSettings.fCaps->generation() < k130_GrGLSLGeneration) { 240 this->write(dim); 241 } 242 if (proj) { 243 this->write("Proj"); 244 } 245 246 } else { 247 this->write(c.fFunction.fName); 248 } 249 this->write("("); 250 const char* separator = ""; 251 for (const auto& arg : c.fArguments) { 252 this->write(separator); 253 separator = ", "; 254 this->writeExpression(*arg, kSequence_Precedence); 255 } 256 this->write(")"); 257} 258 259void GLSLCodeGenerator::writeConstructor(const Constructor& c) { 260 this->write(c.fType.name() + "("); 261 const char* separator = ""; 262 for (const auto& arg : c.fArguments) { 263 this->write(separator); 264 separator = ", "; 265 this->writeExpression(*arg, kSequence_Precedence); 266 } 267 this->write(")"); 268} 269 270void GLSLCodeGenerator::writeFragCoord() { 271 // We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers 272 // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the 273 // declaration varies in earlier GLSL specs. So it is simpler to omit it. 274 if (!fProgram.fSettings.fFlipY) { 275 this->write("gl_FragCoord"); 276 } else if (const char* extension = 277 fProgram.fSettings.fCaps->fragCoordConventionsExtensionString()) { 278 if (!fSetupFragPositionGlobal) { 279 if (fProgram.fSettings.fCaps->generation() < k150_GrGLSLGeneration) { 280 fHeader.writeText("#extension "); 281 fHeader.writeText(extension); 282 fHeader.writeText(" : require\n"); 283 } 284 fHeader.writeText("layout(origin_upper_left) in vec4 gl_FragCoord;\n"); 285 fSetupFragPositionGlobal = true; 286 } 287 this->write("gl_FragCoord"); 288 } else { 289 if (!fSetupFragPositionGlobal) { 290 // The Adreno compiler seems to be very touchy about access to "gl_FragCoord". 291 // Accessing glFragCoord.zw can cause a program to fail to link. Additionally, 292 // depending on the surrounding code, accessing .xy with a uniform involved can 293 // do the same thing. Copying gl_FragCoord.xy into a temp vec2 beforehand 294 // (and only accessing .xy) seems to "fix" things. 295 const char* precision = fProgram.fSettings.fCaps->usesPrecisionModifiers() ? "highp " 296 : ""; 297 fHeader.writeText("uniform "); 298 fHeader.writeText(precision); 299 fHeader.writeText("float " SKSL_RTHEIGHT_NAME ";\n"); 300 fSetupFragPositionGlobal = true; 301 } 302 if (!fSetupFragPositionLocal) { 303 const char* precision = fProgram.fSettings.fCaps->usesPrecisionModifiers() ? "highp " 304 : ""; 305 fFunctionHeader += precision; 306 fFunctionHeader += " vec2 _sktmpCoord = gl_FragCoord.xy;\n"; 307 fFunctionHeader += precision; 308 fFunctionHeader += " vec4 sk_FragCoord = vec4(_sktmpCoord.x, " SKSL_RTHEIGHT_NAME 309 " - _sktmpCoord.y, 1.0, 1.0);\n"; 310 fSetupFragPositionLocal = true; 311 } 312 this->write("sk_FragCoord"); 313 } 314} 315 316 317void GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) { 318 switch (ref.fVariable.fModifiers.fLayout.fBuiltin) { 319 case SK_FRAGCOLOR_BUILTIN: 320 if (fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput()) { 321 this->write("sk_FragColor"); 322 } else { 323 this->write("gl_FragColor"); 324 } 325 break; 326 case SK_FRAGCOORD_BUILTIN: 327 this->writeFragCoord(); 328 break; 329 case SK_VERTEXID_BUILTIN: 330 this->write("gl_VertexID"); 331 break; 332 case SK_CLIPDISTANCE_BUILTIN: 333 this->write("gl_ClipDistance"); 334 break; 335 case SK_IN_BUILTIN: 336 this->write("gl_in"); 337 break; 338 case SK_INVOCATIONID_BUILTIN: 339 this->write("gl_InvocationID"); 340 break; 341 default: 342 this->write(ref.fVariable.fName); 343 } 344} 345 346void GLSLCodeGenerator::writeIndexExpression(const IndexExpression& expr) { 347 this->writeExpression(*expr.fBase, kPostfix_Precedence); 348 this->write("["); 349 this->writeExpression(*expr.fIndex, kTopLevel_Precedence); 350 this->write("]"); 351} 352 353void GLSLCodeGenerator::writeFieldAccess(const FieldAccess& f) { 354 if (f.fOwnerKind == FieldAccess::kDefault_OwnerKind) { 355 this->writeExpression(*f.fBase, kPostfix_Precedence); 356 this->write("."); 357 } 358 switch (f.fBase->fType.fields()[f.fFieldIndex].fModifiers.fLayout.fBuiltin) { 359 case SK_CLIPDISTANCE_BUILTIN: 360 this->write("gl_ClipDistance"); 361 break; 362 default: 363 this->write(f.fBase->fType.fields()[f.fFieldIndex].fName); 364 } 365} 366 367void GLSLCodeGenerator::writeSwizzle(const Swizzle& swizzle) { 368 this->writeExpression(*swizzle.fBase, kPostfix_Precedence); 369 this->write("."); 370 for (int c : swizzle.fComponents) { 371 this->write(&("x\0y\0z\0w\0"[c * 2])); 372 } 373} 374 375static GLSLCodeGenerator::Precedence get_binary_precedence(Token::Kind op) { 376 switch (op) { 377 case Token::STAR: // fall through 378 case Token::SLASH: // fall through 379 case Token::PERCENT: return GLSLCodeGenerator::kMultiplicative_Precedence; 380 case Token::PLUS: // fall through 381 case Token::MINUS: return GLSLCodeGenerator::kAdditive_Precedence; 382 case Token::SHL: // fall through 383 case Token::SHR: return GLSLCodeGenerator::kShift_Precedence; 384 case Token::LT: // fall through 385 case Token::GT: // fall through 386 case Token::LTEQ: // fall through 387 case Token::GTEQ: return GLSLCodeGenerator::kRelational_Precedence; 388 case Token::EQEQ: // fall through 389 case Token::NEQ: return GLSLCodeGenerator::kEquality_Precedence; 390 case Token::BITWISEAND: return GLSLCodeGenerator::kBitwiseAnd_Precedence; 391 case Token::BITWISEXOR: return GLSLCodeGenerator::kBitwiseXor_Precedence; 392 case Token::BITWISEOR: return GLSLCodeGenerator::kBitwiseOr_Precedence; 393 case Token::LOGICALAND: return GLSLCodeGenerator::kLogicalAnd_Precedence; 394 case Token::LOGICALXOR: return GLSLCodeGenerator::kLogicalXor_Precedence; 395 case Token::LOGICALOR: return GLSLCodeGenerator::kLogicalOr_Precedence; 396 case Token::EQ: // fall through 397 case Token::PLUSEQ: // fall through 398 case Token::MINUSEQ: // fall through 399 case Token::STAREQ: // fall through 400 case Token::SLASHEQ: // fall through 401 case Token::PERCENTEQ: // fall through 402 case Token::SHLEQ: // fall through 403 case Token::SHREQ: // fall through 404 case Token::LOGICALANDEQ: // fall through 405 case Token::LOGICALXOREQ: // fall through 406 case Token::LOGICALOREQ: // fall through 407 case Token::BITWISEANDEQ: // fall through 408 case Token::BITWISEXOREQ: // fall through 409 case Token::BITWISEOREQ: return GLSLCodeGenerator::kAssignment_Precedence; 410 default: ABORT("unsupported binary operator"); 411 } 412} 413 414void GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b, 415 Precedence parentPrecedence) { 416 Precedence precedence = get_binary_precedence(b.fOperator); 417 if (precedence >= parentPrecedence) { 418 this->write("("); 419 } 420 this->writeExpression(*b.fLeft, precedence); 421 this->write(" " + Token::OperatorName(b.fOperator) + " "); 422 this->writeExpression(*b.fRight, precedence); 423 if (precedence >= parentPrecedence) { 424 this->write(")"); 425 } 426} 427 428void GLSLCodeGenerator::writeTernaryExpression(const TernaryExpression& t, 429 Precedence parentPrecedence) { 430 if (kTernary_Precedence >= parentPrecedence) { 431 this->write("("); 432 } 433 this->writeExpression(*t.fTest, kTernary_Precedence); 434 this->write(" ? "); 435 this->writeExpression(*t.fIfTrue, kTernary_Precedence); 436 this->write(" : "); 437 this->writeExpression(*t.fIfFalse, kTernary_Precedence); 438 if (kTernary_Precedence >= parentPrecedence) { 439 this->write(")"); 440 } 441} 442 443void GLSLCodeGenerator::writePrefixExpression(const PrefixExpression& p, 444 Precedence parentPrecedence) { 445 if (kPrefix_Precedence >= parentPrecedence) { 446 this->write("("); 447 } 448 this->write(Token::OperatorName(p.fOperator)); 449 this->writeExpression(*p.fOperand, kPrefix_Precedence); 450 if (kPrefix_Precedence >= parentPrecedence) { 451 this->write(")"); 452 } 453} 454 455void GLSLCodeGenerator::writePostfixExpression(const PostfixExpression& p, 456 Precedence parentPrecedence) { 457 if (kPostfix_Precedence >= parentPrecedence) { 458 this->write("("); 459 } 460 this->writeExpression(*p.fOperand, kPostfix_Precedence); 461 this->write(Token::OperatorName(p.fOperator)); 462 if (kPostfix_Precedence >= parentPrecedence) { 463 this->write(")"); 464 } 465} 466 467void GLSLCodeGenerator::writeBoolLiteral(const BoolLiteral& b) { 468 this->write(b.fValue ? "true" : "false"); 469} 470 471void GLSLCodeGenerator::writeIntLiteral(const IntLiteral& i) { 472 if (i.fType == *fContext.fUInt_Type) { 473 this->write(to_string(i.fValue & 0xffffffff) + "u"); 474 } else { 475 this->write(to_string((int32_t) i.fValue)); 476 } 477} 478 479void GLSLCodeGenerator::writeFloatLiteral(const FloatLiteral& f) { 480 this->write(to_string(f.fValue)); 481} 482 483void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) { 484 this->writeType(f.fDeclaration.fReturnType); 485 this->write(" " + f.fDeclaration.fName + "("); 486 const char* separator = ""; 487 for (const auto& param : f.fDeclaration.fParameters) { 488 this->write(separator); 489 separator = ", "; 490 this->writeModifiers(param->fModifiers, false); 491 std::vector<int> sizes; 492 const Type* type = ¶m->fType; 493 while (type->kind() == Type::kArray_Kind) { 494 sizes.push_back(type->columns()); 495 type = &type->componentType(); 496 } 497 this->writeType(*type); 498 this->write(" " + param->fName); 499 for (int s : sizes) { 500 if (s <= 0) { 501 this->write("[]"); 502 } else { 503 this->write("[" + to_string(s) + "]"); 504 } 505 } 506 } 507 this->writeLine(") {"); 508 509 fFunctionHeader = ""; 510 SkWStream* oldOut = fOut; 511 SkDynamicMemoryWStream buffer; 512 fOut = &buffer; 513 fIndentation++; 514 for (const auto& s : f.fBody->fStatements) { 515 this->writeStatement(*s); 516 this->writeLine(); 517 } 518 fIndentation--; 519 this->writeLine("}"); 520 521 fOut = oldOut; 522 this->write(fFunctionHeader); 523 sk_sp<SkData> data(buffer.detachAsData()); 524 this->write(SkString((const char*) data->data(), data->size())); 525} 526 527void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers, 528 bool globalContext) { 529 if (modifiers.fFlags & Modifiers::kFlat_Flag) { 530 this->write("flat "); 531 } 532 if (modifiers.fFlags & Modifiers::kNoPerspective_Flag) { 533 this->write("noperspective "); 534 } 535 SkString layout = modifiers.fLayout.description(); 536 if (layout.size()) { 537 this->write(layout + " "); 538 } 539 if (modifiers.fFlags & Modifiers::kReadOnly_Flag) { 540 this->write("readonly "); 541 } 542 if (modifiers.fFlags & Modifiers::kWriteOnly_Flag) { 543 this->write("writeonly "); 544 } 545 if (modifiers.fFlags & Modifiers::kCoherent_Flag) { 546 this->write("coherent "); 547 } 548 if (modifiers.fFlags & Modifiers::kVolatile_Flag) { 549 this->write("volatile "); 550 } 551 if (modifiers.fFlags & Modifiers::kRestrict_Flag) { 552 this->write("restrict "); 553 } 554 if ((modifiers.fFlags & Modifiers::kIn_Flag) && 555 (modifiers.fFlags & Modifiers::kOut_Flag)) { 556 this->write("inout "); 557 } else if (modifiers.fFlags & Modifiers::kIn_Flag) { 558 if (globalContext && 559 fProgram.fSettings.fCaps->generation() < GrGLSLGeneration::k130_GrGLSLGeneration) { 560 this->write(fProgramKind == Program::kVertex_Kind ? "attribute " 561 : "varying "); 562 } else { 563 this->write("in "); 564 } 565 } else if (modifiers.fFlags & Modifiers::kOut_Flag) { 566 if (globalContext && 567 fProgram.fSettings.fCaps->generation() < GrGLSLGeneration::k130_GrGLSLGeneration) { 568 this->write("varying "); 569 } else { 570 this->write("out "); 571 } 572 } 573 if (modifiers.fFlags & Modifiers::kUniform_Flag) { 574 this->write("uniform "); 575 } 576 if (modifiers.fFlags & Modifiers::kConst_Flag) { 577 this->write("const "); 578 } 579 if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) { 580 if (modifiers.fFlags & Modifiers::kLowp_Flag) { 581 this->write("lowp "); 582 } 583 if (modifiers.fFlags & Modifiers::kMediump_Flag) { 584 this->write("mediump "); 585 } 586 if (modifiers.fFlags & Modifiers::kHighp_Flag) { 587 this->write("highp "); 588 } 589 } 590} 591 592void GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) { 593 if (intf.fTypeName == "sk_PerVertex") { 594 return; 595 } 596 this->writeModifiers(intf.fVariable.fModifiers, true); 597 this->writeLine(intf.fTypeName + " {"); 598 fIndentation++; 599 const Type* structType = &intf.fVariable.fType; 600 while (structType->kind() == Type::kArray_Kind) { 601 structType = &structType->componentType(); 602 } 603 for (const auto& f : structType->fields()) { 604 this->writeModifiers(f.fModifiers, false); 605 this->writeType(*f.fType); 606 this->writeLine(" " + f.fName + ";"); 607 } 608 fIndentation--; 609 this->write("}"); 610 if (intf.fInstanceName.size()) { 611 this->write(" "); 612 this->write(intf.fInstanceName); 613 for (const auto& size : intf.fSizes) { 614 this->write("["); 615 if (size) { 616 this->writeExpression(*size, kTopLevel_Precedence); 617 } 618 this->write("]"); 619 } 620 } 621 this->writeLine(";"); 622} 623 624void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, bool global) { 625 ASSERT(decl.fVars.size() > 0); 626 this->writeModifiers(decl.fVars[0].fVar->fModifiers, global); 627 this->writeType(decl.fBaseType); 628 SkString separator(" "); 629 for (const auto& var : decl.fVars) { 630 ASSERT(var.fVar->fModifiers == decl.fVars[0].fVar->fModifiers); 631 this->write(separator); 632 separator = SkString(", "); 633 this->write(var.fVar->fName); 634 for (const auto& size : var.fSizes) { 635 this->write("["); 636 if (size) { 637 this->writeExpression(*size, kTopLevel_Precedence); 638 } 639 this->write("]"); 640 } 641 if (var.fValue) { 642 this->write(" = "); 643 this->writeExpression(*var.fValue, kTopLevel_Precedence); 644 } 645 if (!fFoundImageDecl && var.fVar->fType == *fContext.fImage2D_Type) { 646 if (fProgram.fSettings.fCaps->imageLoadStoreExtensionString()) { 647 fHeader.writeText("#extension "); 648 fHeader.writeText(fProgram.fSettings.fCaps->imageLoadStoreExtensionString()); 649 fHeader.writeText(" : require\n"); 650 } 651 fFoundImageDecl = true; 652 } 653 } 654 this->write(";"); 655} 656 657void GLSLCodeGenerator::writeStatement(const Statement& s) { 658 switch (s.fKind) { 659 case Statement::kBlock_Kind: 660 this->writeBlock((Block&) s); 661 break; 662 case Statement::kExpression_Kind: 663 this->writeExpression(*((ExpressionStatement&) s).fExpression, kTopLevel_Precedence); 664 this->write(";"); 665 break; 666 case Statement::kReturn_Kind: 667 this->writeReturnStatement((ReturnStatement&) s); 668 break; 669 case Statement::kVarDeclarations_Kind: 670 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration, false); 671 break; 672 case Statement::kIf_Kind: 673 this->writeIfStatement((IfStatement&) s); 674 break; 675 case Statement::kFor_Kind: 676 this->writeForStatement((ForStatement&) s); 677 break; 678 case Statement::kWhile_Kind: 679 this->writeWhileStatement((WhileStatement&) s); 680 break; 681 case Statement::kDo_Kind: 682 this->writeDoStatement((DoStatement&) s); 683 break; 684 case Statement::kSwitch_Kind: 685 this->writeSwitchStatement((SwitchStatement&) s); 686 break; 687 case Statement::kBreak_Kind: 688 this->write("break;"); 689 break; 690 case Statement::kContinue_Kind: 691 this->write("continue;"); 692 break; 693 case Statement::kDiscard_Kind: 694 this->write("discard;"); 695 break; 696 default: 697 ABORT("unsupported statement: %s", s.description().c_str()); 698 } 699} 700 701void GLSLCodeGenerator::writeBlock(const Block& b) { 702 this->writeLine("{"); 703 fIndentation++; 704 for (const auto& s : b.fStatements) { 705 this->writeStatement(*s); 706 this->writeLine(); 707 } 708 fIndentation--; 709 this->write("}"); 710} 711 712void GLSLCodeGenerator::writeIfStatement(const IfStatement& stmt) { 713 this->write("if ("); 714 this->writeExpression(*stmt.fTest, kTopLevel_Precedence); 715 this->write(") "); 716 this->writeStatement(*stmt.fIfTrue); 717 if (stmt.fIfFalse) { 718 this->write(" else "); 719 this->writeStatement(*stmt.fIfFalse); 720 } 721} 722 723void GLSLCodeGenerator::writeForStatement(const ForStatement& f) { 724 this->write("for ("); 725 if (f.fInitializer) { 726 this->writeStatement(*f.fInitializer); 727 } else { 728 this->write("; "); 729 } 730 if (f.fTest) { 731 this->writeExpression(*f.fTest, kTopLevel_Precedence); 732 } 733 this->write("; "); 734 if (f.fNext) { 735 this->writeExpression(*f.fNext, kTopLevel_Precedence); 736 } 737 this->write(") "); 738 this->writeStatement(*f.fStatement); 739} 740 741void GLSLCodeGenerator::writeWhileStatement(const WhileStatement& w) { 742 this->write("while ("); 743 this->writeExpression(*w.fTest, kTopLevel_Precedence); 744 this->write(") "); 745 this->writeStatement(*w.fStatement); 746} 747 748void GLSLCodeGenerator::writeDoStatement(const DoStatement& d) { 749 this->write("do "); 750 this->writeStatement(*d.fStatement); 751 this->write(" while ("); 752 this->writeExpression(*d.fTest, kTopLevel_Precedence); 753 this->write(");"); 754} 755 756void GLSLCodeGenerator::writeSwitchStatement(const SwitchStatement& s) { 757 this->write("switch ("); 758 this->writeExpression(*s.fValue, kTopLevel_Precedence); 759 this->writeLine(") {"); 760 fIndentation++; 761 for (const auto& c : s.fCases) { 762 if (c->fValue) { 763 this->write("case "); 764 this->writeExpression(*c->fValue, kTopLevel_Precedence); 765 this->writeLine(":"); 766 } else { 767 this->writeLine("default:"); 768 } 769 fIndentation++; 770 for (const auto& stmt : c->fStatements) { 771 this->writeStatement(*stmt); 772 this->writeLine(); 773 } 774 fIndentation--; 775 } 776 fIndentation--; 777 this->write("}"); 778} 779 780void GLSLCodeGenerator::writeReturnStatement(const ReturnStatement& r) { 781 this->write("return"); 782 if (r.fExpression) { 783 this->write(" "); 784 this->writeExpression(*r.fExpression, kTopLevel_Precedence); 785 } 786 this->write(";"); 787} 788 789bool GLSLCodeGenerator::generateCode() { 790 SkWStream* rawOut = fOut; 791 fOut = &fHeader; 792 fProgramKind = fProgram.fKind; 793 this->write(fProgram.fSettings.fCaps->versionDeclString()); 794 this->writeLine(); 795 for (const auto& e : fProgram.fElements) { 796 if (e->fKind == ProgramElement::kExtension_Kind) { 797 this->writeExtension((Extension&) *e); 798 } 799 } 800 SkDynamicMemoryWStream body; 801 fOut = &body; 802 if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) { 803 this->write("precision "); 804 switch (fProgram.fDefaultPrecision) { 805 case Modifiers::kLowp_Flag: 806 this->write("lowp"); 807 break; 808 case Modifiers::kMediump_Flag: 809 this->write("mediump"); 810 break; 811 case Modifiers::kHighp_Flag: 812 this->write("highp"); 813 break; 814 default: 815 ASSERT(false); 816 this->write("<error>"); 817 } 818 this->writeLine(" float;"); 819 } 820 for (const auto& e : fProgram.fElements) { 821 switch (e->fKind) { 822 case ProgramElement::kExtension_Kind: 823 break; 824 case ProgramElement::kVar_Kind: { 825 VarDeclarations& decl = (VarDeclarations&) *e; 826 if (decl.fVars.size() > 0) { 827 int builtin = decl.fVars[0].fVar->fModifiers.fLayout.fBuiltin; 828 if (builtin == -1) { 829 // normal var 830 this->writeVarDeclarations(decl, true); 831 this->writeLine(); 832 } else if (builtin == SK_FRAGCOLOR_BUILTIN && 833 fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput()) { 834 this->write("out "); 835 if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) { 836 this->write("mediump "); 837 } 838 this->writeLine("vec4 sk_FragColor;"); 839 } 840 } 841 break; 842 } 843 case ProgramElement::kInterfaceBlock_Kind: 844 this->writeInterfaceBlock((InterfaceBlock&) *e); 845 break; 846 case ProgramElement::kFunction_Kind: 847 this->writeFunction((FunctionDefinition&) *e); 848 break; 849 case ProgramElement::kModifiers_Kind: 850 this->writeModifiers(((ModifiersDeclaration&) *e).fModifiers, true); 851 this->writeLine(";"); 852 break; 853 default: 854 printf("%s\n", e->description().c_str()); 855 ABORT("unsupported program element"); 856 } 857 } 858 fOut = nullptr; 859 860 write_data(*fHeader.detachAsData(), *rawOut); 861 write_data(*body.detachAsData(), *rawOut); 862 return true; 863} 864 865} 866