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