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 bool isTextureFunctionWithBias = false; 509 if (c.fFunction.fName == "texture" && c.fFunction.fBuiltin) { 510 const char* dim = ""; 511 bool proj = false; 512 switch (c.fArguments[0]->fType.dimensions()) { 513 case SpvDim1D: 514 dim = "1D"; 515 isTextureFunctionWithBias = true; 516 if (c.fArguments[1]->fType == *fContext.fFloat_Type) { 517 proj = false; 518 } else { 519 ASSERT(c.fArguments[1]->fType == *fContext.fFloat2_Type); 520 proj = true; 521 } 522 break; 523 case SpvDim2D: 524 dim = "2D"; 525 if (c.fArguments[0]->fType != *fContext.fSamplerExternalOES_Type) { 526 isTextureFunctionWithBias = true; 527 } 528 if (c.fArguments[1]->fType == *fContext.fFloat2_Type) { 529 proj = false; 530 } else { 531 ASSERT(c.fArguments[1]->fType == *fContext.fFloat3_Type); 532 proj = true; 533 } 534 break; 535 case SpvDim3D: 536 dim = "3D"; 537 isTextureFunctionWithBias = true; 538 if (c.fArguments[1]->fType == *fContext.fFloat3_Type) { 539 proj = false; 540 } else { 541 ASSERT(c.fArguments[1]->fType == *fContext.fFloat4_Type); 542 proj = true; 543 } 544 break; 545 case SpvDimCube: 546 dim = "Cube"; 547 isTextureFunctionWithBias = true; 548 proj = false; 549 break; 550 case SpvDimRect: 551 dim = "Rect"; 552 proj = false; 553 break; 554 case SpvDimBuffer: 555 ASSERT(false); // doesn't exist 556 dim = "Buffer"; 557 proj = false; 558 break; 559 case SpvDimSubpassData: 560 ASSERT(false); // doesn't exist 561 dim = "SubpassData"; 562 proj = false; 563 break; 564 } 565 this->write("texture"); 566 if (fProgram.fSettings.fCaps->generation() < k130_GrGLSLGeneration) { 567 this->write(dim); 568 } 569 if (proj) { 570 this->write("Proj"); 571 } 572 573 } else { 574 this->write(c.fFunction.fName); 575 } 576 this->write("("); 577 const char* separator = ""; 578 for (const auto& arg : c.fArguments) { 579 this->write(separator); 580 separator = ", "; 581 this->writeExpression(*arg, kSequence_Precedence); 582 } 583 if (fProgram.fSettings.fSharpenTextures && isTextureFunctionWithBias) { 584 this->write(", -0.5"); 585 } 586 this->write(")"); 587} 588 589void GLSLCodeGenerator::writeConstructor(const Constructor& c, Precedence parentPrecedence) { 590 if (c.fArguments.size() == 1 && 591 this->getTypeName(c.fType) == this->getTypeName(c.fArguments[0]->fType)) { 592 // in cases like half(float), they're different types as far as SkSL is concerned but the 593 // same type as far as GLSL is concerned. We avoid a redundant float(float) by just writing 594 // out the inner expression here. 595 this->writeExpression(*c.fArguments[0], parentPrecedence); 596 return; 597 } 598 this->writeType(c.fType); 599 this->write("("); 600 const char* separator = ""; 601 for (const auto& arg : c.fArguments) { 602 this->write(separator); 603 separator = ", "; 604 this->writeExpression(*arg, kSequence_Precedence); 605 } 606 this->write(")"); 607} 608 609void GLSLCodeGenerator::writeFragCoord() { 610 if (!fProgram.fSettings.fCaps->canUseFragCoord()) { 611 if (!fSetupFragCoordWorkaround) { 612 const char* precision = usesPrecisionModifiers() ? "highp " : ""; 613 fFunctionHeader += precision; 614 fFunctionHeader += " float sk_FragCoord_InvW = 1. / sk_FragCoord_Workaround.w;\n"; 615 fFunctionHeader += precision; 616 fFunctionHeader += " vec4 sk_FragCoord_Resolved = " 617 "vec4(sk_FragCoord_Workaround.xyz * sk_FragCoord_InvW, sk_FragCoord_InvW);\n"; 618 // Ensure that we get exact .5 values for x and y. 619 fFunctionHeader += " sk_FragCoord_Resolved.xy = floor(sk_FragCoord_Resolved.xy) + " 620 "vec2(.5);\n"; 621 fSetupFragCoordWorkaround = true; 622 } 623 this->write("sk_FragCoord_Resolved"); 624 return; 625 } 626 627 // We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers 628 // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the 629 // declaration varies in earlier GLSL specs. So it is simpler to omit it. 630 if (!fProgram.fSettings.fFlipY) { 631 this->write("gl_FragCoord"); 632 } else if (const char* extension = 633 fProgram.fSettings.fCaps->fragCoordConventionsExtensionString()) { 634 if (!fSetupFragPositionGlobal) { 635 if (fProgram.fSettings.fCaps->generation() < k150_GrGLSLGeneration) { 636 fHeader.writeText("#extension "); 637 fHeader.writeText(extension); 638 fHeader.writeText(" : require\n"); 639 } 640 fHeader.writeText("layout(origin_upper_left) in vec4 gl_FragCoord;\n"); 641 fSetupFragPositionGlobal = true; 642 } 643 this->write("gl_FragCoord"); 644 } else { 645 if (!fSetupFragPositionGlobal) { 646 // The Adreno compiler seems to be very touchy about access to "gl_FragCoord". 647 // Accessing glFragCoord.zw can cause a program to fail to link. Additionally, 648 // depending on the surrounding code, accessing .xy with a uniform involved can 649 // do the same thing. Copying gl_FragCoord.xy into a temp float2 beforehand 650 // (and only accessing .xy) seems to "fix" things. 651 const char* precision = usesPrecisionModifiers() ? "highp " : ""; 652 fHeader.writeText("uniform "); 653 fHeader.writeText(precision); 654 fHeader.writeText("float " SKSL_RTHEIGHT_NAME ";\n"); 655 fSetupFragPositionGlobal = true; 656 } 657 if (!fSetupFragPositionLocal) { 658 const char* precision = usesPrecisionModifiers() ? "highp " : ""; 659 fFunctionHeader += precision; 660 fFunctionHeader += " vec2 _sktmpCoord = gl_FragCoord.xy;\n"; 661 fFunctionHeader += precision; 662 fFunctionHeader += " vec4 sk_FragCoord = vec4(_sktmpCoord.x, " SKSL_RTHEIGHT_NAME 663 " - _sktmpCoord.y, 1.0, 1.0);\n"; 664 fSetupFragPositionLocal = true; 665 } 666 this->write("sk_FragCoord"); 667 } 668} 669 670void GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) { 671 switch (ref.fVariable.fModifiers.fLayout.fBuiltin) { 672 case SK_FRAGCOLOR_BUILTIN: 673 if (fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput()) { 674 this->write("sk_FragColor"); 675 } else { 676 this->write("gl_FragColor"); 677 } 678 break; 679 case SK_FRAGCOORD_BUILTIN: 680 this->writeFragCoord(); 681 break; 682 case SK_VERTEXID_BUILTIN: 683 this->write("gl_VertexID"); 684 break; 685 case SK_INSTANCEID_BUILTIN: 686 this->write("gl_InstanceID"); 687 break; 688 case SK_CLIPDISTANCE_BUILTIN: 689 this->write("gl_ClipDistance"); 690 break; 691 case SK_IN_BUILTIN: 692 this->write("gl_in"); 693 break; 694 case SK_INVOCATIONID_BUILTIN: 695 this->write("gl_InvocationID"); 696 break; 697 default: 698 this->write(ref.fVariable.fName); 699 } 700} 701 702void GLSLCodeGenerator::writeIndexExpression(const IndexExpression& expr) { 703 this->writeExpression(*expr.fBase, kPostfix_Precedence); 704 this->write("["); 705 this->writeExpression(*expr.fIndex, kTopLevel_Precedence); 706 this->write("]"); 707} 708 709bool is_sk_position(const FieldAccess& f) { 710 return "sk_Position" == f.fBase->fType.fields()[f.fFieldIndex].fName; 711} 712 713void GLSLCodeGenerator::writeFieldAccess(const FieldAccess& f) { 714 if (f.fOwnerKind == FieldAccess::kDefault_OwnerKind) { 715 this->writeExpression(*f.fBase, kPostfix_Precedence); 716 this->write("."); 717 } 718 switch (f.fBase->fType.fields()[f.fFieldIndex].fModifiers.fLayout.fBuiltin) { 719 case SK_CLIPDISTANCE_BUILTIN: 720 this->write("gl_ClipDistance"); 721 break; 722 default: 723 StringFragment name = f.fBase->fType.fields()[f.fFieldIndex].fName; 724 if (name == "sk_Position") { 725 this->write("gl_Position"); 726 } else if (name == "sk_PointSize") { 727 this->write("gl_PointSize"); 728 } else { 729 this->write(f.fBase->fType.fields()[f.fFieldIndex].fName); 730 } 731 } 732} 733 734void GLSLCodeGenerator::writeSwizzle(const Swizzle& swizzle) { 735 this->writeExpression(*swizzle.fBase, kPostfix_Precedence); 736 this->write("."); 737 for (int c : swizzle.fComponents) { 738 this->write(&("x\0y\0z\0w\0"[c * 2])); 739 } 740} 741 742GLSLCodeGenerator::Precedence GLSLCodeGenerator::GetBinaryPrecedence(Token::Kind op) { 743 switch (op) { 744 case Token::STAR: // fall through 745 case Token::SLASH: // fall through 746 case Token::PERCENT: return GLSLCodeGenerator::kMultiplicative_Precedence; 747 case Token::PLUS: // fall through 748 case Token::MINUS: return GLSLCodeGenerator::kAdditive_Precedence; 749 case Token::SHL: // fall through 750 case Token::SHR: return GLSLCodeGenerator::kShift_Precedence; 751 case Token::LT: // fall through 752 case Token::GT: // fall through 753 case Token::LTEQ: // fall through 754 case Token::GTEQ: return GLSLCodeGenerator::kRelational_Precedence; 755 case Token::EQEQ: // fall through 756 case Token::NEQ: return GLSLCodeGenerator::kEquality_Precedence; 757 case Token::BITWISEAND: return GLSLCodeGenerator::kBitwiseAnd_Precedence; 758 case Token::BITWISEXOR: return GLSLCodeGenerator::kBitwiseXor_Precedence; 759 case Token::BITWISEOR: return GLSLCodeGenerator::kBitwiseOr_Precedence; 760 case Token::LOGICALAND: return GLSLCodeGenerator::kLogicalAnd_Precedence; 761 case Token::LOGICALXOR: return GLSLCodeGenerator::kLogicalXor_Precedence; 762 case Token::LOGICALOR: return GLSLCodeGenerator::kLogicalOr_Precedence; 763 case Token::EQ: // fall through 764 case Token::PLUSEQ: // fall through 765 case Token::MINUSEQ: // fall through 766 case Token::STAREQ: // fall through 767 case Token::SLASHEQ: // fall through 768 case Token::PERCENTEQ: // fall through 769 case Token::SHLEQ: // fall through 770 case Token::SHREQ: // fall through 771 case Token::LOGICALANDEQ: // fall through 772 case Token::LOGICALXOREQ: // fall through 773 case Token::LOGICALOREQ: // fall through 774 case Token::BITWISEANDEQ: // fall through 775 case Token::BITWISEXOREQ: // fall through 776 case Token::BITWISEOREQ: return GLSLCodeGenerator::kAssignment_Precedence; 777 case Token::COMMA: return GLSLCodeGenerator::kSequence_Precedence; 778 default: ABORT("unsupported binary operator"); 779 } 780} 781 782void GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b, 783 Precedence parentPrecedence) { 784 Precedence precedence = GetBinaryPrecedence(b.fOperator); 785 if (precedence >= parentPrecedence) { 786 this->write("("); 787 } 788 bool positionWorkaround = Compiler::IsAssignment(b.fOperator) && 789 Expression::kFieldAccess_Kind == b.fLeft->fKind && 790 is_sk_position((FieldAccess&) *b.fLeft) && 791 !strstr(b.fRight->description().c_str(), "sk_RTAdjust") && 792 !fProgram.fSettings.fCaps->canUseFragCoord(); 793 if (positionWorkaround) { 794 this->write("sk_FragCoord_Workaround = ("); 795 } 796 this->writeExpression(*b.fLeft, precedence); 797 this->write(" "); 798 this->write(Compiler::OperatorName(b.fOperator)); 799 this->write(" "); 800 this->writeExpression(*b.fRight, precedence); 801 if (positionWorkaround) { 802 this->write(")"); 803 } 804 if (precedence >= parentPrecedence) { 805 this->write(")"); 806 } 807} 808 809void GLSLCodeGenerator::writeTernaryExpression(const TernaryExpression& t, 810 Precedence parentPrecedence) { 811 if (kTernary_Precedence >= parentPrecedence) { 812 this->write("("); 813 } 814 this->writeExpression(*t.fTest, kTernary_Precedence); 815 this->write(" ? "); 816 this->writeExpression(*t.fIfTrue, kTernary_Precedence); 817 this->write(" : "); 818 this->writeExpression(*t.fIfFalse, kTernary_Precedence); 819 if (kTernary_Precedence >= parentPrecedence) { 820 this->write(")"); 821 } 822} 823 824void GLSLCodeGenerator::writePrefixExpression(const PrefixExpression& p, 825 Precedence parentPrecedence) { 826 if (kPrefix_Precedence >= parentPrecedence) { 827 this->write("("); 828 } 829 this->write(Compiler::OperatorName(p.fOperator)); 830 this->writeExpression(*p.fOperand, kPrefix_Precedence); 831 if (kPrefix_Precedence >= parentPrecedence) { 832 this->write(")"); 833 } 834} 835 836void GLSLCodeGenerator::writePostfixExpression(const PostfixExpression& p, 837 Precedence parentPrecedence) { 838 if (kPostfix_Precedence >= parentPrecedence) { 839 this->write("("); 840 } 841 this->writeExpression(*p.fOperand, kPostfix_Precedence); 842 this->write(Compiler::OperatorName(p.fOperator)); 843 if (kPostfix_Precedence >= parentPrecedence) { 844 this->write(")"); 845 } 846} 847 848void GLSLCodeGenerator::writeBoolLiteral(const BoolLiteral& b) { 849 this->write(b.fValue ? "true" : "false"); 850} 851 852void GLSLCodeGenerator::writeIntLiteral(const IntLiteral& i) { 853 if (i.fType == *fContext.fUInt_Type) { 854 this->write(to_string(i.fValue & 0xffffffff) + "u"); 855 } else if (i.fType == *fContext.fUShort_Type) { 856 this->write(to_string(i.fValue & 0xffff) + "u"); 857 } else { 858 this->write(to_string((int32_t) i.fValue)); 859 } 860} 861 862void GLSLCodeGenerator::writeFloatLiteral(const FloatLiteral& f) { 863 this->write(to_string(f.fValue)); 864} 865 866void GLSLCodeGenerator::writeSetting(const Setting& s) { 867 ABORT("internal error; setting was not folded to a constant during compilation\n"); 868} 869 870void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) { 871 this->writeTypePrecision(f.fDeclaration.fReturnType); 872 this->writeType(f.fDeclaration.fReturnType); 873 this->write(" " + f.fDeclaration.fName + "("); 874 const char* separator = ""; 875 for (const auto& param : f.fDeclaration.fParameters) { 876 this->write(separator); 877 separator = ", "; 878 this->writeModifiers(param->fModifiers, false); 879 std::vector<int> sizes; 880 const Type* type = ¶m->fType; 881 while (type->kind() == Type::kArray_Kind) { 882 sizes.push_back(type->columns()); 883 type = &type->componentType(); 884 } 885 this->writeTypePrecision(*type); 886 this->writeType(*type); 887 this->write(" " + param->fName); 888 for (int s : sizes) { 889 if (s <= 0) { 890 this->write("[]"); 891 } else { 892 this->write("[" + to_string(s) + "]"); 893 } 894 } 895 } 896 this->writeLine(") {"); 897 898 fFunctionHeader = ""; 899 OutputStream* oldOut = fOut; 900 StringStream buffer; 901 fOut = &buffer; 902 fIndentation++; 903 this->writeStatements(((Block&) *f.fBody).fStatements); 904 fIndentation--; 905 this->writeLine("}"); 906 907 fOut = oldOut; 908 this->write(fFunctionHeader); 909 this->write(buffer.str()); 910} 911 912void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers, 913 bool globalContext) { 914 if (modifiers.fFlags & Modifiers::kFlat_Flag) { 915 this->write("flat "); 916 } 917 if (modifiers.fFlags & Modifiers::kNoPerspective_Flag) { 918 this->write("noperspective "); 919 } 920 String layout = modifiers.fLayout.description(); 921 if (layout.size()) { 922 this->write(layout + " "); 923 } 924 if (modifiers.fFlags & Modifiers::kReadOnly_Flag) { 925 this->write("readonly "); 926 } 927 if (modifiers.fFlags & Modifiers::kWriteOnly_Flag) { 928 this->write("writeonly "); 929 } 930 if (modifiers.fFlags & Modifiers::kCoherent_Flag) { 931 this->write("coherent "); 932 } 933 if (modifiers.fFlags & Modifiers::kVolatile_Flag) { 934 this->write("volatile "); 935 } 936 if (modifiers.fFlags & Modifiers::kRestrict_Flag) { 937 this->write("restrict "); 938 } 939 if ((modifiers.fFlags & Modifiers::kIn_Flag) && 940 (modifiers.fFlags & Modifiers::kOut_Flag)) { 941 this->write("inout "); 942 } else if (modifiers.fFlags & Modifiers::kIn_Flag) { 943 if (globalContext && 944 fProgram.fSettings.fCaps->generation() < GrGLSLGeneration::k130_GrGLSLGeneration) { 945 this->write(fProgramKind == Program::kVertex_Kind ? "attribute " 946 : "varying "); 947 } else { 948 this->write("in "); 949 } 950 } else if (modifiers.fFlags & Modifiers::kOut_Flag) { 951 if (globalContext && 952 fProgram.fSettings.fCaps->generation() < GrGLSLGeneration::k130_GrGLSLGeneration) { 953 this->write("varying "); 954 } else { 955 this->write("out "); 956 } 957 } 958 if (modifiers.fFlags & Modifiers::kUniform_Flag) { 959 this->write("uniform "); 960 } 961 if (modifiers.fFlags & Modifiers::kConst_Flag) { 962 this->write("const "); 963 } 964 if (usesPrecisionModifiers()) { 965 if (modifiers.fFlags & Modifiers::kLowp_Flag) { 966 this->write("lowp "); 967 } 968 if (modifiers.fFlags & Modifiers::kMediump_Flag) { 969 this->write("mediump "); 970 } 971 if (modifiers.fFlags & Modifiers::kHighp_Flag) { 972 this->write("highp "); 973 } 974 } 975} 976 977void GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) { 978 if (intf.fTypeName == "sk_PerVertex") { 979 return; 980 } 981 this->writeModifiers(intf.fVariable.fModifiers, true); 982 this->writeLine(intf.fTypeName + " {"); 983 fIndentation++; 984 const Type* structType = &intf.fVariable.fType; 985 while (structType->kind() == Type::kArray_Kind) { 986 structType = &structType->componentType(); 987 } 988 for (const auto& f : structType->fields()) { 989 this->writeModifiers(f.fModifiers, false); 990 this->writeTypePrecision(*f.fType); 991 this->writeType(*f.fType); 992 this->writeLine(" " + f.fName + ";"); 993 } 994 fIndentation--; 995 this->write("}"); 996 if (intf.fInstanceName.size()) { 997 this->write(" "); 998 this->write(intf.fInstanceName); 999 for (const auto& size : intf.fSizes) { 1000 this->write("["); 1001 if (size) { 1002 this->writeExpression(*size, kTopLevel_Precedence); 1003 } 1004 this->write("]"); 1005 } 1006 } 1007 this->writeLine(";"); 1008} 1009 1010void GLSLCodeGenerator::writeVarInitializer(const Variable& var, const Expression& value) { 1011 this->writeExpression(value, kTopLevel_Precedence); 1012} 1013 1014const char* GLSLCodeGenerator::getTypePrecision(const Type& type) { 1015 if (usesPrecisionModifiers()) { 1016 switch (type.kind()) { 1017 case Type::kScalar_Kind: 1018 if (type == *fContext.fHalf_Type || type == *fContext.fShort_Type || 1019 type == *fContext.fUShort_Type) { 1020 return fProgram.fSettings.fForceHighPrecision ? "highp " : "mediump "; 1021 } 1022 if (type == *fContext.fFloat_Type || type == *fContext.fInt_Type || 1023 type == *fContext.fUInt_Type) { 1024 return "highp "; 1025 } 1026 return ""; 1027 case Type::kVector_Kind: // fall through 1028 case Type::kMatrix_Kind: 1029 return this->getTypePrecision(type.componentType()); 1030 default: 1031 break; 1032 } 1033 } 1034 return ""; 1035} 1036 1037void GLSLCodeGenerator::writeTypePrecision(const Type& type) { 1038 this->write(this->getTypePrecision(type)); 1039} 1040 1041void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, bool global) { 1042 if (!decl.fVars.size()) { 1043 return; 1044 } 1045 bool wroteType = false; 1046 for (const auto& stmt : decl.fVars) { 1047 VarDeclaration& var = (VarDeclaration&) *stmt; 1048 if (wroteType) { 1049 this->write(", "); 1050 } else { 1051 this->writeModifiers(var.fVar->fModifiers, global); 1052 this->writeTypePrecision(decl.fBaseType); 1053 this->writeType(decl.fBaseType); 1054 this->write(" "); 1055 wroteType = true; 1056 } 1057 this->write(var.fVar->fName); 1058 for (const auto& size : var.fSizes) { 1059 this->write("["); 1060 if (size) { 1061 this->writeExpression(*size, kTopLevel_Precedence); 1062 } 1063 this->write("]"); 1064 } 1065 if (var.fValue) { 1066 this->write(" = "); 1067 this->writeVarInitializer(*var.fVar, *var.fValue); 1068 } 1069 if (!fFoundImageDecl && var.fVar->fType == *fContext.fImage2D_Type) { 1070 if (fProgram.fSettings.fCaps->imageLoadStoreExtensionString()) { 1071 fHeader.writeText("#extension "); 1072 fHeader.writeText(fProgram.fSettings.fCaps->imageLoadStoreExtensionString()); 1073 fHeader.writeText(" : require\n"); 1074 } 1075 fFoundImageDecl = true; 1076 } 1077 } 1078 if (wroteType) { 1079 this->write(";"); 1080 } 1081} 1082 1083void GLSLCodeGenerator::writeStatement(const Statement& s) { 1084 switch (s.fKind) { 1085 case Statement::kBlock_Kind: 1086 this->writeBlock((Block&) s); 1087 break; 1088 case Statement::kExpression_Kind: 1089 this->writeExpression(*((ExpressionStatement&) s).fExpression, kTopLevel_Precedence); 1090 this->write(";"); 1091 break; 1092 case Statement::kReturn_Kind: 1093 this->writeReturnStatement((ReturnStatement&) s); 1094 break; 1095 case Statement::kVarDeclarations_Kind: 1096 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration, false); 1097 break; 1098 case Statement::kIf_Kind: 1099 this->writeIfStatement((IfStatement&) s); 1100 break; 1101 case Statement::kFor_Kind: 1102 this->writeForStatement((ForStatement&) s); 1103 break; 1104 case Statement::kWhile_Kind: 1105 this->writeWhileStatement((WhileStatement&) s); 1106 break; 1107 case Statement::kDo_Kind: 1108 this->writeDoStatement((DoStatement&) s); 1109 break; 1110 case Statement::kSwitch_Kind: 1111 this->writeSwitchStatement((SwitchStatement&) s); 1112 break; 1113 case Statement::kBreak_Kind: 1114 this->write("break;"); 1115 break; 1116 case Statement::kContinue_Kind: 1117 this->write("continue;"); 1118 break; 1119 case Statement::kDiscard_Kind: 1120 this->write("discard;"); 1121 break; 1122 case Statement::kNop_Kind: 1123 this->write(";"); 1124 break; 1125 default: 1126 ABORT("unsupported statement: %s", s.description().c_str()); 1127 } 1128} 1129 1130void GLSLCodeGenerator::writeStatements(const std::vector<std::unique_ptr<Statement>>& statements) { 1131 for (const auto& s : statements) { 1132 if (!s->isEmpty()) { 1133 this->writeStatement(*s); 1134 this->writeLine(); 1135 } 1136 } 1137} 1138 1139void GLSLCodeGenerator::writeBlock(const Block& b) { 1140 this->writeLine("{"); 1141 fIndentation++; 1142 this->writeStatements(b.fStatements); 1143 fIndentation--; 1144 this->write("}"); 1145} 1146 1147void GLSLCodeGenerator::writeIfStatement(const IfStatement& stmt) { 1148 this->write("if ("); 1149 this->writeExpression(*stmt.fTest, kTopLevel_Precedence); 1150 this->write(") "); 1151 this->writeStatement(*stmt.fIfTrue); 1152 if (stmt.fIfFalse) { 1153 this->write(" else "); 1154 this->writeStatement(*stmt.fIfFalse); 1155 } 1156} 1157 1158void GLSLCodeGenerator::writeForStatement(const ForStatement& f) { 1159 this->write("for ("); 1160 if (f.fInitializer && !f.fInitializer->isEmpty()) { 1161 this->writeStatement(*f.fInitializer); 1162 } else { 1163 this->write("; "); 1164 } 1165 if (f.fTest) { 1166 this->writeExpression(*f.fTest, kTopLevel_Precedence); 1167 } 1168 this->write("; "); 1169 if (f.fNext) { 1170 this->writeExpression(*f.fNext, kTopLevel_Precedence); 1171 } 1172 this->write(") "); 1173 this->writeStatement(*f.fStatement); 1174} 1175 1176void GLSLCodeGenerator::writeWhileStatement(const WhileStatement& w) { 1177 this->write("while ("); 1178 this->writeExpression(*w.fTest, kTopLevel_Precedence); 1179 this->write(") "); 1180 this->writeStatement(*w.fStatement); 1181} 1182 1183void GLSLCodeGenerator::writeDoStatement(const DoStatement& d) { 1184 this->write("do "); 1185 this->writeStatement(*d.fStatement); 1186 this->write(" while ("); 1187 this->writeExpression(*d.fTest, kTopLevel_Precedence); 1188 this->write(");"); 1189} 1190 1191void GLSLCodeGenerator::writeSwitchStatement(const SwitchStatement& s) { 1192 this->write("switch ("); 1193 this->writeExpression(*s.fValue, kTopLevel_Precedence); 1194 this->writeLine(") {"); 1195 fIndentation++; 1196 for (const auto& c : s.fCases) { 1197 if (c->fValue) { 1198 this->write("case "); 1199 this->writeExpression(*c->fValue, kTopLevel_Precedence); 1200 this->writeLine(":"); 1201 } else { 1202 this->writeLine("default:"); 1203 } 1204 fIndentation++; 1205 for (const auto& stmt : c->fStatements) { 1206 this->writeStatement(*stmt); 1207 this->writeLine(); 1208 } 1209 fIndentation--; 1210 } 1211 fIndentation--; 1212 this->write("}"); 1213} 1214 1215void GLSLCodeGenerator::writeReturnStatement(const ReturnStatement& r) { 1216 this->write("return"); 1217 if (r.fExpression) { 1218 this->write(" "); 1219 this->writeExpression(*r.fExpression, kTopLevel_Precedence); 1220 } 1221 this->write(";"); 1222} 1223 1224void GLSLCodeGenerator::writeHeader() { 1225 this->write(fProgram.fSettings.fCaps->versionDeclString()); 1226 this->writeLine(); 1227 for (const auto& e : fProgram.fElements) { 1228 if (e->fKind == ProgramElement::kExtension_Kind) { 1229 this->writeExtension((Extension&) *e); 1230 } 1231 } 1232 if (!fProgram.fSettings.fCaps->canUseFragCoord()) { 1233 Layout layout; 1234 switch (fProgram.fKind) { 1235 case Program::kVertex_Kind: { 1236 Modifiers modifiers(layout, Modifiers::kOut_Flag | Modifiers::kHighp_Flag); 1237 this->writeModifiers(modifiers, true); 1238 this->write("vec4 sk_FragCoord_Workaround;\n"); 1239 break; 1240 } 1241 case Program::kFragment_Kind: { 1242 Modifiers modifiers(layout, Modifiers::kIn_Flag | Modifiers::kHighp_Flag); 1243 this->writeModifiers(modifiers, true); 1244 this->write("vec4 sk_FragCoord_Workaround;\n"); 1245 break; 1246 } 1247 default: 1248 break; 1249 } 1250 } 1251} 1252 1253void GLSLCodeGenerator::writeProgramElement(const ProgramElement& e) { 1254 switch (e.fKind) { 1255 case ProgramElement::kExtension_Kind: 1256 break; 1257 case ProgramElement::kVar_Kind: { 1258 VarDeclarations& decl = (VarDeclarations&) e; 1259 if (decl.fVars.size() > 0) { 1260 int builtin = ((VarDeclaration&) *decl.fVars[0]).fVar->fModifiers.fLayout.fBuiltin; 1261 if (builtin == -1) { 1262 // normal var 1263 this->writeVarDeclarations(decl, true); 1264 this->writeLine(); 1265 } else if (builtin == SK_FRAGCOLOR_BUILTIN && 1266 fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput()) { 1267 if (fProgram.fSettings.fFragColorIsInOut) { 1268 this->write("inout "); 1269 } else { 1270 this->write("out "); 1271 } 1272 if (usesPrecisionModifiers()) { 1273 this->write("mediump "); 1274 } 1275 this->writeLine("vec4 sk_FragColor;"); 1276 } 1277 } 1278 break; 1279 } 1280 case ProgramElement::kInterfaceBlock_Kind: 1281 this->writeInterfaceBlock((InterfaceBlock&) e); 1282 break; 1283 case ProgramElement::kFunction_Kind: 1284 this->writeFunction((FunctionDefinition&) e); 1285 break; 1286 case ProgramElement::kModifiers_Kind: { 1287 const Modifiers& modifiers = ((ModifiersDeclaration&) e).fModifiers; 1288 if (!fFoundGSInvocations && modifiers.fLayout.fInvocations >= 0) { 1289 if (fProgram.fSettings.fCaps->gsInvocationsExtensionString()) { 1290 fHeader.writeText("#extension "); 1291 fHeader.writeText(fProgram.fSettings.fCaps->gsInvocationsExtensionString()); 1292 fHeader.writeText(" : require\n"); 1293 } 1294 fFoundGSInvocations = true; 1295 } 1296 this->writeModifiers(modifiers, true); 1297 this->writeLine(";"); 1298 break; 1299 } 1300 case ProgramElement::kEnum_Kind: 1301 break; 1302 default: 1303 printf("%s\n", e.description().c_str()); 1304 ABORT("unsupported program element"); 1305 } 1306} 1307 1308bool GLSLCodeGenerator::generateCode() { 1309 OutputStream* rawOut = fOut; 1310 fOut = &fHeader; 1311 fProgramKind = fProgram.fKind; 1312 this->writeHeader(); 1313 if (Program::kGeometry_Kind == fProgramKind && 1314 fProgram.fSettings.fCaps->geometryShaderExtensionString()) { 1315 fHeader.writeText("#extension "); 1316 fHeader.writeText(fProgram.fSettings.fCaps->geometryShaderExtensionString()); 1317 fHeader.writeText(" : require\n"); 1318 } 1319 StringStream body; 1320 fOut = &body; 1321 for (const auto& e : fProgram.fElements) { 1322 this->writeProgramElement(*e); 1323 } 1324 fOut = rawOut; 1325 1326 write_stringstream(fHeader, *rawOut); 1327 if (this->usesPrecisionModifiers()) { 1328 this->writeLine("precision mediump float;"); 1329 } 1330 write_stringstream(fExtraFunctions, *rawOut); 1331 write_stringstream(body, *rawOut); 1332 return true; 1333} 1334 1335} 1336