Line data Source code
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 "SkSLCodeGenerator.h"
16 : #include "SkSLMemoryLayout.h"
17 : #include "ir/SkSLBinaryExpression.h"
18 : #include "ir/SkSLBoolLiteral.h"
19 : #include "ir/SkSLConstructor.h"
20 : #include "ir/SkSLDoStatement.h"
21 : #include "ir/SkSLFloatLiteral.h"
22 : #include "ir/SkSLIfStatement.h"
23 : #include "ir/SkSLIndexExpression.h"
24 : #include "ir/SkSLInterfaceBlock.h"
25 : #include "ir/SkSLIntLiteral.h"
26 : #include "ir/SkSLFieldAccess.h"
27 : #include "ir/SkSLForStatement.h"
28 : #include "ir/SkSLFunctionCall.h"
29 : #include "ir/SkSLFunctionDeclaration.h"
30 : #include "ir/SkSLFunctionDefinition.h"
31 : #include "ir/SkSLPrefixExpression.h"
32 : #include "ir/SkSLPostfixExpression.h"
33 : #include "ir/SkSLProgramElement.h"
34 : #include "ir/SkSLReturnStatement.h"
35 : #include "ir/SkSLStatement.h"
36 : #include "ir/SkSLSwizzle.h"
37 : #include "ir/SkSLTernaryExpression.h"
38 : #include "ir/SkSLVarDeclarations.h"
39 : #include "ir/SkSLVarDeclarationsStatement.h"
40 : #include "ir/SkSLVariableReference.h"
41 : #include "ir/SkSLWhileStatement.h"
42 : #include "spirv.h"
43 :
44 : namespace SkSL {
45 :
46 : #define kLast_Capability SpvCapabilityMultiViewport
47 :
48 : /**
49 : * Converts a Program into a SPIR-V binary.
50 : */
51 0 : class SPIRVCodeGenerator : public CodeGenerator {
52 : public:
53 0 : class LValue {
54 : public:
55 0 : virtual ~LValue() {}
56 :
57 : // returns a pointer to the lvalue, if possible. If the lvalue cannot be directly referenced
58 : // by a pointer (e.g. vector swizzles), returns 0.
59 : virtual SpvId getPointer() = 0;
60 :
61 : virtual SpvId load(OutputStream& out) = 0;
62 :
63 : virtual void store(SpvId value, OutputStream& out) = 0;
64 : };
65 :
66 0 : SPIRVCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors,
67 : OutputStream* out)
68 0 : : INHERITED(program, errors, out)
69 : , fContext(*context)
70 : , fDefaultLayout(MemoryLayout::k140_Standard)
71 : , fCapabilities(1 << SpvCapabilityShader)
72 : , fIdCount(1)
73 : , fBoolTrue(0)
74 : , fBoolFalse(0)
75 : , fSetupFragPosition(false)
76 : , fCurrentBlock(0)
77 0 : , fSynthetics(nullptr, errors) {
78 0 : this->setupIntrinsics();
79 0 : }
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, OutputStream& 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, OutputStream& out);
120 :
121 : SpvId writeInterfaceBlock(const InterfaceBlock& intf);
122 :
123 : SpvId writeFunctionStart(const FunctionDeclaration& f, OutputStream& out);
124 :
125 : SpvId writeFunctionDeclaration(const FunctionDeclaration& f, OutputStream& out);
126 :
127 : SpvId writeFunction(const FunctionDefinition& f, OutputStream& out);
128 :
129 : void writeGlobalVars(Program::Kind kind, const VarDeclarations& v, OutputStream& out);
130 :
131 : void writeVarDeclarations(const VarDeclarations& decl, OutputStream& out);
132 :
133 : SpvId writeVariableReference(const VariableReference& ref, OutputStream& out);
134 :
135 : std::unique_ptr<LValue> getLValue(const Expression& value, OutputStream& out);
136 :
137 : SpvId writeExpression(const Expression& expr, OutputStream& out);
138 :
139 : SpvId writeIntrinsicCall(const FunctionCall& c, OutputStream& out);
140 :
141 : SpvId writeFunctionCall(const FunctionCall& c, OutputStream& out);
142 :
143 : SpvId writeSpecialIntrinsic(const FunctionCall& c, SpecialIntrinsic kind, OutputStream& out);
144 :
145 : SpvId writeConstantVector(const Constructor& c);
146 :
147 : SpvId writeFloatConstructor(const Constructor& c, OutputStream& out);
148 :
149 : SpvId writeIntConstructor(const Constructor& c, OutputStream& 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, OutputStream& 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 : OutputStream& out);
164 :
165 : SpvId writeMatrixConstructor(const Constructor& c, OutputStream& out);
166 :
167 : SpvId writeVectorConstructor(const Constructor& c, OutputStream& out);
168 :
169 : SpvId writeConstructor(const Constructor& c, OutputStream& out);
170 :
171 : SpvId writeFieldAccess(const FieldAccess& f, OutputStream& out);
172 :
173 : SpvId writeSwizzle(const Swizzle& swizzle, OutputStream& 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, OutputStream& 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, OutputStream& out);
186 :
187 : SpvId writeBinaryOperation(const BinaryExpression& expr, SpvOp_ ifFloat, SpvOp_ ifInt,
188 : SpvOp_ ifUInt, OutputStream& out);
189 :
190 : SpvId writeBinaryExpression(const BinaryExpression& b, OutputStream& out);
191 :
192 : SpvId writeTernaryExpression(const TernaryExpression& t, OutputStream& out);
193 :
194 : SpvId writeIndexExpression(const IndexExpression& expr, OutputStream& out);
195 :
196 : SpvId writeLogicalAnd(const BinaryExpression& b, OutputStream& out);
197 :
198 : SpvId writeLogicalOr(const BinaryExpression& o, OutputStream& out);
199 :
200 : SpvId writePrefixExpression(const PrefixExpression& p, OutputStream& out);
201 :
202 : SpvId writePostfixExpression(const PostfixExpression& p, OutputStream& 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, OutputStream& out);
211 :
212 : void writeBlock(const Block& b, OutputStream& out);
213 :
214 : void writeIfStatement(const IfStatement& stmt, OutputStream& out);
215 :
216 : void writeForStatement(const ForStatement& f, OutputStream& out);
217 :
218 : void writeWhileStatement(const WhileStatement& w, OutputStream& out);
219 :
220 : void writeDoStatement(const DoStatement& d, OutputStream& out);
221 :
222 : void writeReturnStatement(const ReturnStatement& r, OutputStream& out);
223 :
224 : void writeCapabilities(OutputStream& out);
225 :
226 : void writeInstructions(const Program& program, OutputStream& out);
227 :
228 : void writeOpCode(SpvOp_ opCode, int length, OutputStream& out);
229 :
230 : void writeWord(int32_t word, OutputStream& out);
231 :
232 : void writeString(const char* string, OutputStream& out);
233 :
234 : void writeLabel(SpvId id, OutputStream& out);
235 :
236 : void writeInstruction(SpvOp_ opCode, OutputStream& out);
237 :
238 : void writeInstruction(SpvOp_ opCode, const char* string, OutputStream& out);
239 :
240 : void writeInstruction(SpvOp_ opCode, int32_t word1, OutputStream& out);
241 :
242 : void writeInstruction(SpvOp_ opCode, int32_t word1, const char* string, OutputStream& out);
243 :
244 : void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, const char* string,
245 : OutputStream& out);
246 :
247 : void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, OutputStream& out);
248 :
249 : void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3,
250 : OutputStream& out);
251 :
252 : void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4,
253 : OutputStream& out);
254 :
255 : void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4,
256 : int32_t word5, OutputStream& 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, OutputStream& 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, OutputStream& 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 : OutputStream& 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<String, 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<String, SpvId> fTypeMap;
280 : StringStream fCapabilitiesBuffer;
281 : StringStream fGlobalInitializersBuffer;
282 : StringStream fConstantBuffer;
283 : StringStream fExtraGlobalsBuffer;
284 : StringStream fExternalFunctionsBuffer;
285 : StringStream fVariableBuffer;
286 : StringStream fNameBuffer;
287 : StringStream 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 : // holds variables synthesized during output, for lifetime purposes
303 : SymbolTable fSynthetics;
304 :
305 : friend class PointerLValue;
306 : friend class SwizzleLValue;
307 :
308 : typedef CodeGenerator INHERITED;
309 : };
310 :
311 : }
312 :
313 : #endif
|