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 "SkSLCompiler.h" 11 #include "ir/SkSLExpressionStatement.h" 12 #include "ir/SkSLExtension.h" 13 #include "ir/SkSLIndexExpression.h" 14 #include "ir/SkSLModifiersDeclaration.h" 15 #include "ir/SkSLNop.h" 16 #include "ir/SkSLVariableReference.h" 17 18 #ifndef SKSL_STANDALONE 19 #include "SkOnce.h" 20 #endif 21 22 namespace SkSL { 23 24 void GLSLCodeGenerator::write(const char* s) { 25 if (s[0] == 0) { 26 return; 27 } 28 if (fAtLineStart) { 29 for (int i = 0; i < fIndentation; i++) { 30 fOut->writeText(" "); 31 } 32 } 33 fOut->writeText(s); 34 fAtLineStart = false; 35 } 36 37 void GLSLCodeGenerator::writeLine(const char* s) { 38 this->write(s); 39 fOut->writeText(fLineEnding); 40 fAtLineStart = true; 41 } 42 43 void GLSLCodeGenerator::write(const String& s) { 44 this->write(s.c_str()); 45 } 46 47 void GLSLCodeGenerator::write(StringFragment s) { 48 if (!s.fLength) { 49 return; 50 } 51 if (fAtLineStart) { 52 for (int i = 0; i < fIndentation; i++) { 53 fOut->writeText(" "); 54 } 55 } 56 fOut->write(s.fChars, s.fLength); 57 fAtLineStart = false; 58 } 59 60 void GLSLCodeGenerator::writeLine(const String& s) { 61 this->writeLine(s.c_str()); 62 } 63 64 void GLSLCodeGenerator::writeLine() { 65 this->writeLine(""); 66 } 67 68 void GLSLCodeGenerator::writeExtension(const String& name) { 69 this->writeExtension(name, true); 70 } 71 72 void GLSLCodeGenerator::writeExtension(const String& name, bool require) { 73 fExtensions.writeText("#extension "); 74 fExtensions.write(name.c_str(), name.length()); 75 fExtensions.writeText(require ? " : require\n" : " : enable\n"); 76 } 77 78 bool GLSLCodeGenerator::usesPrecisionModifiers() const { 79 return fProgram.fSettings.fCaps->usesPrecisionModifiers(); 80 } 81 82 String GLSLCodeGenerator::getTypeName(const Type& type) { 83 switch (type.kind()) { 84 case Type::kVector_Kind: { 85 Type component = type.componentType(); 86 String result; 87 if (component == *fContext.fFloat_Type || component == *fContext.fHalf_Type) { 88 result = "vec"; 89 } 90 else if (component == *fContext.fDouble_Type) { 91 result = "dvec"; 92 } 93 else if (component.isSigned()) { 94 result = "ivec"; 95 } 96 else if (component.isUnsigned()) { 97 result = "uvec"; 98 } 99 else if (component == *fContext.fBool_Type) { 100 result = "bvec"; 101 } 102 else { 103 ABORT("unsupported vector type"); 104 } 105 result += to_string(type.columns()); 106 return result; 107 } 108 case Type::kMatrix_Kind: { 109 String result; 110 Type component = type.componentType(); 111 if (component == *fContext.fFloat_Type || component == *fContext.fHalf_Type) { 112 result = "mat"; 113 } 114 else if (component == *fContext.fDouble_Type) { 115 result = "dmat"; 116 } 117 else { 118 ABORT("unsupported matrix type"); 119 } 120 result += to_string(type.columns()); 121 if (type.columns() != type.rows()) { 122 result += "x"; 123 result += to_string(type.rows()); 124 } 125 return result; 126 } 127 case Type::kArray_Kind: { 128 String result = this->getTypeName(type.componentType()) + "["; 129 if (type.columns() != -1) { 130 result += to_string(type.columns()); 131 } 132 result += "]"; 133 return result; 134 } 135 case Type::kScalar_Kind: { 136 if (type == *fContext.fHalf_Type) { 137 return "float"; 138 } 139 else if (type == *fContext.fShort_Type) { 140 return "int"; 141 } 142 else if (type == *fContext.fUShort_Type) { 143 return "uint"; 144 } 145 else if (type == *fContext.fByte_Type) { 146 return "int"; 147 } 148 else if (type == *fContext.fUByte_Type) { 149 return "uint"; 150 } 151 else { 152 return type.name(); 153 } 154 break; 155 } 156 default: 157 return type.name(); 158 } 159 } 160 161 void GLSLCodeGenerator::writeType(const Type& type) { 162 if (type.kind() == Type::kStruct_Kind) { 163 for (const Type* search : fWrittenStructs) { 164 if (*search == type) { 165 // already written 166 this->write(type.fName); 167 return; 168 } 169 } 170 fWrittenStructs.push_back(&type); 171 this->write("struct "); 172 this->write(type.fName); 173 this->writeLine(" {"); 174 fIndentation++; 175 for (const auto& f : type.fields()) { 176 this->writeModifiers(f.fModifiers, false); 177 this->writeTypePrecision(*f.fType); 178 // sizes (which must be static in structs) are part of the type name here 179 this->writeType(*f.fType); 180 this->write(" "); 181 this->write(f.fName); 182 this->writeLine(";"); 183 } 184 fIndentation--; 185 this->write("}"); 186 } else { 187 this->write(this->getTypeName(type)); 188 } 189 } 190 191 void GLSLCodeGenerator::writeExpression(const Expression& expr, Precedence parentPrecedence) { 192 switch (expr.fKind) { 193 case Expression::kBinary_Kind: 194 this->writeBinaryExpression((BinaryExpression&) expr, parentPrecedence); 195 break; 196 case Expression::kBoolLiteral_Kind: 197 this->writeBoolLiteral((BoolLiteral&) expr); 198 break; 199 case Expression::kConstructor_Kind: 200 this->writeConstructor((Constructor&) expr, parentPrecedence); 201 break; 202 case Expression::kIntLiteral_Kind: 203 this->writeIntLiteral((IntLiteral&) expr); 204 break; 205 case Expression::kFieldAccess_Kind: 206 this->writeFieldAccess(((FieldAccess&) expr)); 207 break; 208 case Expression::kFloatLiteral_Kind: 209 this->writeFloatLiteral(((FloatLiteral&) expr)); 210 break; 211 case Expression::kFunctionCall_Kind: 212 this->writeFunctionCall((FunctionCall&) expr); 213 break; 214 case Expression::kPrefix_Kind: 215 this->writePrefixExpression((PrefixExpression&) expr, parentPrecedence); 216 break; 217 case Expression::kPostfix_Kind: 218 this->writePostfixExpression((PostfixExpression&) expr, parentPrecedence); 219 break; 220 case Expression::kSetting_Kind: 221 this->writeSetting((Setting&) expr); 222 break; 223 case Expression::kSwizzle_Kind: 224 this->writeSwizzle((Swizzle&) expr); 225 break; 226 case Expression::kVariableReference_Kind: 227 this->writeVariableReference((VariableReference&) expr); 228 break; 229 case Expression::kTernary_Kind: 230 this->writeTernaryExpression((TernaryExpression&) expr, parentPrecedence); 231 break; 232 case Expression::kIndex_Kind: 233 this->writeIndexExpression((IndexExpression&) expr); 234 break; 235 default: 236 ABORT("unsupported expression: %s", expr.description().c_str()); 237 } 238 } 239 240 static bool is_abs(Expression& expr) { 241 if (expr.fKind != Expression::kFunctionCall_Kind) { 242 return false; 243 } 244 return ((FunctionCall&) expr).fFunction.fName == "abs"; 245 } 246 247 // turns min(abs(x), y) into ((tmpVar1 = abs(x)) < (tmpVar2 = y) ? tmpVar1 : tmpVar2) to avoid a 248 // Tegra3 compiler bug. 249 void GLSLCodeGenerator::writeMinAbsHack(Expression& absExpr, Expression& otherExpr) { 250 SkASSERT(!fProgram.fSettings.fCaps->canUseMinAndAbsTogether()); 251 String tmpVar1 = "minAbsHackVar" + to_string(fVarCount++); 252 String tmpVar2 = "minAbsHackVar" + to_string(fVarCount++); 253 this->fFunctionHeader += String(" ") + this->getTypePrecision(absExpr.fType) + 254 this->getTypeName(absExpr.fType) + " " + tmpVar1 + ";\n"; 255 this->fFunctionHeader += String(" ") + this->getTypePrecision(otherExpr.fType) + 256 this->getTypeName(otherExpr.fType) + " " + tmpVar2 + ";\n"; 257 this->write("((" + tmpVar1 + " = "); 258 this->writeExpression(absExpr, kTopLevel_Precedence); 259 this->write(") < (" + tmpVar2 + " = "); 260 this->writeExpression(otherExpr, kAssignment_Precedence); 261 this->write(") ? " + tmpVar1 + " : " + tmpVar2 + ")"); 262 } 263 264 void GLSLCodeGenerator::writeInverseSqrtHack(const Expression& x) { 265 this->write("(1.0 / sqrt("); 266 this->writeExpression(x, kTopLevel_Precedence); 267 this->write("))"); 268 } 269 270 void GLSLCodeGenerator::writeDeterminantHack(const Expression& mat) { 271 String name; 272 if (mat.fType == *fContext.fFloat2x2_Type || mat.fType == *fContext.fHalf2x2_Type) { 273 name = "_determinant2"; 274 if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) { 275 fWrittenIntrinsics.insert(name); 276 fExtraFunctions.writeText(( 277 "float " + name + "(mat2 m) {" 278 " return m[0][0] * m[1][1] - m[0][1] * m[1][0];" 279 "}" 280 ).c_str()); 281 } 282 } 283 else if (mat.fType == *fContext.fFloat3x3_Type || mat.fType == *fContext.fHalf3x3_Type) { 284 name = "_determinant3"; 285 if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) { 286 fWrittenIntrinsics.insert(name); 287 fExtraFunctions.writeText(( 288 "float " + name + "(mat3 m) {" 289 " float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];" 290 " float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];" 291 " float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];" 292 " float b01 = a22 * a11 - a12 * a21;" 293 " float b11 = -a22 * a10 + a12 * a20;" 294 " float b21 = a21 * a10 - a11 * a20;" 295 " return a00 * b01 + a01 * b11 + a02 * b21;" 296 "}" 297 ).c_str()); 298 } 299 } 300 else if (mat.fType == *fContext.fFloat4x4_Type || mat.fType == *fContext.fHalf4x4_Type) { 301 name = "_determinant3"; 302 if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) { 303 fWrittenIntrinsics.insert(name); 304 fExtraFunctions.writeText(( 305 "mat4 " + name + "(mat4 m) {" 306 " float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2], a03 = m[0][3];" 307 " float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2], a13 = m[1][3];" 308 " float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2], a23 = m[2][3];" 309 " float a30 = m[3][0], a31 = m[3][1], a32 = m[3][2], a33 = m[3][3];" 310 " float b00 = a00 * a11 - a01 * a10;" 311 " float b01 = a00 * a12 - a02 * a10;" 312 " float b02 = a00 * a13 - a03 * a10;" 313 " float b03 = a01 * a12 - a02 * a11;" 314 " float b04 = a01 * a13 - a03 * a11;" 315 " float b05 = a02 * a13 - a03 * a12;" 316 " float b06 = a20 * a31 - a21 * a30;" 317 " float b07 = a20 * a32 - a22 * a30;" 318 " float b08 = a20 * a33 - a23 * a30;" 319 " float b09 = a21 * a32 - a22 * a31;" 320 " float b10 = a21 * a33 - a23 * a31;" 321 " float b11 = a22 * a33 - a23 * a32;" 322 " return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;" 323 "}" 324 ).c_str()); 325 } 326 } 327 else { 328 SkASSERT(false); 329 } 330 this->write(name + "("); 331 this->writeExpression(mat, kTopLevel_Precedence); 332 this->write(")"); 333 } 334 335 void GLSLCodeGenerator::writeInverseHack(const Expression& mat) { 336 String name; 337 if (mat.fType == *fContext.fFloat2x2_Type || mat.fType == *fContext.fHalf2x2_Type) { 338 name = "_inverse2"; 339 if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) { 340 fWrittenIntrinsics.insert(name); 341 fExtraFunctions.writeText(( 342 "mat2 " + name + "(mat2 m) {" 343 " return mat2(m[1][1], -m[0][1], -m[1][0], m[0][0]) / " 344 "(m[0][0] * m[1][1] - m[0][1] * m[1][0]);" 345 "}" 346 ).c_str()); 347 } 348 } 349 else if (mat.fType == *fContext.fFloat3x3_Type || mat.fType == *fContext.fHalf3x3_Type) { 350 name = "_inverse3"; 351 if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) { 352 fWrittenIntrinsics.insert(name); 353 fExtraFunctions.writeText(( 354 "mat3 " + name + "(mat3 m) {" 355 " float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];" 356 " float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];" 357 " float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];" 358 " float b01 = a22 * a11 - a12 * a21;" 359 " float b11 = -a22 * a10 + a12 * a20;" 360 " float b21 = a21 * a10 - a11 * a20;" 361 " float det = a00 * b01 + a01 * b11 + a02 * b21;" 362 " return mat3(b01, (-a22 * a01 + a02 * a21), (a12 * a01 - a02 * a11)," 363 " b11, (a22 * a00 - a02 * a20), (-a12 * a00 + a02 * a10)," 364 " b21, (-a21 * a00 + a01 * a20), (a11 * a00 - a01 * a10)) / det;" 365 "}" 366 ).c_str()); 367 } 368 } 369 else if (mat.fType == *fContext.fFloat4x4_Type || mat.fType == *fContext.fHalf4x4_Type) { 370 name = "_inverse4"; 371 if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) { 372 fWrittenIntrinsics.insert(name); 373 fExtraFunctions.writeText(( 374 "mat4 " + name + "(mat4 m) {" 375 " float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2], a03 = m[0][3];" 376 " float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2], a13 = m[1][3];" 377 " float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2], a23 = m[2][3];" 378 " float a30 = m[3][0], a31 = m[3][1], a32 = m[3][2], a33 = m[3][3];" 379 " float b00 = a00 * a11 - a01 * a10;" 380 " float b01 = a00 * a12 - a02 * a10;" 381 " float b02 = a00 * a13 - a03 * a10;" 382 " float b03 = a01 * a12 - a02 * a11;" 383 " float b04 = a01 * a13 - a03 * a11;" 384 " float b05 = a02 * a13 - a03 * a12;" 385 " float b06 = a20 * a31 - a21 * a30;" 386 " float b07 = a20 * a32 - a22 * a30;" 387 " float b08 = a20 * a33 - a23 * a30;" 388 " float b09 = a21 * a32 - a22 * a31;" 389 " float b10 = a21 * a33 - a23 * a31;" 390 " float b11 = a22 * a33 - a23 * a32;" 391 " float det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - " 392 " b04 * b07 + b05 * b06;" 393 " return mat4(" 394 " a11 * b11 - a12 * b10 + a13 * b09," 395 " a02 * b10 - a01 * b11 - a03 * b09," 396 " a31 * b05 - a32 * b04 + a33 * b03," 397 " a22 * b04 - a21 * b05 - a23 * b03," 398 " a12 * b08 - a10 * b11 - a13 * b07," 399 " a00 * b11 - a02 * b08 + a03 * b07," 400 " a32 * b02 - a30 * b05 - a33 * b01," 401 " a20 * b05 - a22 * b02 + a23 * b01," 402 " a10 * b10 - a11 * b08 + a13 * b06," 403 " a01 * b08 - a00 * b10 - a03 * b06," 404 " a30 * b04 - a31 * b02 + a33 * b00," 405 " a21 * b02 - a20 * b04 - a23 * b00," 406 " a11 * b07 - a10 * b09 - a12 * b06," 407 " a00 * b09 - a01 * b07 + a02 * b06," 408 " a31 * b01 - a30 * b03 - a32 * b00," 409 " a20 * b03 - a21 * b01 + a22 * b00) / det;" 410 "}" 411 ).c_str()); 412 } 413 } 414 else { 415 SkASSERT(false); 416 } 417 this->write(name + "("); 418 this->writeExpression(mat, kTopLevel_Precedence); 419 this->write(")"); 420 } 421 422 void GLSLCodeGenerator::writeTransposeHack(const Expression& mat) { 423 String name = "transpose" + to_string(mat.fType.columns()) + to_string(mat.fType.rows()); 424 if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) { 425 fWrittenIntrinsics.insert(name); 426 String type = this->getTypeName(mat.fType); 427 const Type& base = mat.fType.componentType(); 428 String transposed = this->getTypeName(base.toCompound(fContext, 429 mat.fType.rows(), 430 mat.fType.columns())); 431 fExtraFunctions.writeText((transposed + " " + name + "(" + type + " m) {\nreturn " + 432 transposed + "(").c_str()); 433 const char* separator = ""; 434 for (int row = 0; row < mat.fType.rows(); ++row) { 435 for (int column = 0; column < mat.fType.columns(); ++column) { 436 fExtraFunctions.writeText(separator); 437 fExtraFunctions.writeText(("m[" + to_string(column) + "][" + to_string(row) + 438 "]").c_str()); 439 separator = ", "; 440 } 441 } 442 fExtraFunctions.writeText("); }"); 443 } 444 this->write(name + "("); 445 this->writeExpression(mat, kTopLevel_Precedence); 446 this->write(")"); 447 } 448 449 std::unordered_map<StringFragment, GLSLCodeGenerator::FunctionClass>* 450 GLSLCodeGenerator::fFunctionClasses = nullptr; 451 452 void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) { 453 #ifdef SKSL_STANDALONE 454 if (!fFunctionClasses) { 455 #else 456 static SkOnce once; 457 once([] { 458 #endif 459 fFunctionClasses = new std::unordered_map<StringFragment, FunctionClass>(); 460 (*fFunctionClasses)["abs"] = FunctionClass::kAbs; 461 (*fFunctionClasses)["atan"] = FunctionClass::kAtan; 462 (*fFunctionClasses)["determinant"] = FunctionClass::kDeterminant; 463 (*fFunctionClasses)["dFdx"] = FunctionClass::kDFdx; 464 (*fFunctionClasses)["dFdy"] = FunctionClass::kDFdy; 465 (*fFunctionClasses)["fwidth"] = FunctionClass::kFwidth; 466 (*fFunctionClasses)["fma"] = FunctionClass::kFMA; 467 (*fFunctionClasses)["fract"] = FunctionClass::kFract; 468 (*fFunctionClasses)["inverse"] = FunctionClass::kInverse; 469 (*fFunctionClasses)["inverseSqrt"] = FunctionClass::kInverseSqrt; 470 (*fFunctionClasses)["min"] = FunctionClass::kMin; 471 (*fFunctionClasses)["pow"] = FunctionClass::kPow; 472 (*fFunctionClasses)["saturate"] = FunctionClass::kSaturate; 473 (*fFunctionClasses)["texture"] = FunctionClass::kTexture; 474 (*fFunctionClasses)["transpose"] = FunctionClass::kTranspose; 475 } 476 #ifndef SKSL_STANDALONE 477 ); 478 #endif 479 const auto found = c.fFunction.fBuiltin ? fFunctionClasses->find(c.fFunction.fName) : 480 fFunctionClasses->end(); 481 bool isTextureFunctionWithBias = false; 482 bool nameWritten = false; 483 if (found != fFunctionClasses->end()) { 484 switch (found->second) { 485 case FunctionClass::kAbs: { 486 if (!fProgram.fSettings.fCaps->emulateAbsIntFunction()) 487 break; 488 SkASSERT(c.fArguments.size() == 1); 489 if (c.fArguments[0]->fType != *fContext.fInt_Type) 490 break; 491 // abs(int) on Intel OSX is incorrect, so emulate it: 492 String name = "_absemulation"; 493 this->write(name); 494 nameWritten = true; 495 if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) { 496 fWrittenIntrinsics.insert(name); 497 fExtraFunctions.writeText(( 498 "int " + name + "(int x) {\n" 499 " return x * sign(x);\n" 500 "}\n" 501 ).c_str()); 502 } 503 break; 504 } 505 case FunctionClass::kAtan: 506 if (fProgram.fSettings.fCaps->mustForceNegatedAtanParamToFloat() && 507 c.fArguments.size() == 2 && 508 c.fArguments[1]->fKind == Expression::kPrefix_Kind) { 509 const PrefixExpression& p = (PrefixExpression&) *c.fArguments[1]; 510 if (p.fOperator == Token::MINUS) { 511 this->write("atan("); 512 this->writeExpression(*c.fArguments[0], kSequence_Precedence); 513 this->write(", -1.0 * "); 514 this->writeExpression(*p.fOperand, kMultiplicative_Precedence); 515 this->write(")"); 516 return; 517 } 518 } 519 break; 520 case FunctionClass::kDFdy: 521 if (fProgram.fSettings.fFlipY) { 522 // Flipping Y also negates the Y derivatives. 523 this->write("-dFdy"); 524 nameWritten = true; 525 } 526 // fallthru 527 case FunctionClass::kDFdx: 528 case FunctionClass::kFwidth: 529 if (!fFoundDerivatives && 530 fProgram.fSettings.fCaps->shaderDerivativeExtensionString()) { 531 SkASSERT(fProgram.fSettings.fCaps->shaderDerivativeSupport()); 532 this->writeExtension(fProgram.fSettings.fCaps->shaderDerivativeExtensionString()); 533 fFoundDerivatives = true; 534 } 535 break; 536 case FunctionClass::kDeterminant: 537 if (fProgram.fSettings.fCaps->generation() < k150_GrGLSLGeneration) { 538 SkASSERT(c.fArguments.size() == 1); 539 this->writeDeterminantHack(*c.fArguments[0]); 540 return; 541 } 542 break; 543 case FunctionClass::kFMA: 544 if (!fProgram.fSettings.fCaps->builtinFMASupport()) { 545 SkASSERT(c.fArguments.size() == 3); 546 this->write("(("); 547 this->writeExpression(*c.fArguments[0], kSequence_Precedence); 548 this->write(") * ("); 549 this->writeExpression(*c.fArguments[1], kSequence_Precedence); 550 this->write(") + ("); 551 this->writeExpression(*c.fArguments[2], kSequence_Precedence); 552 this->write("))"); 553 return; 554 } 555 break; 556 case FunctionClass::kFract: 557 if (!fProgram.fSettings.fCaps->canUseFractForNegativeValues()) { 558 SkASSERT(c.fArguments.size() == 1); 559 this->write("(0.5 - sign("); 560 this->writeExpression(*c.fArguments[0], kSequence_Precedence); 561 this->write(") * (0.5 - fract(abs("); 562 this->writeExpression(*c.fArguments[0], kSequence_Precedence); 563 this->write("))))"); 564 return; 565 } 566 break; 567 case FunctionClass::kInverse: 568 if (fProgram.fSettings.fCaps->generation() < k140_GrGLSLGeneration) { 569 SkASSERT(c.fArguments.size() == 1); 570 this->writeInverseHack(*c.fArguments[0]); 571 return; 572 } 573 break; 574 case FunctionClass::kInverseSqrt: 575 if (fProgram.fSettings.fCaps->generation() < k130_GrGLSLGeneration) { 576 SkASSERT(c.fArguments.size() == 1); 577 this->writeInverseSqrtHack(*c.fArguments[0]); 578 return; 579 } 580 break; 581 case FunctionClass::kMin: 582 if (!fProgram.fSettings.fCaps->canUseMinAndAbsTogether()) { 583 SkASSERT(c.fArguments.size() == 2); 584 if (is_abs(*c.fArguments[0])) { 585 this->writeMinAbsHack(*c.fArguments[0], *c.fArguments[1]); 586 return; 587 } 588 if (is_abs(*c.fArguments[1])) { 589 // note that this violates the GLSL left-to-right evaluation semantics. 590 // I doubt it will ever end up mattering, but it's worth calling out. 591 this->writeMinAbsHack(*c.fArguments[1], *c.fArguments[0]); 592 return; 593 } 594 } 595 break; 596 case FunctionClass::kPow: 597 if (!fProgram.fSettings.fCaps->removePowWithConstantExponent()) { 598 break; 599 } 600 // pow(x, y) on some NVIDIA drivers causes crashes if y is a 601 // constant. It's hard to tell what constitutes "constant" here 602 // so just replace in all cases. 603 604 // Change pow(x, y) into exp2(y * log2(x)) 605 this->write("exp2("); 606 this->writeExpression(*c.fArguments[1], kMultiplicative_Precedence); 607 this->write(" * log2("); 608 this->writeExpression(*c.fArguments[0], kSequence_Precedence); 609 this->write("))"); 610 return; 611 case FunctionClass::kSaturate: 612 SkASSERT(c.fArguments.size() == 1); 613 this->write("clamp("); 614 this->writeExpression(*c.fArguments[0], kSequence_Precedence); 615 this->write(", 0.0, 1.0)"); 616 return; 617 case FunctionClass::kTexture: { 618 const char* dim = ""; 619 bool proj = false; 620 switch (c.fArguments[0]->fType.dimensions()) { 621 case SpvDim1D: 622 dim = "1D"; 623 isTextureFunctionWithBias = true; 624 if (c.fArguments[1]->fType == *fContext.fFloat_Type) { 625 proj = false; 626 } else { 627 SkASSERT(c.fArguments[1]->fType == *fContext.fFloat2_Type); 628 proj = true; 629 } 630 break; 631 case SpvDim2D: 632 dim = "2D"; 633 if (c.fArguments[0]->fType != *fContext.fSamplerExternalOES_Type) { 634 isTextureFunctionWithBias = true; 635 } 636 if (c.fArguments[1]->fType == *fContext.fFloat2_Type) { 637 proj = false; 638 } else { 639 SkASSERT(c.fArguments[1]->fType == *fContext.fFloat3_Type); 640 proj = true; 641 } 642 break; 643 case SpvDim3D: 644 dim = "3D"; 645 isTextureFunctionWithBias = true; 646 if (c.fArguments[1]->fType == *fContext.fFloat3_Type) { 647 proj = false; 648 } else { 649 SkASSERT(c.fArguments[1]->fType == *fContext.fFloat4_Type); 650 proj = true; 651 } 652 break; 653 case SpvDimCube: 654 dim = "Cube"; 655 isTextureFunctionWithBias = true; 656 proj = false; 657 break; 658 case SpvDimRect: 659 dim = "Rect"; 660 proj = false; 661 break; 662 case SpvDimBuffer: 663 SkASSERT(false); // doesn't exist 664 dim = "Buffer"; 665 proj = false; 666 break; 667 case SpvDimSubpassData: 668 SkASSERT(false); // doesn't exist 669 dim = "SubpassData"; 670 proj = false; 671 break; 672 } 673 this->write("texture"); 674 if (fProgram.fSettings.fCaps->generation() < k130_GrGLSLGeneration) { 675 this->write(dim); 676 } 677 if (proj) { 678 this->write("Proj"); 679 } 680 nameWritten = true; 681 break; 682 } 683 case FunctionClass::kTranspose: 684 if (fProgram.fSettings.fCaps->generation() < k130_GrGLSLGeneration) { 685 SkASSERT(c.fArguments.size() == 1); 686 this->writeTransposeHack(*c.fArguments[0]); 687 return; 688 } 689 break; 690 } 691 } 692 if (!nameWritten) { 693 this->write(c.fFunction.fName); 694 } 695 this->write("("); 696 const char* separator = ""; 697 for (const auto& arg : c.fArguments) { 698 this->write(separator); 699 separator = ", "; 700 this->writeExpression(*arg, kSequence_Precedence); 701 } 702 if (fProgram.fSettings.fSharpenTextures && isTextureFunctionWithBias) { 703 this->write(", -0.5"); 704 } 705 this->write(")"); 706 } 707 708 void GLSLCodeGenerator::writeConstructor(const Constructor& c, Precedence parentPrecedence) { 709 if (c.fArguments.size() == 1 && 710 (this->getTypeName(c.fType) == this->getTypeName(c.fArguments[0]->fType) || 711 (c.fType.kind() == Type::kScalar_Kind && 712 c.fArguments[0]->fType == *fContext.fFloatLiteral_Type))) { 713 // in cases like half(float), they're different types as far as SkSL is concerned but the 714 // same type as far as GLSL is concerned. We avoid a redundant float(float) by just writing 715 // out the inner expression here. 716 this->writeExpression(*c.fArguments[0], parentPrecedence); 717 return; 718 } 719 this->writeType(c.fType); 720 this->write("("); 721 const char* separator = ""; 722 for (const auto& arg : c.fArguments) { 723 this->write(separator); 724 separator = ", "; 725 this->writeExpression(*arg, kSequence_Precedence); 726 } 727 this->write(")"); 728 } 729 730 void GLSLCodeGenerator::writeFragCoord() { 731 if (!fProgram.fSettings.fCaps->canUseFragCoord()) { 732 if (!fSetupFragCoordWorkaround) { 733 const char* precision = usesPrecisionModifiers() ? "highp " : ""; 734 fFunctionHeader += precision; 735 fFunctionHeader += " float sk_FragCoord_InvW = 1. / sk_FragCoord_Workaround.w;\n"; 736 fFunctionHeader += precision; 737 fFunctionHeader += " vec4 sk_FragCoord_Resolved = " 738 "vec4(sk_FragCoord_Workaround.xyz * sk_FragCoord_InvW, sk_FragCoord_InvW);\n"; 739 // Ensure that we get exact .5 values for x and y. 740 fFunctionHeader += " sk_FragCoord_Resolved.xy = floor(sk_FragCoord_Resolved.xy) + " 741 "vec2(.5);\n"; 742 fSetupFragCoordWorkaround = true; 743 } 744 this->write("sk_FragCoord_Resolved"); 745 return; 746 } 747 748 // We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers 749 // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the 750 // declaration varies in earlier GLSL specs. So it is simpler to omit it. 751 if (!fProgram.fSettings.fFlipY) { 752 this->write("gl_FragCoord"); 753 } else if (const char* extension = 754 fProgram.fSettings.fCaps->fragCoordConventionsExtensionString()) { 755 if (!fSetupFragPositionGlobal) { 756 if (fProgram.fSettings.fCaps->generation() < k150_GrGLSLGeneration) { 757 this->writeExtension(extension); 758 } 759 fGlobals.writeText("layout(origin_upper_left) in vec4 gl_FragCoord;\n"); 760 fSetupFragPositionGlobal = true; 761 } 762 this->write("gl_FragCoord"); 763 } else { 764 if (!fSetupFragPositionLocal) { 765 fFunctionHeader += usesPrecisionModifiers() ? "highp " : ""; 766 fFunctionHeader += " vec4 sk_FragCoord = vec4(gl_FragCoord.x, " SKSL_RTHEIGHT_NAME 767 " - gl_FragCoord.y, gl_FragCoord.z, gl_FragCoord.w);\n"; 768 fSetupFragPositionLocal = true; 769 } 770 this->write("sk_FragCoord"); 771 } 772 } 773 774 void GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) { 775 switch (ref.fVariable.fModifiers.fLayout.fBuiltin) { 776 case SK_FRAGCOLOR_BUILTIN: 777 if (fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput()) { 778 this->write("sk_FragColor"); 779 } else { 780 this->write("gl_FragColor"); 781 } 782 break; 783 case SK_FRAGCOORD_BUILTIN: 784 this->writeFragCoord(); 785 break; 786 case SK_WIDTH_BUILTIN: 787 this->write("u_skRTWidth"); 788 break; 789 case SK_HEIGHT_BUILTIN: 790 this->write("u_skRTHeight"); 791 break; 792 case SK_CLOCKWISE_BUILTIN: 793 this->write(fProgram.fSettings.fFlipY ? "(!gl_FrontFacing)" : "gl_FrontFacing"); 794 break; 795 case SK_VERTEXID_BUILTIN: 796 this->write("gl_VertexID"); 797 break; 798 case SK_INSTANCEID_BUILTIN: 799 this->write("gl_InstanceID"); 800 break; 801 case SK_CLIPDISTANCE_BUILTIN: 802 this->write("gl_ClipDistance"); 803 break; 804 case SK_IN_BUILTIN: 805 this->write("gl_in"); 806 break; 807 case SK_INVOCATIONID_BUILTIN: 808 this->write("gl_InvocationID"); 809 break; 810 case SK_LASTFRAGCOLOR_BUILTIN: 811 this->write(fProgram.fSettings.fCaps->fbFetchColorName()); 812 break; 813 default: 814 this->write(ref.fVariable.fName); 815 } 816 } 817 818 void GLSLCodeGenerator::writeIndexExpression(const IndexExpression& expr) { 819 this->writeExpression(*expr.fBase, kPostfix_Precedence); 820 this->write("["); 821 this->writeExpression(*expr.fIndex, kTopLevel_Precedence); 822 this->write("]"); 823 } 824 825 bool is_sk_position(const FieldAccess& f) { 826 return "sk_Position" == f.fBase->fType.fields()[f.fFieldIndex].fName; 827 } 828 829 void GLSLCodeGenerator::writeFieldAccess(const FieldAccess& f) { 830 if (f.fOwnerKind == FieldAccess::kDefault_OwnerKind) { 831 this->writeExpression(*f.fBase, kPostfix_Precedence); 832 this->write("."); 833 } 834 switch (f.fBase->fType.fields()[f.fFieldIndex].fModifiers.fLayout.fBuiltin) { 835 case SK_CLIPDISTANCE_BUILTIN: 836 this->write("gl_ClipDistance"); 837 break; 838 default: 839 StringFragment name = f.fBase->fType.fields()[f.fFieldIndex].fName; 840 if (name == "sk_Position") { 841 this->write("gl_Position"); 842 } else if (name == "sk_PointSize") { 843 this->write("gl_PointSize"); 844 } else { 845 this->write(f.fBase->fType.fields()[f.fFieldIndex].fName); 846 } 847 } 848 } 849 850 void GLSLCodeGenerator::writeSwizzle(const Swizzle& swizzle) { 851 int last = swizzle.fComponents.back(); 852 if (last == SKSL_SWIZZLE_0 || last == SKSL_SWIZZLE_1) { 853 this->writeType(swizzle.fType); 854 this->write("("); 855 } 856 this->writeExpression(*swizzle.fBase, kPostfix_Precedence); 857 this->write("."); 858 for (int c : swizzle.fComponents) { 859 if (c >= 0) { 860 this->write(&("x\0y\0z\0w\0"[c * 2])); 861 } 862 } 863 if (last == SKSL_SWIZZLE_0) { 864 this->write(", 0)"); 865 } 866 else if (last == SKSL_SWIZZLE_1) { 867 this->write(", 1)"); 868 } 869 } 870 871 GLSLCodeGenerator::Precedence GLSLCodeGenerator::GetBinaryPrecedence(Token::Kind op) { 872 switch (op) { 873 case Token::STAR: // fall through 874 case Token::SLASH: // fall through 875 case Token::PERCENT: return GLSLCodeGenerator::kMultiplicative_Precedence; 876 case Token::PLUS: // fall through 877 case Token::MINUS: return GLSLCodeGenerator::kAdditive_Precedence; 878 case Token::SHL: // fall through 879 case Token::SHR: return GLSLCodeGenerator::kShift_Precedence; 880 case Token::LT: // fall through 881 case Token::GT: // fall through 882 case Token::LTEQ: // fall through 883 case Token::GTEQ: return GLSLCodeGenerator::kRelational_Precedence; 884 case Token::EQEQ: // fall through 885 case Token::NEQ: return GLSLCodeGenerator::kEquality_Precedence; 886 case Token::BITWISEAND: return GLSLCodeGenerator::kBitwiseAnd_Precedence; 887 case Token::BITWISEXOR: return GLSLCodeGenerator::kBitwiseXor_Precedence; 888 case Token::BITWISEOR: return GLSLCodeGenerator::kBitwiseOr_Precedence; 889 case Token::LOGICALAND: return GLSLCodeGenerator::kLogicalAnd_Precedence; 890 case Token::LOGICALXOR: return GLSLCodeGenerator::kLogicalXor_Precedence; 891 case Token::LOGICALOR: return GLSLCodeGenerator::kLogicalOr_Precedence; 892 case Token::EQ: // fall through 893 case Token::PLUSEQ: // fall through 894 case Token::MINUSEQ: // fall through 895 case Token::STAREQ: // fall through 896 case Token::SLASHEQ: // fall through 897 case Token::PERCENTEQ: // fall through 898 case Token::SHLEQ: // fall through 899 case Token::SHREQ: // fall through 900 case Token::LOGICALANDEQ: // fall through 901 case Token::LOGICALXOREQ: // fall through 902 case Token::LOGICALOREQ: // fall through 903 case Token::BITWISEANDEQ: // fall through 904 case Token::BITWISEXOREQ: // fall through 905 case Token::BITWISEOREQ: return GLSLCodeGenerator::kAssignment_Precedence; 906 case Token::COMMA: return GLSLCodeGenerator::kSequence_Precedence; 907 default: ABORT("unsupported binary operator"); 908 } 909 } 910 911 void GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b, 912 Precedence parentPrecedence) { 913 if (fProgram.fSettings.fCaps->unfoldShortCircuitAsTernary() && 914 (b.fOperator == Token::LOGICALAND || b.fOperator == Token::LOGICALOR)) { 915 this->writeShortCircuitWorkaroundExpression(b, parentPrecedence); 916 return; 917 } 918 919 Precedence precedence = GetBinaryPrecedence(b.fOperator); 920 if (precedence >= parentPrecedence) { 921 this->write("("); 922 } 923 bool positionWorkaround = fProgramKind == Program::Kind::kVertex_Kind && 924 Compiler::IsAssignment(b.fOperator) && 925 Expression::kFieldAccess_Kind == b.fLeft->fKind && 926 is_sk_position((FieldAccess&) *b.fLeft) && 927 !strstr(b.fRight->description().c_str(), "sk_RTAdjust") && 928 !fProgram.fSettings.fCaps->canUseFragCoord(); 929 if (positionWorkaround) { 930 this->write("sk_FragCoord_Workaround = ("); 931 } 932 this->writeExpression(*b.fLeft, precedence); 933 this->write(" "); 934 this->write(Compiler::OperatorName(b.fOperator)); 935 this->write(" "); 936 this->writeExpression(*b.fRight, precedence); 937 if (positionWorkaround) { 938 this->write(")"); 939 } 940 if (precedence >= parentPrecedence) { 941 this->write(")"); 942 } 943 } 944 945 void GLSLCodeGenerator::writeShortCircuitWorkaroundExpression(const BinaryExpression& b, 946 Precedence parentPrecedence) { 947 if (kTernary_Precedence >= parentPrecedence) { 948 this->write("("); 949 } 950 951 // Transform: 952 // a && b => a ? b : false 953 // a || b => a ? true : b 954 this->writeExpression(*b.fLeft, kTernary_Precedence); 955 this->write(" ? "); 956 if (b.fOperator == Token::LOGICALAND) { 957 this->writeExpression(*b.fRight, kTernary_Precedence); 958 } else { 959 BoolLiteral boolTrue(fContext, -1, true); 960 this->writeBoolLiteral(boolTrue); 961 } 962 this->write(" : "); 963 if (b.fOperator == Token::LOGICALAND) { 964 BoolLiteral boolFalse(fContext, -1, false); 965 this->writeBoolLiteral(boolFalse); 966 } else { 967 this->writeExpression(*b.fRight, kTernary_Precedence); 968 } 969 if (kTernary_Precedence >= parentPrecedence) { 970 this->write(")"); 971 } 972 } 973 974 void GLSLCodeGenerator::writeTernaryExpression(const TernaryExpression& t, 975 Precedence parentPrecedence) { 976 if (kTernary_Precedence >= parentPrecedence) { 977 this->write("("); 978 } 979 this->writeExpression(*t.fTest, kTernary_Precedence); 980 this->write(" ? "); 981 this->writeExpression(*t.fIfTrue, kTernary_Precedence); 982 this->write(" : "); 983 this->writeExpression(*t.fIfFalse, kTernary_Precedence); 984 if (kTernary_Precedence >= parentPrecedence) { 985 this->write(")"); 986 } 987 } 988 989 void GLSLCodeGenerator::writePrefixExpression(const PrefixExpression& p, 990 Precedence parentPrecedence) { 991 if (kPrefix_Precedence >= parentPrecedence) { 992 this->write("("); 993 } 994 this->write(Compiler::OperatorName(p.fOperator)); 995 this->writeExpression(*p.fOperand, kPrefix_Precedence); 996 if (kPrefix_Precedence >= parentPrecedence) { 997 this->write(")"); 998 } 999 } 1000 1001 void GLSLCodeGenerator::writePostfixExpression(const PostfixExpression& p, 1002 Precedence parentPrecedence) { 1003 if (kPostfix_Precedence >= parentPrecedence) { 1004 this->write("("); 1005 } 1006 this->writeExpression(*p.fOperand, kPostfix_Precedence); 1007 this->write(Compiler::OperatorName(p.fOperator)); 1008 if (kPostfix_Precedence >= parentPrecedence) { 1009 this->write(")"); 1010 } 1011 } 1012 1013 void GLSLCodeGenerator::writeBoolLiteral(const BoolLiteral& b) { 1014 this->write(b.fValue ? "true" : "false"); 1015 } 1016 1017 void GLSLCodeGenerator::writeIntLiteral(const IntLiteral& i) { 1018 if (i.fType == *fContext.fUInt_Type) { 1019 this->write(to_string(i.fValue & 0xffffffff) + "u"); 1020 } else if (i.fType == *fContext.fUShort_Type) { 1021 this->write(to_string(i.fValue & 0xffff) + "u"); 1022 } else if (i.fType == *fContext.fUByte_Type) { 1023 this->write(to_string(i.fValue & 0xff) + "u"); 1024 } else { 1025 this->write(to_string((int32_t) i.fValue)); 1026 } 1027 } 1028 1029 void GLSLCodeGenerator::writeFloatLiteral(const FloatLiteral& f) { 1030 this->write(to_string(f.fValue)); 1031 } 1032 1033 void GLSLCodeGenerator::writeSetting(const Setting& s) { 1034 ABORT("internal error; setting was not folded to a constant during compilation\n"); 1035 } 1036 1037 void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) { 1038 if (fProgramKind != Program::kPipelineStage_Kind) { 1039 this->writeTypePrecision(f.fDeclaration.fReturnType); 1040 this->writeType(f.fDeclaration.fReturnType); 1041 this->write(" " + f.fDeclaration.fName + "("); 1042 const char* separator = ""; 1043 for (const auto& param : f.fDeclaration.fParameters) { 1044 this->write(separator); 1045 separator = ", "; 1046 this->writeModifiers(param->fModifiers, false); 1047 std::vector<int> sizes; 1048 const Type* type = ¶m->fType; 1049 while (type->kind() == Type::kArray_Kind) { 1050 sizes.push_back(type->columns()); 1051 type = &type->componentType(); 1052 } 1053 this->writeTypePrecision(*type); 1054 this->writeType(*type); 1055 this->write(" " + param->fName); 1056 for (int s : sizes) { 1057 if (s <= 0) { 1058 this->write("[]"); 1059 } else { 1060 this->write("[" + to_string(s) + "]"); 1061 } 1062 } 1063 } 1064 this->writeLine(") {"); 1065 fIndentation++; 1066 } 1067 fFunctionHeader = ""; 1068 OutputStream* oldOut = fOut; 1069 StringStream buffer; 1070 fOut = &buffer; 1071 this->writeStatements(((Block&) *f.fBody).fStatements); 1072 if (fProgramKind != Program::kPipelineStage_Kind) { 1073 fIndentation--; 1074 this->writeLine("}"); 1075 } 1076 1077 fOut = oldOut; 1078 this->write(fFunctionHeader); 1079 this->write(buffer.str()); 1080 } 1081 1082 void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers, 1083 bool globalContext) { 1084 if (modifiers.fFlags & Modifiers::kFlat_Flag) { 1085 this->write("flat "); 1086 } 1087 if (modifiers.fFlags & Modifiers::kNoPerspective_Flag) { 1088 this->write("noperspective "); 1089 } 1090 String layout = modifiers.fLayout.description(); 1091 if (layout.size()) { 1092 this->write(layout + " "); 1093 } 1094 if (modifiers.fFlags & Modifiers::kReadOnly_Flag) { 1095 this->write("readonly "); 1096 } 1097 if (modifiers.fFlags & Modifiers::kWriteOnly_Flag) { 1098 this->write("writeonly "); 1099 } 1100 if (modifiers.fFlags & Modifiers::kCoherent_Flag) { 1101 this->write("coherent "); 1102 } 1103 if (modifiers.fFlags & Modifiers::kVolatile_Flag) { 1104 this->write("volatile "); 1105 } 1106 if (modifiers.fFlags & Modifiers::kRestrict_Flag) { 1107 this->write("restrict "); 1108 } 1109 if ((modifiers.fFlags & Modifiers::kIn_Flag) && 1110 (modifiers.fFlags & Modifiers::kOut_Flag)) { 1111 this->write("inout "); 1112 } else if (modifiers.fFlags & Modifiers::kIn_Flag) { 1113 if (globalContext && 1114 fProgram.fSettings.fCaps->generation() < GrGLSLGeneration::k130_GrGLSLGeneration) { 1115 this->write(fProgramKind == Program::kVertex_Kind ? "attribute " 1116 : "varying "); 1117 } else { 1118 this->write("in "); 1119 } 1120 } else if (modifiers.fFlags & Modifiers::kOut_Flag) { 1121 if (globalContext && 1122 fProgram.fSettings.fCaps->generation() < GrGLSLGeneration::k130_GrGLSLGeneration) { 1123 this->write("varying "); 1124 } else { 1125 this->write("out "); 1126 } 1127 } 1128 if (modifiers.fFlags & Modifiers::kUniform_Flag) { 1129 this->write("uniform "); 1130 } 1131 if (modifiers.fFlags & Modifiers::kConst_Flag) { 1132 this->write("const "); 1133 } 1134 if (modifiers.fFlags & Modifiers::kPLS_Flag) { 1135 this->write("__pixel_localEXT "); 1136 } 1137 if (modifiers.fFlags & Modifiers::kPLSIn_Flag) { 1138 this->write("__pixel_local_inEXT "); 1139 } 1140 if (modifiers.fFlags & Modifiers::kPLSOut_Flag) { 1141 this->write("__pixel_local_outEXT "); 1142 } 1143 switch (modifiers.fLayout.fFormat) { 1144 case Layout::Format::kUnspecified: 1145 break; 1146 case Layout::Format::kRGBA32F: // fall through 1147 case Layout::Format::kR32F: 1148 this->write("highp "); 1149 break; 1150 case Layout::Format::kRGBA16F: // fall through 1151 case Layout::Format::kR16F: // fall through 1152 case Layout::Format::kRG16F: 1153 this->write("mediump "); 1154 break; 1155 case Layout::Format::kRGBA8: // fall through 1156 case Layout::Format::kR8: // fall through 1157 case Layout::Format::kRGBA8I: // fall through 1158 case Layout::Format::kR8I: 1159 this->write("lowp "); 1160 break; 1161 } 1162 } 1163 1164 void GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) { 1165 if (intf.fTypeName == "sk_PerVertex") { 1166 return; 1167 } 1168 this->writeModifiers(intf.fVariable.fModifiers, true); 1169 this->writeLine(intf.fTypeName + " {"); 1170 fIndentation++; 1171 const Type* structType = &intf.fVariable.fType; 1172 while (structType->kind() == Type::kArray_Kind) { 1173 structType = &structType->componentType(); 1174 } 1175 for (const auto& f : structType->fields()) { 1176 this->writeModifiers(f.fModifiers, false); 1177 this->writeTypePrecision(*f.fType); 1178 this->writeType(*f.fType); 1179 this->writeLine(" " + f.fName + ";"); 1180 } 1181 fIndentation--; 1182 this->write("}"); 1183 if (intf.fInstanceName.size()) { 1184 this->write(" "); 1185 this->write(intf.fInstanceName); 1186 for (const auto& size : intf.fSizes) { 1187 this->write("["); 1188 if (size) { 1189 this->writeExpression(*size, kTopLevel_Precedence); 1190 } 1191 this->write("]"); 1192 } 1193 } 1194 this->writeLine(";"); 1195 } 1196 1197 void GLSLCodeGenerator::writeVarInitializer(const Variable& var, const Expression& value) { 1198 this->writeExpression(value, kTopLevel_Precedence); 1199 } 1200 1201 const char* GLSLCodeGenerator::getTypePrecision(const Type& type) { 1202 if (usesPrecisionModifiers()) { 1203 switch (type.kind()) { 1204 case Type::kScalar_Kind: 1205 if (type == *fContext.fShort_Type || type == *fContext.fUShort_Type || 1206 type == *fContext.fByte_Type || type == *fContext.fUByte_Type) { 1207 if (fProgram.fSettings.fForceHighPrecision || 1208 fProgram.fSettings.fCaps->incompleteShortIntPrecision()) { 1209 return "highp "; 1210 } 1211 return "mediump "; 1212 } 1213 if (type == *fContext.fHalf_Type) { 1214 return fProgram.fSettings.fForceHighPrecision ? "highp " : "mediump "; 1215 } 1216 if (type == *fContext.fFloat_Type || type == *fContext.fInt_Type || 1217 type == *fContext.fUInt_Type) { 1218 return "highp "; 1219 } 1220 return ""; 1221 case Type::kVector_Kind: // fall through 1222 case Type::kMatrix_Kind: 1223 return this->getTypePrecision(type.componentType()); 1224 default: 1225 break; 1226 } 1227 } 1228 return ""; 1229 } 1230 1231 void GLSLCodeGenerator::writeTypePrecision(const Type& type) { 1232 this->write(this->getTypePrecision(type)); 1233 } 1234 1235 void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, bool global) { 1236 if (!decl.fVars.size()) { 1237 return; 1238 } 1239 bool wroteType = false; 1240 for (const auto& stmt : decl.fVars) { 1241 VarDeclaration& var = (VarDeclaration&) *stmt; 1242 if (wroteType) { 1243 this->write(", "); 1244 } else { 1245 this->writeModifiers(var.fVar->fModifiers, global); 1246 this->writeTypePrecision(decl.fBaseType); 1247 this->writeType(decl.fBaseType); 1248 this->write(" "); 1249 wroteType = true; 1250 } 1251 this->write(var.fVar->fName); 1252 for (const auto& size : var.fSizes) { 1253 this->write("["); 1254 if (size) { 1255 this->writeExpression(*size, kTopLevel_Precedence); 1256 } 1257 this->write("]"); 1258 } 1259 if (var.fValue) { 1260 this->write(" = "); 1261 this->writeVarInitializer(*var.fVar, *var.fValue); 1262 } 1263 if (!fFoundImageDecl && var.fVar->fType == *fContext.fImage2D_Type) { 1264 if (fProgram.fSettings.fCaps->imageLoadStoreExtensionString()) { 1265 this->writeExtension(fProgram.fSettings.fCaps->imageLoadStoreExtensionString()); 1266 } 1267 fFoundImageDecl = true; 1268 } 1269 if (!fFoundExternalSamplerDecl && var.fVar->fType == *fContext.fSamplerExternalOES_Type) { 1270 if (fProgram.fSettings.fCaps->externalTextureExtensionString()) { 1271 this->writeExtension(fProgram.fSettings.fCaps->externalTextureExtensionString()); 1272 } 1273 if (fProgram.fSettings.fCaps->secondExternalTextureExtensionString()) { 1274 this->writeExtension( 1275 fProgram.fSettings.fCaps->secondExternalTextureExtensionString()); 1276 } 1277 fFoundExternalSamplerDecl = true; 1278 } 1279 } 1280 if (wroteType) { 1281 this->write(";"); 1282 } 1283 } 1284 1285 void GLSLCodeGenerator::writeStatement(const Statement& s) { 1286 switch (s.fKind) { 1287 case Statement::kBlock_Kind: 1288 this->writeBlock((Block&) s); 1289 break; 1290 case Statement::kExpression_Kind: 1291 this->writeExpression(*((ExpressionStatement&) s).fExpression, kTopLevel_Precedence); 1292 this->write(";"); 1293 break; 1294 case Statement::kReturn_Kind: 1295 this->writeReturnStatement((ReturnStatement&) s); 1296 break; 1297 case Statement::kVarDeclarations_Kind: 1298 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration, false); 1299 break; 1300 case Statement::kIf_Kind: 1301 this->writeIfStatement((IfStatement&) s); 1302 break; 1303 case Statement::kFor_Kind: 1304 this->writeForStatement((ForStatement&) s); 1305 break; 1306 case Statement::kWhile_Kind: 1307 this->writeWhileStatement((WhileStatement&) s); 1308 break; 1309 case Statement::kDo_Kind: 1310 this->writeDoStatement((DoStatement&) s); 1311 break; 1312 case Statement::kSwitch_Kind: 1313 this->writeSwitchStatement((SwitchStatement&) s); 1314 break; 1315 case Statement::kBreak_Kind: 1316 this->write("break;"); 1317 break; 1318 case Statement::kContinue_Kind: 1319 this->write("continue;"); 1320 break; 1321 case Statement::kDiscard_Kind: 1322 this->write("discard;"); 1323 break; 1324 case Statement::kNop_Kind: 1325 this->write(";"); 1326 break; 1327 default: 1328 ABORT("unsupported statement: %s", s.description().c_str()); 1329 } 1330 } 1331 1332 void GLSLCodeGenerator::writeStatements(const std::vector<std::unique_ptr<Statement>>& statements) { 1333 for (const auto& s : statements) { 1334 if (!s->isEmpty()) { 1335 this->writeStatement(*s); 1336 this->writeLine(); 1337 } 1338 } 1339 } 1340 1341 void GLSLCodeGenerator::writeBlock(const Block& b) { 1342 this->writeLine("{"); 1343 fIndentation++; 1344 this->writeStatements(b.fStatements); 1345 fIndentation--; 1346 this->write("}"); 1347 } 1348 1349 void GLSLCodeGenerator::writeIfStatement(const IfStatement& stmt) { 1350 this->write("if ("); 1351 this->writeExpression(*stmt.fTest, kTopLevel_Precedence); 1352 this->write(") "); 1353 this->writeStatement(*stmt.fIfTrue); 1354 if (stmt.fIfFalse) { 1355 this->write(" else "); 1356 this->writeStatement(*stmt.fIfFalse); 1357 } 1358 } 1359 1360 void GLSLCodeGenerator::writeForStatement(const ForStatement& f) { 1361 this->write("for ("); 1362 if (f.fInitializer && !f.fInitializer->isEmpty()) { 1363 this->writeStatement(*f.fInitializer); 1364 } else { 1365 this->write("; "); 1366 } 1367 if (f.fTest) { 1368 if (fProgram.fSettings.fCaps->addAndTrueToLoopCondition()) { 1369 std::unique_ptr<Expression> and_true(new BinaryExpression( 1370 -1, f.fTest->clone(), Token::LOGICALAND, 1371 std::unique_ptr<BoolLiteral>(new BoolLiteral(fContext, -1, 1372 true)), 1373 *fContext.fBool_Type)); 1374 this->writeExpression(*and_true, kTopLevel_Precedence); 1375 } else { 1376 this->writeExpression(*f.fTest, kTopLevel_Precedence); 1377 } 1378 } 1379 this->write("; "); 1380 if (f.fNext) { 1381 this->writeExpression(*f.fNext, kTopLevel_Precedence); 1382 } 1383 this->write(") "); 1384 this->writeStatement(*f.fStatement); 1385 } 1386 1387 void GLSLCodeGenerator::writeWhileStatement(const WhileStatement& w) { 1388 this->write("while ("); 1389 this->writeExpression(*w.fTest, kTopLevel_Precedence); 1390 this->write(") "); 1391 this->writeStatement(*w.fStatement); 1392 } 1393 1394 void GLSLCodeGenerator::writeDoStatement(const DoStatement& d) { 1395 if (!fProgram.fSettings.fCaps->rewriteDoWhileLoops()) { 1396 this->write("do "); 1397 this->writeStatement(*d.fStatement); 1398 this->write(" while ("); 1399 this->writeExpression(*d.fTest, kTopLevel_Precedence); 1400 this->write(");"); 1401 return; 1402 } 1403 1404 // Otherwise, do the do while loop workaround, to rewrite loops of the form: 1405 // do { 1406 // CODE; 1407 // } while (CONDITION) 1408 // 1409 // to loops of the form 1410 // bool temp = false; 1411 // while (true) { 1412 // if (temp) { 1413 // if (!CONDITION) { 1414 // break; 1415 // } 1416 // } 1417 // temp = true; 1418 // CODE; 1419 // } 1420 String tmpVar = "_tmpLoopSeenOnce" + to_string(fVarCount++); 1421 this->write("bool "); 1422 this->write(tmpVar); 1423 this->writeLine(" = false;"); 1424 this->writeLine("while (true) {"); 1425 fIndentation++; 1426 this->write("if ("); 1427 this->write(tmpVar); 1428 this->writeLine(") {"); 1429 fIndentation++; 1430 this->write("if (!"); 1431 this->writeExpression(*d.fTest, kPrefix_Precedence); 1432 this->writeLine(") {"); 1433 fIndentation++; 1434 this->writeLine("break;"); 1435 fIndentation--; 1436 this->writeLine("}"); 1437 fIndentation--; 1438 this->writeLine("}"); 1439 this->write(tmpVar); 1440 this->writeLine(" = true;"); 1441 this->writeStatement(*d.fStatement); 1442 this->writeLine(); 1443 fIndentation--; 1444 this->write("}"); 1445 } 1446 1447 void GLSLCodeGenerator::writeSwitchStatement(const SwitchStatement& s) { 1448 this->write("switch ("); 1449 this->writeExpression(*s.fValue, kTopLevel_Precedence); 1450 this->writeLine(") {"); 1451 fIndentation++; 1452 for (const auto& c : s.fCases) { 1453 if (c->fValue) { 1454 this->write("case "); 1455 this->writeExpression(*c->fValue, kTopLevel_Precedence); 1456 this->writeLine(":"); 1457 } else { 1458 this->writeLine("default:"); 1459 } 1460 fIndentation++; 1461 for (const auto& stmt : c->fStatements) { 1462 this->writeStatement(*stmt); 1463 this->writeLine(); 1464 } 1465 fIndentation--; 1466 } 1467 fIndentation--; 1468 this->write("}"); 1469 } 1470 1471 void GLSLCodeGenerator::writeReturnStatement(const ReturnStatement& r) { 1472 this->write("return"); 1473 if (r.fExpression) { 1474 this->write(" "); 1475 this->writeExpression(*r.fExpression, kTopLevel_Precedence); 1476 } 1477 this->write(";"); 1478 } 1479 1480 void GLSLCodeGenerator::writeHeader() { 1481 this->write(fProgram.fSettings.fCaps->versionDeclString()); 1482 this->writeLine(); 1483 } 1484 1485 void GLSLCodeGenerator::writeProgramElement(const ProgramElement& e) { 1486 switch (e.fKind) { 1487 case ProgramElement::kExtension_Kind: 1488 this->writeExtension(((Extension&) e).fName); 1489 break; 1490 case ProgramElement::kVar_Kind: { 1491 VarDeclarations& decl = (VarDeclarations&) e; 1492 if (decl.fVars.size() > 0) { 1493 int builtin = ((VarDeclaration&) *decl.fVars[0]).fVar->fModifiers.fLayout.fBuiltin; 1494 if (builtin == -1) { 1495 // normal var 1496 this->writeVarDeclarations(decl, true); 1497 this->writeLine(); 1498 } else if (builtin == SK_FRAGCOLOR_BUILTIN && 1499 fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput() && 1500 ((VarDeclaration&) *decl.fVars[0]).fVar->fWriteCount) { 1501 if (fProgram.fSettings.fFragColorIsInOut) { 1502 this->write("inout "); 1503 } else { 1504 this->write("out "); 1505 } 1506 if (usesPrecisionModifiers()) { 1507 this->write("mediump "); 1508 } 1509 this->writeLine("vec4 sk_FragColor;"); 1510 } 1511 } 1512 break; 1513 } 1514 case ProgramElement::kInterfaceBlock_Kind: 1515 this->writeInterfaceBlock((InterfaceBlock&) e); 1516 break; 1517 case ProgramElement::kFunction_Kind: 1518 this->writeFunction((FunctionDefinition&) e); 1519 break; 1520 case ProgramElement::kModifiers_Kind: { 1521 const Modifiers& modifiers = ((ModifiersDeclaration&) e).fModifiers; 1522 if (!fFoundGSInvocations && modifiers.fLayout.fInvocations >= 0) { 1523 if (fProgram.fSettings.fCaps->gsInvocationsExtensionString()) { 1524 this->writeExtension(fProgram.fSettings.fCaps->gsInvocationsExtensionString()); 1525 } 1526 fFoundGSInvocations = true; 1527 } 1528 this->writeModifiers(modifiers, true); 1529 this->writeLine(";"); 1530 break; 1531 } 1532 case ProgramElement::kEnum_Kind: 1533 break; 1534 default: 1535 printf("%s\n", e.description().c_str()); 1536 ABORT("unsupported program element"); 1537 } 1538 } 1539 1540 void GLSLCodeGenerator::writeInputVars() { 1541 if (fProgram.fInputs.fRTWidth) { 1542 const char* precision = usesPrecisionModifiers() ? "highp " : ""; 1543 fGlobals.writeText("uniform "); 1544 fGlobals.writeText(precision); 1545 fGlobals.writeText("float " SKSL_RTWIDTH_NAME ";\n"); 1546 } 1547 if (fProgram.fInputs.fRTHeight) { 1548 const char* precision = usesPrecisionModifiers() ? "highp " : ""; 1549 fGlobals.writeText("uniform "); 1550 fGlobals.writeText(precision); 1551 fGlobals.writeText("float " SKSL_RTHEIGHT_NAME ";\n"); 1552 } 1553 } 1554 1555 bool GLSLCodeGenerator::generateCode() { 1556 if (fProgramKind != Program::kPipelineStage_Kind) { 1557 this->writeHeader(); 1558 } 1559 if (Program::kGeometry_Kind == fProgramKind && 1560 fProgram.fSettings.fCaps->geometryShaderExtensionString()) { 1561 this->writeExtension(fProgram.fSettings.fCaps->geometryShaderExtensionString()); 1562 } 1563 OutputStream* rawOut = fOut; 1564 StringStream body; 1565 fOut = &body; 1566 for (const auto& e : fProgram) { 1567 this->writeProgramElement(e); 1568 } 1569 fOut = rawOut; 1570 1571 write_stringstream(fExtensions, *rawOut); 1572 this->writeInputVars(); 1573 write_stringstream(fGlobals, *rawOut); 1574 1575 if (!fProgram.fSettings.fCaps->canUseFragCoord()) { 1576 Layout layout; 1577 switch (fProgram.fKind) { 1578 case Program::kVertex_Kind: { 1579 Modifiers modifiers(layout, Modifiers::kOut_Flag); 1580 this->writeModifiers(modifiers, true); 1581 if (this->usesPrecisionModifiers()) { 1582 this->write("highp "); 1583 } 1584 this->write("vec4 sk_FragCoord_Workaround;\n"); 1585 break; 1586 } 1587 case Program::kFragment_Kind: { 1588 Modifiers modifiers(layout, Modifiers::kIn_Flag); 1589 this->writeModifiers(modifiers, true); 1590 if (this->usesPrecisionModifiers()) { 1591 this->write("highp "); 1592 } 1593 this->write("vec4 sk_FragCoord_Workaround;\n"); 1594 break; 1595 } 1596 default: 1597 break; 1598 } 1599 } 1600 1601 if (this->usesPrecisionModifiers()) { 1602 this->writeLine("precision mediump float;"); 1603 } 1604 write_stringstream(fExtraFunctions, *rawOut); 1605 write_stringstream(body, *rawOut); 1606 return true; 1607 } 1608 1609 } 1610