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 <stack> 12 #include <tuple> 13 #include <unordered_map> 14 15 #include "src/sksl/SkSLCodeGenerator.h" 16 #include "src/sksl/SkSLMemoryLayout.h" 17 #include "src/sksl/SkSLStringStream.h" 18 #include "src/sksl/ir/SkSLBinaryExpression.h" 19 #include "src/sksl/ir/SkSLBoolLiteral.h" 20 #include "src/sksl/ir/SkSLConstructor.h" 21 #include "src/sksl/ir/SkSLDoStatement.h" 22 #include "src/sksl/ir/SkSLExtension.h" 23 #include "src/sksl/ir/SkSLFieldAccess.h" 24 #include "src/sksl/ir/SkSLFloatLiteral.h" 25 #include "src/sksl/ir/SkSLForStatement.h" 26 #include "src/sksl/ir/SkSLFunctionCall.h" 27 #include "src/sksl/ir/SkSLFunctionDeclaration.h" 28 #include "src/sksl/ir/SkSLFunctionDefinition.h" 29 #include "src/sksl/ir/SkSLIfStatement.h" 30 #include "src/sksl/ir/SkSLIndexExpression.h" 31 #include "src/sksl/ir/SkSLIntLiteral.h" 32 #include "src/sksl/ir/SkSLInterfaceBlock.h" 33 #include "src/sksl/ir/SkSLPostfixExpression.h" 34 #include "src/sksl/ir/SkSLPrefixExpression.h" 35 #include "src/sksl/ir/SkSLProgramElement.h" 36 #include "src/sksl/ir/SkSLReturnStatement.h" 37 #include "src/sksl/ir/SkSLSetting.h" 38 #include "src/sksl/ir/SkSLStatement.h" 39 #include "src/sksl/ir/SkSLSwitchStatement.h" 40 #include "src/sksl/ir/SkSLSwizzle.h" 41 #include "src/sksl/ir/SkSLTernaryExpression.h" 42 #include "src/sksl/ir/SkSLVarDeclarations.h" 43 #include "src/sksl/ir/SkSLVarDeclarationsStatement.h" 44 #include "src/sksl/ir/SkSLVariableReference.h" 45 #include "src/sksl/ir/SkSLWhileStatement.h" 46 47 namespace SkSL { 48 49 #define kLast_Capability SpvCapabilityMultiViewport 50 51 /** 52 * Converts a Program into Metal code. 53 */ 54 class MetalCodeGenerator : public CodeGenerator { 55 public: 56 static constexpr const char* SAMPLER_SUFFIX = "Smplr"; 57 static constexpr const char* PACKED_PREFIX = "packed_"; 58 59 enum Precedence { 60 kParentheses_Precedence = 1, 61 kPostfix_Precedence = 2, 62 kPrefix_Precedence = 3, 63 kMultiplicative_Precedence = 4, 64 kAdditive_Precedence = 5, 65 kShift_Precedence = 6, 66 kRelational_Precedence = 7, 67 kEquality_Precedence = 8, 68 kBitwiseAnd_Precedence = 9, 69 kBitwiseXor_Precedence = 10, 70 kBitwiseOr_Precedence = 11, 71 kLogicalAnd_Precedence = 12, 72 kLogicalXor_Precedence = 13, 73 kLogicalOr_Precedence = 14, 74 kTernary_Precedence = 15, 75 kAssignment_Precedence = 16, 76 kSequence_Precedence = 17, 77 kTopLevel_Precedence = kSequence_Precedence 78 }; 79 MetalCodeGenerator(const Context * context,const Program * program,ErrorReporter * errors,OutputStream * out)80 MetalCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors, 81 OutputStream* out) 82 : INHERITED(program, errors, out) 83 , fReservedWords({"atan2", "rsqrt", "dfdx", "dfdy", "vertex", "fragment"}) 84 , fLineEnding("\n") 85 , fContext(*context) { 86 this->setupIntrinsics(); 87 } 88 89 bool generateCode() override; 90 91 protected: 92 typedef int Requirements; 93 static constexpr Requirements kNo_Requirements = 0; 94 static constexpr Requirements kInputs_Requirement = 1 << 0; 95 static constexpr Requirements kOutputs_Requirement = 1 << 1; 96 static constexpr Requirements kUniforms_Requirement = 1 << 2; 97 static constexpr Requirements kGlobals_Requirement = 1 << 3; 98 static constexpr Requirements kFragCoord_Requirement = 1 << 4; 99 100 enum IntrinsicKind { 101 kSpecial_IntrinsicKind, 102 kMetal_IntrinsicKind, 103 }; 104 105 enum SpecialIntrinsic { 106 kTexture_SpecialIntrinsic, 107 kMod_SpecialIntrinsic, 108 }; 109 110 enum MetalIntrinsic { 111 kEqual_MetalIntrinsic, 112 kNotEqual_MetalIntrinsic, 113 kLessThan_MetalIntrinsic, 114 kLessThanEqual_MetalIntrinsic, 115 kGreaterThan_MetalIntrinsic, 116 kGreaterThanEqual_MetalIntrinsic, 117 }; 118 119 void setupIntrinsics(); 120 121 void write(const char* s); 122 123 void writeLine(); 124 125 void writeLine(const char* s); 126 127 void write(const String& s); 128 129 void writeLine(const String& s); 130 131 void writeHeader(); 132 133 void writeUniformStruct(); 134 135 void writeInputStruct(); 136 137 void writeOutputStruct(); 138 139 void writeInterfaceBlocks(); 140 141 void writeFields(const std::vector<Type::Field>& fields, int parentOffset, 142 const InterfaceBlock* parentIntf = nullptr); 143 144 int size(const Type* type, bool isPacked) const; 145 146 int alignment(const Type* type, bool isPacked) const; 147 148 void writeGlobalStruct(); 149 150 void writePrecisionModifier(); 151 152 String typeName(const Type& type); 153 154 void writeType(const Type& type); 155 156 void writeExtension(const Extension& ext); 157 158 void writeInterfaceBlock(const InterfaceBlock& intf); 159 160 void writeFunctionStart(const FunctionDeclaration& f); 161 162 void writeFunctionDeclaration(const FunctionDeclaration& f); 163 164 void writeFunction(const FunctionDefinition& f); 165 166 void writeLayout(const Layout& layout); 167 168 void writeModifiers(const Modifiers& modifiers, bool globalContext); 169 170 void writeGlobalVars(const VarDeclaration& vs); 171 172 void writeVarInitializer(const Variable& var, const Expression& value); 173 174 void writeName(const String& name); 175 176 void writeVarDeclarations(const VarDeclarations& decl, bool global); 177 178 void writeFragCoord(); 179 180 void writeVariableReference(const VariableReference& ref); 181 182 void writeExpression(const Expression& expr, Precedence parentPrecedence); 183 184 void writeIntrinsicCall(const FunctionCall& c); 185 186 void writeMinAbsHack(Expression& absExpr, Expression& otherExpr); 187 188 void writeFunctionCall(const FunctionCall& c); 189 190 void writeInverseHack(const Expression& mat); 191 192 String getMatrixConstructHelper(const Type& matrix, const Type& arg); 193 194 void writeMatrixTimesEqualHelper(const Type& left, const Type& right, const Type& result); 195 196 void writeSpecialIntrinsic(const FunctionCall& c, SpecialIntrinsic kind); 197 198 bool canCoerce(const Type& t1, const Type& t2); 199 200 void writeConstructor(const Constructor& c, Precedence parentPrecedence); 201 202 void writeFieldAccess(const FieldAccess& f); 203 204 void writeSwizzle(const Swizzle& swizzle); 205 206 static Precedence GetBinaryPrecedence(Token::Kind op); 207 208 void writeBinaryExpression(const BinaryExpression& b, Precedence parentPrecedence); 209 210 void writeTernaryExpression(const TernaryExpression& t, Precedence parentPrecedence); 211 212 void writeIndexExpression(const IndexExpression& expr); 213 214 void writePrefixExpression(const PrefixExpression& p, Precedence parentPrecedence); 215 216 void writePostfixExpression(const PostfixExpression& p, Precedence parentPrecedence); 217 218 void writeBoolLiteral(const BoolLiteral& b); 219 220 void writeIntLiteral(const IntLiteral& i); 221 222 void writeFloatLiteral(const FloatLiteral& f); 223 224 void writeSetting(const Setting& s); 225 226 void writeStatement(const Statement& s); 227 228 void writeStatements(const std::vector<std::unique_ptr<Statement>>& statements); 229 230 void writeBlock(const Block& b); 231 232 void writeIfStatement(const IfStatement& stmt); 233 234 void writeForStatement(const ForStatement& f); 235 236 void writeWhileStatement(const WhileStatement& w); 237 238 void writeDoStatement(const DoStatement& d); 239 240 void writeSwitchStatement(const SwitchStatement& s); 241 242 void writeReturnStatement(const ReturnStatement& r); 243 244 void writeProgramElement(const ProgramElement& e); 245 246 Requirements requirements(const FunctionDeclaration& f); 247 248 Requirements requirements(const Expression& e); 249 250 Requirements requirements(const Statement& e); 251 252 typedef std::pair<IntrinsicKind, int32_t> Intrinsic; 253 std::unordered_map<String, Intrinsic> fIntrinsicMap; 254 std::unordered_set<String> fReservedWords; 255 std::vector<const VarDeclaration*> fInitNonConstGlobalVars; 256 std::vector<const Variable*> fTextures; 257 std::unordered_map<const Type::Field*, const InterfaceBlock*> fInterfaceBlockMap; 258 std::unordered_map<const InterfaceBlock*, String> fInterfaceBlockNameMap; 259 int fAnonInterfaceCount = 0; 260 int fPaddingCount = 0; 261 bool fNeedsGlobalStructInit = false; 262 const char* fLineEnding; 263 const Context& fContext; 264 StringStream fHeader; 265 String fFunctionHeader; 266 StringStream fExtraFunctions; 267 Program::Kind fProgramKind; 268 int fVarCount = 0; 269 int fIndentation = 0; 270 bool fAtLineStart = false; 271 // Keeps track of which struct types we have written. Given that we are unlikely to ever write 272 // more than one or two structs per shader, a simple linear search will be faster than anything 273 // fancier. 274 std::vector<const Type*> fWrittenStructs; 275 std::set<String> fWrittenIntrinsics; 276 // true if we have run into usages of dFdx / dFdy 277 bool fFoundDerivatives = false; 278 std::unordered_map<const FunctionDeclaration*, Requirements> fRequirements; 279 bool fSetupFragPositionGlobal = false; 280 bool fSetupFragPositionLocal = false; 281 std::unordered_map<String, String> fHelpers; 282 int fUniformBuffer = -1; 283 String fRTHeightName; 284 285 typedef CodeGenerator INHERITED; 286 }; 287 288 } 289 290 #endif 291