• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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