• 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_SPIRVCODEGENERATOR
9 #define SKSL_SPIRVCODEGENERATOR
10 
11 #include <stack>
12 #include <tuple>
13 #include <unordered_map>
14 
15 #include "SkStream.h"
16 #include "SkSLCodeGenerator.h"
17 #include "SkSLMemoryLayout.h"
18 #include "ir/SkSLBinaryExpression.h"
19 #include "ir/SkSLBoolLiteral.h"
20 #include "ir/SkSLConstructor.h"
21 #include "ir/SkSLDoStatement.h"
22 #include "ir/SkSLFloatLiteral.h"
23 #include "ir/SkSLIfStatement.h"
24 #include "ir/SkSLIndexExpression.h"
25 #include "ir/SkSLInterfaceBlock.h"
26 #include "ir/SkSLIntLiteral.h"
27 #include "ir/SkSLFieldAccess.h"
28 #include "ir/SkSLForStatement.h"
29 #include "ir/SkSLFunctionCall.h"
30 #include "ir/SkSLFunctionDeclaration.h"
31 #include "ir/SkSLFunctionDefinition.h"
32 #include "ir/SkSLPrefixExpression.h"
33 #include "ir/SkSLPostfixExpression.h"
34 #include "ir/SkSLProgramElement.h"
35 #include "ir/SkSLReturnStatement.h"
36 #include "ir/SkSLStatement.h"
37 #include "ir/SkSLSwizzle.h"
38 #include "ir/SkSLTernaryExpression.h"
39 #include "ir/SkSLVarDeclarations.h"
40 #include "ir/SkSLVarDeclarationsStatement.h"
41 #include "ir/SkSLVariableReference.h"
42 #include "ir/SkSLWhileStatement.h"
43 #include "spirv.h"
44 
45 namespace SkSL {
46 
47 #define kLast_Capability SpvCapabilityMultiViewport
48 
49 /**
50  * Converts a Program into a SPIR-V binary.
51  */
52 class SPIRVCodeGenerator : public CodeGenerator {
53 public:
54     class LValue {
55     public:
~LValue()56         virtual ~LValue() {}
57 
58         // returns a pointer to the lvalue, if possible. If the lvalue cannot be directly referenced
59         // by a pointer (e.g. vector swizzles), returns 0.
60         virtual SpvId getPointer() = 0;
61 
62         virtual SpvId load(SkWStream& out) = 0;
63 
64         virtual void store(SpvId value, SkWStream& out) = 0;
65     };
66 
SPIRVCodeGenerator(const Context * context,const Program * program,ErrorReporter * errors,SkWStream * out)67     SPIRVCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors,
68                        SkWStream* out)
69     : INHERITED(program, errors, out)
70     , fContext(*context)
71     , fDefaultLayout(MemoryLayout::k140_Standard)
72     , fCapabilities(1 << SpvCapabilityShader)
73     , fIdCount(1)
74     , fBoolTrue(0)
75     , fBoolFalse(0)
76     , fSetupFragPosition(false)
77     , fCurrentBlock(0) {
78         this->setupIntrinsics();
79     }
80 
81     bool generateCode() override;
82 
83 private:
84     enum IntrinsicKind {
85         kGLSL_STD_450_IntrinsicKind,
86         kSPIRV_IntrinsicKind,
87         kSpecial_IntrinsicKind
88     };
89 
90     enum SpecialIntrinsic {
91         kAtan_SpecialIntrinsic,
92         kTexture_SpecialIntrinsic,
93         kSubpassLoad_SpecialIntrinsic,
94     };
95 
96     void setupIntrinsics();
97 
98     SpvId nextId();
99 
100     SpvId getType(const Type& type);
101 
102     SpvId getType(const Type& type, const MemoryLayout& layout);
103 
104     SpvId getFunctionType(const FunctionDeclaration& function);
105 
106     SpvId getPointerType(const Type& type, SpvStorageClass_ storageClass);
107 
108     SpvId getPointerType(const Type& type, const MemoryLayout& layout,
109                          SpvStorageClass_ storageClass);
110 
111     std::vector<SpvId> getAccessChain(const Expression& expr, SkWStream& out);
112 
113     void writeLayout(const Layout& layout, SpvId target);
114 
115     void writeLayout(const Layout& layout, SpvId target, int member);
116 
117     void writeStruct(const Type& type, const MemoryLayout& layout, SpvId resultId);
118 
119     void writeProgramElement(const ProgramElement& pe, SkWStream& out);
120 
121     SpvId writeInterfaceBlock(const InterfaceBlock& intf);
122 
123     SpvId writeFunctionStart(const FunctionDeclaration& f, SkWStream& out);
124 
125     SpvId writeFunctionDeclaration(const FunctionDeclaration& f, SkWStream& out);
126 
127     SpvId writeFunction(const FunctionDefinition& f, SkWStream& out);
128 
129     void writeGlobalVars(Program::Kind kind, const VarDeclarations& v, SkWStream& out);
130 
131     void writeVarDeclarations(const VarDeclarations& decl, SkWStream& out);
132 
133     SpvId writeVariableReference(const VariableReference& ref, SkWStream& out);
134 
135     std::unique_ptr<LValue> getLValue(const Expression& value, SkWStream& out);
136 
137     SpvId writeExpression(const Expression& expr, SkWStream& out);
138 
139     SpvId writeIntrinsicCall(const FunctionCall& c, SkWStream& out);
140 
141     SpvId writeFunctionCall(const FunctionCall& c, SkWStream& out);
142 
143     SpvId writeSpecialIntrinsic(const FunctionCall& c, SpecialIntrinsic kind, SkWStream& out);
144 
145     SpvId writeConstantVector(const Constructor& c);
146 
147     SpvId writeFloatConstructor(const Constructor& c, SkWStream& out);
148 
149     SpvId writeIntConstructor(const Constructor& c, SkWStream& out);
150 
151     /**
152      * Writes a matrix with the diagonal entries all equal to the provided expression, and all other
153      * entries equal to zero.
154      */
155     void writeUniformScaleMatrix(SpvId id, SpvId diagonal, const Type& type, SkWStream& out);
156 
157     /**
158      * Writes a potentially-different-sized copy of a matrix. Entries which do not exist in the
159      * source matrix are filled with zero; entries which do not exist in the destination matrix are
160      * ignored.
161      */
162     void writeMatrixCopy(SpvId id, SpvId src, const Type& srcType, const Type& dstType,
163                          SkWStream& out);
164 
165     SpvId writeMatrixConstructor(const Constructor& c, SkWStream& out);
166 
167     SpvId writeVectorConstructor(const Constructor& c, SkWStream& out);
168 
169     SpvId writeConstructor(const Constructor& c, SkWStream& out);
170 
171     SpvId writeFieldAccess(const FieldAccess& f, SkWStream& out);
172 
173     SpvId writeSwizzle(const Swizzle& swizzle, SkWStream& out);
174 
175     /**
176      * Folds the potentially-vector result of a logical operation down to a single bool. If
177      * operandType is a vector type, assumes that the intermediate result in id is a bvec of the
178      * same dimensions, and applys all() to it to fold it down to a single bool value. Otherwise,
179      * returns the original id value.
180      */
181     SpvId foldToBool(SpvId id, const Type& operandType, SkWStream& out);
182 
183     SpvId writeBinaryOperation(const Type& resultType, const Type& operandType, SpvId lhs,
184                                SpvId rhs, SpvOp_ ifFloat, SpvOp_ ifInt, SpvOp_ ifUInt,
185                                SpvOp_ ifBool, SkWStream& out);
186 
187     SpvId writeBinaryOperation(const BinaryExpression& expr, SpvOp_ ifFloat, SpvOp_ ifInt,
188                                SpvOp_ ifUInt, SkWStream& out);
189 
190     SpvId writeBinaryExpression(const BinaryExpression& b, SkWStream& out);
191 
192     SpvId writeTernaryExpression(const TernaryExpression& t, SkWStream& out);
193 
194     SpvId writeIndexExpression(const IndexExpression& expr, SkWStream& out);
195 
196     SpvId writeLogicalAnd(const BinaryExpression& b, SkWStream& out);
197 
198     SpvId writeLogicalOr(const BinaryExpression& o, SkWStream& out);
199 
200     SpvId writePrefixExpression(const PrefixExpression& p, SkWStream& out);
201 
202     SpvId writePostfixExpression(const PostfixExpression& p, SkWStream& out);
203 
204     SpvId writeBoolLiteral(const BoolLiteral& b);
205 
206     SpvId writeIntLiteral(const IntLiteral& i);
207 
208     SpvId writeFloatLiteral(const FloatLiteral& f);
209 
210     void writeStatement(const Statement& s, SkWStream& out);
211 
212     void writeBlock(const Block& b, SkWStream& out);
213 
214     void writeIfStatement(const IfStatement& stmt, SkWStream& out);
215 
216     void writeForStatement(const ForStatement& f, SkWStream& out);
217 
218     void writeWhileStatement(const WhileStatement& w, SkWStream& out);
219 
220     void writeDoStatement(const DoStatement& d, SkWStream& out);
221 
222     void writeReturnStatement(const ReturnStatement& r, SkWStream& out);
223 
224     void writeCapabilities(SkWStream& out);
225 
226     void writeInstructions(const Program& program, SkWStream& out);
227 
228     void writeOpCode(SpvOp_ opCode, int length, SkWStream& out);
229 
230     void writeWord(int32_t word, SkWStream& out);
231 
232     void writeString(const char* string, SkWStream& out);
233 
234     void writeLabel(SpvId id, SkWStream& out);
235 
236     void writeInstruction(SpvOp_ opCode, SkWStream& out);
237 
238     void writeInstruction(SpvOp_ opCode, const char* string, SkWStream& out);
239 
240     void writeInstruction(SpvOp_ opCode, int32_t word1, SkWStream& out);
241 
242     void writeInstruction(SpvOp_ opCode, int32_t word1, const char* string, SkWStream& out);
243 
244     void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, const char* string,
245                           SkWStream& out);
246 
247     void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, SkWStream& out);
248 
249     void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3,
250                           SkWStream& out);
251 
252     void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4,
253                           SkWStream& out);
254 
255     void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4,
256                           int32_t word5, SkWStream& out);
257 
258     void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4,
259                           int32_t word5, int32_t word6, SkWStream& out);
260 
261     void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4,
262                           int32_t word5, int32_t word6, int32_t word7, SkWStream& out);
263 
264     void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4,
265                           int32_t word5, int32_t word6, int32_t word7, int32_t word8,
266                           SkWStream& out);
267 
268     const Context& fContext;
269     const MemoryLayout fDefaultLayout;
270 
271     uint64_t fCapabilities;
272     SpvId fIdCount;
273     SpvId fGLSLExtendedInstructions;
274     typedef std::tuple<IntrinsicKind, int32_t, int32_t, int32_t, int32_t> Intrinsic;
275     std::unordered_map<SkString, Intrinsic> fIntrinsicMap;
276     std::unordered_map<const FunctionDeclaration*, SpvId> fFunctionMap;
277     std::unordered_map<const Variable*, SpvId> fVariableMap;
278     std::unordered_map<const Variable*, int32_t> fInterfaceBlockMap;
279     std::unordered_map<SkString, SpvId> fTypeMap;
280     SkDynamicMemoryWStream fCapabilitiesBuffer;
281     SkDynamicMemoryWStream fGlobalInitializersBuffer;
282     SkDynamicMemoryWStream fConstantBuffer;
283     SkDynamicMemoryWStream fExtraGlobalsBuffer;
284     SkDynamicMemoryWStream fExternalFunctionsBuffer;
285     SkDynamicMemoryWStream fVariableBuffer;
286     SkDynamicMemoryWStream fNameBuffer;
287     SkDynamicMemoryWStream fDecorationBuffer;
288 
289     SpvId fBoolTrue;
290     SpvId fBoolFalse;
291     std::unordered_map<int64_t, SpvId> fIntConstants;
292     std::unordered_map<uint64_t, SpvId> fUIntConstants;
293     std::unordered_map<float, SpvId> fFloatConstants;
294     std::unordered_map<double, SpvId> fDoubleConstants;
295     bool fSetupFragPosition;
296     // label of the current block, or 0 if we are not in a block
297     SpvId fCurrentBlock;
298     std::stack<SpvId> fBreakTarget;
299     std::stack<SpvId> fContinueTarget;
300     SpvId fRTHeightStructId = (SpvId) -1;
301     SpvId fRTHeightFieldIndex = (SpvId) -1;
302 
303     friend class PointerLValue;
304     friend class SwizzleLValue;
305 
306     typedef CodeGenerator INHERITED;
307 };
308 
309 }
310 
311 #endif
312