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