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