1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2016 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/sksl/codegen/SkSLGLSLCodeGenerator.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include <memory> 11cb93a386Sopenharmony_ci 12cb93a386Sopenharmony_ci#include "src/sksl/SkSLCompiler.h" 13cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLBinaryExpression.h" 14cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLConstructorArrayCast.h" 15cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLConstructorDiagonalMatrix.h" 16cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLDoStatement.h" 17cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLExpressionStatement.h" 18cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLExtension.h" 19cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLFieldAccess.h" 20cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLForStatement.h" 21cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLFunctionCall.h" 22cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLFunctionDefinition.h" 23cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLFunctionPrototype.h" 24cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLIfStatement.h" 25cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLIndexExpression.h" 26cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLInterfaceBlock.h" 27cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLModifiersDeclaration.h" 28cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLNop.h" 29cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLPostfixExpression.h" 30cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLPrefixExpression.h" 31cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLReturnStatement.h" 32cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLSetting.h" 33cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLStructDefinition.h" 34cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLSwitchCase.h" 35cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLSwitchStatement.h" 36cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLSwizzle.h" 37cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLVariableReference.h" 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_ci#ifndef SKSL_STANDALONE 40cb93a386Sopenharmony_ci#include "include/private/SkOnce.h" 41cb93a386Sopenharmony_ci#endif 42cb93a386Sopenharmony_ci 43cb93a386Sopenharmony_cinamespace SkSL { 44cb93a386Sopenharmony_ci 45cb93a386Sopenharmony_civoid GLSLCodeGenerator::write(skstd::string_view s) { 46cb93a386Sopenharmony_ci if (!s.length()) { 47cb93a386Sopenharmony_ci return; 48cb93a386Sopenharmony_ci } 49cb93a386Sopenharmony_ci if (fAtLineStart) { 50cb93a386Sopenharmony_ci for (int i = 0; i < fIndentation; i++) { 51cb93a386Sopenharmony_ci fOut->writeText(" "); 52cb93a386Sopenharmony_ci } 53cb93a386Sopenharmony_ci } 54cb93a386Sopenharmony_ci fOut->write(s.data(), s.length()); 55cb93a386Sopenharmony_ci fAtLineStart = false; 56cb93a386Sopenharmony_ci} 57cb93a386Sopenharmony_ci 58cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeLine(skstd::string_view s) { 59cb93a386Sopenharmony_ci this->write(s); 60cb93a386Sopenharmony_ci fOut->writeText(fLineEnding); 61cb93a386Sopenharmony_ci fAtLineStart = true; 62cb93a386Sopenharmony_ci} 63cb93a386Sopenharmony_ci 64cb93a386Sopenharmony_civoid GLSLCodeGenerator::finishLine() { 65cb93a386Sopenharmony_ci if (!fAtLineStart) { 66cb93a386Sopenharmony_ci this->writeLine(); 67cb93a386Sopenharmony_ci } 68cb93a386Sopenharmony_ci} 69cb93a386Sopenharmony_ci 70cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeExtension(skstd::string_view name, bool require) { 71cb93a386Sopenharmony_ci fExtensions.writeText("#extension "); 72cb93a386Sopenharmony_ci fExtensions.write(name.data(), name.length()); 73cb93a386Sopenharmony_ci fExtensions.writeText(require ? " : require\n" : " : enable\n"); 74cb93a386Sopenharmony_ci} 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_cibool GLSLCodeGenerator::usesPrecisionModifiers() const { 77cb93a386Sopenharmony_ci return this->caps().usesPrecisionModifiers(); 78cb93a386Sopenharmony_ci} 79cb93a386Sopenharmony_ci 80cb93a386Sopenharmony_ci// Returns the name of the type with array dimensions, e.g. `float[2]`. 81cb93a386Sopenharmony_ciString GLSLCodeGenerator::getTypeName(const Type& type) { 82cb93a386Sopenharmony_ci switch (type.typeKind()) { 83cb93a386Sopenharmony_ci case Type::TypeKind::kVector: { 84cb93a386Sopenharmony_ci const Type& component = type.componentType(); 85cb93a386Sopenharmony_ci String result; 86cb93a386Sopenharmony_ci if (component == *fContext.fTypes.fFloat || component == *fContext.fTypes.fHalf) { 87cb93a386Sopenharmony_ci result = "vec"; 88cb93a386Sopenharmony_ci } 89cb93a386Sopenharmony_ci else if (component.isSigned()) { 90cb93a386Sopenharmony_ci result = "ivec"; 91cb93a386Sopenharmony_ci } 92cb93a386Sopenharmony_ci else if (component.isUnsigned()) { 93cb93a386Sopenharmony_ci result = "uvec"; 94cb93a386Sopenharmony_ci } 95cb93a386Sopenharmony_ci else if (component == *fContext.fTypes.fBool) { 96cb93a386Sopenharmony_ci result = "bvec"; 97cb93a386Sopenharmony_ci } 98cb93a386Sopenharmony_ci else { 99cb93a386Sopenharmony_ci SK_ABORT("unsupported vector type"); 100cb93a386Sopenharmony_ci } 101cb93a386Sopenharmony_ci result += to_string(type.columns()); 102cb93a386Sopenharmony_ci return result; 103cb93a386Sopenharmony_ci } 104cb93a386Sopenharmony_ci case Type::TypeKind::kMatrix: { 105cb93a386Sopenharmony_ci String result; 106cb93a386Sopenharmony_ci const Type& component = type.componentType(); 107cb93a386Sopenharmony_ci if (component == *fContext.fTypes.fFloat || component == *fContext.fTypes.fHalf) { 108cb93a386Sopenharmony_ci result = "mat"; 109cb93a386Sopenharmony_ci } 110cb93a386Sopenharmony_ci else { 111cb93a386Sopenharmony_ci SK_ABORT("unsupported matrix type"); 112cb93a386Sopenharmony_ci } 113cb93a386Sopenharmony_ci result += to_string(type.columns()); 114cb93a386Sopenharmony_ci if (type.columns() != type.rows()) { 115cb93a386Sopenharmony_ci result += "x"; 116cb93a386Sopenharmony_ci result += to_string(type.rows()); 117cb93a386Sopenharmony_ci } 118cb93a386Sopenharmony_ci return result; 119cb93a386Sopenharmony_ci } 120cb93a386Sopenharmony_ci case Type::TypeKind::kArray: { 121cb93a386Sopenharmony_ci String baseTypeName = this->getTypeName(type.componentType()); 122cb93a386Sopenharmony_ci return String::printf("%s[%d]", baseTypeName.c_str(), type.columns()); 123cb93a386Sopenharmony_ci } 124cb93a386Sopenharmony_ci case Type::TypeKind::kScalar: { 125cb93a386Sopenharmony_ci if (type == *fContext.fTypes.fHalf) { 126cb93a386Sopenharmony_ci return "float"; 127cb93a386Sopenharmony_ci } 128cb93a386Sopenharmony_ci else if (type == *fContext.fTypes.fShort) { 129cb93a386Sopenharmony_ci return "int"; 130cb93a386Sopenharmony_ci } 131cb93a386Sopenharmony_ci else if (type == *fContext.fTypes.fUShort) { 132cb93a386Sopenharmony_ci return "uint"; 133cb93a386Sopenharmony_ci } 134cb93a386Sopenharmony_ci else { 135cb93a386Sopenharmony_ci return String(type.name()); 136cb93a386Sopenharmony_ci } 137cb93a386Sopenharmony_ci break; 138cb93a386Sopenharmony_ci } 139cb93a386Sopenharmony_ci default: 140cb93a386Sopenharmony_ci return String(type.name()); 141cb93a386Sopenharmony_ci } 142cb93a386Sopenharmony_ci} 143cb93a386Sopenharmony_ci 144cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeStructDefinition(const StructDefinition& s) { 145cb93a386Sopenharmony_ci const Type& type = s.type(); 146cb93a386Sopenharmony_ci this->write("struct "); 147cb93a386Sopenharmony_ci this->write(type.name()); 148cb93a386Sopenharmony_ci this->writeLine(" {"); 149cb93a386Sopenharmony_ci fIndentation++; 150cb93a386Sopenharmony_ci for (const auto& f : type.fields()) { 151cb93a386Sopenharmony_ci this->writeModifiers(f.fModifiers, false); 152cb93a386Sopenharmony_ci this->writeTypePrecision(*f.fType); 153cb93a386Sopenharmony_ci const Type& baseType = f.fType->isArray() ? f.fType->componentType() : *f.fType; 154cb93a386Sopenharmony_ci this->writeType(baseType); 155cb93a386Sopenharmony_ci this->write(" "); 156cb93a386Sopenharmony_ci this->write(f.fName); 157cb93a386Sopenharmony_ci if (f.fType->isArray()) { 158cb93a386Sopenharmony_ci this->write("[" + to_string(f.fType->columns()) + "]"); 159cb93a386Sopenharmony_ci } 160cb93a386Sopenharmony_ci this->writeLine(";"); 161cb93a386Sopenharmony_ci } 162cb93a386Sopenharmony_ci fIndentation--; 163cb93a386Sopenharmony_ci this->writeLine("};"); 164cb93a386Sopenharmony_ci} 165cb93a386Sopenharmony_ci 166cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeType(const Type& type) { 167cb93a386Sopenharmony_ci this->write(this->getTypeName(type)); 168cb93a386Sopenharmony_ci} 169cb93a386Sopenharmony_ci 170cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeExpression(const Expression& expr, Precedence parentPrecedence) { 171cb93a386Sopenharmony_ci switch (expr.kind()) { 172cb93a386Sopenharmony_ci case Expression::Kind::kBinary: 173cb93a386Sopenharmony_ci this->writeBinaryExpression(expr.as<BinaryExpression>(), parentPrecedence); 174cb93a386Sopenharmony_ci break; 175cb93a386Sopenharmony_ci case Expression::Kind::kConstructorDiagonalMatrix: 176cb93a386Sopenharmony_ci this->writeConstructorDiagonalMatrix(expr.as<ConstructorDiagonalMatrix>(), 177cb93a386Sopenharmony_ci parentPrecedence); 178cb93a386Sopenharmony_ci break; 179cb93a386Sopenharmony_ci case Expression::Kind::kConstructorArrayCast: 180cb93a386Sopenharmony_ci this->writeExpression(*expr.as<ConstructorArrayCast>().argument(), parentPrecedence); 181cb93a386Sopenharmony_ci break; 182cb93a386Sopenharmony_ci case Expression::Kind::kConstructorArray: 183cb93a386Sopenharmony_ci case Expression::Kind::kConstructorCompound: 184cb93a386Sopenharmony_ci case Expression::Kind::kConstructorMatrixResize: 185cb93a386Sopenharmony_ci case Expression::Kind::kConstructorSplat: 186cb93a386Sopenharmony_ci case Expression::Kind::kConstructorStruct: 187cb93a386Sopenharmony_ci this->writeAnyConstructor(expr.asAnyConstructor(), parentPrecedence); 188cb93a386Sopenharmony_ci break; 189cb93a386Sopenharmony_ci case Expression::Kind::kConstructorScalarCast: 190cb93a386Sopenharmony_ci case Expression::Kind::kConstructorCompoundCast: 191cb93a386Sopenharmony_ci this->writeCastConstructor(expr.asAnyConstructor(), parentPrecedence); 192cb93a386Sopenharmony_ci break; 193cb93a386Sopenharmony_ci case Expression::Kind::kFieldAccess: 194cb93a386Sopenharmony_ci this->writeFieldAccess(expr.as<FieldAccess>()); 195cb93a386Sopenharmony_ci break; 196cb93a386Sopenharmony_ci case Expression::Kind::kFunctionCall: 197cb93a386Sopenharmony_ci this->writeFunctionCall(expr.as<FunctionCall>()); 198cb93a386Sopenharmony_ci break; 199cb93a386Sopenharmony_ci case Expression::Kind::kLiteral: 200cb93a386Sopenharmony_ci this->writeLiteral(expr.as<Literal>()); 201cb93a386Sopenharmony_ci break; 202cb93a386Sopenharmony_ci case Expression::Kind::kPrefix: 203cb93a386Sopenharmony_ci this->writePrefixExpression(expr.as<PrefixExpression>(), parentPrecedence); 204cb93a386Sopenharmony_ci break; 205cb93a386Sopenharmony_ci case Expression::Kind::kPostfix: 206cb93a386Sopenharmony_ci this->writePostfixExpression(expr.as<PostfixExpression>(), parentPrecedence); 207cb93a386Sopenharmony_ci break; 208cb93a386Sopenharmony_ci case Expression::Kind::kSetting: 209cb93a386Sopenharmony_ci this->writeSetting(expr.as<Setting>()); 210cb93a386Sopenharmony_ci break; 211cb93a386Sopenharmony_ci case Expression::Kind::kSwizzle: 212cb93a386Sopenharmony_ci this->writeSwizzle(expr.as<Swizzle>()); 213cb93a386Sopenharmony_ci break; 214cb93a386Sopenharmony_ci case Expression::Kind::kVariableReference: 215cb93a386Sopenharmony_ci this->writeVariableReference(expr.as<VariableReference>()); 216cb93a386Sopenharmony_ci break; 217cb93a386Sopenharmony_ci case Expression::Kind::kTernary: 218cb93a386Sopenharmony_ci this->writeTernaryExpression(expr.as<TernaryExpression>(), parentPrecedence); 219cb93a386Sopenharmony_ci break; 220cb93a386Sopenharmony_ci case Expression::Kind::kIndex: 221cb93a386Sopenharmony_ci this->writeIndexExpression(expr.as<IndexExpression>()); 222cb93a386Sopenharmony_ci break; 223cb93a386Sopenharmony_ci default: 224cb93a386Sopenharmony_ci SkDEBUGFAILF("unsupported expression: %s", expr.description().c_str()); 225cb93a386Sopenharmony_ci break; 226cb93a386Sopenharmony_ci } 227cb93a386Sopenharmony_ci} 228cb93a386Sopenharmony_ci 229cb93a386Sopenharmony_cistatic bool is_abs(Expression& expr) { 230cb93a386Sopenharmony_ci return expr.is<FunctionCall>() && 231cb93a386Sopenharmony_ci expr.as<FunctionCall>().function().intrinsicKind() == k_abs_IntrinsicKind; 232cb93a386Sopenharmony_ci} 233cb93a386Sopenharmony_ci 234cb93a386Sopenharmony_ci// turns min(abs(x), y) into ((tmpVar1 = abs(x)) < (tmpVar2 = y) ? tmpVar1 : tmpVar2) to avoid a 235cb93a386Sopenharmony_ci// Tegra3 compiler bug. 236cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeMinAbsHack(Expression& absExpr, Expression& otherExpr) { 237cb93a386Sopenharmony_ci SkASSERT(!this->caps().canUseMinAndAbsTogether()); 238cb93a386Sopenharmony_ci String tmpVar1 = "minAbsHackVar" + to_string(fVarCount++); 239cb93a386Sopenharmony_ci String tmpVar2 = "minAbsHackVar" + to_string(fVarCount++); 240cb93a386Sopenharmony_ci this->fFunctionHeader += String(" ") + this->getTypePrecision(absExpr.type()) + 241cb93a386Sopenharmony_ci this->getTypeName(absExpr.type()) + " " + tmpVar1 + ";\n"; 242cb93a386Sopenharmony_ci this->fFunctionHeader += String(" ") + this->getTypePrecision(otherExpr.type()) + 243cb93a386Sopenharmony_ci this->getTypeName(otherExpr.type()) + " " + tmpVar2 + ";\n"; 244cb93a386Sopenharmony_ci this->write("((" + tmpVar1 + " = "); 245cb93a386Sopenharmony_ci this->writeExpression(absExpr, Precedence::kTopLevel); 246cb93a386Sopenharmony_ci this->write(") < (" + tmpVar2 + " = "); 247cb93a386Sopenharmony_ci this->writeExpression(otherExpr, Precedence::kAssignment); 248cb93a386Sopenharmony_ci this->write(") ? " + tmpVar1 + " : " + tmpVar2 + ")"); 249cb93a386Sopenharmony_ci} 250cb93a386Sopenharmony_ci 251cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeInverseSqrtHack(const Expression& x) { 252cb93a386Sopenharmony_ci this->write("(1.0 / sqrt("); 253cb93a386Sopenharmony_ci this->writeExpression(x, Precedence::kTopLevel); 254cb93a386Sopenharmony_ci this->write("))"); 255cb93a386Sopenharmony_ci} 256cb93a386Sopenharmony_ci 257cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeDeterminantHack(const Expression& mat) { 258cb93a386Sopenharmony_ci String name; 259cb93a386Sopenharmony_ci const Type& type = mat.type(); 260cb93a386Sopenharmony_ci if (type == *fContext.fTypes.fFloat2x2 || type == *fContext.fTypes.fHalf2x2) { 261cb93a386Sopenharmony_ci name = "_determinant2"; 262cb93a386Sopenharmony_ci if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) { 263cb93a386Sopenharmony_ci fWrittenIntrinsics.insert(name); 264cb93a386Sopenharmony_ci fExtraFunctions.writeText(( 265cb93a386Sopenharmony_ci "float " + name + "(mat2 m) {" 266cb93a386Sopenharmony_ci " return m[0][0] * m[1][1] - m[0][1] * m[1][0];" 267cb93a386Sopenharmony_ci "}" 268cb93a386Sopenharmony_ci ).c_str()); 269cb93a386Sopenharmony_ci } 270cb93a386Sopenharmony_ci } 271cb93a386Sopenharmony_ci else if (type == *fContext.fTypes.fFloat3x3 || type == *fContext.fTypes.fHalf3x3) { 272cb93a386Sopenharmony_ci name = "_determinant3"; 273cb93a386Sopenharmony_ci if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) { 274cb93a386Sopenharmony_ci fWrittenIntrinsics.insert(name); 275cb93a386Sopenharmony_ci fExtraFunctions.writeText(( 276cb93a386Sopenharmony_ci "float " + name + "(mat3 m) {" 277cb93a386Sopenharmony_ci " float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];" 278cb93a386Sopenharmony_ci " float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];" 279cb93a386Sopenharmony_ci " float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];" 280cb93a386Sopenharmony_ci " float b01 = a22 * a11 - a12 * a21;" 281cb93a386Sopenharmony_ci " float b11 = -a22 * a10 + a12 * a20;" 282cb93a386Sopenharmony_ci " float b21 = a21 * a10 - a11 * a20;" 283cb93a386Sopenharmony_ci " return a00 * b01 + a01 * b11 + a02 * b21;" 284cb93a386Sopenharmony_ci "}" 285cb93a386Sopenharmony_ci ).c_str()); 286cb93a386Sopenharmony_ci } 287cb93a386Sopenharmony_ci } 288cb93a386Sopenharmony_ci else if (type == *fContext.fTypes.fFloat4x4 || type == *fContext.fTypes.fHalf4x4) { 289cb93a386Sopenharmony_ci name = "_determinant4"; 290cb93a386Sopenharmony_ci if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) { 291cb93a386Sopenharmony_ci fWrittenIntrinsics.insert(name); 292cb93a386Sopenharmony_ci fExtraFunctions.writeText(( 293cb93a386Sopenharmony_ci "mat4 " + name + "(mat4 m) {" 294cb93a386Sopenharmony_ci " float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2], a03 = m[0][3];" 295cb93a386Sopenharmony_ci " float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2], a13 = m[1][3];" 296cb93a386Sopenharmony_ci " float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2], a23 = m[2][3];" 297cb93a386Sopenharmony_ci " float a30 = m[3][0], a31 = m[3][1], a32 = m[3][2], a33 = m[3][3];" 298cb93a386Sopenharmony_ci " float b00 = a00 * a11 - a01 * a10;" 299cb93a386Sopenharmony_ci " float b01 = a00 * a12 - a02 * a10;" 300cb93a386Sopenharmony_ci " float b02 = a00 * a13 - a03 * a10;" 301cb93a386Sopenharmony_ci " float b03 = a01 * a12 - a02 * a11;" 302cb93a386Sopenharmony_ci " float b04 = a01 * a13 - a03 * a11;" 303cb93a386Sopenharmony_ci " float b05 = a02 * a13 - a03 * a12;" 304cb93a386Sopenharmony_ci " float b06 = a20 * a31 - a21 * a30;" 305cb93a386Sopenharmony_ci " float b07 = a20 * a32 - a22 * a30;" 306cb93a386Sopenharmony_ci " float b08 = a20 * a33 - a23 * a30;" 307cb93a386Sopenharmony_ci " float b09 = a21 * a32 - a22 * a31;" 308cb93a386Sopenharmony_ci " float b10 = a21 * a33 - a23 * a31;" 309cb93a386Sopenharmony_ci " float b11 = a22 * a33 - a23 * a32;" 310cb93a386Sopenharmony_ci " return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;" 311cb93a386Sopenharmony_ci "}" 312cb93a386Sopenharmony_ci ).c_str()); 313cb93a386Sopenharmony_ci } 314cb93a386Sopenharmony_ci } 315cb93a386Sopenharmony_ci else { 316cb93a386Sopenharmony_ci SkASSERT(false); 317cb93a386Sopenharmony_ci } 318cb93a386Sopenharmony_ci this->write(name + "("); 319cb93a386Sopenharmony_ci this->writeExpression(mat, Precedence::kTopLevel); 320cb93a386Sopenharmony_ci this->write(")"); 321cb93a386Sopenharmony_ci} 322cb93a386Sopenharmony_ci 323cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeInverseHack(const Expression& mat) { 324cb93a386Sopenharmony_ci String name; 325cb93a386Sopenharmony_ci const Type& type = mat.type(); 326cb93a386Sopenharmony_ci if (type == *fContext.fTypes.fFloat2x2 || type == *fContext.fTypes.fHalf2x2) { 327cb93a386Sopenharmony_ci name = "_inverse2"; 328cb93a386Sopenharmony_ci if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) { 329cb93a386Sopenharmony_ci fWrittenIntrinsics.insert(name); 330cb93a386Sopenharmony_ci fExtraFunctions.writeText(( 331cb93a386Sopenharmony_ci "mat2 " + name + "(mat2 m) {" 332cb93a386Sopenharmony_ci " return mat2(m[1][1], -m[0][1], -m[1][0], m[0][0]) / " 333cb93a386Sopenharmony_ci "(m[0][0] * m[1][1] - m[0][1] * m[1][0]);" 334cb93a386Sopenharmony_ci "}" 335cb93a386Sopenharmony_ci ).c_str()); 336cb93a386Sopenharmony_ci } 337cb93a386Sopenharmony_ci } 338cb93a386Sopenharmony_ci else if (type == *fContext.fTypes.fFloat3x3 || type == *fContext.fTypes.fHalf3x3) { 339cb93a386Sopenharmony_ci name = "_inverse3"; 340cb93a386Sopenharmony_ci if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) { 341cb93a386Sopenharmony_ci fWrittenIntrinsics.insert(name); 342cb93a386Sopenharmony_ci fExtraFunctions.writeText(( 343cb93a386Sopenharmony_ci "mat3 " + name + "(mat3 m) {" 344cb93a386Sopenharmony_ci " float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];" 345cb93a386Sopenharmony_ci " float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];" 346cb93a386Sopenharmony_ci " float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];" 347cb93a386Sopenharmony_ci " float b01 = a22 * a11 - a12 * a21;" 348cb93a386Sopenharmony_ci " float b11 = -a22 * a10 + a12 * a20;" 349cb93a386Sopenharmony_ci " float b21 = a21 * a10 - a11 * a20;" 350cb93a386Sopenharmony_ci " float det = a00 * b01 + a01 * b11 + a02 * b21;" 351cb93a386Sopenharmony_ci " return mat3(b01, (-a22 * a01 + a02 * a21), (a12 * a01 - a02 * a11)," 352cb93a386Sopenharmony_ci " b11, (a22 * a00 - a02 * a20), (-a12 * a00 + a02 * a10)," 353cb93a386Sopenharmony_ci " b21, (-a21 * a00 + a01 * a20), (a11 * a00 - a01 * a10)) / det;" 354cb93a386Sopenharmony_ci "}" 355cb93a386Sopenharmony_ci ).c_str()); 356cb93a386Sopenharmony_ci } 357cb93a386Sopenharmony_ci } 358cb93a386Sopenharmony_ci else if (type == *fContext.fTypes.fFloat4x4 || type == *fContext.fTypes.fHalf4x4) { 359cb93a386Sopenharmony_ci name = "_inverse4"; 360cb93a386Sopenharmony_ci if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) { 361cb93a386Sopenharmony_ci fWrittenIntrinsics.insert(name); 362cb93a386Sopenharmony_ci fExtraFunctions.writeText(( 363cb93a386Sopenharmony_ci "mat4 " + name + "(mat4 m) {" 364cb93a386Sopenharmony_ci " float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2], a03 = m[0][3];" 365cb93a386Sopenharmony_ci " float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2], a13 = m[1][3];" 366cb93a386Sopenharmony_ci " float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2], a23 = m[2][3];" 367cb93a386Sopenharmony_ci " float a30 = m[3][0], a31 = m[3][1], a32 = m[3][2], a33 = m[3][3];" 368cb93a386Sopenharmony_ci " float b00 = a00 * a11 - a01 * a10;" 369cb93a386Sopenharmony_ci " float b01 = a00 * a12 - a02 * a10;" 370cb93a386Sopenharmony_ci " float b02 = a00 * a13 - a03 * a10;" 371cb93a386Sopenharmony_ci " float b03 = a01 * a12 - a02 * a11;" 372cb93a386Sopenharmony_ci " float b04 = a01 * a13 - a03 * a11;" 373cb93a386Sopenharmony_ci " float b05 = a02 * a13 - a03 * a12;" 374cb93a386Sopenharmony_ci " float b06 = a20 * a31 - a21 * a30;" 375cb93a386Sopenharmony_ci " float b07 = a20 * a32 - a22 * a30;" 376cb93a386Sopenharmony_ci " float b08 = a20 * a33 - a23 * a30;" 377cb93a386Sopenharmony_ci " float b09 = a21 * a32 - a22 * a31;" 378cb93a386Sopenharmony_ci " float b10 = a21 * a33 - a23 * a31;" 379cb93a386Sopenharmony_ci " float b11 = a22 * a33 - a23 * a32;" 380cb93a386Sopenharmony_ci " float det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - " 381cb93a386Sopenharmony_ci " b04 * b07 + b05 * b06;" 382cb93a386Sopenharmony_ci " return mat4(" 383cb93a386Sopenharmony_ci " a11 * b11 - a12 * b10 + a13 * b09," 384cb93a386Sopenharmony_ci " a02 * b10 - a01 * b11 - a03 * b09," 385cb93a386Sopenharmony_ci " a31 * b05 - a32 * b04 + a33 * b03," 386cb93a386Sopenharmony_ci " a22 * b04 - a21 * b05 - a23 * b03," 387cb93a386Sopenharmony_ci " a12 * b08 - a10 * b11 - a13 * b07," 388cb93a386Sopenharmony_ci " a00 * b11 - a02 * b08 + a03 * b07," 389cb93a386Sopenharmony_ci " a32 * b02 - a30 * b05 - a33 * b01," 390cb93a386Sopenharmony_ci " a20 * b05 - a22 * b02 + a23 * b01," 391cb93a386Sopenharmony_ci " a10 * b10 - a11 * b08 + a13 * b06," 392cb93a386Sopenharmony_ci " a01 * b08 - a00 * b10 - a03 * b06," 393cb93a386Sopenharmony_ci " a30 * b04 - a31 * b02 + a33 * b00," 394cb93a386Sopenharmony_ci " a21 * b02 - a20 * b04 - a23 * b00," 395cb93a386Sopenharmony_ci " a11 * b07 - a10 * b09 - a12 * b06," 396cb93a386Sopenharmony_ci " a00 * b09 - a01 * b07 + a02 * b06," 397cb93a386Sopenharmony_ci " a31 * b01 - a30 * b03 - a32 * b00," 398cb93a386Sopenharmony_ci " a20 * b03 - a21 * b01 + a22 * b00) / det;" 399cb93a386Sopenharmony_ci "}" 400cb93a386Sopenharmony_ci ).c_str()); 401cb93a386Sopenharmony_ci } 402cb93a386Sopenharmony_ci } 403cb93a386Sopenharmony_ci else { 404cb93a386Sopenharmony_ci SkASSERT(false); 405cb93a386Sopenharmony_ci } 406cb93a386Sopenharmony_ci this->write(name + "("); 407cb93a386Sopenharmony_ci this->writeExpression(mat, Precedence::kTopLevel); 408cb93a386Sopenharmony_ci this->write(")"); 409cb93a386Sopenharmony_ci} 410cb93a386Sopenharmony_ci 411cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeTransposeHack(const Expression& mat) { 412cb93a386Sopenharmony_ci const Type& type = mat.type(); 413cb93a386Sopenharmony_ci String name = "transpose" + to_string(type.columns()) + to_string(type.rows()); 414cb93a386Sopenharmony_ci if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) { 415cb93a386Sopenharmony_ci fWrittenIntrinsics.insert(name); 416cb93a386Sopenharmony_ci String typeName = this->getTypeName(type); 417cb93a386Sopenharmony_ci const Type& base = type.componentType(); 418cb93a386Sopenharmony_ci String transposed = this->getTypeName(base.toCompound(fContext, 419cb93a386Sopenharmony_ci type.rows(), 420cb93a386Sopenharmony_ci type.columns())); 421cb93a386Sopenharmony_ci fExtraFunctions.writeText((transposed + " " + name + "(" + typeName + " m) {\nreturn " + 422cb93a386Sopenharmony_ci transposed + "(").c_str()); 423cb93a386Sopenharmony_ci const char* separator = ""; 424cb93a386Sopenharmony_ci for (int row = 0; row < type.rows(); ++row) { 425cb93a386Sopenharmony_ci for (int column = 0; column < type.columns(); ++column) { 426cb93a386Sopenharmony_ci fExtraFunctions.writeText(separator); 427cb93a386Sopenharmony_ci fExtraFunctions.writeText(("m[" + to_string(column) + "][" + to_string(row) + 428cb93a386Sopenharmony_ci "]").c_str()); 429cb93a386Sopenharmony_ci separator = ", "; 430cb93a386Sopenharmony_ci } 431cb93a386Sopenharmony_ci } 432cb93a386Sopenharmony_ci fExtraFunctions.writeText("); }"); 433cb93a386Sopenharmony_ci } 434cb93a386Sopenharmony_ci this->write(name + "("); 435cb93a386Sopenharmony_ci this->writeExpression(mat, Precedence::kTopLevel); 436cb93a386Sopenharmony_ci this->write(")"); 437cb93a386Sopenharmony_ci} 438cb93a386Sopenharmony_ci 439cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) { 440cb93a386Sopenharmony_ci const FunctionDeclaration& function = c.function(); 441cb93a386Sopenharmony_ci const ExpressionArray& arguments = c.arguments(); 442cb93a386Sopenharmony_ci bool isTextureFunctionWithBias = false; 443cb93a386Sopenharmony_ci bool nameWritten = false; 444cb93a386Sopenharmony_ci const char* closingParen = ")"; 445cb93a386Sopenharmony_ci switch (c.function().intrinsicKind()) { 446cb93a386Sopenharmony_ci case k_abs_IntrinsicKind: { 447cb93a386Sopenharmony_ci if (!this->caps().emulateAbsIntFunction()) 448cb93a386Sopenharmony_ci break; 449cb93a386Sopenharmony_ci SkASSERT(arguments.size() == 1); 450cb93a386Sopenharmony_ci if (arguments[0]->type() != *fContext.fTypes.fInt) { 451cb93a386Sopenharmony_ci break; 452cb93a386Sopenharmony_ci } 453cb93a386Sopenharmony_ci // abs(int) on Intel OSX is incorrect, so emulate it: 454cb93a386Sopenharmony_ci String name = "_absemulation"; 455cb93a386Sopenharmony_ci this->write(name); 456cb93a386Sopenharmony_ci nameWritten = true; 457cb93a386Sopenharmony_ci if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) { 458cb93a386Sopenharmony_ci fWrittenIntrinsics.insert(name); 459cb93a386Sopenharmony_ci fExtraFunctions.writeText(( 460cb93a386Sopenharmony_ci "int " + name + "(int x) {\n" 461cb93a386Sopenharmony_ci " return x * sign(x);\n" 462cb93a386Sopenharmony_ci "}\n" 463cb93a386Sopenharmony_ci ).c_str()); 464cb93a386Sopenharmony_ci } 465cb93a386Sopenharmony_ci break; 466cb93a386Sopenharmony_ci } 467cb93a386Sopenharmony_ci case k_atan_IntrinsicKind: 468cb93a386Sopenharmony_ci if (this->caps().mustForceNegatedAtanParamToFloat() && 469cb93a386Sopenharmony_ci arguments.size() == 2 && 470cb93a386Sopenharmony_ci arguments[1]->kind() == Expression::Kind::kPrefix) { 471cb93a386Sopenharmony_ci const PrefixExpression& p = (PrefixExpression&) *arguments[1]; 472cb93a386Sopenharmony_ci if (p.getOperator().kind() == Token::Kind::TK_MINUS) { 473cb93a386Sopenharmony_ci this->write("atan("); 474cb93a386Sopenharmony_ci this->writeExpression(*arguments[0], Precedence::kSequence); 475cb93a386Sopenharmony_ci this->write(", -1.0 * "); 476cb93a386Sopenharmony_ci this->writeExpression(*p.operand(), Precedence::kMultiplicative); 477cb93a386Sopenharmony_ci this->write(")"); 478cb93a386Sopenharmony_ci return; 479cb93a386Sopenharmony_ci } 480cb93a386Sopenharmony_ci } 481cb93a386Sopenharmony_ci break; 482cb93a386Sopenharmony_ci case k_ldexp_IntrinsicKind: 483cb93a386Sopenharmony_ci if (this->caps().mustForceNegatedLdexpParamToMultiply() && 484cb93a386Sopenharmony_ci arguments.size() == 2 && 485cb93a386Sopenharmony_ci arguments[1]->is<PrefixExpression>()) { 486cb93a386Sopenharmony_ci const PrefixExpression& p = arguments[1]->as<PrefixExpression>(); 487cb93a386Sopenharmony_ci if (p.getOperator().kind() == Token::Kind::TK_MINUS) { 488cb93a386Sopenharmony_ci this->write("ldexp("); 489cb93a386Sopenharmony_ci this->writeExpression(*arguments[0], Precedence::kSequence); 490cb93a386Sopenharmony_ci this->write(", "); 491cb93a386Sopenharmony_ci this->writeExpression(*p.operand(), Precedence::kMultiplicative); 492cb93a386Sopenharmony_ci this->write(" * -1)"); 493cb93a386Sopenharmony_ci return; 494cb93a386Sopenharmony_ci } 495cb93a386Sopenharmony_ci } 496cb93a386Sopenharmony_ci break; 497cb93a386Sopenharmony_ci case k_dFdy_IntrinsicKind: 498cb93a386Sopenharmony_ci // Flipping Y also negates the Y derivatives. 499cb93a386Sopenharmony_ci closingParen = "))"; 500cb93a386Sopenharmony_ci this->write("(" SKSL_RTFLIP_NAME ".y * dFdy"); 501cb93a386Sopenharmony_ci nameWritten = true; 502cb93a386Sopenharmony_ci [[fallthrough]]; 503cb93a386Sopenharmony_ci case k_dFdx_IntrinsicKind: 504cb93a386Sopenharmony_ci case k_fwidth_IntrinsicKind: 505cb93a386Sopenharmony_ci if (!fFoundDerivatives && 506cb93a386Sopenharmony_ci this->caps().shaderDerivativeExtensionString()) { 507cb93a386Sopenharmony_ci this->writeExtension(this->caps().shaderDerivativeExtensionString()); 508cb93a386Sopenharmony_ci fFoundDerivatives = true; 509cb93a386Sopenharmony_ci } 510cb93a386Sopenharmony_ci break; 511cb93a386Sopenharmony_ci case k_determinant_IntrinsicKind: 512cb93a386Sopenharmony_ci if (!this->caps().builtinDeterminantSupport()) { 513cb93a386Sopenharmony_ci SkASSERT(arguments.size() == 1); 514cb93a386Sopenharmony_ci this->writeDeterminantHack(*arguments[0]); 515cb93a386Sopenharmony_ci return; 516cb93a386Sopenharmony_ci } 517cb93a386Sopenharmony_ci break; 518cb93a386Sopenharmony_ci case k_fma_IntrinsicKind: 519cb93a386Sopenharmony_ci if (!this->caps().builtinFMASupport()) { 520cb93a386Sopenharmony_ci SkASSERT(arguments.size() == 3); 521cb93a386Sopenharmony_ci this->write("(("); 522cb93a386Sopenharmony_ci this->writeExpression(*arguments[0], Precedence::kSequence); 523cb93a386Sopenharmony_ci this->write(") * ("); 524cb93a386Sopenharmony_ci this->writeExpression(*arguments[1], Precedence::kSequence); 525cb93a386Sopenharmony_ci this->write(") + ("); 526cb93a386Sopenharmony_ci this->writeExpression(*arguments[2], Precedence::kSequence); 527cb93a386Sopenharmony_ci this->write("))"); 528cb93a386Sopenharmony_ci return; 529cb93a386Sopenharmony_ci } 530cb93a386Sopenharmony_ci break; 531cb93a386Sopenharmony_ci case k_fract_IntrinsicKind: 532cb93a386Sopenharmony_ci if (!this->caps().canUseFractForNegativeValues()) { 533cb93a386Sopenharmony_ci SkASSERT(arguments.size() == 1); 534cb93a386Sopenharmony_ci this->write("(0.5 - sign("); 535cb93a386Sopenharmony_ci this->writeExpression(*arguments[0], Precedence::kSequence); 536cb93a386Sopenharmony_ci this->write(") * (0.5 - fract(abs("); 537cb93a386Sopenharmony_ci this->writeExpression(*arguments[0], Precedence::kSequence); 538cb93a386Sopenharmony_ci this->write("))))"); 539cb93a386Sopenharmony_ci return; 540cb93a386Sopenharmony_ci } 541cb93a386Sopenharmony_ci break; 542cb93a386Sopenharmony_ci case k_inverse_IntrinsicKind: 543cb93a386Sopenharmony_ci if (this->caps().generation() < k140_GrGLSLGeneration) { 544cb93a386Sopenharmony_ci SkASSERT(arguments.size() == 1); 545cb93a386Sopenharmony_ci this->writeInverseHack(*arguments[0]); 546cb93a386Sopenharmony_ci return; 547cb93a386Sopenharmony_ci } 548cb93a386Sopenharmony_ci break; 549cb93a386Sopenharmony_ci case k_inversesqrt_IntrinsicKind: 550cb93a386Sopenharmony_ci if (this->caps().generation() < k130_GrGLSLGeneration) { 551cb93a386Sopenharmony_ci SkASSERT(arguments.size() == 1); 552cb93a386Sopenharmony_ci this->writeInverseSqrtHack(*arguments[0]); 553cb93a386Sopenharmony_ci return; 554cb93a386Sopenharmony_ci } 555cb93a386Sopenharmony_ci break; 556cb93a386Sopenharmony_ci case k_min_IntrinsicKind: 557cb93a386Sopenharmony_ci if (!this->caps().canUseMinAndAbsTogether()) { 558cb93a386Sopenharmony_ci SkASSERT(arguments.size() == 2); 559cb93a386Sopenharmony_ci if (is_abs(*arguments[0])) { 560cb93a386Sopenharmony_ci this->writeMinAbsHack(*arguments[0], *arguments[1]); 561cb93a386Sopenharmony_ci return; 562cb93a386Sopenharmony_ci } 563cb93a386Sopenharmony_ci if (is_abs(*arguments[1])) { 564cb93a386Sopenharmony_ci // note that this violates the GLSL left-to-right evaluation semantics. 565cb93a386Sopenharmony_ci // I doubt it will ever end up mattering, but it's worth calling out. 566cb93a386Sopenharmony_ci this->writeMinAbsHack(*arguments[1], *arguments[0]); 567cb93a386Sopenharmony_ci return; 568cb93a386Sopenharmony_ci } 569cb93a386Sopenharmony_ci } 570cb93a386Sopenharmony_ci break; 571cb93a386Sopenharmony_ci case k_pow_IntrinsicKind: 572cb93a386Sopenharmony_ci if (!this->caps().removePowWithConstantExponent()) { 573cb93a386Sopenharmony_ci break; 574cb93a386Sopenharmony_ci } 575cb93a386Sopenharmony_ci // pow(x, y) on some NVIDIA drivers causes crashes if y is a 576cb93a386Sopenharmony_ci // constant. It's hard to tell what constitutes "constant" here 577cb93a386Sopenharmony_ci // so just replace in all cases. 578cb93a386Sopenharmony_ci 579cb93a386Sopenharmony_ci // Change pow(x, y) into exp2(y * log2(x)) 580cb93a386Sopenharmony_ci this->write("exp2("); 581cb93a386Sopenharmony_ci this->writeExpression(*arguments[1], Precedence::kMultiplicative); 582cb93a386Sopenharmony_ci this->write(" * log2("); 583cb93a386Sopenharmony_ci this->writeExpression(*arguments[0], Precedence::kSequence); 584cb93a386Sopenharmony_ci this->write("))"); 585cb93a386Sopenharmony_ci return; 586cb93a386Sopenharmony_ci case k_saturate_IntrinsicKind: 587cb93a386Sopenharmony_ci SkASSERT(arguments.size() == 1); 588cb93a386Sopenharmony_ci this->write("clamp("); 589cb93a386Sopenharmony_ci this->writeExpression(*arguments[0], Precedence::kSequence); 590cb93a386Sopenharmony_ci this->write(", 0.0, 1.0)"); 591cb93a386Sopenharmony_ci return; 592cb93a386Sopenharmony_ci case k_sample_IntrinsicKind: { 593cb93a386Sopenharmony_ci const char* dim = ""; 594cb93a386Sopenharmony_ci bool proj = false; 595cb93a386Sopenharmony_ci const Type& arg0Type = arguments[0]->type(); 596cb93a386Sopenharmony_ci const Type& arg1Type = arguments[1]->type(); 597cb93a386Sopenharmony_ci switch (arg0Type.dimensions()) { 598cb93a386Sopenharmony_ci case SpvDim1D: 599cb93a386Sopenharmony_ci dim = "1D"; 600cb93a386Sopenharmony_ci isTextureFunctionWithBias = true; 601cb93a386Sopenharmony_ci if (arg1Type == *fContext.fTypes.fFloat) { 602cb93a386Sopenharmony_ci proj = false; 603cb93a386Sopenharmony_ci } else { 604cb93a386Sopenharmony_ci SkASSERT(arg1Type == *fContext.fTypes.fFloat2); 605cb93a386Sopenharmony_ci proj = true; 606cb93a386Sopenharmony_ci } 607cb93a386Sopenharmony_ci break; 608cb93a386Sopenharmony_ci case SpvDim2D: 609cb93a386Sopenharmony_ci dim = "2D"; 610cb93a386Sopenharmony_ci if (arg0Type != *fContext.fTypes.fSamplerExternalOES) { 611cb93a386Sopenharmony_ci isTextureFunctionWithBias = true; 612cb93a386Sopenharmony_ci } 613cb93a386Sopenharmony_ci if (arg1Type == *fContext.fTypes.fFloat2) { 614cb93a386Sopenharmony_ci proj = false; 615cb93a386Sopenharmony_ci } else { 616cb93a386Sopenharmony_ci SkASSERT(arg1Type == *fContext.fTypes.fFloat3); 617cb93a386Sopenharmony_ci proj = true; 618cb93a386Sopenharmony_ci } 619cb93a386Sopenharmony_ci break; 620cb93a386Sopenharmony_ci case SpvDim3D: 621cb93a386Sopenharmony_ci dim = "3D"; 622cb93a386Sopenharmony_ci isTextureFunctionWithBias = true; 623cb93a386Sopenharmony_ci if (arg1Type == *fContext.fTypes.fFloat3) { 624cb93a386Sopenharmony_ci proj = false; 625cb93a386Sopenharmony_ci } else { 626cb93a386Sopenharmony_ci SkASSERT(arg1Type == *fContext.fTypes.fFloat4); 627cb93a386Sopenharmony_ci proj = true; 628cb93a386Sopenharmony_ci } 629cb93a386Sopenharmony_ci break; 630cb93a386Sopenharmony_ci case SpvDimCube: 631cb93a386Sopenharmony_ci dim = "Cube"; 632cb93a386Sopenharmony_ci isTextureFunctionWithBias = true; 633cb93a386Sopenharmony_ci proj = false; 634cb93a386Sopenharmony_ci break; 635cb93a386Sopenharmony_ci case SpvDimRect: 636cb93a386Sopenharmony_ci dim = "2DRect"; 637cb93a386Sopenharmony_ci proj = false; 638cb93a386Sopenharmony_ci break; 639cb93a386Sopenharmony_ci case SpvDimBuffer: 640cb93a386Sopenharmony_ci SkASSERT(false); // doesn't exist 641cb93a386Sopenharmony_ci dim = "Buffer"; 642cb93a386Sopenharmony_ci proj = false; 643cb93a386Sopenharmony_ci break; 644cb93a386Sopenharmony_ci case SpvDimSubpassData: 645cb93a386Sopenharmony_ci SkASSERT(false); // doesn't exist 646cb93a386Sopenharmony_ci dim = "SubpassData"; 647cb93a386Sopenharmony_ci proj = false; 648cb93a386Sopenharmony_ci break; 649cb93a386Sopenharmony_ci } 650cb93a386Sopenharmony_ci if (!fTextureFunctionOverride.empty()) { 651cb93a386Sopenharmony_ci this->write(fTextureFunctionOverride.c_str()); 652cb93a386Sopenharmony_ci } else { 653cb93a386Sopenharmony_ci this->write("texture"); 654cb93a386Sopenharmony_ci if (this->caps().generation() < k130_GrGLSLGeneration) { 655cb93a386Sopenharmony_ci this->write(dim); 656cb93a386Sopenharmony_ci } 657cb93a386Sopenharmony_ci if (proj) { 658cb93a386Sopenharmony_ci this->write("Proj"); 659cb93a386Sopenharmony_ci } 660cb93a386Sopenharmony_ci } 661cb93a386Sopenharmony_ci nameWritten = true; 662cb93a386Sopenharmony_ci break; 663cb93a386Sopenharmony_ci } 664cb93a386Sopenharmony_ci case k_transpose_IntrinsicKind: 665cb93a386Sopenharmony_ci if (this->caps().generation() < k130_GrGLSLGeneration) { 666cb93a386Sopenharmony_ci SkASSERT(arguments.size() == 1); 667cb93a386Sopenharmony_ci this->writeTransposeHack(*arguments[0]); 668cb93a386Sopenharmony_ci return; 669cb93a386Sopenharmony_ci } 670cb93a386Sopenharmony_ci break; 671cb93a386Sopenharmony_ci default: 672cb93a386Sopenharmony_ci break; 673cb93a386Sopenharmony_ci } 674cb93a386Sopenharmony_ci 675cb93a386Sopenharmony_ci if (!nameWritten) { 676cb93a386Sopenharmony_ci this->write(function.mangledName()); 677cb93a386Sopenharmony_ci } 678cb93a386Sopenharmony_ci this->write("("); 679cb93a386Sopenharmony_ci const char* separator = ""; 680cb93a386Sopenharmony_ci for (const auto& arg : arguments) { 681cb93a386Sopenharmony_ci this->write(separator); 682cb93a386Sopenharmony_ci separator = ", "; 683cb93a386Sopenharmony_ci this->writeExpression(*arg, Precedence::kSequence); 684cb93a386Sopenharmony_ci } 685cb93a386Sopenharmony_ci if (fProgram.fConfig->fSettings.fSharpenTextures && isTextureFunctionWithBias) { 686cb93a386Sopenharmony_ci this->write(", -0.5"); 687cb93a386Sopenharmony_ci } 688cb93a386Sopenharmony_ci this->write(closingParen); 689cb93a386Sopenharmony_ci} 690cb93a386Sopenharmony_ci 691cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeConstructorDiagonalMatrix(const ConstructorDiagonalMatrix& c, 692cb93a386Sopenharmony_ci Precedence parentPrecedence) { 693cb93a386Sopenharmony_ci if (c.type().columns() == 4 && c.type().rows() == 2) { 694cb93a386Sopenharmony_ci // Due to a longstanding bug in glslang and Mesa, several GPU drivers generate diagonal 4x2 695cb93a386Sopenharmony_ci // matrices incorrectly. (skia:12003, https://github.com/KhronosGroup/glslang/pull/2646) 696cb93a386Sopenharmony_ci // We can work around this issue by multiplying a scalar by the identity matrix. 697cb93a386Sopenharmony_ci // In practice, this doesn't come up naturally in real code and we don't know every affected 698cb93a386Sopenharmony_ci // driver, so we just apply this workaround everywhere. 699cb93a386Sopenharmony_ci this->write("("); 700cb93a386Sopenharmony_ci this->writeType(c.type()); 701cb93a386Sopenharmony_ci this->write("(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) * "); 702cb93a386Sopenharmony_ci this->writeExpression(*c.argument(), Precedence::kMultiplicative); 703cb93a386Sopenharmony_ci this->write(")"); 704cb93a386Sopenharmony_ci return; 705cb93a386Sopenharmony_ci } 706cb93a386Sopenharmony_ci this->writeAnyConstructor(c, parentPrecedence); 707cb93a386Sopenharmony_ci} 708cb93a386Sopenharmony_ci 709cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeCastConstructor(const AnyConstructor& c, Precedence parentPrecedence) { 710cb93a386Sopenharmony_ci const auto arguments = c.argumentSpan(); 711cb93a386Sopenharmony_ci SkASSERT(arguments.size() == 1); 712cb93a386Sopenharmony_ci 713cb93a386Sopenharmony_ci const Expression& argument = *arguments.front(); 714cb93a386Sopenharmony_ci if ((this->getTypeName(c.type()) == this->getTypeName(argument.type()) || 715cb93a386Sopenharmony_ci (argument.type() == *fContext.fTypes.fFloatLiteral))) { 716cb93a386Sopenharmony_ci // In cases like half(float), they're different types as far as SkSL is concerned but 717cb93a386Sopenharmony_ci // the same type as far as GLSL is concerned. We avoid a redundant float(float) by just 718cb93a386Sopenharmony_ci // writing out the inner expression here. 719cb93a386Sopenharmony_ci this->writeExpression(argument, parentPrecedence); 720cb93a386Sopenharmony_ci return; 721cb93a386Sopenharmony_ci } 722cb93a386Sopenharmony_ci 723cb93a386Sopenharmony_ci // This cast should be emitted as-is. 724cb93a386Sopenharmony_ci return this->writeAnyConstructor(c, parentPrecedence); 725cb93a386Sopenharmony_ci} 726cb93a386Sopenharmony_ci 727cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeAnyConstructor(const AnyConstructor& c, Precedence parentPrecedence) { 728cb93a386Sopenharmony_ci this->writeType(c.type()); 729cb93a386Sopenharmony_ci this->write("("); 730cb93a386Sopenharmony_ci const char* separator = ""; 731cb93a386Sopenharmony_ci for (const auto& arg : c.argumentSpan()) { 732cb93a386Sopenharmony_ci this->write(separator); 733cb93a386Sopenharmony_ci separator = ", "; 734cb93a386Sopenharmony_ci this->writeExpression(*arg, Precedence::kSequence); 735cb93a386Sopenharmony_ci } 736cb93a386Sopenharmony_ci this->write(")"); 737cb93a386Sopenharmony_ci} 738cb93a386Sopenharmony_ci 739cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeFragCoord() { 740cb93a386Sopenharmony_ci if (!this->caps().canUseFragCoord()) { 741cb93a386Sopenharmony_ci if (!fSetupFragCoordWorkaround) { 742cb93a386Sopenharmony_ci const char* precision = usesPrecisionModifiers() ? "highp " : ""; 743cb93a386Sopenharmony_ci fFunctionHeader += precision; 744cb93a386Sopenharmony_ci fFunctionHeader += " float sk_FragCoord_InvW = 1. / sk_FragCoord_Workaround.w;\n"; 745cb93a386Sopenharmony_ci fFunctionHeader += precision; 746cb93a386Sopenharmony_ci fFunctionHeader += " vec4 sk_FragCoord_Resolved = " 747cb93a386Sopenharmony_ci "vec4(sk_FragCoord_Workaround.xyz * sk_FragCoord_InvW, sk_FragCoord_InvW);\n"; 748cb93a386Sopenharmony_ci // Ensure that we get exact .5 values for x and y. 749cb93a386Sopenharmony_ci fFunctionHeader += " sk_FragCoord_Resolved.xy = floor(sk_FragCoord_Resolved.xy) + " 750cb93a386Sopenharmony_ci "vec2(.5);\n"; 751cb93a386Sopenharmony_ci fSetupFragCoordWorkaround = true; 752cb93a386Sopenharmony_ci } 753cb93a386Sopenharmony_ci this->write("sk_FragCoord_Resolved"); 754cb93a386Sopenharmony_ci return; 755cb93a386Sopenharmony_ci } 756cb93a386Sopenharmony_ci 757cb93a386Sopenharmony_ci if (!fSetupFragPosition) { 758cb93a386Sopenharmony_ci fFunctionHeader += usesPrecisionModifiers() ? "highp " : ""; 759cb93a386Sopenharmony_ci fFunctionHeader += " vec4 sk_FragCoord = vec4(" 760cb93a386Sopenharmony_ci "gl_FragCoord.x, " 761cb93a386Sopenharmony_ci SKSL_RTFLIP_NAME ".x + " SKSL_RTFLIP_NAME ".y * gl_FragCoord.y, " 762cb93a386Sopenharmony_ci "gl_FragCoord.z, " 763cb93a386Sopenharmony_ci "gl_FragCoord.w);\n"; 764cb93a386Sopenharmony_ci fSetupFragPosition = true; 765cb93a386Sopenharmony_ci } 766cb93a386Sopenharmony_ci this->write("sk_FragCoord"); 767cb93a386Sopenharmony_ci} 768cb93a386Sopenharmony_ci 769cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) { 770cb93a386Sopenharmony_ci switch (ref.variable()->modifiers().fLayout.fBuiltin) { 771cb93a386Sopenharmony_ci case SK_FRAGCOLOR_BUILTIN: 772cb93a386Sopenharmony_ci if (this->caps().mustDeclareFragmentShaderOutput()) { 773cb93a386Sopenharmony_ci this->write("sk_FragColor"); 774cb93a386Sopenharmony_ci } else { 775cb93a386Sopenharmony_ci this->write("gl_FragColor"); 776cb93a386Sopenharmony_ci } 777cb93a386Sopenharmony_ci break; 778cb93a386Sopenharmony_ci case SK_SECONDARYFRAGCOLOR_BUILTIN: 779cb93a386Sopenharmony_ci this->write("gl_SecondaryFragColorEXT"); 780cb93a386Sopenharmony_ci break; 781cb93a386Sopenharmony_ci case SK_FRAGCOORD_BUILTIN: 782cb93a386Sopenharmony_ci this->writeFragCoord(); 783cb93a386Sopenharmony_ci break; 784cb93a386Sopenharmony_ci case SK_CLOCKWISE_BUILTIN: 785cb93a386Sopenharmony_ci if (!fSetupClockwise) { 786cb93a386Sopenharmony_ci fFunctionHeader += 787cb93a386Sopenharmony_ci " bool sk_Clockwise = gl_FrontFacing;\n" 788cb93a386Sopenharmony_ci " if (" SKSL_RTFLIP_NAME ".y < 0.0) {\n" 789cb93a386Sopenharmony_ci " sk_Clockwise = !sk_Clockwise;\n" 790cb93a386Sopenharmony_ci " }\n"; 791cb93a386Sopenharmony_ci fSetupClockwise = true; 792cb93a386Sopenharmony_ci } 793cb93a386Sopenharmony_ci this->write("sk_Clockwise"); 794cb93a386Sopenharmony_ci break; 795cb93a386Sopenharmony_ci case SK_VERTEXID_BUILTIN: 796cb93a386Sopenharmony_ci this->write("gl_VertexID"); 797cb93a386Sopenharmony_ci break; 798cb93a386Sopenharmony_ci case SK_INSTANCEID_BUILTIN: 799cb93a386Sopenharmony_ci this->write("gl_InstanceID"); 800cb93a386Sopenharmony_ci break; 801cb93a386Sopenharmony_ci case SK_LASTFRAGCOLOR_BUILTIN: 802cb93a386Sopenharmony_ci if (this->caps().fbFetchSupport()) { 803cb93a386Sopenharmony_ci this->write(this->caps().fbFetchColorName()); 804cb93a386Sopenharmony_ci } else { 805cb93a386Sopenharmony_ci fContext.fErrors->error(ref.fLine, 806cb93a386Sopenharmony_ci "sk_LastFragColor requires framebuffer fetch support"); 807cb93a386Sopenharmony_ci } 808cb93a386Sopenharmony_ci break; 809cb93a386Sopenharmony_ci default: 810cb93a386Sopenharmony_ci this->write(ref.variable()->name()); 811cb93a386Sopenharmony_ci break; 812cb93a386Sopenharmony_ci } 813cb93a386Sopenharmony_ci} 814cb93a386Sopenharmony_ci 815cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeIndexExpression(const IndexExpression& expr) { 816cb93a386Sopenharmony_ci this->writeExpression(*expr.base(), Precedence::kPostfix); 817cb93a386Sopenharmony_ci this->write("["); 818cb93a386Sopenharmony_ci this->writeExpression(*expr.index(), Precedence::kTopLevel); 819cb93a386Sopenharmony_ci this->write("]"); 820cb93a386Sopenharmony_ci} 821cb93a386Sopenharmony_ci 822cb93a386Sopenharmony_cibool is_sk_position(const FieldAccess& f) { 823cb93a386Sopenharmony_ci return "sk_Position" == f.base()->type().fields()[f.fieldIndex()].fName; 824cb93a386Sopenharmony_ci} 825cb93a386Sopenharmony_ci 826cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeFieldAccess(const FieldAccess& f) { 827cb93a386Sopenharmony_ci if (f.ownerKind() == FieldAccess::OwnerKind::kDefault) { 828cb93a386Sopenharmony_ci this->writeExpression(*f.base(), Precedence::kPostfix); 829cb93a386Sopenharmony_ci this->write("."); 830cb93a386Sopenharmony_ci } 831cb93a386Sopenharmony_ci const Type& baseType = f.base()->type(); 832cb93a386Sopenharmony_ci skstd::string_view name = baseType.fields()[f.fieldIndex()].fName; 833cb93a386Sopenharmony_ci if (name == "sk_Position") { 834cb93a386Sopenharmony_ci this->write("gl_Position"); 835cb93a386Sopenharmony_ci } else if (name == "sk_PointSize") { 836cb93a386Sopenharmony_ci this->write("gl_PointSize"); 837cb93a386Sopenharmony_ci } else { 838cb93a386Sopenharmony_ci this->write(baseType.fields()[f.fieldIndex()].fName); 839cb93a386Sopenharmony_ci } 840cb93a386Sopenharmony_ci} 841cb93a386Sopenharmony_ci 842cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeSwizzle(const Swizzle& swizzle) { 843cb93a386Sopenharmony_ci this->writeExpression(*swizzle.base(), Precedence::kPostfix); 844cb93a386Sopenharmony_ci this->write("."); 845cb93a386Sopenharmony_ci for (int c : swizzle.components()) { 846cb93a386Sopenharmony_ci SkASSERT(c >= 0 && c <= 3); 847cb93a386Sopenharmony_ci this->write(&("x\0y\0z\0w\0"[c * 2])); 848cb93a386Sopenharmony_ci } 849cb93a386Sopenharmony_ci} 850cb93a386Sopenharmony_ci 851cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeMatrixComparisonWorkaround(const BinaryExpression& b) { 852cb93a386Sopenharmony_ci const Expression& left = *b.left(); 853cb93a386Sopenharmony_ci const Expression& right = *b.right(); 854cb93a386Sopenharmony_ci Operator op = b.getOperator(); 855cb93a386Sopenharmony_ci 856cb93a386Sopenharmony_ci SkASSERT(op.kind() == Token::Kind::TK_EQEQ || op.kind() == Token::Kind::TK_NEQ); 857cb93a386Sopenharmony_ci SkASSERT(left.type().isMatrix()); 858cb93a386Sopenharmony_ci SkASSERT(right.type().isMatrix()); 859cb93a386Sopenharmony_ci 860cb93a386Sopenharmony_ci String tempMatrix1 = "_tempMatrix" + to_string(fVarCount++); 861cb93a386Sopenharmony_ci String tempMatrix2 = "_tempMatrix" + to_string(fVarCount++); 862cb93a386Sopenharmony_ci 863cb93a386Sopenharmony_ci this->fFunctionHeader += String(" ") + this->getTypePrecision(left.type()) + 864cb93a386Sopenharmony_ci this->getTypeName(left.type()) + " " + tempMatrix1 + ";\n " + 865cb93a386Sopenharmony_ci this->getTypePrecision(right.type()) + 866cb93a386Sopenharmony_ci this->getTypeName(right.type()) + " " + tempMatrix2 + ";\n"; 867cb93a386Sopenharmony_ci this->write("((" + tempMatrix1 + " = "); 868cb93a386Sopenharmony_ci this->writeExpression(left, Precedence::kAssignment); 869cb93a386Sopenharmony_ci this->write("), (" + tempMatrix2 + " = "); 870cb93a386Sopenharmony_ci this->writeExpression(right, Precedence::kAssignment); 871cb93a386Sopenharmony_ci this->write("), (" + tempMatrix1 + " "); 872cb93a386Sopenharmony_ci this->write(op.operatorName()); 873cb93a386Sopenharmony_ci this->write(" " + tempMatrix2 + "))"); 874cb93a386Sopenharmony_ci} 875cb93a386Sopenharmony_ci 876cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b, 877cb93a386Sopenharmony_ci Precedence parentPrecedence) { 878cb93a386Sopenharmony_ci const Expression& left = *b.left(); 879cb93a386Sopenharmony_ci const Expression& right = *b.right(); 880cb93a386Sopenharmony_ci Operator op = b.getOperator(); 881cb93a386Sopenharmony_ci if (this->caps().unfoldShortCircuitAsTernary() && 882cb93a386Sopenharmony_ci (op.kind() == Token::Kind::TK_LOGICALAND || op.kind() == Token::Kind::TK_LOGICALOR)) { 883cb93a386Sopenharmony_ci this->writeShortCircuitWorkaroundExpression(b, parentPrecedence); 884cb93a386Sopenharmony_ci return; 885cb93a386Sopenharmony_ci } 886cb93a386Sopenharmony_ci 887cb93a386Sopenharmony_ci if (this->caps().rewriteMatrixComparisons() && 888cb93a386Sopenharmony_ci left.type().isMatrix() && right.type().isMatrix() && 889cb93a386Sopenharmony_ci (op.kind() == Token::Kind::TK_EQEQ || op.kind() == Token::Kind::TK_NEQ)) { 890cb93a386Sopenharmony_ci this->writeMatrixComparisonWorkaround(b); 891cb93a386Sopenharmony_ci return; 892cb93a386Sopenharmony_ci } 893cb93a386Sopenharmony_ci 894cb93a386Sopenharmony_ci Precedence precedence = op.getBinaryPrecedence(); 895cb93a386Sopenharmony_ci if (precedence >= parentPrecedence) { 896cb93a386Sopenharmony_ci this->write("("); 897cb93a386Sopenharmony_ci } 898cb93a386Sopenharmony_ci bool positionWorkaround = fProgram.fConfig->fKind == ProgramKind::kVertex && 899cb93a386Sopenharmony_ci op.isAssignment() && 900cb93a386Sopenharmony_ci left.is<FieldAccess>() && 901cb93a386Sopenharmony_ci is_sk_position(left.as<FieldAccess>()) && 902cb93a386Sopenharmony_ci !right.containsRTAdjust() && 903cb93a386Sopenharmony_ci !this->caps().canUseFragCoord(); 904cb93a386Sopenharmony_ci if (positionWorkaround) { 905cb93a386Sopenharmony_ci this->write("sk_FragCoord_Workaround = ("); 906cb93a386Sopenharmony_ci } 907cb93a386Sopenharmony_ci this->writeExpression(left, precedence); 908cb93a386Sopenharmony_ci this->write(" "); 909cb93a386Sopenharmony_ci this->write(op.operatorName()); 910cb93a386Sopenharmony_ci this->write(" "); 911cb93a386Sopenharmony_ci this->writeExpression(right, precedence); 912cb93a386Sopenharmony_ci if (positionWorkaround) { 913cb93a386Sopenharmony_ci this->write(")"); 914cb93a386Sopenharmony_ci } 915cb93a386Sopenharmony_ci if (precedence >= parentPrecedence) { 916cb93a386Sopenharmony_ci this->write(")"); 917cb93a386Sopenharmony_ci } 918cb93a386Sopenharmony_ci} 919cb93a386Sopenharmony_ci 920cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeShortCircuitWorkaroundExpression(const BinaryExpression& b, 921cb93a386Sopenharmony_ci Precedence parentPrecedence) { 922cb93a386Sopenharmony_ci if (Precedence::kTernary >= parentPrecedence) { 923cb93a386Sopenharmony_ci this->write("("); 924cb93a386Sopenharmony_ci } 925cb93a386Sopenharmony_ci 926cb93a386Sopenharmony_ci // Transform: 927cb93a386Sopenharmony_ci // a && b => a ? b : false 928cb93a386Sopenharmony_ci // a || b => a ? true : b 929cb93a386Sopenharmony_ci this->writeExpression(*b.left(), Precedence::kTernary); 930cb93a386Sopenharmony_ci this->write(" ? "); 931cb93a386Sopenharmony_ci if (b.getOperator().kind() == Token::Kind::TK_LOGICALAND) { 932cb93a386Sopenharmony_ci this->writeExpression(*b.right(), Precedence::kTernary); 933cb93a386Sopenharmony_ci } else { 934cb93a386Sopenharmony_ci Literal boolTrue(/*line=*/-1, /*value=*/1, fContext.fTypes.fBool.get()); 935cb93a386Sopenharmony_ci this->writeLiteral(boolTrue); 936cb93a386Sopenharmony_ci } 937cb93a386Sopenharmony_ci this->write(" : "); 938cb93a386Sopenharmony_ci if (b.getOperator().kind() == Token::Kind::TK_LOGICALAND) { 939cb93a386Sopenharmony_ci Literal boolFalse(/*line=*/-1, /*value=*/0, fContext.fTypes.fBool.get()); 940cb93a386Sopenharmony_ci this->writeLiteral(boolFalse); 941cb93a386Sopenharmony_ci } else { 942cb93a386Sopenharmony_ci this->writeExpression(*b.right(), Precedence::kTernary); 943cb93a386Sopenharmony_ci } 944cb93a386Sopenharmony_ci if (Precedence::kTernary >= parentPrecedence) { 945cb93a386Sopenharmony_ci this->write(")"); 946cb93a386Sopenharmony_ci } 947cb93a386Sopenharmony_ci} 948cb93a386Sopenharmony_ci 949cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeTernaryExpression(const TernaryExpression& t, 950cb93a386Sopenharmony_ci Precedence parentPrecedence) { 951cb93a386Sopenharmony_ci if (Precedence::kTernary >= parentPrecedence) { 952cb93a386Sopenharmony_ci this->write("("); 953cb93a386Sopenharmony_ci } 954cb93a386Sopenharmony_ci this->writeExpression(*t.test(), Precedence::kTernary); 955cb93a386Sopenharmony_ci this->write(" ? "); 956cb93a386Sopenharmony_ci this->writeExpression(*t.ifTrue(), Precedence::kTernary); 957cb93a386Sopenharmony_ci this->write(" : "); 958cb93a386Sopenharmony_ci this->writeExpression(*t.ifFalse(), Precedence::kTernary); 959cb93a386Sopenharmony_ci if (Precedence::kTernary >= parentPrecedence) { 960cb93a386Sopenharmony_ci this->write(")"); 961cb93a386Sopenharmony_ci } 962cb93a386Sopenharmony_ci} 963cb93a386Sopenharmony_ci 964cb93a386Sopenharmony_civoid GLSLCodeGenerator::writePrefixExpression(const PrefixExpression& p, 965cb93a386Sopenharmony_ci Precedence parentPrecedence) { 966cb93a386Sopenharmony_ci if (Precedence::kPrefix >= parentPrecedence) { 967cb93a386Sopenharmony_ci this->write("("); 968cb93a386Sopenharmony_ci } 969cb93a386Sopenharmony_ci this->write(p.getOperator().operatorName()); 970cb93a386Sopenharmony_ci this->writeExpression(*p.operand(), Precedence::kPrefix); 971cb93a386Sopenharmony_ci if (Precedence::kPrefix >= parentPrecedence) { 972cb93a386Sopenharmony_ci this->write(")"); 973cb93a386Sopenharmony_ci } 974cb93a386Sopenharmony_ci} 975cb93a386Sopenharmony_ci 976cb93a386Sopenharmony_civoid GLSLCodeGenerator::writePostfixExpression(const PostfixExpression& p, 977cb93a386Sopenharmony_ci Precedence parentPrecedence) { 978cb93a386Sopenharmony_ci if (Precedence::kPostfix >= parentPrecedence) { 979cb93a386Sopenharmony_ci this->write("("); 980cb93a386Sopenharmony_ci } 981cb93a386Sopenharmony_ci this->writeExpression(*p.operand(), Precedence::kPostfix); 982cb93a386Sopenharmony_ci this->write(p.getOperator().operatorName()); 983cb93a386Sopenharmony_ci if (Precedence::kPostfix >= parentPrecedence) { 984cb93a386Sopenharmony_ci this->write(")"); 985cb93a386Sopenharmony_ci } 986cb93a386Sopenharmony_ci} 987cb93a386Sopenharmony_ci 988cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeLiteral(const Literal& l) { 989cb93a386Sopenharmony_ci const Type& type = l.type(); 990cb93a386Sopenharmony_ci if (type.isFloat()) { 991cb93a386Sopenharmony_ci this->write(to_string(l.floatValue())); 992cb93a386Sopenharmony_ci return; 993cb93a386Sopenharmony_ci } 994cb93a386Sopenharmony_ci if (type.isInteger()) { 995cb93a386Sopenharmony_ci if (type == *fContext.fTypes.fUInt) { 996cb93a386Sopenharmony_ci this->write(to_string(l.intValue() & 0xffffffff) + "u"); 997cb93a386Sopenharmony_ci } else if (type == *fContext.fTypes.fUShort) { 998cb93a386Sopenharmony_ci this->write(to_string(l.intValue() & 0xffff) + "u"); 999cb93a386Sopenharmony_ci } else { 1000cb93a386Sopenharmony_ci this->write(to_string(l.intValue())); 1001cb93a386Sopenharmony_ci } 1002cb93a386Sopenharmony_ci return; 1003cb93a386Sopenharmony_ci } 1004cb93a386Sopenharmony_ci SkASSERT(type.isBoolean()); 1005cb93a386Sopenharmony_ci this->write(l.boolValue() ? "true" : "false"); 1006cb93a386Sopenharmony_ci} 1007cb93a386Sopenharmony_ci 1008cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeSetting(const Setting& s) { 1009cb93a386Sopenharmony_ci SK_ABORT("internal error; setting was not folded to a constant during compilation\n"); 1010cb93a386Sopenharmony_ci} 1011cb93a386Sopenharmony_ci 1012cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeFunctionDeclaration(const FunctionDeclaration& f) { 1013cb93a386Sopenharmony_ci this->writeTypePrecision(f.returnType()); 1014cb93a386Sopenharmony_ci this->writeType(f.returnType()); 1015cb93a386Sopenharmony_ci this->write(" " + f.mangledName() + "("); 1016cb93a386Sopenharmony_ci const char* separator = ""; 1017cb93a386Sopenharmony_ci for (const auto& param : f.parameters()) { 1018cb93a386Sopenharmony_ci // This is a workaround for our test files. They use the runtime effect signature, so main 1019cb93a386Sopenharmony_ci // takes a coords parameter. The IR generator tags those with a builtin ID (sk_FragCoord), 1020cb93a386Sopenharmony_ci // and we omit them from the declaration here, so the function is valid GLSL. 1021cb93a386Sopenharmony_ci if (f.isMain() && param->modifiers().fLayout.fBuiltin != -1) { 1022cb93a386Sopenharmony_ci continue; 1023cb93a386Sopenharmony_ci } 1024cb93a386Sopenharmony_ci this->write(separator); 1025cb93a386Sopenharmony_ci separator = ", "; 1026cb93a386Sopenharmony_ci this->writeModifiers(param->modifiers(), false); 1027cb93a386Sopenharmony_ci std::vector<int> sizes; 1028cb93a386Sopenharmony_ci const Type* type = ¶m->type(); 1029cb93a386Sopenharmony_ci if (type->isArray()) { 1030cb93a386Sopenharmony_ci sizes.push_back(type->columns()); 1031cb93a386Sopenharmony_ci type = &type->componentType(); 1032cb93a386Sopenharmony_ci } 1033cb93a386Sopenharmony_ci this->writeTypePrecision(*type); 1034cb93a386Sopenharmony_ci this->writeType(*type); 1035cb93a386Sopenharmony_ci this->write(" " + param->name()); 1036cb93a386Sopenharmony_ci for (int s : sizes) { 1037cb93a386Sopenharmony_ci this->write("[" + to_string(s) + "]"); 1038cb93a386Sopenharmony_ci } 1039cb93a386Sopenharmony_ci } 1040cb93a386Sopenharmony_ci this->write(")"); 1041cb93a386Sopenharmony_ci} 1042cb93a386Sopenharmony_ci 1043cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) { 1044cb93a386Sopenharmony_ci fSetupFragPosition = false; 1045cb93a386Sopenharmony_ci fSetupFragCoordWorkaround = false; 1046cb93a386Sopenharmony_ci 1047cb93a386Sopenharmony_ci this->writeFunctionDeclaration(f.declaration()); 1048cb93a386Sopenharmony_ci this->writeLine(" {"); 1049cb93a386Sopenharmony_ci fIndentation++; 1050cb93a386Sopenharmony_ci 1051cb93a386Sopenharmony_ci fFunctionHeader.clear(); 1052cb93a386Sopenharmony_ci OutputStream* oldOut = fOut; 1053cb93a386Sopenharmony_ci StringStream buffer; 1054cb93a386Sopenharmony_ci fOut = &buffer; 1055cb93a386Sopenharmony_ci for (const std::unique_ptr<Statement>& stmt : f.body()->as<Block>().children()) { 1056cb93a386Sopenharmony_ci if (!stmt->isEmpty()) { 1057cb93a386Sopenharmony_ci this->writeStatement(*stmt); 1058cb93a386Sopenharmony_ci this->finishLine(); 1059cb93a386Sopenharmony_ci } 1060cb93a386Sopenharmony_ci } 1061cb93a386Sopenharmony_ci 1062cb93a386Sopenharmony_ci fIndentation--; 1063cb93a386Sopenharmony_ci this->writeLine("}"); 1064cb93a386Sopenharmony_ci 1065cb93a386Sopenharmony_ci fOut = oldOut; 1066cb93a386Sopenharmony_ci this->write(fFunctionHeader); 1067cb93a386Sopenharmony_ci this->write(buffer.str()); 1068cb93a386Sopenharmony_ci} 1069cb93a386Sopenharmony_ci 1070cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeFunctionPrototype(const FunctionPrototype& f) { 1071cb93a386Sopenharmony_ci this->writeFunctionDeclaration(f.declaration()); 1072cb93a386Sopenharmony_ci this->writeLine(";"); 1073cb93a386Sopenharmony_ci} 1074cb93a386Sopenharmony_ci 1075cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers, 1076cb93a386Sopenharmony_ci bool globalContext) { 1077cb93a386Sopenharmony_ci String layout = modifiers.fLayout.description(); 1078cb93a386Sopenharmony_ci if (layout.size()) { 1079cb93a386Sopenharmony_ci this->write(layout + " "); 1080cb93a386Sopenharmony_ci } 1081cb93a386Sopenharmony_ci 1082cb93a386Sopenharmony_ci // For GLSL 4.1 and below, qualifier-order matters! These are written out in Modifier-bit order. 1083cb93a386Sopenharmony_ci if (modifiers.fFlags & Modifiers::kFlat_Flag) { 1084cb93a386Sopenharmony_ci this->write("flat "); 1085cb93a386Sopenharmony_ci } 1086cb93a386Sopenharmony_ci if (modifiers.fFlags & Modifiers::kNoPerspective_Flag) { 1087cb93a386Sopenharmony_ci this->write("noperspective "); 1088cb93a386Sopenharmony_ci } 1089cb93a386Sopenharmony_ci 1090cb93a386Sopenharmony_ci if (modifiers.fFlags & Modifiers::kConst_Flag) { 1091cb93a386Sopenharmony_ci this->write("const "); 1092cb93a386Sopenharmony_ci } 1093cb93a386Sopenharmony_ci if (modifiers.fFlags & Modifiers::kUniform_Flag) { 1094cb93a386Sopenharmony_ci this->write("uniform "); 1095cb93a386Sopenharmony_ci } 1096cb93a386Sopenharmony_ci if ((modifiers.fFlags & Modifiers::kIn_Flag) && 1097cb93a386Sopenharmony_ci (modifiers.fFlags & Modifiers::kOut_Flag)) { 1098cb93a386Sopenharmony_ci this->write("inout "); 1099cb93a386Sopenharmony_ci } else if (modifiers.fFlags & Modifiers::kIn_Flag) { 1100cb93a386Sopenharmony_ci if (globalContext && 1101cb93a386Sopenharmony_ci this->caps().generation() < GrGLSLGeneration::k130_GrGLSLGeneration) { 1102cb93a386Sopenharmony_ci this->write(fProgram.fConfig->fKind == ProgramKind::kVertex ? "attribute " 1103cb93a386Sopenharmony_ci : "varying "); 1104cb93a386Sopenharmony_ci } else { 1105cb93a386Sopenharmony_ci this->write("in "); 1106cb93a386Sopenharmony_ci } 1107cb93a386Sopenharmony_ci } else if (modifiers.fFlags & Modifiers::kOut_Flag) { 1108cb93a386Sopenharmony_ci if (globalContext && 1109cb93a386Sopenharmony_ci this->caps().generation() < GrGLSLGeneration::k130_GrGLSLGeneration) { 1110cb93a386Sopenharmony_ci this->write("varying "); 1111cb93a386Sopenharmony_ci } else { 1112cb93a386Sopenharmony_ci this->write("out "); 1113cb93a386Sopenharmony_ci } 1114cb93a386Sopenharmony_ci } 1115cb93a386Sopenharmony_ci 1116cb93a386Sopenharmony_ci} 1117cb93a386Sopenharmony_ci 1118cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) { 1119cb93a386Sopenharmony_ci if (intf.typeName() == "sk_PerVertex") { 1120cb93a386Sopenharmony_ci return; 1121cb93a386Sopenharmony_ci } 1122cb93a386Sopenharmony_ci this->writeModifiers(intf.variable().modifiers(), true); 1123cb93a386Sopenharmony_ci this->writeLine(intf.typeName() + " {"); 1124cb93a386Sopenharmony_ci fIndentation++; 1125cb93a386Sopenharmony_ci const Type* structType = &intf.variable().type(); 1126cb93a386Sopenharmony_ci if (structType->isArray()) { 1127cb93a386Sopenharmony_ci structType = &structType->componentType(); 1128cb93a386Sopenharmony_ci } 1129cb93a386Sopenharmony_ci for (const auto& f : structType->fields()) { 1130cb93a386Sopenharmony_ci this->writeModifiers(f.fModifiers, false); 1131cb93a386Sopenharmony_ci this->writeTypePrecision(*f.fType); 1132cb93a386Sopenharmony_ci this->writeType(*f.fType); 1133cb93a386Sopenharmony_ci this->writeLine(" " + f.fName + ";"); 1134cb93a386Sopenharmony_ci } 1135cb93a386Sopenharmony_ci fIndentation--; 1136cb93a386Sopenharmony_ci this->write("}"); 1137cb93a386Sopenharmony_ci if (intf.instanceName().size()) { 1138cb93a386Sopenharmony_ci this->write(" "); 1139cb93a386Sopenharmony_ci this->write(intf.instanceName()); 1140cb93a386Sopenharmony_ci if (intf.arraySize() > 0) { 1141cb93a386Sopenharmony_ci this->write("["); 1142cb93a386Sopenharmony_ci this->write(to_string(intf.arraySize())); 1143cb93a386Sopenharmony_ci this->write("]"); 1144cb93a386Sopenharmony_ci } 1145cb93a386Sopenharmony_ci } 1146cb93a386Sopenharmony_ci this->writeLine(";"); 1147cb93a386Sopenharmony_ci} 1148cb93a386Sopenharmony_ci 1149cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeVarInitializer(const Variable& var, const Expression& value) { 1150cb93a386Sopenharmony_ci this->writeExpression(value, Precedence::kTopLevel); 1151cb93a386Sopenharmony_ci} 1152cb93a386Sopenharmony_ci 1153cb93a386Sopenharmony_ciconst char* GLSLCodeGenerator::getTypePrecision(const Type& type) { 1154cb93a386Sopenharmony_ci if (usesPrecisionModifiers()) { 1155cb93a386Sopenharmony_ci switch (type.typeKind()) { 1156cb93a386Sopenharmony_ci case Type::TypeKind::kScalar: 1157cb93a386Sopenharmony_ci if (type == *fContext.fTypes.fShort || type == *fContext.fTypes.fUShort) { 1158cb93a386Sopenharmony_ci if (fProgram.fConfig->fSettings.fForceHighPrecision || 1159cb93a386Sopenharmony_ci this->caps().incompleteShortIntPrecision()) { 1160cb93a386Sopenharmony_ci return "highp "; 1161cb93a386Sopenharmony_ci } 1162cb93a386Sopenharmony_ci return "mediump "; 1163cb93a386Sopenharmony_ci } 1164cb93a386Sopenharmony_ci if (type == *fContext.fTypes.fHalf) { 1165cb93a386Sopenharmony_ci return fProgram.fConfig->fSettings.fForceHighPrecision ? "highp " : "mediump "; 1166cb93a386Sopenharmony_ci } 1167cb93a386Sopenharmony_ci if (type == *fContext.fTypes.fFloat || type == *fContext.fTypes.fInt || 1168cb93a386Sopenharmony_ci type == *fContext.fTypes.fUInt) { 1169cb93a386Sopenharmony_ci return "highp "; 1170cb93a386Sopenharmony_ci } 1171cb93a386Sopenharmony_ci return ""; 1172cb93a386Sopenharmony_ci case Type::TypeKind::kVector: // fall through 1173cb93a386Sopenharmony_ci case Type::TypeKind::kMatrix: 1174cb93a386Sopenharmony_ci case Type::TypeKind::kArray: 1175cb93a386Sopenharmony_ci return this->getTypePrecision(type.componentType()); 1176cb93a386Sopenharmony_ci default: 1177cb93a386Sopenharmony_ci break; 1178cb93a386Sopenharmony_ci } 1179cb93a386Sopenharmony_ci } 1180cb93a386Sopenharmony_ci return ""; 1181cb93a386Sopenharmony_ci} 1182cb93a386Sopenharmony_ci 1183cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeTypePrecision(const Type& type) { 1184cb93a386Sopenharmony_ci this->write(this->getTypePrecision(type)); 1185cb93a386Sopenharmony_ci} 1186cb93a386Sopenharmony_ci 1187cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeVarDeclaration(const VarDeclaration& var, bool global) { 1188cb93a386Sopenharmony_ci this->writeModifiers(var.var().modifiers(), global); 1189cb93a386Sopenharmony_ci this->writeTypePrecision(var.baseType()); 1190cb93a386Sopenharmony_ci this->writeType(var.baseType()); 1191cb93a386Sopenharmony_ci this->write(" "); 1192cb93a386Sopenharmony_ci this->write(var.var().name()); 1193cb93a386Sopenharmony_ci if (var.arraySize() > 0) { 1194cb93a386Sopenharmony_ci this->write("["); 1195cb93a386Sopenharmony_ci this->write(to_string(var.arraySize())); 1196cb93a386Sopenharmony_ci this->write("]"); 1197cb93a386Sopenharmony_ci } 1198cb93a386Sopenharmony_ci if (var.value()) { 1199cb93a386Sopenharmony_ci this->write(" = "); 1200cb93a386Sopenharmony_ci this->writeVarInitializer(var.var(), *var.value()); 1201cb93a386Sopenharmony_ci } 1202cb93a386Sopenharmony_ci if (!fFoundExternalSamplerDecl && var.var().type() == *fContext.fTypes.fSamplerExternalOES) { 1203cb93a386Sopenharmony_ci if (this->caps().externalTextureExtensionString()) { 1204cb93a386Sopenharmony_ci this->writeExtension(this->caps().externalTextureExtensionString()); 1205cb93a386Sopenharmony_ci } 1206cb93a386Sopenharmony_ci if (this->caps().secondExternalTextureExtensionString()) { 1207cb93a386Sopenharmony_ci this->writeExtension(this->caps().secondExternalTextureExtensionString()); 1208cb93a386Sopenharmony_ci } 1209cb93a386Sopenharmony_ci fFoundExternalSamplerDecl = true; 1210cb93a386Sopenharmony_ci } 1211cb93a386Sopenharmony_ci if (!fFoundRectSamplerDecl && var.var().type() == *fContext.fTypes.fSampler2DRect) { 1212cb93a386Sopenharmony_ci fFoundRectSamplerDecl = true; 1213cb93a386Sopenharmony_ci } 1214cb93a386Sopenharmony_ci this->write(";"); 1215cb93a386Sopenharmony_ci} 1216cb93a386Sopenharmony_ci 1217cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeStatement(const Statement& s) { 1218cb93a386Sopenharmony_ci switch (s.kind()) { 1219cb93a386Sopenharmony_ci case Statement::Kind::kBlock: 1220cb93a386Sopenharmony_ci this->writeBlock(s.as<Block>()); 1221cb93a386Sopenharmony_ci break; 1222cb93a386Sopenharmony_ci case Statement::Kind::kExpression: 1223cb93a386Sopenharmony_ci this->writeExpression(*s.as<ExpressionStatement>().expression(), Precedence::kTopLevel); 1224cb93a386Sopenharmony_ci this->write(";"); 1225cb93a386Sopenharmony_ci break; 1226cb93a386Sopenharmony_ci case Statement::Kind::kReturn: 1227cb93a386Sopenharmony_ci this->writeReturnStatement(s.as<ReturnStatement>()); 1228cb93a386Sopenharmony_ci break; 1229cb93a386Sopenharmony_ci case Statement::Kind::kVarDeclaration: 1230cb93a386Sopenharmony_ci this->writeVarDeclaration(s.as<VarDeclaration>(), false); 1231cb93a386Sopenharmony_ci break; 1232cb93a386Sopenharmony_ci case Statement::Kind::kIf: 1233cb93a386Sopenharmony_ci this->writeIfStatement(s.as<IfStatement>()); 1234cb93a386Sopenharmony_ci break; 1235cb93a386Sopenharmony_ci case Statement::Kind::kFor: 1236cb93a386Sopenharmony_ci this->writeForStatement(s.as<ForStatement>()); 1237cb93a386Sopenharmony_ci break; 1238cb93a386Sopenharmony_ci case Statement::Kind::kDo: 1239cb93a386Sopenharmony_ci this->writeDoStatement(s.as<DoStatement>()); 1240cb93a386Sopenharmony_ci break; 1241cb93a386Sopenharmony_ci case Statement::Kind::kSwitch: 1242cb93a386Sopenharmony_ci this->writeSwitchStatement(s.as<SwitchStatement>()); 1243cb93a386Sopenharmony_ci break; 1244cb93a386Sopenharmony_ci case Statement::Kind::kBreak: 1245cb93a386Sopenharmony_ci this->write("break;"); 1246cb93a386Sopenharmony_ci break; 1247cb93a386Sopenharmony_ci case Statement::Kind::kContinue: 1248cb93a386Sopenharmony_ci this->write("continue;"); 1249cb93a386Sopenharmony_ci break; 1250cb93a386Sopenharmony_ci case Statement::Kind::kDiscard: 1251cb93a386Sopenharmony_ci this->write("discard;"); 1252cb93a386Sopenharmony_ci break; 1253cb93a386Sopenharmony_ci case Statement::Kind::kInlineMarker: 1254cb93a386Sopenharmony_ci case Statement::Kind::kNop: 1255cb93a386Sopenharmony_ci this->write(";"); 1256cb93a386Sopenharmony_ci break; 1257cb93a386Sopenharmony_ci default: 1258cb93a386Sopenharmony_ci SkDEBUGFAILF("unsupported statement: %s", s.description().c_str()); 1259cb93a386Sopenharmony_ci break; 1260cb93a386Sopenharmony_ci } 1261cb93a386Sopenharmony_ci} 1262cb93a386Sopenharmony_ci 1263cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeBlock(const Block& b) { 1264cb93a386Sopenharmony_ci // Write scope markers if this block is a scope, or if the block is empty (since we need to emit 1265cb93a386Sopenharmony_ci // something here to make the code valid). 1266cb93a386Sopenharmony_ci bool isScope = b.isScope() || b.isEmpty(); 1267cb93a386Sopenharmony_ci if (isScope) { 1268cb93a386Sopenharmony_ci this->writeLine("{"); 1269cb93a386Sopenharmony_ci fIndentation++; 1270cb93a386Sopenharmony_ci } 1271cb93a386Sopenharmony_ci for (const std::unique_ptr<Statement>& stmt : b.children()) { 1272cb93a386Sopenharmony_ci if (!stmt->isEmpty()) { 1273cb93a386Sopenharmony_ci this->writeStatement(*stmt); 1274cb93a386Sopenharmony_ci this->finishLine(); 1275cb93a386Sopenharmony_ci } 1276cb93a386Sopenharmony_ci } 1277cb93a386Sopenharmony_ci if (isScope) { 1278cb93a386Sopenharmony_ci fIndentation--; 1279cb93a386Sopenharmony_ci this->write("}"); 1280cb93a386Sopenharmony_ci } 1281cb93a386Sopenharmony_ci} 1282cb93a386Sopenharmony_ci 1283cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeIfStatement(const IfStatement& stmt) { 1284cb93a386Sopenharmony_ci this->write("if ("); 1285cb93a386Sopenharmony_ci this->writeExpression(*stmt.test(), Precedence::kTopLevel); 1286cb93a386Sopenharmony_ci this->write(") "); 1287cb93a386Sopenharmony_ci this->writeStatement(*stmt.ifTrue()); 1288cb93a386Sopenharmony_ci if (stmt.ifFalse()) { 1289cb93a386Sopenharmony_ci this->write(" else "); 1290cb93a386Sopenharmony_ci this->writeStatement(*stmt.ifFalse()); 1291cb93a386Sopenharmony_ci } 1292cb93a386Sopenharmony_ci} 1293cb93a386Sopenharmony_ci 1294cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeForStatement(const ForStatement& f) { 1295cb93a386Sopenharmony_ci // Emit loops of the form 'for(;test;)' as 'while(test)', which is probably how they started 1296cb93a386Sopenharmony_ci if (!f.initializer() && f.test() && !f.next()) { 1297cb93a386Sopenharmony_ci this->write("while ("); 1298cb93a386Sopenharmony_ci this->writeExpression(*f.test(), Precedence::kTopLevel); 1299cb93a386Sopenharmony_ci this->write(") "); 1300cb93a386Sopenharmony_ci this->writeStatement(*f.statement()); 1301cb93a386Sopenharmony_ci return; 1302cb93a386Sopenharmony_ci } 1303cb93a386Sopenharmony_ci 1304cb93a386Sopenharmony_ci this->write("for ("); 1305cb93a386Sopenharmony_ci if (f.initializer() && !f.initializer()->isEmpty()) { 1306cb93a386Sopenharmony_ci this->writeStatement(*f.initializer()); 1307cb93a386Sopenharmony_ci } else { 1308cb93a386Sopenharmony_ci this->write("; "); 1309cb93a386Sopenharmony_ci } 1310cb93a386Sopenharmony_ci if (f.test()) { 1311cb93a386Sopenharmony_ci if (this->caps().addAndTrueToLoopCondition()) { 1312cb93a386Sopenharmony_ci std::unique_ptr<Expression> and_true(new BinaryExpression( 1313cb93a386Sopenharmony_ci /*line=*/-1, f.test()->clone(), Token::Kind::TK_LOGICALAND, 1314cb93a386Sopenharmony_ci Literal::MakeBool(fContext, /*line=*/-1, /*value=*/true), 1315cb93a386Sopenharmony_ci fContext.fTypes.fBool.get())); 1316cb93a386Sopenharmony_ci this->writeExpression(*and_true, Precedence::kTopLevel); 1317cb93a386Sopenharmony_ci } else { 1318cb93a386Sopenharmony_ci this->writeExpression(*f.test(), Precedence::kTopLevel); 1319cb93a386Sopenharmony_ci } 1320cb93a386Sopenharmony_ci } 1321cb93a386Sopenharmony_ci this->write("; "); 1322cb93a386Sopenharmony_ci if (f.next()) { 1323cb93a386Sopenharmony_ci this->writeExpression(*f.next(), Precedence::kTopLevel); 1324cb93a386Sopenharmony_ci } 1325cb93a386Sopenharmony_ci this->write(") "); 1326cb93a386Sopenharmony_ci this->writeStatement(*f.statement()); 1327cb93a386Sopenharmony_ci} 1328cb93a386Sopenharmony_ci 1329cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeDoStatement(const DoStatement& d) { 1330cb93a386Sopenharmony_ci if (!this->caps().rewriteDoWhileLoops()) { 1331cb93a386Sopenharmony_ci this->write("do "); 1332cb93a386Sopenharmony_ci this->writeStatement(*d.statement()); 1333cb93a386Sopenharmony_ci this->write(" while ("); 1334cb93a386Sopenharmony_ci this->writeExpression(*d.test(), Precedence::kTopLevel); 1335cb93a386Sopenharmony_ci this->write(");"); 1336cb93a386Sopenharmony_ci return; 1337cb93a386Sopenharmony_ci } 1338cb93a386Sopenharmony_ci 1339cb93a386Sopenharmony_ci // Otherwise, do the do while loop workaround, to rewrite loops of the form: 1340cb93a386Sopenharmony_ci // do { 1341cb93a386Sopenharmony_ci // CODE; 1342cb93a386Sopenharmony_ci // } while (CONDITION) 1343cb93a386Sopenharmony_ci // 1344cb93a386Sopenharmony_ci // to loops of the form 1345cb93a386Sopenharmony_ci // bool temp = false; 1346cb93a386Sopenharmony_ci // while (true) { 1347cb93a386Sopenharmony_ci // if (temp) { 1348cb93a386Sopenharmony_ci // if (!CONDITION) { 1349cb93a386Sopenharmony_ci // break; 1350cb93a386Sopenharmony_ci // } 1351cb93a386Sopenharmony_ci // } 1352cb93a386Sopenharmony_ci // temp = true; 1353cb93a386Sopenharmony_ci // CODE; 1354cb93a386Sopenharmony_ci // } 1355cb93a386Sopenharmony_ci String tmpVar = "_tmpLoopSeenOnce" + to_string(fVarCount++); 1356cb93a386Sopenharmony_ci this->write("bool "); 1357cb93a386Sopenharmony_ci this->write(tmpVar); 1358cb93a386Sopenharmony_ci this->writeLine(" = false;"); 1359cb93a386Sopenharmony_ci this->writeLine("while (true) {"); 1360cb93a386Sopenharmony_ci fIndentation++; 1361cb93a386Sopenharmony_ci this->write("if ("); 1362cb93a386Sopenharmony_ci this->write(tmpVar); 1363cb93a386Sopenharmony_ci this->writeLine(") {"); 1364cb93a386Sopenharmony_ci fIndentation++; 1365cb93a386Sopenharmony_ci this->write("if (!"); 1366cb93a386Sopenharmony_ci this->writeExpression(*d.test(), Precedence::kPrefix); 1367cb93a386Sopenharmony_ci this->writeLine(") {"); 1368cb93a386Sopenharmony_ci fIndentation++; 1369cb93a386Sopenharmony_ci this->writeLine("break;"); 1370cb93a386Sopenharmony_ci fIndentation--; 1371cb93a386Sopenharmony_ci this->writeLine("}"); 1372cb93a386Sopenharmony_ci fIndentation--; 1373cb93a386Sopenharmony_ci this->writeLine("}"); 1374cb93a386Sopenharmony_ci this->write(tmpVar); 1375cb93a386Sopenharmony_ci this->writeLine(" = true;"); 1376cb93a386Sopenharmony_ci this->writeStatement(*d.statement()); 1377cb93a386Sopenharmony_ci this->finishLine(); 1378cb93a386Sopenharmony_ci fIndentation--; 1379cb93a386Sopenharmony_ci this->write("}"); 1380cb93a386Sopenharmony_ci} 1381cb93a386Sopenharmony_ci 1382cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeSwitchStatement(const SwitchStatement& s) { 1383cb93a386Sopenharmony_ci if (this->caps().rewriteSwitchStatements()) { 1384cb93a386Sopenharmony_ci String fallthroughVar = "_tmpSwitchFallthrough" + to_string(fVarCount++); 1385cb93a386Sopenharmony_ci String valueVar = "_tmpSwitchValue" + to_string(fVarCount++); 1386cb93a386Sopenharmony_ci String loopVar = "_tmpSwitchLoop" + to_string(fVarCount++); 1387cb93a386Sopenharmony_ci this->write("int "); 1388cb93a386Sopenharmony_ci this->write(valueVar); 1389cb93a386Sopenharmony_ci this->write(" = "); 1390cb93a386Sopenharmony_ci this->writeExpression(*s.value(), Precedence::kAssignment); 1391cb93a386Sopenharmony_ci this->write(", "); 1392cb93a386Sopenharmony_ci this->write(fallthroughVar); 1393cb93a386Sopenharmony_ci this->writeLine(" = 0;"); 1394cb93a386Sopenharmony_ci this->write("for (int "); 1395cb93a386Sopenharmony_ci this->write(loopVar); 1396cb93a386Sopenharmony_ci this->write(" = 0; "); 1397cb93a386Sopenharmony_ci this->write(loopVar); 1398cb93a386Sopenharmony_ci this->write(" < 1; "); 1399cb93a386Sopenharmony_ci this->write(loopVar); 1400cb93a386Sopenharmony_ci this->writeLine("++) {"); 1401cb93a386Sopenharmony_ci fIndentation++; 1402cb93a386Sopenharmony_ci 1403cb93a386Sopenharmony_ci bool firstCase = true; 1404cb93a386Sopenharmony_ci for (const std::unique_ptr<Statement>& stmt : s.cases()) { 1405cb93a386Sopenharmony_ci const SwitchCase& c = stmt->as<SwitchCase>(); 1406cb93a386Sopenharmony_ci if (c.value()) { 1407cb93a386Sopenharmony_ci this->write("if (("); 1408cb93a386Sopenharmony_ci if (firstCase) { 1409cb93a386Sopenharmony_ci firstCase = false; 1410cb93a386Sopenharmony_ci } else { 1411cb93a386Sopenharmony_ci this->write(fallthroughVar); 1412cb93a386Sopenharmony_ci this->write(" > 0) || ("); 1413cb93a386Sopenharmony_ci } 1414cb93a386Sopenharmony_ci this->write(valueVar); 1415cb93a386Sopenharmony_ci this->write(" == "); 1416cb93a386Sopenharmony_ci this->writeExpression(*c.value(), Precedence::kEquality); 1417cb93a386Sopenharmony_ci this->writeLine(")) {"); 1418cb93a386Sopenharmony_ci fIndentation++; 1419cb93a386Sopenharmony_ci 1420cb93a386Sopenharmony_ci // We write the entire case-block statement here, and then set `switchFallthrough` 1421cb93a386Sopenharmony_ci // to 1. If the case-block had a break statement in it, we break out of the outer 1422cb93a386Sopenharmony_ci // for-loop entirely, meaning the `switchFallthrough` assignment never occurs, nor 1423cb93a386Sopenharmony_ci // does any code after it inside the switch. We've forbidden `continue` statements 1424cb93a386Sopenharmony_ci // inside switch case-blocks entirely, so we don't need to consider their effect on 1425cb93a386Sopenharmony_ci // control flow; see the Finalizer in FunctionDefinition::Convert. 1426cb93a386Sopenharmony_ci this->writeStatement(*c.statement()); 1427cb93a386Sopenharmony_ci this->finishLine(); 1428cb93a386Sopenharmony_ci this->write(fallthroughVar); 1429cb93a386Sopenharmony_ci this->write(" = 1;"); 1430cb93a386Sopenharmony_ci this->writeLine(); 1431cb93a386Sopenharmony_ci 1432cb93a386Sopenharmony_ci fIndentation--; 1433cb93a386Sopenharmony_ci this->writeLine("}"); 1434cb93a386Sopenharmony_ci } else { 1435cb93a386Sopenharmony_ci // This is the default case. Since it's always last, we can just dump in the code. 1436cb93a386Sopenharmony_ci this->writeStatement(*c.statement()); 1437cb93a386Sopenharmony_ci this->finishLine(); 1438cb93a386Sopenharmony_ci } 1439cb93a386Sopenharmony_ci } 1440cb93a386Sopenharmony_ci 1441cb93a386Sopenharmony_ci fIndentation--; 1442cb93a386Sopenharmony_ci this->writeLine("}"); 1443cb93a386Sopenharmony_ci return; 1444cb93a386Sopenharmony_ci } 1445cb93a386Sopenharmony_ci 1446cb93a386Sopenharmony_ci this->write("switch ("); 1447cb93a386Sopenharmony_ci this->writeExpression(*s.value(), Precedence::kTopLevel); 1448cb93a386Sopenharmony_ci this->writeLine(") {"); 1449cb93a386Sopenharmony_ci fIndentation++; 1450cb93a386Sopenharmony_ci // If a switch contains only a `default` case and nothing else, this confuses some drivers and 1451cb93a386Sopenharmony_ci // can lead to a crash. Adding a real case before the default seems to work around the bug, 1452cb93a386Sopenharmony_ci // and doesn't change the meaning of the switch. (skia:12465) 1453cb93a386Sopenharmony_ci if (s.cases().size() == 1 && !s.cases().front()->as<SwitchCase>().value()) { 1454cb93a386Sopenharmony_ci this->writeLine("case 0:"); 1455cb93a386Sopenharmony_ci } 1456cb93a386Sopenharmony_ci for (const std::unique_ptr<Statement>& stmt : s.cases()) { 1457cb93a386Sopenharmony_ci const SwitchCase& c = stmt->as<SwitchCase>(); 1458cb93a386Sopenharmony_ci if (c.value()) { 1459cb93a386Sopenharmony_ci this->write("case "); 1460cb93a386Sopenharmony_ci this->writeExpression(*c.value(), Precedence::kTopLevel); 1461cb93a386Sopenharmony_ci this->writeLine(":"); 1462cb93a386Sopenharmony_ci } else { 1463cb93a386Sopenharmony_ci this->writeLine("default:"); 1464cb93a386Sopenharmony_ci } 1465cb93a386Sopenharmony_ci if (!c.statement()->isEmpty()) { 1466cb93a386Sopenharmony_ci fIndentation++; 1467cb93a386Sopenharmony_ci this->writeStatement(*c.statement()); 1468cb93a386Sopenharmony_ci this->finishLine(); 1469cb93a386Sopenharmony_ci fIndentation--; 1470cb93a386Sopenharmony_ci } 1471cb93a386Sopenharmony_ci } 1472cb93a386Sopenharmony_ci fIndentation--; 1473cb93a386Sopenharmony_ci this->finishLine(); 1474cb93a386Sopenharmony_ci this->write("}"); 1475cb93a386Sopenharmony_ci} 1476cb93a386Sopenharmony_ci 1477cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeReturnStatement(const ReturnStatement& r) { 1478cb93a386Sopenharmony_ci this->write("return"); 1479cb93a386Sopenharmony_ci if (r.expression()) { 1480cb93a386Sopenharmony_ci this->write(" "); 1481cb93a386Sopenharmony_ci this->writeExpression(*r.expression(), Precedence::kTopLevel); 1482cb93a386Sopenharmony_ci } 1483cb93a386Sopenharmony_ci this->write(";"); 1484cb93a386Sopenharmony_ci} 1485cb93a386Sopenharmony_ci 1486cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeHeader() { 1487cb93a386Sopenharmony_ci if (this->caps().versionDeclString()) { 1488cb93a386Sopenharmony_ci this->write(this->caps().versionDeclString()); 1489cb93a386Sopenharmony_ci this->finishLine(); 1490cb93a386Sopenharmony_ci } 1491cb93a386Sopenharmony_ci} 1492cb93a386Sopenharmony_ci 1493cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeProgramElement(const ProgramElement& e) { 1494cb93a386Sopenharmony_ci switch (e.kind()) { 1495cb93a386Sopenharmony_ci case ProgramElement::Kind::kExtension: 1496cb93a386Sopenharmony_ci this->writeExtension(e.as<Extension>().name()); 1497cb93a386Sopenharmony_ci break; 1498cb93a386Sopenharmony_ci case ProgramElement::Kind::kGlobalVar: { 1499cb93a386Sopenharmony_ci const VarDeclaration& decl = 1500cb93a386Sopenharmony_ci e.as<GlobalVarDeclaration>().declaration()->as<VarDeclaration>(); 1501cb93a386Sopenharmony_ci int builtin = decl.var().modifiers().fLayout.fBuiltin; 1502cb93a386Sopenharmony_ci if (builtin == -1) { 1503cb93a386Sopenharmony_ci // normal var 1504cb93a386Sopenharmony_ci this->writeVarDeclaration(decl, true); 1505cb93a386Sopenharmony_ci this->finishLine(); 1506cb93a386Sopenharmony_ci } else if (builtin == SK_FRAGCOLOR_BUILTIN && 1507cb93a386Sopenharmony_ci this->caps().mustDeclareFragmentShaderOutput()) { 1508cb93a386Sopenharmony_ci if (fProgram.fConfig->fSettings.fFragColorIsInOut) { 1509cb93a386Sopenharmony_ci this->write("inout "); 1510cb93a386Sopenharmony_ci } else { 1511cb93a386Sopenharmony_ci this->write("out "); 1512cb93a386Sopenharmony_ci } 1513cb93a386Sopenharmony_ci if (usesPrecisionModifiers()) { 1514cb93a386Sopenharmony_ci this->write("mediump "); 1515cb93a386Sopenharmony_ci } 1516cb93a386Sopenharmony_ci this->writeLine("vec4 sk_FragColor;"); 1517cb93a386Sopenharmony_ci } 1518cb93a386Sopenharmony_ci break; 1519cb93a386Sopenharmony_ci } 1520cb93a386Sopenharmony_ci case ProgramElement::Kind::kInterfaceBlock: 1521cb93a386Sopenharmony_ci this->writeInterfaceBlock(e.as<InterfaceBlock>()); 1522cb93a386Sopenharmony_ci break; 1523cb93a386Sopenharmony_ci case ProgramElement::Kind::kFunction: 1524cb93a386Sopenharmony_ci this->writeFunction(e.as<FunctionDefinition>()); 1525cb93a386Sopenharmony_ci break; 1526cb93a386Sopenharmony_ci case ProgramElement::Kind::kFunctionPrototype: 1527cb93a386Sopenharmony_ci this->writeFunctionPrototype(e.as<FunctionPrototype>()); 1528cb93a386Sopenharmony_ci break; 1529cb93a386Sopenharmony_ci case ProgramElement::Kind::kModifiers: { 1530cb93a386Sopenharmony_ci const Modifiers& modifiers = e.as<ModifiersDeclaration>().modifiers(); 1531cb93a386Sopenharmony_ci this->writeModifiers(modifiers, true); 1532cb93a386Sopenharmony_ci this->writeLine(";"); 1533cb93a386Sopenharmony_ci break; 1534cb93a386Sopenharmony_ci } 1535cb93a386Sopenharmony_ci case ProgramElement::Kind::kStructDefinition: 1536cb93a386Sopenharmony_ci this->writeStructDefinition(e.as<StructDefinition>()); 1537cb93a386Sopenharmony_ci break; 1538cb93a386Sopenharmony_ci default: 1539cb93a386Sopenharmony_ci SkDEBUGFAILF("unsupported program element %s\n", e.description().c_str()); 1540cb93a386Sopenharmony_ci break; 1541cb93a386Sopenharmony_ci } 1542cb93a386Sopenharmony_ci} 1543cb93a386Sopenharmony_ci 1544cb93a386Sopenharmony_civoid GLSLCodeGenerator::writeInputVars() { 1545cb93a386Sopenharmony_ci if (fProgram.fInputs.fUseFlipRTUniform) { 1546cb93a386Sopenharmony_ci const char* precision = usesPrecisionModifiers() ? "highp " : ""; 1547cb93a386Sopenharmony_ci fGlobals.writeText("uniform "); 1548cb93a386Sopenharmony_ci fGlobals.writeText(precision); 1549cb93a386Sopenharmony_ci fGlobals.writeText("vec2 " SKSL_RTFLIP_NAME ";\n"); 1550cb93a386Sopenharmony_ci } 1551cb93a386Sopenharmony_ci} 1552cb93a386Sopenharmony_ci 1553cb93a386Sopenharmony_cibool GLSLCodeGenerator::generateCode() { 1554cb93a386Sopenharmony_ci this->writeHeader(); 1555cb93a386Sopenharmony_ci OutputStream* rawOut = fOut; 1556cb93a386Sopenharmony_ci StringStream body; 1557cb93a386Sopenharmony_ci fOut = &body; 1558cb93a386Sopenharmony_ci // Write all the program elements except for functions. 1559cb93a386Sopenharmony_ci for (const ProgramElement* e : fProgram.elements()) { 1560cb93a386Sopenharmony_ci if (!e->is<FunctionDefinition>()) { 1561cb93a386Sopenharmony_ci this->writeProgramElement(*e); 1562cb93a386Sopenharmony_ci } 1563cb93a386Sopenharmony_ci } 1564cb93a386Sopenharmony_ci // Write the functions last. 1565cb93a386Sopenharmony_ci // Why don't we write things in their original order? Because the Inliner likes to move function 1566cb93a386Sopenharmony_ci // bodies around. After inlining, code can inadvertently move upwards, above ProgramElements 1567cb93a386Sopenharmony_ci // that the code relies on. 1568cb93a386Sopenharmony_ci for (const ProgramElement* e : fProgram.elements()) { 1569cb93a386Sopenharmony_ci if (e->is<FunctionDefinition>()) { 1570cb93a386Sopenharmony_ci this->writeProgramElement(*e); 1571cb93a386Sopenharmony_ci } 1572cb93a386Sopenharmony_ci } 1573cb93a386Sopenharmony_ci fOut = rawOut; 1574cb93a386Sopenharmony_ci 1575cb93a386Sopenharmony_ci write_stringstream(fExtensions, *rawOut); 1576cb93a386Sopenharmony_ci this->writeInputVars(); 1577cb93a386Sopenharmony_ci write_stringstream(fGlobals, *rawOut); 1578cb93a386Sopenharmony_ci 1579cb93a386Sopenharmony_ci if (!this->caps().canUseFragCoord()) { 1580cb93a386Sopenharmony_ci Layout layout; 1581cb93a386Sopenharmony_ci switch (fProgram.fConfig->fKind) { 1582cb93a386Sopenharmony_ci case ProgramKind::kVertex: { 1583cb93a386Sopenharmony_ci Modifiers modifiers(layout, Modifiers::kOut_Flag); 1584cb93a386Sopenharmony_ci this->writeModifiers(modifiers, true); 1585cb93a386Sopenharmony_ci if (this->usesPrecisionModifiers()) { 1586cb93a386Sopenharmony_ci this->write("highp "); 1587cb93a386Sopenharmony_ci } 1588cb93a386Sopenharmony_ci this->write("vec4 sk_FragCoord_Workaround;\n"); 1589cb93a386Sopenharmony_ci break; 1590cb93a386Sopenharmony_ci } 1591cb93a386Sopenharmony_ci case ProgramKind::kFragment: { 1592cb93a386Sopenharmony_ci Modifiers modifiers(layout, Modifiers::kIn_Flag); 1593cb93a386Sopenharmony_ci this->writeModifiers(modifiers, true); 1594cb93a386Sopenharmony_ci if (this->usesPrecisionModifiers()) { 1595cb93a386Sopenharmony_ci this->write("highp "); 1596cb93a386Sopenharmony_ci } 1597cb93a386Sopenharmony_ci this->write("vec4 sk_FragCoord_Workaround;\n"); 1598cb93a386Sopenharmony_ci break; 1599cb93a386Sopenharmony_ci } 1600cb93a386Sopenharmony_ci default: 1601cb93a386Sopenharmony_ci break; 1602cb93a386Sopenharmony_ci } 1603cb93a386Sopenharmony_ci } 1604cb93a386Sopenharmony_ci 1605cb93a386Sopenharmony_ci if (this->usesPrecisionModifiers()) { 1606cb93a386Sopenharmony_ci const char* precision = 1607cb93a386Sopenharmony_ci fProgram.fConfig->fSettings.fForceHighPrecision ? "highp" : "mediump"; 1608cb93a386Sopenharmony_ci this->write(String::printf("precision %s float;\n", precision)); 1609cb93a386Sopenharmony_ci this->write(String::printf("precision %s sampler2D;\n", precision)); 1610cb93a386Sopenharmony_ci if (fFoundExternalSamplerDecl && !this->caps().noDefaultPrecisionForExternalSamplers()) { 1611cb93a386Sopenharmony_ci this->write(String::printf("precision %s samplerExternalOES;\n", precision)); 1612cb93a386Sopenharmony_ci } 1613cb93a386Sopenharmony_ci if (fFoundRectSamplerDecl) { 1614cb93a386Sopenharmony_ci this->write(String::printf("precision %s sampler2DRect;\n", precision)); 1615cb93a386Sopenharmony_ci } 1616cb93a386Sopenharmony_ci } 1617cb93a386Sopenharmony_ci write_stringstream(fExtraFunctions, *rawOut); 1618cb93a386Sopenharmony_ci write_stringstream(body, *rawOut); 1619cb93a386Sopenharmony_ci return fContext.fErrors->errorCount() == 0; 1620cb93a386Sopenharmony_ci} 1621cb93a386Sopenharmony_ci 1622cb93a386Sopenharmony_ci} // namespace SkSL 1623