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