• 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 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