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 #ifndef SKSL_METALCODEGENERATOR 9 #define SKSL_METALCODEGENERATOR 10 11 #include <set> 12 #include <stack> 13 #include <tuple> 14 #include <unordered_map> 15 #include <unordered_set> 16 17 #include "include/private/SkSLProgramElement.h" 18 #include "include/private/SkSLStatement.h" 19 #include "src/sksl/SkSLOperators.h" 20 #include "src/sksl/SkSLStringStream.h" 21 #include "src/sksl/codegen/SkSLCodeGenerator.h" 22 #include "src/sksl/ir/SkSLBinaryExpression.h" 23 #include "src/sksl/ir/SkSLBoolLiteral.h" 24 #include "src/sksl/ir/SkSLConstructor.h" 25 #include "src/sksl/ir/SkSLConstructorCompound.h" 26 #include "src/sksl/ir/SkSLConstructorMatrixResize.h" 27 #include "src/sksl/ir/SkSLDoStatement.h" 28 #include "src/sksl/ir/SkSLExtension.h" 29 #include "src/sksl/ir/SkSLFieldAccess.h" 30 #include "src/sksl/ir/SkSLFloatLiteral.h" 31 #include "src/sksl/ir/SkSLForStatement.h" 32 #include "src/sksl/ir/SkSLFunctionCall.h" 33 #include "src/sksl/ir/SkSLFunctionDeclaration.h" 34 #include "src/sksl/ir/SkSLFunctionDefinition.h" 35 #include "src/sksl/ir/SkSLFunctionPrototype.h" 36 #include "src/sksl/ir/SkSLIfStatement.h" 37 #include "src/sksl/ir/SkSLIndexExpression.h" 38 #include "src/sksl/ir/SkSLInlineMarker.h" 39 #include "src/sksl/ir/SkSLIntLiteral.h" 40 #include "src/sksl/ir/SkSLInterfaceBlock.h" 41 #include "src/sksl/ir/SkSLPostfixExpression.h" 42 #include "src/sksl/ir/SkSLPrefixExpression.h" 43 #include "src/sksl/ir/SkSLReturnStatement.h" 44 #include "src/sksl/ir/SkSLSetting.h" 45 #include "src/sksl/ir/SkSLSwitchStatement.h" 46 #include "src/sksl/ir/SkSLSwizzle.h" 47 #include "src/sksl/ir/SkSLTernaryExpression.h" 48 #include "src/sksl/ir/SkSLVarDeclarations.h" 49 #include "src/sksl/ir/SkSLVariableReference.h" 50 51 namespace SkSL { 52 53 /** 54 * Converts a Program into Metal code. 55 */ 56 class MetalCodeGenerator : public CodeGenerator { 57 public: 58 static constexpr const char* SAMPLER_SUFFIX = "Smplr"; 59 static constexpr const char* PACKED_PREFIX = "packed_"; 60 MetalCodeGenerator(const Context * context,const Program * program,ErrorReporter * errors,OutputStream * out)61 MetalCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors, 62 OutputStream* out) 63 : INHERITED(program, errors, out) 64 , fReservedWords({"atan2", "rsqrt", "rint", "dfdx", "dfdy", "vertex", "fragment"}) 65 , fLineEnding("\n") 66 , fContext(*context) {} 67 68 bool generateCode() override; 69 70 protected: 71 using Precedence = Operator::Precedence; 72 73 typedef int Requirements; 74 static constexpr Requirements kNo_Requirements = 0; 75 static constexpr Requirements kInputs_Requirement = 1 << 0; 76 static constexpr Requirements kOutputs_Requirement = 1 << 1; 77 static constexpr Requirements kUniforms_Requirement = 1 << 2; 78 static constexpr Requirements kGlobals_Requirement = 1 << 3; 79 static constexpr Requirements kFragCoord_Requirement = 1 << 4; 80 81 static const char* OperatorName(Operator op); 82 83 class GlobalStructVisitor; 84 void visitGlobalStruct(GlobalStructVisitor* visitor); 85 86 void write(const char* s); 87 88 void writeLine(); 89 90 void writeLine(const char* s); 91 92 void write(const String& s); 93 94 void writeLine(const String& s); 95 96 void finishLine(); 97 98 void writeHeader(); 99 100 void writeUniformStruct(); 101 102 void writeInputStruct(); 103 104 void writeOutputStruct(); 105 106 void writeInterfaceBlocks(); 107 108 void writeStructDefinitions(); 109 110 void writeFields(const std::vector<Type::Field>& fields, int parentOffset, 111 const InterfaceBlock* parentIntf = nullptr); 112 113 int size(const Type* type, bool isPacked) const; 114 115 int alignment(const Type* type, bool isPacked) const; 116 117 void writeGlobalStruct(); 118 119 void writeGlobalInit(); 120 121 void writePrecisionModifier(); 122 123 String typeName(const Type& type); 124 125 void writeStructDefinition(const StructDefinition& s); 126 127 void writeType(const Type& type); 128 129 void writeExtension(const Extension& ext); 130 131 void writeInterfaceBlock(const InterfaceBlock& intf); 132 133 void writeFunctionStart(const FunctionDeclaration& f); 134 135 void writeFunctionRequirementParams(const FunctionDeclaration& f, 136 const char*& separator); 137 138 void writeFunctionRequirementArgs(const FunctionDeclaration& f, const char*& separator); 139 140 bool writeFunctionDeclaration(const FunctionDeclaration& f); 141 142 void writeFunction(const FunctionDefinition& f); 143 144 void writeFunctionPrototype(const FunctionPrototype& f); 145 146 void writeLayout(const Layout& layout); 147 148 void writeModifiers(const Modifiers& modifiers, bool globalContext); 149 150 void writeVarInitializer(const Variable& var, const Expression& value); 151 152 void writeName(const String& name); 153 154 void writeVarDeclaration(const VarDeclaration& decl, bool global); 155 156 void writeFragCoord(); 157 158 void writeVariableReference(const VariableReference& ref); 159 160 void writeExpression(const Expression& expr, Precedence parentPrecedence); 161 162 void writeMinAbsHack(Expression& absExpr, Expression& otherExpr); 163 164 String getOutParamHelper(const FunctionCall& c, 165 const ExpressionArray& arguments, 166 const SkTArray<VariableReference*>& outVars); 167 168 String getInversePolyfill(const ExpressionArray& arguments); 169 170 String getBitcastIntrinsic(const Type& outType); 171 172 String getTempVariable(const Type& varType); 173 174 void writeFunctionCall(const FunctionCall& c); 175 176 bool matrixConstructHelperIsNeeded(const ConstructorCompound& c); 177 String getMatrixConstructHelper(const AnyConstructor& c); 178 void assembleMatrixFromMatrix(const Type& sourceMatrix, int rows, int columns); 179 void assembleMatrixFromExpressions(const AnyConstructor& ctor, int rows, int columns); 180 181 void writeMatrixCompMult(); 182 183 void writeMatrixTimesEqualHelper(const Type& left, const Type& right, const Type& result); 184 185 void writeMatrixEqualityHelpers(const Type& left, const Type& right); 186 187 void writeArrayEqualityHelpers(const Type& type); 188 189 void writeStructEqualityHelpers(const Type& type); 190 191 void writeEqualityHelpers(const Type& leftType, const Type& rightType); 192 193 void writeArgumentList(const ExpressionArray& arguments); 194 195 void writeSimpleIntrinsic(const FunctionCall& c); 196 197 bool writeIntrinsicCall(const FunctionCall& c, IntrinsicKind kind); 198 199 bool canCoerce(const Type& t1, const Type& t2); 200 201 void writeConstructorCompound(const ConstructorCompound& c, Precedence parentPrecedence); 202 203 void writeConstructorCompoundMatrix(const ConstructorCompound& c, Precedence parentPrecedence); 204 205 void writeConstructorMatrixResize(const ConstructorMatrixResize& c, 206 Precedence parentPrecedence); 207 208 void writeAnyConstructor(const AnyConstructor& c, 209 const char* leftBracket, 210 const char* rightBracket, 211 Precedence parentPrecedence); 212 213 void writeCastConstructor(const AnyConstructor& c, 214 const char* leftBracket, 215 const char* rightBracket, 216 Precedence parentPrecedence); 217 218 void writeFieldAccess(const FieldAccess& f); 219 220 void writeSwizzle(const Swizzle& swizzle); 221 222 void writeBinaryExpression(const BinaryExpression& b, Precedence parentPrecedence); 223 224 void writeTernaryExpression(const TernaryExpression& t, Precedence parentPrecedence); 225 226 void writeIndexExpression(const IndexExpression& expr); 227 228 void writePrefixExpression(const PrefixExpression& p, Precedence parentPrecedence); 229 230 void writePostfixExpression(const PostfixExpression& p, Precedence parentPrecedence); 231 232 void writeBoolLiteral(const BoolLiteral& b); 233 234 void writeIntLiteral(const IntLiteral& i); 235 236 void writeFloatLiteral(const FloatLiteral& f); 237 238 void writeSetting(const Setting& s); 239 240 void writeStatement(const Statement& s); 241 242 void writeStatements(const StatementArray& statements); 243 244 void writeBlock(const Block& b); 245 246 void writeIfStatement(const IfStatement& stmt); 247 248 void writeForStatement(const ForStatement& f); 249 250 void writeDoStatement(const DoStatement& d); 251 252 void writeSwitchStatement(const SwitchStatement& s); 253 254 void writeReturnStatementFromMain(); 255 256 void writeReturnStatement(const ReturnStatement& r); 257 258 void writeProgramElement(const ProgramElement& e); 259 260 Requirements requirements(const FunctionDeclaration& f); 261 262 Requirements requirements(const Expression* e); 263 264 Requirements requirements(const Statement* s); 265 266 int getUniformBinding(const Modifiers& m); 267 268 int getUniformSet(const Modifiers& m); 269 270 std::unordered_set<String> fReservedWords; 271 std::unordered_map<const Type::Field*, const InterfaceBlock*> fInterfaceBlockMap; 272 std::unordered_map<const InterfaceBlock*, String> fInterfaceBlockNameMap; 273 int fAnonInterfaceCount = 0; 274 int fPaddingCount = 0; 275 const char* fLineEnding; 276 const Context& fContext; 277 String fFunctionHeader; 278 StringStream fExtraFunctions; 279 int fVarCount = 0; 280 int fIndentation = 0; 281 bool fAtLineStart = false; 282 std::set<String> fWrittenIntrinsics; 283 // true if we have run into usages of dFdx / dFdy 284 bool fFoundDerivatives = false; 285 std::unordered_map<const FunctionDeclaration*, Requirements> fRequirements; 286 bool fSetupFragPositionGlobal = false; 287 bool fSetupFragPositionLocal = false; 288 std::unordered_set<String> fHelpers; 289 int fUniformBuffer = -1; 290 String fRTHeightName; 291 const FunctionDeclaration* fCurrentFunction = nullptr; 292 int fSwizzleHelperCount = 0; 293 bool fIgnoreVariableReferenceModifiers = false; 294 295 using INHERITED = CodeGenerator; 296 }; 297 298 } // namespace SkSL 299 300 #endif 301