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