Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/sksl/SkSLSPIRVCodeGenerator.cpp

Issue 1984363002: initial checkin of SkSL compiler (Closed) Base URL: https://skia.googlesource.com/skia@master
Patch Set: SPIRVCodeGenerator updates Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 #include "SkSLSPIRVCodeGenerator.h"
9
10 #include "string.h"
11
12 #include "GLSL.std.450.h"
13
14 #include "ir/SkSLExpressionStatement.h"
15 #include "ir/SkSLExtension.h"
16 #include "ir/SkSLIndexExpression.h"
17 #include "ir/SkSLVariableReference.h"
18
19 namespace SkSL {
20
21 #define SPIRV_DEBUG 0
22
23 static const int32_t SKSL_MAGIC = 0x0; // FIXME: we should probably register a magic number
24
25 void SPIRVCodeGenerator::setupIntrinsics() {
26 #define ALL_GLSL(x) std::make_tuple(kGLSL_STD_450_IntrinsicKind, GLSLstd450 ## x , GLSLstd450 ## x, \
27 GLSLstd450 ## x, GLSLstd450 ## x)
28 #define BY_TYPE_GLSL(ifFloat, ifInt, ifUInt) std::make_tuple(kGLSL_STD_450_Intri nsicKind, \
29 GLSLstd450 ## ifFlo at, \
30 GLSLstd450 ## ifInt , \
31 GLSLstd450 ## ifUIn t, \
32 SpvOpUndef)
33 #define SPECIAL(x) std::make_tuple(kSpecial_IntrinsicKind, k ## x ## _SpecialInt rinsic, \
34 k ## x ## _SpecialIntrinsic, k ## x ## _Speci alIntrinsic, \
35 k ## x ## _SpecialIntrinsic)
36 fIntrinsicMap["round"] = ALL_GLSL(Round);
37 fIntrinsicMap["roundEven"] = ALL_GLSL(RoundEven);
38 fIntrinsicMap["trunc"] = ALL_GLSL(Trunc);
39 fIntrinsicMap["abs"] = BY_TYPE_GLSL(FAbs, SAbs, SAbs);
40 fIntrinsicMap["sign"] = BY_TYPE_GLSL(FSign, SSign, SSign);
41 fIntrinsicMap["floor"] = ALL_GLSL(Floor);
42 fIntrinsicMap["ceil"] = ALL_GLSL(Ceil);
43 fIntrinsicMap["fract"] = ALL_GLSL(Fract);
44 fIntrinsicMap["radians"] = ALL_GLSL(Radians);
45 fIntrinsicMap["degrees"] = ALL_GLSL(Degrees);
46 fIntrinsicMap["sin"] = ALL_GLSL(Sin);
47 fIntrinsicMap["cos"] = ALL_GLSL(Cos);
48 fIntrinsicMap["tan"] = ALL_GLSL(Tan);
49 fIntrinsicMap["asin"] = ALL_GLSL(Asin);
50 fIntrinsicMap["acos"] = ALL_GLSL(Acos);
51 fIntrinsicMap["atan"] = SPECIAL(Atan);
52 fIntrinsicMap["sinh"] = ALL_GLSL(Sinh);
53 fIntrinsicMap["cosh"] = ALL_GLSL(Cosh);
54 fIntrinsicMap["tanh"] = ALL_GLSL(Tanh);
55 fIntrinsicMap["asinh"] = ALL_GLSL(Asinh);
56 fIntrinsicMap["acosh"] = ALL_GLSL(Acosh);
57 fIntrinsicMap["atanh"] = ALL_GLSL(Atanh);
58 fIntrinsicMap["pow"] = ALL_GLSL(Pow);
59 fIntrinsicMap["exp"] = ALL_GLSL(Exp);
60 fIntrinsicMap["log"] = ALL_GLSL(Log);
61 fIntrinsicMap["exp2"] = ALL_GLSL(Exp2);
62 fIntrinsicMap["log2"] = ALL_GLSL(Log2);
63 fIntrinsicMap["sqrt"] = ALL_GLSL(Sqrt);
64 fIntrinsicMap["inversesqrt"] = ALL_GLSL(InverseSqrt);
65 fIntrinsicMap["determinant"] = ALL_GLSL(Determinant);
66 fIntrinsicMap["matrixInverse"] = ALL_GLSL(MatrixInverse);
67 fIntrinsicMap["mod"] = std::make_tuple(kSPIRV_IntrinsicKind, SpvOp FMod, SpvOpSMod,
68 SpvOpUMod, SpvOpUndef);
69 fIntrinsicMap["min"] = BY_TYPE_GLSL(FMin, SMin, UMin);
70 fIntrinsicMap["max"] = BY_TYPE_GLSL(FMax, SMax, UMax);
71 fIntrinsicMap["clamp"] = BY_TYPE_GLSL(FClamp, SClamp, UClamp);
72 fIntrinsicMap["dot"] = std::make_tuple(kSPIRV_IntrinsicKind, SpvOp Dot, SpvOpUndef,
73 SpvOpUndef, SpvOpUndef);
74 fIntrinsicMap["mix"] = ALL_GLSL(FMix);
75 fIntrinsicMap["step"] = ALL_GLSL(Step);
76 fIntrinsicMap["smoothstep"] = ALL_GLSL(SmoothStep);
77 fIntrinsicMap["fma"] = ALL_GLSL(Fma);
78 fIntrinsicMap["frexp"] = ALL_GLSL(Frexp);
79 fIntrinsicMap["ldexp"] = ALL_GLSL(Ldexp);
80
81 #define PACK(type) fIntrinsicMap["pack" #type] = ALL_GLSL(Pack ## type); \
82 fIntrinsicMap["unpack" #type] = ALL_GLSL(Unpack ## type)
83 PACK(Snorm4x8);
84 PACK(Unorm4x8);
85 PACK(Snorm2x16);
86 PACK(Unorm2x16);
87 PACK(Half2x16);
88 PACK(Double2x32);
89 fIntrinsicMap["length"] = ALL_GLSL(Length);
90 fIntrinsicMap["distance"] = ALL_GLSL(Distance);
91 fIntrinsicMap["cross"] = ALL_GLSL(Cross);
92 fIntrinsicMap["normalize"] = ALL_GLSL(Normalize);
93 fIntrinsicMap["faceForward"] = ALL_GLSL(FaceForward);
94 fIntrinsicMap["reflect"] = ALL_GLSL(Reflect);
95 fIntrinsicMap["refract"] = ALL_GLSL(Refract);
96 fIntrinsicMap["findLSB"] = ALL_GLSL(FindILsb);
97 fIntrinsicMap["findMSB"] = BY_TYPE_GLSL(FindSMsb, FindSMsb, FindUMsb);
98 fIntrinsicMap["dFdx"] = std::make_tuple(kSPIRV_IntrinsicKind, SpvOpDP dx, SpvOpUndef,
99 SpvOpUndef, SpvOpUndef);
100 fIntrinsicMap["dFdy"] = std::make_tuple(kSPIRV_IntrinsicKind, SpvOpDP dy, SpvOpUndef,
101 SpvOpUndef, SpvOpUndef);
102 fIntrinsicMap["dFdy"] = std::make_tuple(kSPIRV_IntrinsicKind, SpvOpDP dy, SpvOpUndef,
103 SpvOpUndef, SpvOpUndef);
104 fIntrinsicMap["texture"] = SPECIAL(Texture);
105 fIntrinsicMap["texture2D"] = SPECIAL(Texture2D);
106 fIntrinsicMap["textureProj"] = SPECIAL(TextureProj);
107
108 fIntrinsicMap["any"] = std::make_tuple(kSPIRV_IntrinsicKind, Sp vOpUndef,
109 SpvOpUndef, SpvOpUndef, SpvOpAny);
110 fIntrinsicMap["all"] = std::make_tuple(kSPIRV_IntrinsicKind, Sp vOpUndef,
111 SpvOpUndef, SpvOpUndef, SpvOpAll);
112 fIntrinsicMap["equal"] = std::make_tuple(kSPIRV_IntrinsicKind, Sp vOpFOrdEqual,
113 SpvOpIEqual, SpvOpIEqual ,
114 SpvOpLogicalEqual);
115 fIntrinsicMap["notEqual"] = std::make_tuple(kSPIRV_IntrinsicKind, Sp vOpFOrdNotEqual,
116 SpvOpINotEqual, SpvOpINo tEqual,
117 SpvOpLogicalNotEqual);
118 fIntrinsicMap["lessThan"] = std::make_tuple(kSPIRV_IntrinsicKind, Sp vOpSLessThan,
119 SpvOpULessThan, SpvOpFOr dLessThan,
120 SpvOpUndef);
121 fIntrinsicMap["lessThanEqual"] = std::make_tuple(kSPIRV_IntrinsicKind, Sp vOpSLessThanEqual,
122 SpvOpULessThanEqual, Spv OpFOrdLessThanEqual,
123 SpvOpUndef);
124 fIntrinsicMap["greaterThan"] = std::make_tuple(kSPIRV_IntrinsicKind, Sp vOpSGreaterThan,
125 SpvOpUGreaterThan, SpvOp FOrdGreaterThan,
126 SpvOpUndef);
127 fIntrinsicMap["greaterThanEqual"] = std::make_tuple(kSPIRV_IntrinsicKind,
128 SpvOpSGreaterThanEqual,
129 SpvOpUGreaterThanEqual,
130 SpvOpFOrdGreaterThanEqua l,
131 SpvOpUndef);
132
133 // interpolateAt* not yet supported...
134 }
135
136 void SPIRVCodeGenerator::writeWord(int32_t word, std::ostream& out) {
137 #if SPIRV_DEBUG
138 out << "(" << word << ") ";
139 #else
140 out.write((const char*) &word, sizeof(word));
141 #endif
142 }
143
144 static bool is_float(std::shared_ptr<Type> type) {
145 if (type->kind() == Type::kVector_Kind) {
146 return is_float(type->componentType());
147 }
148 return type == kFloat_Type || type == kDouble_Type;
149 }
150
151 static bool is_signed(std::shared_ptr<Type> type) {
152 if (type->kind() == Type::kVector_Kind) {
153 return is_signed(type->componentType());
154 }
155 return type == kInt_Type;
156 }
157
158 static bool is_unsigned(std::shared_ptr<Type> type) {
159 if (type->kind() == Type::kVector_Kind) {
160 return is_unsigned(type->componentType());
161 }
162 return type == kUInt_Type;
163 }
164
165 static bool is_bool(std::shared_ptr<Type> type) {
166 if (type->kind() == Type::kVector_Kind) {
167 return is_bool(type->componentType());
168 }
169 return type == kBool_Type;
170 }
171
172 static bool is_out(std::shared_ptr<Variable> var) {
173 return (var->fModifiers.fFlags & Modifiers::kOut_Flag) != 0;
174 }
175
176 static std::string opcode_text(SpvOp_ opCode) {
177 switch (opCode) {
178 case SpvOpNop:
179 return "Nop";
180 case SpvOpUndef:
181 return "Undef";
182 case SpvOpSourceContinued:
183 return "SourceContinued";
184 case SpvOpSource:
185 return "Source";
186 case SpvOpSourceExtension:
187 return "SourceExtension";
188 case SpvOpName:
189 return "Name";
190 case SpvOpMemberName:
191 return "MemberName";
192 case SpvOpString:
193 return "String";
194 case SpvOpLine:
195 return "Line";
196 case SpvOpExtension:
197 return "Extension";
198 case SpvOpExtInstImport:
199 return "ExtInstImport";
200 case SpvOpExtInst:
201 return "ExtInst";
202 case SpvOpMemoryModel:
203 return "MemoryModel";
204 case SpvOpEntryPoint:
205 return "EntryPoint";
206 case SpvOpExecutionMode:
207 return "ExecutionMode";
208 case SpvOpCapability:
209 return "Capability";
210 case SpvOpTypeVoid:
211 return "TypeVoid";
212 case SpvOpTypeBool:
213 return "TypeBool";
214 case SpvOpTypeInt:
215 return "TypeInt";
216 case SpvOpTypeFloat:
217 return "TypeFloat";
218 case SpvOpTypeVector:
219 return "TypeVector";
220 case SpvOpTypeMatrix:
221 return "TypeMatrix";
222 case SpvOpTypeImage:
223 return "TypeImage";
224 case SpvOpTypeSampler:
225 return "TypeSampler";
226 case SpvOpTypeSampledImage:
227 return "TypeSampledImage";
228 case SpvOpTypeArray:
229 return "TypeArray";
230 case SpvOpTypeRuntimeArray:
231 return "TypeRuntimeArray";
232 case SpvOpTypeStruct:
233 return "TypeStruct";
234 case SpvOpTypeOpaque:
235 return "TypeOpaque";
236 case SpvOpTypePointer:
237 return "TypePointer";
238 case SpvOpTypeFunction:
239 return "TypeFunction";
240 case SpvOpTypeEvent:
241 return "TypeEvent";
242 case SpvOpTypeDeviceEvent:
243 return "TypeDeviceEvent";
244 case SpvOpTypeReserveId:
245 return "TypeReserveId";
246 case SpvOpTypeQueue:
247 return "TypeQueue";
248 case SpvOpTypePipe:
249 return "TypePipe";
250 case SpvOpTypeForwardPointer:
251 return "TypeForwardPointer";
252 case SpvOpConstantTrue:
253 return "ConstantTrue";
254 case SpvOpConstantFalse:
255 return "ConstantFalse";
256 case SpvOpConstant:
257 return "Constant";
258 case SpvOpConstantComposite:
259 return "ConstantComposite";
260 case SpvOpConstantSampler:
261 return "ConstantSampler";
262 case SpvOpConstantNull:
263 return "ConstantNull";
264 case SpvOpSpecConstantTrue:
265 return "SpecConstantTrue";
266 case SpvOpSpecConstantFalse:
267 return "SpecConstantFalse";
268 case SpvOpSpecConstant:
269 return "SpecConstant";
270 case SpvOpSpecConstantComposite:
271 return "SpecConstantComposite";
272 case SpvOpSpecConstantOp:
273 return "SpecConstantOp";
274 case SpvOpFunction:
275 return "Function";
276 case SpvOpFunctionParameter:
277 return "FunctionParameter";
278 case SpvOpFunctionEnd:
279 return "FunctionEnd";
280 case SpvOpFunctionCall:
281 return "FunctionCall";
282 case SpvOpVariable:
283 return "Variable";
284 case SpvOpImageTexelPointer:
285 return "ImageTexelPointer";
286 case SpvOpLoad:
287 return "Load";
288 case SpvOpStore:
289 return "Store";
290 case SpvOpCopyMemory:
291 return "CopyMemory";
292 case SpvOpCopyMemorySized:
293 return "CopyMemorySized";
294 case SpvOpAccessChain:
295 return "AccessChain";
296 case SpvOpInBoundsAccessChain:
297 return "InBoundsAccessChain";
298 case SpvOpPtrAccessChain:
299 return "PtrAccessChain";
300 case SpvOpArrayLength:
301 return "ArrayLength";
302 case SpvOpGenericPtrMemSemantics:
303 return "GenericPtrMemSemantics";
304 case SpvOpInBoundsPtrAccessChain:
305 return "InBoundsPtrAccessChain";
306 case SpvOpDecorate:
307 return "Decorate";
308 case SpvOpMemberDecorate:
309 return "MemberDecorate";
310 case SpvOpDecorationGroup:
311 return "DecorationGroup";
312 case SpvOpGroupDecorate:
313 return "GroupDecorate";
314 case SpvOpGroupMemberDecorate:
315 return "GroupMemberDecorate";
316 case SpvOpVectorExtractDynamic:
317 return "VectorExtractDynamic";
318 case SpvOpVectorInsertDynamic:
319 return "VectorInsertDynamic";
320 case SpvOpVectorShuffle:
321 return "VectorShuffle";
322 case SpvOpCompositeConstruct:
323 return "CompositeConstruct";
324 case SpvOpCompositeExtract:
325 return "CompositeExtract";
326 case SpvOpCompositeInsert:
327 return "CompositeInsert";
328 case SpvOpCopyObject:
329 return "CopyObject";
330 case SpvOpTranspose:
331 return "Transpose";
332 case SpvOpSampledImage:
333 return "SampledImage";
334 case SpvOpImageSampleImplicitLod:
335 return "ImageSampleImplicitLod";
336 case SpvOpImageSampleExplicitLod:
337 return "ImageSampleExplicitLod";
338 case SpvOpImageSampleDrefImplicitLod:
339 return "ImageSampleDrefImplicitLod";
340 case SpvOpImageSampleDrefExplicitLod:
341 return "ImageSampleDrefExplicitLod";
342 case SpvOpImageSampleProjImplicitLod:
343 return "ImageSampleProjImplicitLod";
344 case SpvOpImageSampleProjExplicitLod:
345 return "ImageSampleProjExplicitLod";
346 case SpvOpImageSampleProjDrefImplicitLod:
347 return "ImageSampleProjDrefImplicitLod";
348 case SpvOpImageSampleProjDrefExplicitLod:
349 return "ImageSampleProjDrefExplicitLod";
350 case SpvOpImageFetch:
351 return "ImageFetch";
352 case SpvOpImageGather:
353 return "ImageGather";
354 case SpvOpImageDrefGather:
355 return "ImageDrefGather";
356 case SpvOpImageRead:
357 return "ImageRead";
358 case SpvOpImageWrite:
359 return "ImageWrite";
360 case SpvOpImage:
361 return "Image";
362 case SpvOpImageQueryFormat:
363 return "ImageQueryFormat";
364 case SpvOpImageQueryOrder:
365 return "ImageQueryOrder";
366 case SpvOpImageQuerySizeLod:
367 return "ImageQuerySizeLod";
368 case SpvOpImageQuerySize:
369 return "ImageQuerySize";
370 case SpvOpImageQueryLod:
371 return "ImageQueryLod";
372 case SpvOpImageQueryLevels:
373 return "ImageQueryLevels";
374 case SpvOpImageQuerySamples:
375 return "ImageQuerySamples";
376 case SpvOpConvertFToU:
377 return "ConvertFToU";
378 case SpvOpConvertFToS:
379 return "ConvertFToS";
380 case SpvOpConvertSToF:
381 return "ConvertSToF";
382 case SpvOpConvertUToF:
383 return "ConvertUToF";
384 case SpvOpUConvert:
385 return "UConvert";
386 case SpvOpSConvert:
387 return "SConvert";
388 case SpvOpFConvert:
389 return "FConvert";
390 case SpvOpQuantizeToF16:
391 return "QuantizeToF16";
392 case SpvOpConvertPtrToU:
393 return "ConvertPtrToU";
394 case SpvOpSatConvertSToU:
395 return "SatConvertSToU";
396 case SpvOpSatConvertUToS:
397 return "SatConvertUToS";
398 case SpvOpConvertUToPtr:
399 return "ConvertUToPtr";
400 case SpvOpPtrCastToGeneric:
401 return "PtrCastToGeneric";
402 case SpvOpGenericCastToPtr:
403 return "GenericCastToPtr";
404 case SpvOpGenericCastToPtrExplicit:
405 return "GenericCastToPtrExplicit";
406 case SpvOpBitcast:
407 return "Bitcast";
408 case SpvOpSNegate:
409 return "SNegate";
410 case SpvOpFNegate:
411 return "FNegate";
412 case SpvOpIAdd:
413 return "IAdd";
414 case SpvOpFAdd:
415 return "FAdd";
416 case SpvOpISub:
417 return "ISub";
418 case SpvOpFSub:
419 return "FSub";
420 case SpvOpIMul:
421 return "IMul";
422 case SpvOpFMul:
423 return "FMul";
424 case SpvOpUDiv:
425 return "UDiv";
426 case SpvOpSDiv:
427 return "SDiv";
428 case SpvOpFDiv:
429 return "FDiv";
430 case SpvOpUMod:
431 return "UMod";
432 case SpvOpSRem:
433 return "SRem";
434 case SpvOpSMod:
435 return "SMod";
436 case SpvOpFRem:
437 return "FRem";
438 case SpvOpFMod:
439 return "FMod";
440 case SpvOpVectorTimesScalar:
441 return "VectorTimesScalar";
442 case SpvOpMatrixTimesScalar:
443 return "MatrixTimesScalar";
444 case SpvOpVectorTimesMatrix:
445 return "VectorTimesMatrix";
446 case SpvOpMatrixTimesVector:
447 return "MatrixTimesVector";
448 case SpvOpMatrixTimesMatrix:
449 return "MatrixTimesMatrix";
450 case SpvOpOuterProduct:
451 return "OuterProduct";
452 case SpvOpDot:
453 return "Dot";
454 case SpvOpIAddCarry:
455 return "IAddCarry";
456 case SpvOpISubBorrow:
457 return "ISubBorrow";
458 case SpvOpUMulExtended:
459 return "UMulExtended";
460 case SpvOpSMulExtended:
461 return "SMulExtended";
462 case SpvOpAny:
463 return "Any";
464 case SpvOpAll:
465 return "All";
466 case SpvOpIsNan:
467 return "IsNan";
468 case SpvOpIsInf:
469 return "IsInf";
470 case SpvOpIsFinite:
471 return "IsFinite";
472 case SpvOpIsNormal:
473 return "IsNormal";
474 case SpvOpSignBitSet:
475 return "SignBitSet";
476 case SpvOpLessOrGreater:
477 return "LessOrGreater";
478 case SpvOpOrdered:
479 return "Ordered";
480 case SpvOpUnordered:
481 return "Unordered";
482 case SpvOpLogicalEqual:
483 return "LogicalEqual";
484 case SpvOpLogicalNotEqual:
485 return "LogicalNotEqual";
486 case SpvOpLogicalOr:
487 return "LogicalOr";
488 case SpvOpLogicalAnd:
489 return "LogicalAnd";
490 case SpvOpLogicalNot:
491 return "LogicalNot";
492 case SpvOpSelect:
493 return "Select";
494 case SpvOpIEqual:
495 return "IEqual";
496 case SpvOpINotEqual:
497 return "INotEqual";
498 case SpvOpUGreaterThan:
499 return "UGreaterThan";
500 case SpvOpSGreaterThan:
501 return "SGreaterThan";
502 case SpvOpUGreaterThanEqual:
503 return "UGreaterThanEqual";
504 case SpvOpSGreaterThanEqual:
505 return "SGreaterThanEqual";
506 case SpvOpULessThan:
507 return "ULessThan";
508 case SpvOpSLessThan:
509 return "SLessThan";
510 case SpvOpULessThanEqual:
511 return "ULessThanEqual";
512 case SpvOpSLessThanEqual:
513 return "SLessThanEqual";
514 case SpvOpFOrdEqual:
515 return "FOrdEqual";
516 case SpvOpFUnordEqual:
517 return "FUnordEqual";
518 case SpvOpFOrdNotEqual:
519 return "FOrdNotEqual";
520 case SpvOpFUnordNotEqual:
521 return "FUnordNotEqual";
522 case SpvOpFOrdLessThan:
523 return "FOrdLessThan";
524 case SpvOpFUnordLessThan:
525 return "FUnordLessThan";
526 case SpvOpFOrdGreaterThan:
527 return "FOrdGreaterThan";
528 case SpvOpFUnordGreaterThan:
529 return "FUnordGreaterThan";
530 case SpvOpFOrdLessThanEqual:
531 return "FOrdLessThanEqual";
532 case SpvOpFUnordLessThanEqual:
533 return "FUnordLessThanEqual";
534 case SpvOpFOrdGreaterThanEqual:
535 return "FOrdGreaterThanEqual";
536 case SpvOpFUnordGreaterThanEqual:
537 return "FUnordGreaterThanEqual";
538 case SpvOpShiftRightLogical:
539 return "ShiftRightLogical";
540 case SpvOpShiftRightArithmetic:
541 return "ShiftRightArithmetic";
542 case SpvOpShiftLeftLogical:
543 return "ShiftLeftLogical";
544 case SpvOpBitwiseOr:
545 return "BitwiseOr";
546 case SpvOpBitwiseXor:
547 return "BitwiseXor";
548 case SpvOpBitwiseAnd:
549 return "BitwiseAnd";
550 case SpvOpNot:
551 return "Not";
552 case SpvOpBitFieldInsert:
553 return "BitFieldInsert";
554 case SpvOpBitFieldSExtract:
555 return "BitFieldSExtract";
556 case SpvOpBitFieldUExtract:
557 return "BitFieldUExtract";
558 case SpvOpBitReverse:
559 return "BitReverse";
560 case SpvOpBitCount:
561 return "BitCount";
562 case SpvOpDPdx:
563 return "DPdx";
564 case SpvOpDPdy:
565 return "DPdy";
566 case SpvOpFwidth:
567 return "Fwidth";
568 case SpvOpDPdxFine:
569 return "DPdxFine";
570 case SpvOpDPdyFine:
571 return "DPdyFine";
572 case SpvOpFwidthFine:
573 return "FwidthFine";
574 case SpvOpDPdxCoarse:
575 return "DPdxCoarse";
576 case SpvOpDPdyCoarse:
577 return "DPdyCoarse";
578 case SpvOpFwidthCoarse:
579 return "FwidthCoarse";
580 case SpvOpEmitVertex:
581 return "EmitVertex";
582 case SpvOpEndPrimitive:
583 return "EndPrimitive";
584 case SpvOpEmitStreamVertex:
585 return "EmitStreamVertex";
586 case SpvOpEndStreamPrimitive:
587 return "EndStreamPrimitive";
588 case SpvOpControlBarrier:
589 return "ControlBarrier";
590 case SpvOpMemoryBarrier:
591 return "MemoryBarrier";
592 case SpvOpAtomicLoad:
593 return "AtomicLoad";
594 case SpvOpAtomicStore:
595 return "AtomicStore";
596 case SpvOpAtomicExchange:
597 return "AtomicExchange";
598 case SpvOpAtomicCompareExchange:
599 return "AtomicCompareExchange";
600 case SpvOpAtomicCompareExchangeWeak:
601 return "AtomicCompareExchangeWeak";
602 case SpvOpAtomicIIncrement:
603 return "AtomicIIncrement";
604 case SpvOpAtomicIDecrement:
605 return "AtomicIDecrement";
606 case SpvOpAtomicIAdd:
607 return "AtomicIAdd";
608 case SpvOpAtomicISub:
609 return "AtomicISub";
610 case SpvOpAtomicSMin:
611 return "AtomicSMin";
612 case SpvOpAtomicUMin:
613 return "AtomicUMin";
614 case SpvOpAtomicSMax:
615 return "AtomicSMax";
616 case SpvOpAtomicUMax:
617 return "AtomicUMax";
618 case SpvOpAtomicAnd:
619 return "AtomicAnd";
620 case SpvOpAtomicOr:
621 return "AtomicOr";
622 case SpvOpAtomicXor:
623 return "AtomicXor";
624 case SpvOpPhi:
625 return "Phi";
626 case SpvOpLoopMerge:
627 return "LoopMerge";
628 case SpvOpSelectionMerge:
629 return "SelectionMerge";
630 case SpvOpLabel:
631 return "Label";
632 case SpvOpBranch:
633 return "Branch";
634 case SpvOpBranchConditional:
635 return "BranchConditional";
636 case SpvOpSwitch:
637 return "Switch";
638 case SpvOpKill:
639 return "Kill";
640 case SpvOpReturn:
641 return "Return";
642 case SpvOpReturnValue:
643 return "ReturnValue";
644 case SpvOpUnreachable:
645 return "Unreachable";
646 case SpvOpLifetimeStart:
647 return "LifetimeStart";
648 case SpvOpLifetimeStop:
649 return "LifetimeStop";
650 case SpvOpGroupAsyncCopy:
651 return "GroupAsyncCopy";
652 case SpvOpGroupWaitEvents:
653 return "GroupWaitEvents";
654 case SpvOpGroupAll:
655 return "GroupAll";
656 case SpvOpGroupAny:
657 return "GroupAny";
658 case SpvOpGroupBroadcast:
659 return "GroupBroadcast";
660 case SpvOpGroupIAdd:
661 return "GroupIAdd";
662 case SpvOpGroupFAdd:
663 return "GroupFAdd";
664 case SpvOpGroupFMin:
665 return "GroupFMin";
666 case SpvOpGroupUMin:
667 return "GroupUMin";
668 case SpvOpGroupSMin:
669 return "GroupSMin";
670 case SpvOpGroupFMax:
671 return "GroupFMax";
672 case SpvOpGroupUMax:
673 return "GroupUMax";
674 case SpvOpGroupSMax:
675 return "GroupSMax";
676 case SpvOpReadPipe:
677 return "ReadPipe";
678 case SpvOpWritePipe:
679 return "WritePipe";
680 case SpvOpReservedReadPipe:
681 return "ReservedReadPipe";
682 case SpvOpReservedWritePipe:
683 return "ReservedWritePipe";
684 case SpvOpReserveReadPipePackets:
685 return "ReserveReadPipePackets";
686 case SpvOpReserveWritePipePackets:
687 return "ReserveWritePipePackets";
688 case SpvOpCommitReadPipe:
689 return "CommitReadPipe";
690 case SpvOpCommitWritePipe:
691 return "CommitWritePipe";
692 case SpvOpIsValidReserveId:
693 return "IsValidReserveId";
694 case SpvOpGetNumPipePackets:
695 return "GetNumPipePackets";
696 case SpvOpGetMaxPipePackets:
697 return "GetMaxPipePackets";
698 case SpvOpGroupReserveReadPipePackets:
699 return "GroupReserveReadPipePackets";
700 case SpvOpGroupReserveWritePipePackets:
701 return "GroupReserveWritePipePackets";
702 case SpvOpGroupCommitReadPipe:
703 return "GroupCommitReadPipe";
704 case SpvOpGroupCommitWritePipe:
705 return "GroupCommitWritePipe";
706 case SpvOpEnqueueMarker:
707 return "EnqueueMarker";
708 case SpvOpEnqueueKernel:
709 return "EnqueueKernel";
710 case SpvOpGetKernelNDrangeSubGroupCount:
711 return "GetKernelNDrangeSubGroupCount";
712 case SpvOpGetKernelNDrangeMaxSubGroupSize:
713 return "GetKernelNDrangeMaxSubGroupSize";
714 case SpvOpGetKernelWorkGroupSize:
715 return "GetKernelWorkGroupSize";
716 case SpvOpGetKernelPreferredWorkGroupSizeMultiple:
717 return "GetKernelPreferredWorkGroupSizeMultiple";
718 case SpvOpRetainEvent:
719 return "RetainEvent";
720 case SpvOpReleaseEvent:
721 return "ReleaseEvent";
722 case SpvOpCreateUserEvent:
723 return "CreateUserEvent";
724 case SpvOpIsValidEvent:
725 return "IsValidEvent";
726 case SpvOpSetUserEventStatus:
727 return "SetUserEventStatus";
728 case SpvOpCaptureEventProfilingInfo:
729 return "CaptureEventProfilingInfo";
730 case SpvOpGetDefaultQueue:
731 return "GetDefaultQueue";
732 case SpvOpBuildNDRange:
733 return "BuildNDRange";
734 case SpvOpImageSparseSampleImplicitLod:
735 return "ImageSparseSampleImplicitLod";
736 case SpvOpImageSparseSampleExplicitLod:
737 return "ImageSparseSampleExplicitLod";
738 case SpvOpImageSparseSampleDrefImplicitLod:
739 return "ImageSparseSampleDrefImplicitLod";
740 case SpvOpImageSparseSampleDrefExplicitLod:
741 return "ImageSparseSampleDrefExplicitLod";
742 case SpvOpImageSparseSampleProjImplicitLod:
743 return "ImageSparseSampleProjImplicitLod";
744 case SpvOpImageSparseSampleProjExplicitLod:
745 return "ImageSparseSampleProjExplicitLod";
746 case SpvOpImageSparseSampleProjDrefImplicitLod:
747 return "ImageSparseSampleProjDrefImplicitLod";
748 case SpvOpImageSparseSampleProjDrefExplicitLod:
749 return "ImageSparseSampleProjDrefExplicitLod";
750 case SpvOpImageSparseFetch:
751 return "ImageSparseFetch";
752 case SpvOpImageSparseGather:
753 return "ImageSparseGather";
754 case SpvOpImageSparseDrefGather:
755 return "ImageSparseDrefGather";
756 case SpvOpImageSparseTexelsResident:
757 return "ImageSparseTexelsResident";
758 case SpvOpNoLine:
759 return "NoLine";
760 case SpvOpAtomicFlagTestAndSet:
761 return "AtomicFlagTestAndSet";
762 case SpvOpAtomicFlagClear:
763 return "AtomicFlagClear";
764 case SpvOpImageSparseRead:
765 return "ImageSparseRead";
766 default:
767 ABORT("unsupported SPIR-V op");
768 }
769 }
770
771 void SPIRVCodeGenerator::writeOpCode(SpvOp_ opCode, int length, std::ostream& ou t) {
772 ASSERT(opCode != SpvOpLabel && opCode != SpvOpUndef);
773 switch (opCode) {
774 case SpvOpReturn: // fall through
775 case SpvOpReturnValue: // fall through
776 case SpvOpBranch: // fall through
777 case SpvOpBranchConditional:
778 if (!fCurrentBlock) {
779 printf("using %s outside of a block\n", opcode_text(opCode).c_st r());
780 ASSERT(false);
781 }
782 fCurrentBlock = 0;
783 break;
784 case SpvOpConstant: // fall through
785 case SpvOpConstantTrue: // fall through
786 case SpvOpConstantFalse: // fall through
787 case SpvOpConstantComposite: // fall through
788 case SpvOpTypeVoid: // fall through
789 case SpvOpTypeInt: // fall through
790 case SpvOpTypeFloat: // fall through
791 case SpvOpTypeBool: // fall through
792 case SpvOpTypeVector: // fall through
793 case SpvOpTypeMatrix: // fall through
794 case SpvOpTypeArray: // fall through
795 case SpvOpTypePointer: // fall through
796 case SpvOpTypeFunction: // fall through
797 case SpvOpTypeRuntimeArray: // fall through
798 case SpvOpTypeStruct: // fall through
799 case SpvOpTypeImage: // fall through
800 case SpvOpTypeSampledImage: // fall through
801 case SpvOpVariable: // fall through
802 case SpvOpFunction: // fall through
803 case SpvOpFunctionParameter: // fall through
804 case SpvOpFunctionEnd: // fall through
805 case SpvOpExecutionMode: // fall through
806 case SpvOpMemoryModel: // fall through
807 case SpvOpCapability: // fall through
808 case SpvOpExtInstImport: // fall through
809 case SpvOpEntryPoint: // fall through
810 case SpvOpSource: // fall through
811 case SpvOpSourceExtension: // fall through
812 case SpvOpName: // fall through
813 case SpvOpMemberName: // fall through
814 case SpvOpDecorate: // fall through
815 case SpvOpMemberDecorate:
816 break;
817 default:
818 if (!fCurrentBlock) {
819 printf("using %s outside of a block\n", opcode_text(opCode).c_st r());
820 ASSERT(false);
821 }
822 }
823 #if SPIRV_DEBUG
824 out << std::endl << opcode_text(opCode) << " ";
825 #else
826 this->writeWord((length << 16) | opCode, out);
827 #endif
828 }
829
830 void SPIRVCodeGenerator::writeLabel(SpvId label, std::ostream& out) {
831 fCurrentBlock = label;
832 this->writeInstruction(SpvOpLabel, label, out);
833 }
834
835 void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, std::ostream& out) {
836 this->writeOpCode(opCode, 1, out);
837 }
838
839 void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, std::ost ream& out) {
840 this->writeOpCode(opCode, 2, out);
841 this->writeWord(word1, out);
842 }
843
844 void SPIRVCodeGenerator::writeString(const char* string, std::ostream& out) {
845 size_t length = strlen(string);
846 out << string;
847 switch (length % 4) {
848 case 1:
849 out << (char) 0;
850 // fall through
851 case 2:
852 out << (char) 0;
853 // fall through
854 case 3:
855 out << (char) 0;
856 break;
857 default:
858 this->writeWord(0, out);
859 }
860 }
861
862 void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, const char* string, std ::ostream& out) {
863 int32_t length = (int32_t) strlen(string);
864 this->writeOpCode(opCode, 1 + (length + 4) / 4, out);
dogben 2016/06/26 03:57:56 nit: maybe define int32_t words_for_string(const c
865 this->writeString(string, out);
866 }
867
868
869 void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, const ch ar* string,
870 std::ostream& out) {
871 int32_t length = (int32_t) strlen(string);
872 this->writeOpCode(opCode, 2 + (length + 4) / 4, out);
873 this->writeWord(word1, out);
874 this->writeString(string, out);
875 }
876
877 void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
878 const char* string, std::ostream& out) {
879 int32_t length = (int32_t) strlen(string);
880 this->writeOpCode(opCode, 3 + (length + 4) / 4, out);
881 this->writeWord(word1, out);
882 this->writeWord(word2, out);
883 this->writeString(string, out);
884 }
885
886 void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
887 std::ostream& out) {
888 this->writeOpCode(opCode, 3, out);
889 this->writeWord(word1, out);
890 this->writeWord(word2, out);
891 }
892
893 void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
894 int32_t word3, std::ostream& out) {
895 this->writeOpCode(opCode, 4, out);
896 this->writeWord(word1, out);
897 this->writeWord(word2, out);
898 this->writeWord(word3, out);
899 }
900
901 void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
902 int32_t word3, int32_t word4, std::ost ream& out) {
903 this->writeOpCode(opCode, 5, out);
904 this->writeWord(word1, out);
905 this->writeWord(word2, out);
906 this->writeWord(word3, out);
907 this->writeWord(word4, out);
908 }
909
910 void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
911 int32_t word3, int32_t word4, int32_t word5,
912 std::ostream& out) {
913 this->writeOpCode(opCode, 6, out);
914 this->writeWord(word1, out);
915 this->writeWord(word2, out);
916 this->writeWord(word3, out);
917 this->writeWord(word4, out);
918 this->writeWord(word5, out);
919 }
920
921 void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
922 int32_t word3, int32_t word4, int32_t word5,
923 int32_t word6, std::ostream& out) {
924 this->writeOpCode(opCode, 7, out);
925 this->writeWord(word1, out);
926 this->writeWord(word2, out);
927 this->writeWord(word3, out);
928 this->writeWord(word4, out);
929 this->writeWord(word5, out);
930 this->writeWord(word6, out);
931 }
932
933 void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
934 int32_t word3, int32_t word4, int32_t word5,
935 int32_t word6, int32_t word7, std::ost ream& out) {
936 this->writeOpCode(opCode, 8, out);
937 this->writeWord(word1, out);
938 this->writeWord(word2, out);
939 this->writeWord(word3, out);
940 this->writeWord(word4, out);
941 this->writeWord(word5, out);
942 this->writeWord(word6, out);
943 this->writeWord(word7, out);
944 }
945
946 void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
947 int32_t word3, int32_t word4, int32_t word5,
948 int32_t word6, int32_t word7, int32_t word8,
949 std::ostream& out) {
950 this->writeOpCode(opCode, 9, out);
951 this->writeWord(word1, out);
952 this->writeWord(word2, out);
953 this->writeWord(word3, out);
954 this->writeWord(word4, out);
955 this->writeWord(word5, out);
956 this->writeWord(word6, out);
957 this->writeWord(word7, out);
958 this->writeWord(word8, out);
959 }
960
961 void SPIRVCodeGenerator::writeCapabilities(std::ostream& out) {
962 for (uint64_t i = 0, bit = 1; i <= kLast_Capability; i++, bit <<= 1) {
963 if (fCapabilities & bit) {
964 this->writeInstruction(SpvOpCapability, (SpvId) i, out);
965 }
966 }
967 }
968
969 SpvId SPIRVCodeGenerator::nextId() {
970 return fIdCount++;
971 }
972
973 void SPIRVCodeGenerator::writeStruct(Type& type, SpvId resultId) {
974 this->writeInstruction(SpvOpName, resultId, type.name().c_str(), fNameBuffer );
975 // go ahead and write all of the field types, so we don't inadvertently writ e them while we're
976 // in the middle of writing the struct instruction
977 std::vector<SpvId> types;
978 for (const auto& f : type.fields()) {
979 types.push_back(this->getType(*f.fType));
980 }
981 this->writeOpCode(SpvOpTypeStruct, 2 + (int32_t) types.size(), fConstantBuff er);
982 this->writeWord(resultId, fConstantBuffer);
983 for (SpvId id : types) {
984 this->writeWord(id, fConstantBuffer);
985 }
986 size_t offset = 0;
987 for (int32_t i = 0; i < (int32_t) type.fields().size(); i++) {
988 size_t size = type.fields()[i].fType->size();
989 size_t alignment = type.fields()[i].fType->alignment();
990 size_t mod = offset % alignment;
991 if (mod != 0) {
992 offset += alignment - mod;
993 }
994 this->writeInstruction(SpvOpMemberName, resultId, i, type.fields()[i].fN ame.c_str(),
995 fNameBuffer);
996 this->writeLayout(type.fields()[i].fModifiers.fLayout, resultId, i);
997 if (type.fields()[i].fModifiers.fLayout.fBuiltin < 0) {
998 this->writeInstruction(SpvOpMemberDecorate, resultId, (SpvId) i, Spv DecorationOffset,
999 (SpvId) offset, fDecorationBuffer);
1000 }
1001 if (type.fields()[i].fType->kind() == Type::kMatrix_Kind) {
1002 this->writeInstruction(SpvOpMemberDecorate, resultId, i, SpvDecorati onColMajor,
1003 fDecorationBuffer);
1004 this->writeInstruction(SpvOpMemberDecorate, resultId, i, SpvDecorati onMatrixStride,
1005 (SpvId) type.fields()[i].fType->stride(), fDe corationBuffer);
1006 }
1007 offset += size;
1008 Type::Kind kind = type.fields()[i].fType->kind();
1009 if ((kind == Type::kArray_Kind || kind == Type::kStruct_Kind) && offset % alignment != 0) {
1010 offset += alignment - offset % alignment;
1011 }
1012 ASSERT(offset % alignment == 0);
1013 }
1014 }
1015
1016 SpvId SPIRVCodeGenerator::getType(Type& type) {
1017 auto entry = fTypeMap.find(type.name());
1018 if (entry == fTypeMap.end()) {
1019 SpvId result = this->nextId();
1020 switch (type.kind()) {
1021 case Type::kScalar_Kind:
1022 if (type == *kBool_Type) {
1023 this->writeInstruction(SpvOpTypeBool, result, fConstantBuffe r);
1024 } else if (type == *kInt_Type) {
1025 this->writeInstruction(SpvOpTypeInt, result, 32, 1, fConstan tBuffer);
1026 } else if (type == *kUInt_Type) {
1027 this->writeInstruction(SpvOpTypeInt, result, 32, 0, fConstan tBuffer);
1028 } else if (type == *kFloat_Type) {
1029 this->writeInstruction(SpvOpTypeFloat, result, 32, fConstant Buffer);
1030 } else if (type == *kDouble_Type) {
1031 this->writeInstruction(SpvOpTypeFloat, result, 64, fConstant Buffer);
1032 } else {
1033 ASSERT(false);
1034 }
1035 break;
1036 case Type::kVector_Kind:
1037 this->writeInstruction(SpvOpTypeVector, result,
1038 this->getType(*type.componentType()),
1039 type.columns(), fConstantBuffer);
1040 break;
1041 case Type::kMatrix_Kind:
1042 this->writeInstruction(SpvOpTypeMatrix, result, this->getType(*i ndex_type(type)),
1043 type.columns(), fConstantBuffer);
1044 break;
1045 case Type::kStruct_Kind:
1046 this->writeStruct(type, result);
1047 break;
1048 case Type::kArray_Kind: {
1049 if (type.columns() > 0) {
1050 IntLiteral count(Position(), type.columns());
1051 this->writeInstruction(SpvOpTypeArray, result,
1052 this->getType(*type.componentType()),
1053 this->writeIntLiteral(count), fConsta ntBuffer);
1054 this->writeInstruction(SpvOpDecorate, result, SpvDecorationA rrayStride,
1055 (int32_t) type.stride(), fDecorationB uffer);
1056 } else {
1057 printf("FIXME: creating a runtime-sized array. this won't ac tually work yet!\n");
1058 this->writeInstruction(SpvOpTypeRuntimeArray, result,
1059 this->getType(*type.componentType()), fConstantBuffer);
1060 }
1061 break;
1062 }
1063 case Type::kSampler_Kind: {
1064 SpvId image = this->nextId();
1065 this->writeInstruction(SpvOpTypeImage, image, this->getType(*kFl oat_Type),
1066 type.dimensions(), type.isDepth(), type.i sArrayed(),
1067 type.isMultisampled(), type.isSampled(),
1068 SpvImageFormatUnknown, fConstantBuffer);
1069 this->writeInstruction(SpvOpTypeSampledImage, result, image, fCo nstantBuffer);
1070 break;
1071 }
1072 default:
1073 if (type == *kVoid_Type) {
1074 this->writeInstruction(SpvOpTypeVoid, result, fConstantBuffe r);
1075 } else {
1076 printf("invalid type: %s\n", type.description().c_str());
1077 ASSERT(false);
1078 }
1079 }
1080 fTypeMap[type.name()] = result;
1081 return result;
1082 }
1083 return entry->second;
1084 }
1085
1086 SpvId SPIRVCodeGenerator::getFunctionType(std::shared_ptr<FunctionDeclaration> f unction) {
1087 std::string key = function->fReturnType->description() + "(";
1088 std::string separator = "";
1089 for (size_t i = 0; i < function->fParameters.size(); i++) {
1090 key += separator;
1091 separator = ", ";
1092 key += function->fParameters[i]->fType->description();
1093 }
1094 key += ")";
1095 auto entry = fTypeMap.find(key);
1096 if (entry == fTypeMap.end()) {
1097 SpvId result = this->nextId();
1098 int32_t length = 3 + (int32_t) function->fParameters.size();
1099 SpvId returnType = this->getType(*function->fReturnType);
1100 std::vector<SpvId> parameterTypes;
1101 for (size_t i = 0; i < function->fParameters.size(); i++) {
1102 // glslang seems to treat all function arguments as pointers whether they need to be or
1103 // not. I was initially puzzled by this until I ran bizarre failure s with certain
1104 // patterns of function calls and control constructs, as exemplified by this minimal
1105 // failure case:
1106 //
1107 // void sphere(float x) {
1108 // }
1109 //
1110 // void map() {
1111 // sphere(1.0);
1112 // }
1113 //
1114 // void main() {
1115 // for (int i = 0; i < 1; i++) {
1116 // map();
1117 // }
1118 // }
1119 //
1120 // As of this writing, compiling this in the "obvious" way (with sph ere taking a float)
1121 // crashes. Making it take a float* and storing the argument in a te mporary variable,
1122 // as glslang does, fixes it. It's entirely possible I simply missed whichever part of
1123 // the spec makes this make sense.
1124 // if (is_out(function->fParameters[i])) {
1125 parameterTypes.push_back(this->getPointerType(function->fParamet ers[i]->fType,
1126 SpvStorageClassFun ction));
1127 // } else {
1128 // parameterTypes.push_back(this->getType(*function->fParameters[ i]->fType));
1129 // }
1130 }
1131 this->writeOpCode(SpvOpTypeFunction, length, fConstantBuffer);
1132 this->writeWord(result, fConstantBuffer);
1133 this->writeWord(returnType, fConstantBuffer);
1134 for (SpvId id : parameterTypes) {
1135 this->writeWord(id, fConstantBuffer);
1136 }
1137 fTypeMap[key] = result;
1138 return result;
1139 }
1140 return entry->second;
1141 }
1142
1143 SpvId SPIRVCodeGenerator::getPointerType(std::shared_ptr<Type> type,
1144 SpvStorageClass_ storageClass) {
1145 std::string key = type->description() + "*" + to_string(storageClass);
1146 auto entry = fTypeMap.find(key);
1147 if (entry == fTypeMap.end()) {
1148 SpvId result = this->nextId();
1149 this->writeInstruction(SpvOpTypePointer, result, storageClass,
1150 this->getType(*type), fConstantBuffer);
1151 fTypeMap[key] = result;
1152 return result;
1153 }
1154 return entry->second;
1155 }
1156
1157 SpvId SPIRVCodeGenerator::writeExpression(Expression& expr, std::ostream& out) {
1158 switch (expr.fKind) {
1159 case Expression::kBinary_Kind:
1160 return this->writeBinaryExpression((BinaryExpression&) expr, out);
1161 case Expression::kBoolLiteral_Kind:
1162 return this->writeBoolLiteral((BoolLiteral&) expr);
1163 case Expression::kConstructor_Kind:
1164 return this->writeConstructor((Constructor&) expr, out);
1165 case Expression::kIntLiteral_Kind:
1166 return this->writeIntLiteral((IntLiteral&) expr);
1167 case Expression::kFieldAccess_Kind:
1168 return this->writeFieldAccess(((FieldAccess&) expr), out);
1169 case Expression::kFloatLiteral_Kind:
1170 return this->writeFloatLiteral(((FloatLiteral&) expr));
1171 case Expression::kFunctionCall_Kind:
1172 return this->writeFunctionCall((FunctionCall&) expr, out);
1173 case Expression::kPrefix_Kind:
1174 return this->writePrefixExpression((PrefixExpression&) expr, out);
1175 case Expression::kPostfix_Kind:
1176 return this->writePostfixExpression((PostfixExpression&) expr, out);
1177 case Expression::kSwizzle_Kind:
1178 return this->writeSwizzle((Swizzle&) expr, out);
1179 case Expression::kVariableReference_Kind:
1180 return this->writeVariableReference((VariableReference&) expr, out);
1181 case Expression::kTernary_Kind:
1182 return this->writeTernaryExpression((TernaryExpression&) expr, out);
1183 case Expression::kIndex_Kind:
1184 return this->writeIndexExpression((IndexExpression&) expr, out);
1185 default:
1186 printf("unsupported expression: %s\n", expr.description().c_str());
1187 ASSERT(false);
1188 }
1189 return -1;
1190 }
1191
1192 SpvId SPIRVCodeGenerator::writeIntrinsicCall(FunctionCall& c, std::ostream& out) {
1193 auto intrinsic = fIntrinsicMap.find(c.fFunction->fName);
1194 ASSERT(intrinsic != fIntrinsicMap.end());
1195 std::shared_ptr<Type> type = c.fArguments[0]->fType;
1196 int32_t intrinsicId;
1197 if (std::get<0>(intrinsic->second) == kSpecial_IntrinsicKind || is_float(typ e)) {
1198 intrinsicId = std::get<1>(intrinsic->second);
1199 } else if (is_signed(type)) {
1200 intrinsicId = std::get<2>(intrinsic->second);
1201 } else if (is_unsigned(type)) {
1202 intrinsicId = std::get<3>(intrinsic->second);
1203 } else if (is_bool(type)) {
1204 intrinsicId = std::get<4>(intrinsic->second);
1205 } else {
1206 ABORT("invalid call %s, cannot operate on '%s'\n", c.description().c_str (),
1207 type->description().c_str());
1208 }
1209 switch (std::get<0>(intrinsic->second)) {
1210 case kGLSL_STD_450_IntrinsicKind: {
1211 SpvId result = this->nextId();
1212 std::vector<SpvId> arguments;
1213 for (size_t i = 0; i < c.fArguments.size(); i++) {
1214 arguments.push_back(this->writeExpression(*c.fArguments[i], out) );
1215 }
1216 this->writeOpCode(SpvOpExtInst, 5 + (int32_t) arguments.size(), out) ;
1217 this->writeWord(this->getType(*c.fType), out);
1218 this->writeWord(result, out);
1219 this->writeWord(fGLSLExtendedInstructions, out);
1220 this->writeWord(intrinsicId, out);
1221 for (SpvId id : arguments) {
1222 this->writeWord(id, out);
1223 }
1224 return result;
1225 }
1226 case kSPIRV_IntrinsicKind: {
1227 SpvId result = this->nextId();
1228 std::vector<SpvId> arguments;
1229 for (size_t i = 0; i < c.fArguments.size(); i++) {
1230 arguments.push_back(this->writeExpression(*c.fArguments[i], out) );
1231 }
1232 this->writeOpCode((SpvOp_) intrinsicId, 3 + (int32_t) arguments.size (), out);
1233 this->writeWord(this->getType(*c.fType), out);
1234 this->writeWord(result, out);
1235 for (SpvId id : arguments) {
1236 this->writeWord(id, out);
1237 }
1238 return result;
1239 }
1240 case kSpecial_IntrinsicKind:
1241 return this->writeSpecialIntrinsic(c, (SpecialIntrinsic) intrinsicId , out);
1242 default:
1243 ABORT("unsupported intrinsic kind");
1244 }
1245 }
1246
1247 SpvId SPIRVCodeGenerator::writeSpecialIntrinsic(FunctionCall& c, SpecialIntrinsi c kind,
1248 std::ostream& out) {
1249 SpvId result = this->nextId();
1250 switch (kind) {
1251 case kAtan_SpecialIntrinsic: {
1252 std::vector<SpvId> arguments;
1253 for (size_t i = 0; i < c.fArguments.size(); i++) {
1254 arguments.push_back(this->writeExpression(*c.fArguments[i], out) );
1255 }
1256 this->writeOpCode(SpvOpExtInst, 5 + (int32_t) arguments.size(), out) ;
1257 this->writeWord(this->getType(*c.fType), out);
1258 this->writeWord(result, out);
1259 this->writeWord(fGLSLExtendedInstructions, out);
1260 this->writeWord(arguments.size() == 2 ? GLSLstd450Atan2 : GLSLstd450 Atan, out);
1261 for (SpvId id : arguments) {
1262 this->writeWord(id, out);
1263 }
1264 return result;
1265 }
1266 case kTexture_SpecialIntrinsic: {
1267 SpvId type = this->getType(*c.fType);
1268 SpvId sampler = this->writeExpression(*c.fArguments[0], out);
1269 SpvId uv = this->writeExpression(*c.fArguments[1], out);
1270 if (c.fArguments.size() == 3) {
1271 this->writeInstruction(SpvOpImageSampleImplicitLod, type, result , sampler, uv,
1272 SpvImageOperandsBiasMask,
1273 this->writeExpression(*c.fArguments[2], o ut),
1274 out);
1275 } else {
1276 ASSERT(c.fArguments.size() == 2);
1277 this->writeInstruction(SpvOpImageSampleImplicitLod, type, result , sampler, uv, out);
1278 }
1279 break;
1280 }
1281 case kTextureProj_SpecialIntrinsic: {
1282 SpvId type = this->getType(*c.fType);
1283 SpvId sampler = this->writeExpression(*c.fArguments[0], out);
1284 SpvId uv = this->writeExpression(*c.fArguments[1], out);
1285 if (c.fArguments.size() == 3) {
1286 this->writeInstruction(SpvOpImageSampleProjImplicitLod, type, re sult, sampler, uv,
1287 SpvImageOperandsBiasMask,
1288 this->writeExpression(*c.fArguments[2], o ut),
1289 out);
1290 } else {
1291 ASSERT(c.fArguments.size() == 2);
1292 this->writeInstruction(SpvOpImageSampleProjImplicitLod, type, re sult, sampler, uv,
1293 out);
1294 }
1295 break;
1296 }
1297 case kTexture2D_SpecialIntrinsic: {
1298 SpvId img = this->writeExpression(*c.fArguments[0], out);
1299 SpvId coords = this->writeExpression(*c.fArguments[1], out);
1300 this->writeInstruction(SpvOpImageSampleImplicitLod,
1301 this->getType(*c.fType),
1302 result,
1303 img,
1304 coords,
1305 out);
1306 break;
1307 }
1308 }
1309 return result;
1310 }
1311
1312 SpvId SPIRVCodeGenerator::writeFunctionCall(FunctionCall& c, std::ostream& out) {
1313 const auto& entry = fFunctionMap.find(c.fFunction);
1314 if (entry == fFunctionMap.end()) {
1315 return this->writeIntrinsicCall(c, out);
1316 }
1317 std::vector<SpvId> arguments;
1318 for (size_t i = 0; i < c.fArguments.size(); i++) {
1319 // see getFunctionType for an explanation of why we're always using out parameters
1320 if (is_out(c.fFunction->fParameters[i])) {
1321 arguments.push_back(this->getLValue(*c.fArguments[i], out));
1322 } else {
1323 SpvId expr = this->writeExpression(*c.fArguments[i], out);
1324 SpvId tmpVar = this->nextId();
1325 this->writeInstruction(SpvOpVariable,
1326 this->getPointerType(c.fArguments[i]->fType,
1327 SpvStorageClassFunction) ,
1328 tmpVar,
1329 SpvStorageClassFunction,
1330 out);
1331 this->writeInstruction(SpvOpStore, tmpVar, expr, out);
1332 arguments.push_back(tmpVar);
1333 }
1334 }
1335 SpvId result = this->nextId();
1336 this->writeOpCode(SpvOpFunctionCall, 4 + (int32_t) c.fArguments.size(), out) ;
1337 this->writeWord(this->getType(*c.fType), out);
1338 this->writeWord(result, out);
1339 this->writeWord(entry->second, out);
1340 for (SpvId id : arguments) {
1341 this->writeWord(id, out);
1342 }
1343 return result;
1344 }
1345
1346 SpvId SPIRVCodeGenerator::writeConstantVector(Constructor& c) {
1347 ASSERT(c.fType->kind() == Type::kVector_Kind && c.isConstant());
1348 SpvId result = this->nextId();
1349 std::vector<SpvId> arguments;
1350 for (size_t i = 0; i < c.fArguments.size(); i++) {
1351 arguments.push_back(this->writeExpression(*c.fArguments[i], fConstantBuf fer));
dogben 2016/06/26 03:57:55 nit: Maybe assert that all arguments are scalar ty
1352 }
1353 SpvId type = this->getType(*c.fType);
1354 if (c.fArguments.size() == 1) {
1355 // with a single argument, a vector will have all of its entries equal t o the argument
1356 this->writeOpCode(SpvOpConstantComposite, 3 + c.fType->columns(), fConst antBuffer);
1357 this->writeWord(type, fConstantBuffer);
1358 this->writeWord(result, fConstantBuffer);
1359 for (int i = 0; i < c.fType->columns(); i++) {
1360 this->writeWord(arguments[0], fConstantBuffer);
1361 }
1362 } else {
1363 this->writeOpCode(SpvOpConstantComposite, 3 + (int32_t) c.fArguments.siz e(),
1364 fConstantBuffer);
1365 this->writeWord(type, fConstantBuffer);
1366 this->writeWord(result, fConstantBuffer);
1367 for (SpvId id : arguments) {
1368 this->writeWord(id, fConstantBuffer);
1369 }
1370 }
1371 return result;
1372 }
1373
1374 SpvId SPIRVCodeGenerator::writeFloatConstructor(Constructor& c, std::ostream& ou t) {
1375 ASSERT(c.fType == kFloat_Type);
1376 ASSERT(c.fArguments.size() == 1);
1377 ASSERT(c.fArguments[0]->fType->isNumber());
1378 SpvId result = this->nextId();
1379 SpvId parameter = this->writeExpression(*c.fArguments[0], out);
1380 if (c.fArguments[0]->fType == kInt_Type) {
1381 this->writeInstruction(SpvOpConvertSToF, this->getType(*c.fType), result , parameter,
1382 out);
1383 } else if (c.fArguments[0]->fType == kUInt_Type) {
1384 this->writeInstruction(SpvOpConvertUToF, this->getType(*c.fType), result , parameter,
1385 out);
1386 } else if (c.fArguments[0]->fType == kFloat_Type) {
1387 return parameter;
1388 }
dogben 2016/06/26 03:57:56 nit: else assert?
1389 return result;
1390 }
1391
1392 SpvId SPIRVCodeGenerator::writeIntConstructor(Constructor& c, std::ostream& out) {
1393 ASSERT(c.fType == kInt_Type);
1394 ASSERT(c.fArguments.size() == 1);
1395 ASSERT(c.fArguments[0]->fType->isNumber());
1396 SpvId result = this->nextId();
1397 SpvId parameter = this->writeExpression(*c.fArguments[0], out);
1398 if (c.fArguments[0]->fType == kFloat_Type) {
1399 this->writeInstruction(SpvOpConvertFToS, this->getType(*c.fType), result , parameter,
1400 out);
1401 } else if (c.fArguments[0]->fType == kUInt_Type) {
1402 this->writeInstruction(SpvOpSatConvertUToS, this->getType(*c.fType), res ult, parameter,
1403 out);
1404 } else if (c.fArguments[0]->fType == kInt_Type) {
1405 return parameter;
1406 }
dogben 2016/06/26 03:57:55 nit: else assert?
1407 return result;
1408 }
1409
1410 SpvId SPIRVCodeGenerator::writeMatrixConstructor(Constructor& c, std::ostream& o ut) {
1411 ASSERT(c.fType->kind() == Type::kMatrix_Kind);
1412 // go ahead and write the arguments so we don't try to write new instruction s in the middle of
1413 // an instruction
1414 std::vector<SpvId> arguments;
1415 for (size_t i = 0; i < c.fArguments.size(); i++) {
1416 arguments.push_back(this->writeExpression(*c.fArguments[i], out));
1417 }
1418 SpvId result = this->nextId();
1419 int rows = c.fType->rows();
1420 int columns = c.fType->columns();
1421 // FIXME this won't work to create a matrix from another matrix
1422 if (arguments.size() == 1) {
1423 // with a single argument, a matrix will have all of its diagonal entrie s equal to the
dogben 2016/06/26 03:57:56 nit: Assert argument is a scalar?
1424 // argument and its other values equal to zero
1425 // FIXME this won't work for int matrices
1426 FloatLiteral zero(Position(), 0);
1427 SpvId zeroId = this->writeFloatLiteral(zero);
1428 std::vector<SpvId> columnIds;
1429 for (int column = 0; column < columns; column++) {
1430 this->writeOpCode(SpvOpCompositeConstruct, 3 + c.fType->rows(),
1431 out);
1432 this->writeWord(this->getType(*c.fType->componentType()->toCompound( rows, 1)), out);
1433 SpvId columnId = this->nextId();
1434 this->writeWord(columnId, out);
1435 columnIds.push_back(columnId);
1436 for (int row = 0; row < c.fType->columns(); row++) {
1437 this->writeWord(row == column ? arguments[0] : zeroId, out);
1438 }
1439 }
1440 this->writeOpCode(SpvOpCompositeConstruct, 3 + columns,
1441 out);
1442 this->writeWord(this->getType(*c.fType), out);
1443 this->writeWord(result, out);
1444 for (SpvId id : columnIds) {
1445 this->writeWord(id, out);
1446 }
1447 } else {
1448 std::vector<SpvId> columnIds;
1449 int currentCount = 0;
1450 for (size_t i = 0; i < arguments.size(); i++) {
1451 if (c.fArguments[i]->fType->kind() == Type::kVector_Kind) {
1452 ASSERT(currentCount == 0);
dogben 2016/06/26 03:57:56 nit: Also assert vector.rows == matrix.rows?
1453 columnIds.push_back(arguments[i]);
1454 currentCount = 0;
1455 } else {
1456 ASSERT(c.fArguments[i]->fType->kind() == Type::kScalar_Kind);
1457 if (currentCount == 0) {
1458 this->writeOpCode(SpvOpCompositeConstruct, 3 + c.fType->rows (), out);
1459 this->writeWord(this->getType(*c.fType->componentType()->toC ompound(rows, 1)),
1460 out);
1461 SpvId id = this->nextId();
1462 this->writeWord(id, out);
1463 columnIds.push_back(id);
1464 }
1465 this->writeWord(arguments[i], out);
1466 currentCount = (currentCount + 1) % rows;
1467 }
1468 }
1469 ASSERT(columnIds.size() == columns)
1470 this->writeOpCode(SpvOpCompositeConstruct, 3 + columns, out);
1471 this->writeWord(this->getType(*c.fType), out);
1472 this->writeWord(result, out);
1473 for (SpvId id : columnIds) {
1474 this->writeWord(id, out);
1475 }
1476 }
1477 return result;
1478 }
1479
1480 SpvId SPIRVCodeGenerator::writeVectorConstructor(Constructor& c, std::ostream& o ut) {
1481 ASSERT(c.fType->kind() == Type::kVector_Kind);
1482 if (c.isConstant()) {
1483 return this->writeConstantVector(c);
1484 }
1485 // go ahead and write the arguments so we don't try to write new instruction s in the middle of
1486 // an instruction
1487 std::vector<SpvId> arguments;
1488 for (size_t i = 0; i < c.fArguments.size(); i++) {
1489 arguments.push_back(this->writeExpression(*c.fArguments[i], out));
1490 }
1491 SpvId result = this->nextId();
1492 if (arguments.size() == 1 && c.fArguments[0]->fType->kind() == Type::kScalar _Kind) {
dogben 2016/06/26 03:57:55 nit: I think the scalar check should just be an as
1493 this->writeOpCode(SpvOpCompositeConstruct, 3 + c.fType->columns(), out);
1494 this->writeWord(this->getType(*c.fType), out);
1495 this->writeWord(result, out);
1496 for (int i = 0; i < c.fType->columns(); i++) {
1497 this->writeWord(arguments[0], out);
1498 }
1499 } else {
1500 this->writeOpCode(SpvOpCompositeConstruct, 3 + (int32_t) c.fArguments.si ze(), out);
1501 this->writeWord(this->getType(*c.fType), out);
1502 this->writeWord(result, out);
1503 for (SpvId id : arguments) {
1504 this->writeWord(id, out);
1505 }
1506 }
1507 return result;
1508 }
1509
1510 SpvId SPIRVCodeGenerator::writeConstructor(Constructor& c, std::ostream& out) {
1511 if (c.fType == kFloat_Type) {
1512 return this->writeFloatConstructor(c, out);
1513 } else if (c.fType == kInt_Type) {
1514 return this->writeIntConstructor(c, out);
1515 }
1516 switch (c.fType->kind()) {
1517 case Type::kVector_Kind:
1518 return this->writeVectorConstructor(c, out);
1519 case Type::kMatrix_Kind:
1520 return this->writeMatrixConstructor(c, out);
1521 default:
1522 ABORT("unsupported constructor: %s", c.description().c_str());
1523 }
1524 }
1525
1526 SpvStorageClass_ get_storage_class(const Modifiers& modifiers) {
1527 if (modifiers.fFlags & Modifiers::kIn_Flag) {
1528 return SpvStorageClassInput;
1529 } else if (modifiers.fFlags & Modifiers::kOut_Flag) {
1530 return SpvStorageClassOutput;
1531 } else if (modifiers.fFlags & Modifiers::kUniform_Flag) {
1532 return SpvStorageClassUniform;
1533 } else {
1534 return SpvStorageClassFunction;
1535 }
1536 }
1537
1538 SpvStorageClass_ get_storage_class(Expression& expr) {
1539 switch (expr.fKind) {
1540 case Expression::kVariableReference_Kind:
1541 return get_storage_class(((VariableReference&) expr).fVariable->fMod ifiers);
1542 case Expression::kFieldAccess_Kind:
1543 return get_storage_class(*((FieldAccess&) expr).fBase);
1544 case Expression::kIndex_Kind:
1545 return get_storage_class(*((IndexExpression&) expr).fBase);
1546 default:
1547 return SpvStorageClassFunction;
1548 }
1549 }
1550
1551 SpvId SPIRVCodeGenerator::getLValue(Expression& value, std::ostream& out) {
1552 switch (value.fKind) {
1553 case Expression::kVariableReference_Kind: {
1554 std::shared_ptr<Variable> var = ((VariableReference&) value).fVariab le;
1555 auto entry = fVariableMap.find(var);
1556 ASSERT(entry != fVariableMap.end());
1557 return entry->second;
1558 }
1559 case Expression::kIndex_Kind: {
1560 IndexExpression& index = (IndexExpression&) value;
1561 SpvId base = this->getLValue(*index.fBase, out);;
1562 SpvId result = this->nextId();
1563 this->writeInstruction(SpvOpAccessChain,
1564 this->getPointerType(index.fType,
1565 get_storage_class(*index .fBase)),
1566 result,
1567 base,
1568 this->writeExpression(*index.fIndex, out),
1569 out);
1570 return result;
1571 }
1572 case Expression::kFieldAccess_Kind: {
1573 FieldAccess& f = (FieldAccess&) value;
1574 SpvId base = this->getLValue(*f.fBase, out);;
1575 IntLiteral index(Position(), f.fFieldIndex);
1576 SpvId result = this->nextId();
1577 this->writeInstruction(SpvOpAccessChain,
1578 this->getPointerType(f.fType,
1579 get_storage_class(*f.fBa se)),
1580 result,
1581 base,
1582 this->writeIntLiteral(index),
1583 out);
1584 return result;
1585 }
1586 default:
1587 SpvId result = this->nextId();
1588 SpvId type = this->getPointerType(value.fType, SpvStorageClassFuncti on);
1589 this->writeInstruction(SpvOpVariable, type, result, SpvStorageClassF unction, out);
1590 this->writeInstruction(SpvOpStore, result, this->writeExpression(val ue, out), out);
1591 return result;
1592 }
1593 }
1594
1595 void SPIRVCodeGenerator::storeToLValue(Expression& lvalue, SpvId value, std::ost ream& out) {
1596 switch (lvalue.fKind) {
1597 case Expression::kVariableReference_Kind: // fall through
1598 case Expression::kIndex_Kind: // fall through
1599 case Expression::kFieldAccess_Kind: {
1600 SpvId id = this->getLValue(lvalue, out);
1601 this->writeInstruction(SpvOpStore, id, value, out);
dogben 2016/06/26 03:57:56 Does SPIR-V automatically handle copying composite
dogben 2016/06/28 03:20:01 Another example: float foo(vec2 c) { c.x++; re
ethannicholas 2016/06/30 15:19:28 The parameters are pointerized by creating a tempo
ethannicholas 2016/06/30 15:19:28 Loading a and storing it in b will duplicate the v
1602 break;
1603 }
1604 case Expression::kSwizzle_Kind: {
1605 Swizzle& swizzle = (Swizzle&) lvalue;
1606 size_t count = swizzle.fComponents.size();
1607 SpvId base = this->getLValue(*swizzle.fBase, out);
1608 if (count == 1) {
1609 IntLiteral index(Position(), swizzle.fComponents[0]);
1610 SpvId target = this->nextId();
1611 this->writeInstruction(SpvOpAccessChain,
1612 this->getPointerType(swizzle.fType,
1613 get_storage_class(*s wizzle.fBase)),
1614 target,
1615 base,
1616 this->writeIntLiteral(index),
1617 out);
1618 this->writeInstruction(SpvOpStore, target, value, out);
1619 } else {
1620 SpvId shuffle = this->nextId();
1621 std::shared_ptr<Type> baseType = swizzle.fBase->fType;
1622 SpvId lhs = this->writeExpression(*swizzle.fBase, out);
1623 this->writeOpCode(SpvOpVectorShuffle, 5 + baseType->columns(), o ut);
1624 this->writeWord(this->getType(*baseType), out);
1625 this->writeWord(shuffle, out);
1626 this->writeWord(lhs, out);
1627 this->writeWord(value, out);
1628 for (int i = 0; i < baseType->columns(); i++) {
1629 int offset = i;
1630 for (size_t j = 0; j < swizzle.fComponents.size(); j++) {
1631 if (swizzle.fComponents[j] == i) {
1632 offset = (int) (j + baseType->columns());
1633 break;
1634 }
1635 }
1636 this->writeWord(offset, out);
1637 }
1638 this->writeInstruction(SpvOpStore, base, shuffle, out);
1639 }
1640 break;
1641 }
1642 default:
1643 printf("cannot use %s as an lvalue\n", lvalue.description().c_str()) ;
1644 ASSERT(false);
1645 }
1646 }
1647
1648 SpvId SPIRVCodeGenerator::writeVariableReference(VariableReference& ref, std::os tream& out) {
1649 auto entry = fVariableMap.find(ref.fVariable);
1650 ASSERT(entry != fVariableMap.end());
1651 SpvId var = entry->second;
1652 SpvId result = this->nextId();
1653 this->writeInstruction(SpvOpLoad, this->getType(*ref.fVariable->fType), resu lt, var, out);
1654 return result;
1655 }
1656
1657 std::vector<SpvId> SPIRVCodeGenerator::getAccessChain(Expression& expr, std::ost ream& out) {
1658 std::vector<SpvId> chain;
1659 switch (expr.fKind) {
1660 case Expression::kIndex_Kind: {
1661 IndexExpression& indexExpr = (IndexExpression&) expr;
1662 chain = this->getAccessChain(*indexExpr.fBase, out);
1663 chain.push_back(this->writeExpression(*indexExpr.fIndex, out));
1664 break;
1665 }
1666 case Expression::kFieldAccess_Kind: {
1667 FieldAccess& fieldExpr = (FieldAccess&) expr;
1668 chain = this->getAccessChain(*fieldExpr.fBase, out);
1669 IntLiteral index(Position(), fieldExpr.fFieldIndex);
1670 chain.push_back(this->writeIntLiteral(index));
1671 break;
1672 }
1673 default:
1674 chain.push_back(this->getLValue(expr, out));
1675 }
1676 return chain;
1677 }
1678
1679 SpvId SPIRVCodeGenerator::writeIndexExpression(IndexExpression& expr, std::ostre am& out) {
1680 std::vector<SpvId> chain = this->getAccessChain(expr, out);
1681 SpvId member = this->nextId();
1682 this->writeOpCode(SpvOpAccessChain, (SpvId) (3 + chain.size()), out);
1683 this->writeWord(this->getPointerType(expr.fType, get_storage_class(*expr.fBa se)), out);
1684 this->writeWord(member, out);
1685 for (SpvId idx : chain) {
1686 this->writeWord(idx, out);
1687 }
1688 SpvId result = this->nextId();
1689 this->writeInstruction(SpvOpLoad, this->getType(*expr.fType), result, member , out);
1690 return result;
1691 }
1692
1693 SpvId SPIRVCodeGenerator::writeFieldAccess(FieldAccess& f, std::ostream& out) {
1694 std::vector<SpvId> chain = this->getAccessChain(f, out);
1695 SpvId member = this->nextId();
1696 this->writeOpCode(SpvOpAccessChain, (SpvId) (3 + chain.size()), out);
1697 this->writeWord(this->getPointerType(f.fType, get_storage_class(*f.fBase)), out);
1698 this->writeWord(member, out);
1699 for (SpvId idx : chain) {
1700 this->writeWord(idx, out);
1701 }
1702 SpvId result = this->nextId();
1703 this->writeInstruction(SpvOpLoad, this->getType(*f.fType), result, member, o ut);
1704 return result;
1705 }
1706
1707 SpvId SPIRVCodeGenerator::writeSwizzle(Swizzle& swizzle, std::ostream& out) {
1708 SpvId base = this->writeExpression(*swizzle.fBase, out);
1709 SpvId result = this->nextId();
1710 size_t count = swizzle.fComponents.size();
1711 if (count == 1) {
1712 this->writeInstruction(SpvOpCompositeExtract, this->getType(*swizzle.fTy pe), result, base,
1713 swizzle.fComponents[0], out);
1714 } else {
1715 this->writeOpCode(SpvOpVectorShuffle, 5 + (int32_t) count, out);
1716 this->writeWord(this->getType(*swizzle.fType), out);
1717 this->writeWord(result, out);
1718 this->writeWord(base, out);
1719 this->writeWord(base, out);
1720 for (int component : swizzle.fComponents) {
1721 this->writeWord(component, out);
1722 }
1723 }
1724 return result;
1725 }
1726
1727 SpvId SPIRVCodeGenerator::writeBinaryOperation(std::shared_ptr<Type> resultType,
1728 std::shared_ptr<Type> operandType , SpvId lhs,
1729 SpvId rhs, SpvOp_ ifFloat, SpvOp_ ifInt,
1730 SpvOp_ ifUInt, SpvOp_ ifBool, std ::ostream& out) {
1731 SpvId result = this->nextId();
1732 if (is_float(operandType)) {
1733 this->writeInstruction(ifFloat, this->getType(*resultType), result, lhs, rhs, out);
1734 } else if (is_signed(operandType)) {
1735 this->writeInstruction(ifInt, this->getType(*resultType), result, lhs, r hs, out);
1736 } else if (is_unsigned(operandType)) {
1737 this->writeInstruction(ifUInt, this->getType(*resultType), result, lhs, rhs, out);
1738 } else if (operandType == kBool_Type) {
1739 this->writeInstruction(ifBool, this->getType(*resultType), result, lhs, rhs, out);
1740 } else {
1741 printf("invalid operandType: %s\n", operandType->description().c_str());
1742 ASSERT(false);
1743 }
1744 return result;
1745 }
1746
1747 SpvId SPIRVCodeGenerator::writeBinaryExpression(BinaryExpression& b, std::ostrea m& out) {
1748 // handle cases where we don't necessarily evaluate both LHS and RHS
1749 switch (b.fOperator) {
1750 case Token::EQ: {
1751 SpvId rhs = this->writeExpression(*b.fRight, out);
1752 this->storeToLValue(*b.fLeft, rhs, out);
1753 return rhs;
1754 }
1755 case Token::LOGICALAND:
1756 return this->writeLogicalAnd(b, out);
1757 case Token::LOGICALOR:
1758 return this->writeLogicalOr(b, out);
1759 default:
1760 break;
1761 }
1762
1763 // "normal" operators
1764 std::shared_ptr<Type> resultType = b.fType;
1765 SpvId lhs = this->writeExpression(*b.fLeft, out);
1766 SpvId rhs = this->writeExpression(*b.fRight, out);
1767 // component type we are operating on: float, int, uint
1768 std::shared_ptr<Type> operandType;
1769 // IR allows mismatched types in expressions (e.g. vec2 * float), but they n eed special handling
1770 // in SPIR-V
1771 if (b.fLeft->fType != b.fRight->fType) {
1772 if (b.fLeft->fType->kind() == Type::kVector_Kind &&
1773 b.fRight->fType->isNumber()) {
1774 // promote number to vector
1775 SpvId vec = this->nextId();
1776 this->writeOpCode(SpvOpCompositeConstruct, 3 + b.fType->columns(), o ut);
1777 this->writeWord(this->getType(*resultType), out);
1778 this->writeWord(vec, out);
1779 for (int i = 0; i < resultType->columns(); i++) {
1780 this->writeWord(rhs, out);
1781 }
1782 rhs = vec;
1783 operandType = b.fRight->fType;
1784 } else if (b.fRight->fType->kind() == Type::kVector_Kind &&
1785 b.fLeft->fType->isNumber()) {
1786 // promote number to vector
1787 SpvId vec = this->nextId();
1788 this->writeOpCode(SpvOpCompositeConstruct, 3 + b.fType->columns(), o ut);
1789 this->writeWord(this->getType(*resultType), out);
1790 this->writeWord(vec, out);
1791 for (int i = 0; i < resultType->columns(); i++) {
1792 this->writeWord(lhs, out);
1793 }
1794 lhs = vec;
1795 operandType = b.fLeft->fType;
1796 } else if (b.fLeft->fType->kind() == Type::kMatrix_Kind) {
1797 SpvOp_ op;
1798 if (b.fRight->fType->kind() == Type::kMatrix_Kind) {
1799 op = SpvOpMatrixTimesMatrix;
1800 } else if (b.fRight->fType->kind() == Type::kVector_Kind) {
1801 op = SpvOpMatrixTimesVector;
1802 } else {
1803 ASSERT(b.fRight->fType->kind() == Type::kScalar_Kind);
1804 op = SpvOpMatrixTimesScalar;
1805 }
1806 SpvId result = this->nextId();
1807 this->writeInstruction(op, this->getType(*b.fType), result, lhs, rhs , out);
1808 if (b.fOperator == Token::STAREQ) {
1809 this->storeToLValue(*b.fLeft, result, out);
1810 } else {
1811 ASSERT(b.fOperator == Token::STAR);
1812 }
1813 return result;
1814 } else if (b.fRight->fType->kind() == Type::kMatrix_Kind) {
1815 SpvId result = this->nextId();
1816 if (b.fLeft->fType->kind() == Type::kVector_Kind) {
1817 this->writeInstruction(SpvOpVectorTimesMatrix, this->getType(*b. fType), result, lhs,
1818 rhs, out);
1819 } else {
1820 ASSERT(b.fLeft->fType->kind() == Type::kScalar_Kind);
1821 this->writeInstruction(SpvOpMatrixTimesScalar, this->getType(*b. fType), result, rhs,
1822 lhs, out);
1823 }
1824 if (b.fOperator == Token::STAREQ) {
1825 this->storeToLValue(*b.fLeft, result, out);
1826 } else {
1827 ASSERT(b.fOperator == Token::STAR);
1828 }
1829 return result;
1830 } else {
1831 printf("unsupported binary expression: %s\n", b.description().c_str( ));
1832 ASSERT(false);
1833 }
1834 } else {
1835 operandType = b.fLeft->fType;
1836 ASSERT(operandType == b.fRight->fType);
1837 }
1838 switch (b.fOperator) {
1839 case Token::EQEQ:
1840 ASSERT(resultType == kBool_Type);
1841 return this->writeBinaryOperation(resultType, operandType, lhs, rhs, SpvOpFOrdEqual,
1842 SpvOpIEqual, SpvOpIEqual, SpvOpLog icalEqual, out);
1843 case Token::NEQ:
1844 ASSERT(resultType == kBool_Type);
1845 return this->writeBinaryOperation(resultType, operandType, lhs, rhs, SpvOpFOrdNotEqual,
1846 SpvOpINotEqual, SpvOpINotEqual, Sp vOpLogicalNotEqual,
1847 out);
1848 case Token::GT:
1849 ASSERT(resultType == kBool_Type);
1850 return this->writeBinaryOperation(resultType, operandType, lhs, rhs,
1851 SpvOpFOrdGreaterThan, SpvOpSGreate rThan,
1852 SpvOpUGreaterThan, SpvOpUndef, out );
1853 case Token::LT:
1854 ASSERT(resultType == kBool_Type);
1855 return this->writeBinaryOperation(resultType, operandType, lhs, rhs, SpvOpFOrdLessThan,
1856 SpvOpSLessThan, SpvOpULessThan, Sp vOpUndef, out);
1857 case Token::GTEQ:
1858 ASSERT(resultType == kBool_Type);
1859 return this->writeBinaryOperation(resultType, operandType, lhs, rhs,
1860 SpvOpFOrdGreaterThanEqual, SpvOpSG reaterThanEqual,
1861 SpvOpUGreaterThanEqual, SpvOpUndef , out);
1862 case Token::LTEQ:
1863 ASSERT(resultType == kBool_Type);
1864 return this->writeBinaryOperation(resultType, operandType, lhs, rhs,
1865 SpvOpFOrdLessThanEqual, SpvOpSLess ThanEqual,
1866 SpvOpULessThanEqual, SpvOpUndef, o ut);
1867 case Token::PLUS:
1868 return this->writeBinaryOperation(resultType, operandType, lhs, rhs, SpvOpFAdd,
1869 SpvOpIAdd, SpvOpIAdd, SpvOpUndef, out);
1870 case Token::MINUS:
1871 return this->writeBinaryOperation(resultType, operandType, lhs, rhs, SpvOpFSub,
1872 SpvOpISub, SpvOpISub, SpvOpUndef, out);
1873 case Token::STAR:
1874 if (b.fLeft->fType->kind() == Type::kMatrix_Kind &&
1875 b.fRight->fType->kind() == Type::kMatrix_Kind) {
1876 // matrix multiply
1877 SpvId result = this->nextId();
1878 this->writeInstruction(SpvOpMatrixTimesMatrix, this->getType(*re sultType), result,
1879 lhs, rhs, out);
1880 return result;
1881 }
1882 return this->writeBinaryOperation(resultType, operandType, lhs, rhs, SpvOpFMul,
1883 SpvOpIMul, SpvOpIMul, SpvOpUndef, out);
1884 case Token::SLASH:
1885 return this->writeBinaryOperation(resultType, operandType, lhs, rhs, SpvOpFDiv,
1886 SpvOpSDiv, SpvOpUDiv, SpvOpUndef, out);
1887 case Token::PLUSEQ: {
1888 SpvId result = this->writeBinaryOperation(resultType, operandType, l hs, rhs, SpvOpFAdd,
1889 SpvOpIAdd, SpvOpIAdd, SpvO pUndef, out);
1890 this->storeToLValue(*b.fLeft, result, out);
1891 return result;
1892 }
1893 case Token::MINUSEQ: {
1894 SpvId result = this->writeBinaryOperation(resultType, operandType, l hs, rhs, SpvOpFSub,
1895 SpvOpISub, SpvOpISub, SpvO pUndef, out);
1896 this->storeToLValue(*b.fLeft, result, out);
1897 return result;
1898 }
1899 case Token::STAREQ: {
1900 if (b.fLeft->fType->kind() == Type::kMatrix_Kind &&
1901 b.fRight->fType->kind() == Type::kMatrix_Kind) {
1902 // matrix multiply
1903 SpvId result = this->nextId();
1904 this->writeInstruction(SpvOpMatrixTimesMatrix, this->getType(*re sultType), result,
1905 lhs, rhs, out);
1906 this->storeToLValue(*b.fLeft, result, out);
1907 return result;
1908 }
1909 SpvId result = this->writeBinaryOperation(resultType, operandType, l hs, rhs, SpvOpFMul,
1910 SpvOpIMul, SpvOpIMul, SpvO pUndef, out);
1911 this->storeToLValue(*b.fLeft, result, out);
1912 return result;
1913 }
1914 case Token::SLASHEQ: {
1915 SpvId result = this->writeBinaryOperation(resultType, operandType, l hs, rhs, SpvOpFDiv,
1916 SpvOpSDiv, SpvOpUDiv, SpvO pUndef, out);
1917 this->storeToLValue(*b.fLeft, result, out);
1918 return result;
1919 }
1920 default:
1921 ABORT("unsupported binary expression: %s\n", b.description().c_str() );
1922 }
1923 }
1924
1925 SpvId SPIRVCodeGenerator::writeLogicalAnd(BinaryExpression& a, std::ostream& out ) {
1926 ASSERT(a.fOperator == Token::LOGICALAND);
1927 BoolLiteral falseLiteral(Position(), false);
1928 SpvId falseConstant = this->writeBoolLiteral(falseLiteral);
1929 SpvId lhs = this->writeExpression(*a.fLeft, out);
1930 SpvId rhsLabel = this->nextId();
1931 SpvId end = this->nextId();
1932 SpvId lhsBlock = fCurrentBlock;
1933 this->writeInstruction(SpvOpSelectionMerge, end, SpvSelectionControlMaskNone , out);
1934 this->writeInstruction(SpvOpBranchConditional, lhs, rhsLabel, end, out);
1935 this->writeLabel(rhsLabel, out);
1936 SpvId rhs = this->writeExpression(*a.fRight, out);
1937 SpvId rhsBlock = fCurrentBlock;
1938 this->writeInstruction(SpvOpBranch, end, out);
1939 this->writeLabel(end, out);
1940 SpvId result = this->nextId();
1941 this->writeInstruction(SpvOpPhi, this->getType(*kBool_Type), result, falseCo nstant, lhsBlock,
1942 rhs, rhsBlock, out);
1943 return result;
1944 }
1945
1946 SpvId SPIRVCodeGenerator::writeLogicalOr(BinaryExpression& o, std::ostream& out) {
1947 ASSERT(o.fOperator == Token::LOGICALOR);
1948 BoolLiteral trueLiteral(Position(), true);
1949 SpvId trueConstant = this->writeBoolLiteral(trueLiteral);
1950 SpvId lhs = this->writeExpression(*o.fLeft, out);
1951 SpvId rhsLabel = this->nextId();
1952 SpvId end = this->nextId();
1953 SpvId lhsBlock = fCurrentBlock;
1954 this->writeInstruction(SpvOpSelectionMerge, end, SpvSelectionControlMaskNone , out);
1955 this->writeInstruction(SpvOpBranchConditional, lhs, end, rhsLabel, out);
1956 this->writeLabel(rhsLabel, out);
1957 SpvId rhs = this->writeExpression(*o.fRight, out);
1958 SpvId rhsBlock = fCurrentBlock;
1959 this->writeInstruction(SpvOpBranch, end, out);
1960 this->writeLabel(end, out);
1961 SpvId result = this->nextId();
1962 this->writeInstruction(SpvOpPhi, this->getType(*kBool_Type), result, trueCon stant, lhsBlock,
1963 rhs, rhsBlock, out);
1964 return result;
1965 }
1966
1967 SpvId SPIRVCodeGenerator::writeTernaryExpression(TernaryExpression& t, std::ostr eam& out) {
1968 SpvId test = this->writeExpression(*t.fTest, out);
1969 if (t.fIfTrue->isConstant() && t.fIfFalse->isConstant()) {
1970 // both true and false are constants, can just use OpSelect
1971 SpvId result = this->nextId();
1972 SpvId trueId = this->writeExpression(*t.fIfTrue, out);
1973 SpvId falseId = this->writeExpression(*t.fIfFalse, out);
1974 this->writeInstruction(SpvOpSelect, this->getType(*t.fType), result, tes t, trueId, falseId,
1975 out);
1976 return result;
1977 }
1978 // was originally using OpPhi to choose the result, but for some reason that is crashing on
1979 // Adreno. Switched to storing the result in a temp variable as glslang does .
1980 SpvId var = this->nextId();
1981 this->writeInstruction(SpvOpVariable, this->getPointerType(t.fType, SpvStora geClassFunction),
1982 var, SpvStorageClassFunction, out);
1983 SpvId trueLabel = this->nextId();
1984 SpvId falseLabel = this->nextId();
1985 SpvId end = this->nextId();
1986 this->writeInstruction(SpvOpSelectionMerge, end, SpvSelectionControlMaskNone , out);
1987 this->writeInstruction(SpvOpBranchConditional, test, trueLabel, falseLabel, out);
1988 this->writeLabel(trueLabel, out);
1989 this->writeInstruction(SpvOpStore, var, this->writeExpression(*t.fIfTrue, ou t), out);
1990 this->writeInstruction(SpvOpBranch, end, out);
1991 this->writeLabel(falseLabel, out);
1992 this->writeInstruction(SpvOpStore, var, this->writeExpression(*t.fIfFalse, o ut), out);
1993 this->writeInstruction(SpvOpBranch, end, out);
1994 this->writeLabel(end, out);
1995 SpvId result = this->nextId();
1996 this->writeInstruction(SpvOpLoad, this->getType(*t.fType), result, var, out) ;
1997 return result;
1998 }
1999
2000 SpvId SPIRVCodeGenerator::writePrefixExpression(PrefixExpression& p, std::ostrea m& out) {
2001 SpvId expr = this->writeExpression(*p.fOperand, out);
2002 if (p.fOperator == Token::MINUS) {
2003 SpvId result = this->nextId();
2004 SpvId typeId = this->getType(*p.fType);
2005 if (is_float(p.fType)) {
2006 this->writeInstruction(SpvOpFNegate, typeId, result, expr, out);
2007 } else if (is_signed(p.fType)) {
2008 this->writeInstruction(SpvOpSNegate, typeId, result, expr, out);
2009 } else {
2010 ABORT("unsupported prefix expression %s\n", p.description().c_str()) ;
2011 };
2012 return result;
2013 }
2014 switch (p.fOperator) {
2015 case Token::PLUS:
2016 return expr;
2017 case Token::PLUSPLUS: {
2018 IntLiteral oneLiteral(Position(), 1);
2019 SpvId one = this->writeExpression(oneLiteral, out);
2020 SpvId result = this->writeBinaryOperation(p.fType, p.fType, expr, on e, SpvOpFAdd,
2021 SpvOpIAdd, SpvOpIAdd, SpvOpU ndef, out);
2022 this->storeToLValue(*p.fOperand, result, out);
2023 return result;
2024 }
2025 case Token::MINUSMINUS: {
2026 IntLiteral oneLiteral(Position(), 1);
2027 SpvId one = this->writeExpression(oneLiteral, out);
2028 SpvId result = this->writeBinaryOperation(p.fType, p.fType, expr, on e, SpvOpFSub,
2029 SpvOpISub, SpvOpISub, SpvOpU ndef, out);
2030 this->storeToLValue(*p.fOperand, result, out);
2031 return result;
2032 }
2033 case Token::NOT: {
2034 ASSERT(p.fOperand->fType == kBool_Type);
2035 SpvId result = this->nextId();
2036 this->writeInstruction(SpvOpLogicalNot, this->getType(*p.fOperand->f Type), result,
2037 this->writeExpression(*p.fOperand, out), out) ;
2038 return result;
2039 }
2040 default:
2041 ABORT("unsupported prefix expression: %s\n", p.description().c_str() );
2042 }
2043 }
2044
2045 SpvId SPIRVCodeGenerator::writePostfixExpression(PostfixExpression& p, std::ostr eam& out) {
2046 SpvId result = this->writeExpression(*p.fOperand, out);
2047 IntLiteral oneLiteral(Position(), 1);
2048 SpvId one = this->writeExpression(oneLiteral, out);
2049 switch (p.fOperator) {
2050 case Token::PLUSPLUS: {
2051 SpvId temp = this->writeBinaryOperation(p.fType, p.fType, result, on e, SpvOpFAdd,
2052 SpvOpIAdd, SpvOpIAdd, SpvOpU ndef, out);
2053 this->storeToLValue(*p.fOperand, temp, out);
2054 return result;
2055 }
2056 case Token::MINUSMINUS: {
2057 SpvId temp = this->writeBinaryOperation(p.fType, p.fType, result, on e, SpvOpFSub,
2058 SpvOpISub, SpvOpISub, SpvOpU ndef, out);
2059 this->storeToLValue(*p.fOperand, temp, out);
2060 return result;
2061 }
2062 default:
2063 ABORT("unsupported postfix expression %s\n", p.description().c_str() );
2064 }
2065 }
2066
2067 SpvId SPIRVCodeGenerator::writeBoolLiteral(BoolLiteral& b) {
2068 if (b.fValue) {
2069 if (fBoolTrue == 0) {
2070 fBoolTrue = this->nextId();
2071 this->writeInstruction(SpvOpConstantTrue, this->getType(*b.fType), f BoolTrue,
2072 fConstantBuffer);
2073 }
2074 return fBoolTrue;
2075 } else {
2076 if (fBoolFalse == 0) {
2077 fBoolFalse = this->nextId();
2078 this->writeInstruction(SpvOpConstantFalse, this->getType(*b.fType), fBoolFalse,
2079 fConstantBuffer);
2080 }
2081 return fBoolFalse;
2082 }
2083 }
2084
2085 SpvId SPIRVCodeGenerator::writeIntLiteral(IntLiteral& i) {
2086 if (i.fType == kInt_Type) {
2087 auto entry = fIntConstants.find(i.fValue);
2088 if (entry == fIntConstants.end()) {
2089 SpvId result = this->nextId();
2090 this->writeInstruction(SpvOpConstant, this->getType(*i.fType), resul t, (SpvId) i.fValue,
2091 fConstantBuffer);
2092 fIntConstants[i.fValue] = result;
2093 return result;
2094 }
2095 return entry->second;
2096 } else {
2097 ASSERT(i.fType == kUInt_Type);
2098 auto entry = fUIntConstants.find(i.fValue);
2099 if (entry == fUIntConstants.end()) {
2100 SpvId result = this->nextId();
2101 this->writeInstruction(SpvOpConstant, this->getType(*i.fType), resul t, (SpvId) i.fValue,
2102 fConstantBuffer);
2103 fUIntConstants[i.fValue] = result;
2104 return result;
2105 }
2106 return entry->second;
2107 }
2108 }
2109
2110 SpvId SPIRVCodeGenerator::writeFloatLiteral(FloatLiteral& f) {
2111 if (f.fType == kFloat_Type) {
2112 float value = (float) f.fValue;
2113 auto entry = fFloatConstants.find(value);
2114 if (entry == fFloatConstants.end()) {
2115 SpvId result = this->nextId();
2116 uint32_t bits;
2117 ASSERT(sizeof(bits) == sizeof(value));
2118 memcpy(&bits, &value, sizeof(bits));
2119 this->writeInstruction(SpvOpConstant, this->getType(*f.fType), resul t, bits,
2120 fConstantBuffer);
2121 fFloatConstants[value] = result;
2122 return result;
2123 }
2124 return entry->second;
2125 } else {
2126 ASSERT(f.fType == kDouble_Type);
2127 auto entry = fDoubleConstants.find(f.fValue);
2128 if (entry == fDoubleConstants.end()) {
2129 SpvId result = this->nextId();
2130 uint64_t bits;
2131 ASSERT(sizeof(bits) == sizeof(f.fValue));
2132 memcpy(&bits, &f.fValue, sizeof(bits));
2133 this->writeInstruction(SpvOpConstant, this->getType(*f.fType), resul t,
2134 bits & 0xffffffff, bits >> 32, fConstantBuffe r);
2135 fDoubleConstants[f.fValue] = result;
2136 return result;
2137 }
2138 return entry->second;
2139 }
2140 }
2141
2142 SpvId SPIRVCodeGenerator::writeFunctionStart(std::shared_ptr<FunctionDeclaration > f,
2143 std::ostream& out) {
2144 SpvId result = fFunctionMap[f];
2145 this->writeInstruction(SpvOpFunction, this->getType(*f->fReturnType), result ,
2146 SpvFunctionControlMaskNone, this->getFunctionType(f), out);
2147 this->writeInstruction(SpvOpName, result, f->fName.c_str(), fNameBuffer);
2148 for (size_t i = 0; i < f->fParameters.size(); i++) {
2149 SpvId id = this->nextId();
2150 fVariableMap[f->fParameters[i]] = id;
2151 SpvId type;
2152 type = this->getPointerType(f->fParameters[i]->fType, SpvStorageClassFun ction);
2153 this->writeInstruction(SpvOpFunctionParameter, type, id, out);
2154 }
2155 return result;
2156 }
2157
2158 SpvId SPIRVCodeGenerator::writeFunctionDeclaration(std::shared_ptr<FunctionDecla ration> f,
2159 std::ostream& out) {
2160 printf("WARNING: writing function declaration for %s\n", f->description().c_ str());
2161 SpvId result = this->writeFunctionStart(f, out);
2162 this->writeInstruction(SpvOpFunctionEnd, out);
2163 return result;
2164 }
2165
2166 SpvId SPIRVCodeGenerator::writeFunction(FunctionDefinition& f, std::ostream& out ) {
2167 SpvId result = this->writeFunctionStart(f.fDeclaration, out);
2168 this->writeLabel(this->nextId(), out);
2169 if (f.fDeclaration->fName == "main") {
2170 out << fGlobalInitializersBuffer.str();
2171 }
2172 std::stringstream bodyBuffer;
2173 this->writeBlock(*f.fBody, bodyBuffer);
2174 out << fVariableBuffer.str();
2175 fVariableBuffer.str("");
2176 out << bodyBuffer.str();
2177 if (fCurrentBlock) {
2178 this->writeInstruction(SpvOpReturn, out);
2179 }
2180 this->writeInstruction(SpvOpFunctionEnd, out);
2181 return result;
2182 }
2183
2184 void SPIRVCodeGenerator::writeLayout(const Layout& layout, SpvId target) {
2185 if (layout.fLocation >= 0) {
2186 this->writeInstruction(SpvOpDecorate, target, SpvDecorationLocation, lay out.fLocation,
2187 fDecorationBuffer);
2188 }
2189 if (layout.fBinding >= 0) {
2190 this->writeInstruction(SpvOpDecorate, target, SpvDecorationBinding, layo ut.fBinding,
2191 fDecorationBuffer);
2192 }
2193 if (layout.fIndex >= 0) {
2194 this->writeInstruction(SpvOpDecorate, target, SpvDecorationIndex, layout .fIndex,
2195 fDecorationBuffer);
2196 }
2197 if (layout.fSet >= 0) {
2198 this->writeInstruction(SpvOpDecorate, target, SpvDecorationDescriptorSet , layout.fSet,
2199 fDecorationBuffer);
2200 }
2201 if (layout.fBuiltin >= 0) {
2202 this->writeInstruction(SpvOpDecorate, target, SpvDecorationBuiltIn, layo ut.fBuiltin,
2203 fDecorationBuffer);
2204 }
2205 }
2206
2207 void SPIRVCodeGenerator::writeLayout(const Layout& layout, SpvId target, int mem ber) {
2208 if (layout.fLocation >= 0) {
2209 this->writeInstruction(SpvOpMemberDecorate, target, member, SpvDecoratio nLocation,
2210 layout.fLocation, fDecorationBuffer);
2211 }
2212 if (layout.fBinding >= 0) {
2213 this->writeInstruction(SpvOpMemberDecorate, target, member, SpvDecoratio nBinding,
2214 layout.fBinding, fDecorationBuffer);
2215 }
2216 if (layout.fIndex >= 0) {
2217 this->writeInstruction(SpvOpMemberDecorate, target, member, SpvDecoratio nIndex,
2218 layout.fIndex, fDecorationBuffer);
2219 }
2220 if (layout.fSet >= 0) {
2221 this->writeInstruction(SpvOpMemberDecorate, target, member, SpvDecoratio nDescriptorSet,
2222 layout.fSet, fDecorationBuffer);
2223 }
2224 if (layout.fBuiltin >= 0) {
2225 this->writeInstruction(SpvOpMemberDecorate, target, member, SpvDecoratio nBuiltIn,
2226 layout.fBuiltin, fDecorationBuffer);
2227 }
2228 }
2229
2230 SpvId SPIRVCodeGenerator::writeInterfaceBlock(InterfaceBlock& intf) {
2231 SpvId type = this->getType(*intf.fVariable->fType);
2232 SpvId result = this->nextId();
2233 this->writeInstruction(SpvOpDecorate, type, SpvDecorationBlock, fDecorationB uffer);
2234 SpvStorageClass_ storageClass = get_storage_class(intf.fVariable->fModifiers );
2235 SpvId ptrType = this->nextId();
2236 this->writeInstruction(SpvOpTypePointer, ptrType, storageClass, type, fConst antBuffer);
dogben 2016/06/26 03:57:55 nit: Any reason this isn't this->getPointerType()?
2237 this->writeInstruction(SpvOpVariable, ptrType, result, storageClass, fConsta ntBuffer);
dogben 2016/06/26 03:57:56 Is fConstantBuffer correct?
2238 this->writeLayout(intf.fVariable->fModifiers.fLayout, result);
2239 fVariableMap[intf.fVariable] = result;
2240 return result;
2241 }
2242
2243 void SPIRVCodeGenerator::writeGlobalVars(VarDeclaration& decl, std::ostream& out ) {
2244 for (size_t i = 0; i < decl.fVars.size(); i++) {
2245 if (!decl.fVars[i]->fIsReadFrom && !decl.fVars[i]->fIsWrittenTo) {
dogben 2016/06/26 03:57:55 nit: Should this be checked in IRGenerator?
2246 continue;
2247 }
2248 SpvStorageClass_ storageClass;
2249 if (decl.fVars[i]->fModifiers.fFlags & Modifiers::kIn_Flag) {
2250 storageClass = SpvStorageClassInput;
2251 } else if (decl.fVars[i]->fModifiers.fFlags & Modifiers::kOut_Flag) {
2252 storageClass = SpvStorageClassOutput;
2253 } else if (decl.fVars[i]->fModifiers.fFlags & Modifiers::kUniform_Flag) {
2254 if (decl.fVars[i]->fType->kind() == Type::kSampler_Kind) {
2255 storageClass = SpvStorageClassUniformConstant;
2256 } else {
2257 storageClass = SpvStorageClassUniform;
2258 }
2259 } else {
2260 storageClass = SpvStorageClassPrivate;
2261 }
2262 SpvId id = this->nextId();
2263 fVariableMap[decl.fVars[i]] = id;
2264 SpvId type = this->getPointerType(decl.fVars[i]->fType, storageClass);
2265 this->writeInstruction(SpvOpVariable, type, id, storageClass, fConstantB uffer);
dogben 2016/06/26 03:57:56 Is fConstantBuffer correct?
2266 this->writeInstruction(SpvOpName, id, decl.fVars[i]->fName.c_str(), fNam eBuffer);
2267 if (decl.fVars[i]->fType->kind() == Type::kMatrix_Kind) {
2268 this->writeInstruction(SpvOpMemberDecorate, id, (SpvId) i, SpvDecora tionColMajor,
2269 fDecorationBuffer);
2270 this->writeInstruction(SpvOpMemberDecorate, id, (SpvId) i, SpvDecora tionMatrixStride,
2271 (SpvId) decl.fVars[i]->fType->stride(), fDeco rationBuffer);
2272 }
2273 if (decl.fValues[i]) {
2274 ASSERT(!fCurrentBlock);
dogben 2016/06/26 03:57:56 nit: wrong indentation
2275 fCurrentBlock = -1;
dogben 2016/06/26 03:57:56 nit: Add comment that this is to avoid the asserts
2276 SpvId value = this->writeExpression(*decl.fValues[i], fGlobalInitial izersBuffer);
2277 this->writeInstruction(SpvOpStore, id, value, fGlobalInitializersBuf fer);
2278 fCurrentBlock = 0;
2279 }
2280 this->writeLayout(decl.fVars[i]->fModifiers.fLayout, id);
2281 }
2282 }
2283
2284 void SPIRVCodeGenerator::writeVarDeclaration(VarDeclaration& decl, std::ostream& out) {
2285 for (size_t i = 0; i < decl.fVars.size(); i++) {
2286 SpvId id = this->nextId();
2287 fVariableMap[decl.fVars[i]] = id;
2288 SpvId type = this->getPointerType(decl.fVars[i]->fType, SpvStorageClassF unction);
2289 this->writeInstruction(SpvOpVariable, type, id, SpvStorageClassFunction, fVariableBuffer);
2290 this->writeInstruction(SpvOpName, id, decl.fVars[i]->fName.c_str(), fNam eBuffer);
2291 if (decl.fValues[i]) {
2292 SpvId value = this->writeExpression(*decl.fValues[i], out);
2293 this->writeInstruction(SpvOpStore, id, value, out);
2294 }
2295 }
2296 }
2297
2298 void SPIRVCodeGenerator::writeStatement(Statement& s, std::ostream& out) {
2299 switch (s.fKind) {
2300 case Statement::kBlock_Kind:
2301 this->writeBlock((Block&) s, out);
2302 break;
2303 case Statement::kExpression_Kind:
2304 this->writeExpression(*((ExpressionStatement&) s).fExpression, out);
2305 break;
2306 case Statement::kReturn_Kind:
2307 this->writeReturnStatement((ReturnStatement&) s, out);
2308 break;
2309 case Statement::kVarDeclaration_Kind:
2310 this->writeVarDeclaration(*((VarDeclarationStatement&) s).fDeclarati on, out);
2311 break;
2312 case Statement::kIf_Kind:
2313 this->writeIfStatement((IfStatement&) s, out);
2314 break;
2315 case Statement::kFor_Kind:
2316 this->writeForStatement((ForStatement&) s, out);
2317 break;
2318 case Statement::kBreak_Kind:
2319 this->writeInstruction(SpvOpBranch, fBreakTarget.top(), out);
2320 break;
2321 case Statement::kContinue_Kind:
2322 this->writeInstruction(SpvOpBranch, fContinueTarget.top(), out);
2323 break;
2324 case Statement::kDiscard_Kind:
2325 this->writeInstruction(SpvOpKill, out);
2326 break;
2327 default:
2328 printf("unsupported statement: %s\n", s.description().c_str());
2329 ASSERT(false);
2330 }
2331 }
2332
2333 void SPIRVCodeGenerator::writeBlock(Block& b, std::ostream& out) {
2334 for (size_t i = 0; i < b.fStatements.size(); i++) {
2335 this->writeStatement(*b.fStatements[i], out);
2336 }
2337 }
2338
2339 void SPIRVCodeGenerator::writeIfStatement(IfStatement& stmt, std::ostream& out) {
2340 SpvId test = this->writeExpression(*stmt.fTest, out);
2341 SpvId ifTrue = this->nextId();
2342 SpvId ifFalse = this->nextId();
2343 if (stmt.fIfFalse) {
2344 SpvId end = this->nextId();
2345 this->writeInstruction(SpvOpSelectionMerge, end, SpvSelectionControlMask None, out);
2346 this->writeInstruction(SpvOpBranchConditional, test, ifTrue, ifFalse, ou t);
2347 this->writeLabel(ifTrue, out);
2348 this->writeStatement(*stmt.fIfTrue, out);
2349 if (fCurrentBlock) {
dogben 2016/06/26 03:57:55 nit: Maybe add a comment to explain fCurrentBlock
2350 this->writeInstruction(SpvOpBranch, end, out);
2351 }
2352 this->writeLabel(ifFalse, out);
2353 this->writeStatement(*stmt.fIfFalse, out);
2354 if (fCurrentBlock) {
2355 this->writeInstruction(SpvOpBranch, end, out);
2356 }
2357 this->writeLabel(end, out);
2358 } else {
2359 this->writeInstruction(SpvOpSelectionMerge, ifFalse, SpvSelectionControl MaskNone, out);
2360 this->writeInstruction(SpvOpBranchConditional, test, ifTrue, ifFalse, ou t);
2361 this->writeLabel(ifTrue, out);
2362 this->writeStatement(*stmt.fIfTrue, out);
2363 if (fCurrentBlock) {
2364 this->writeInstruction(SpvOpBranch, ifFalse, out);
2365 }
2366 this->writeLabel(ifFalse, out);
2367 }
2368 }
2369
2370 void SPIRVCodeGenerator::writeForStatement(ForStatement& f, std::ostream& out) {
2371 if (f.fInitializer) {
2372 this->writeStatement(*f.fInitializer, out);
2373 }
2374 SpvId header = this->nextId();
2375 SpvId start = this->nextId();
2376 SpvId body = this->nextId();
2377 SpvId next = this->nextId();
2378 fContinueTarget.push(next);
2379 SpvId end = this->nextId();
2380 fBreakTarget.push(end);
2381 this->writeInstruction(SpvOpBranch, header, out);
2382 this->writeLabel(header, out);
2383 this->writeInstruction(SpvOpLoopMerge, end, next, SpvLoopControlMaskNone, ou t);
2384 this->writeInstruction(SpvOpBranch, start, out);
dogben 2016/06/26 03:57:56 nit: wrong indentation
2385 this->writeLabel(start, out);
2386 SpvId test = this->writeExpression(*f.fTest, out);
2387 this->writeInstruction(SpvOpBranchConditional, test, body, end, out);
2388 this->writeLabel(body, out);
2389 this->writeStatement(*f.fStatement, out);
2390 if (fCurrentBlock) {
2391 this->writeInstruction(SpvOpBranch, next, out);
2392 }
2393 this->writeLabel(next, out);
2394 if (f.fNext) {
2395 this->writeExpression(*f.fNext, out);
2396 }
2397 this->writeInstruction(SpvOpBranch, header, out);
2398 this->writeLabel(end, out);
2399 fBreakTarget.pop();
2400 fContinueTarget.pop();
2401 }
2402
2403 void SPIRVCodeGenerator::writeReturnStatement(ReturnStatement& r, std::ostream& out) {
2404 if (r.fExpression) {
2405 this->writeInstruction(SpvOpReturnValue, this->writeExpression(*r.fExpre ssion, out),
2406 out);
2407 } else {
2408 this->writeInstruction(SpvOpReturn, out);
2409 }
2410 }
2411
2412 void SPIRVCodeGenerator::writeInstructions(Program& program, std::ostream& out) {
2413 fGLSLExtendedInstructions = this->nextId();
2414 std::stringstream body;
2415 std::vector<SpvId> interfaceVars;
2416 // assign IDs to functions
2417 for (size_t i = 0; i < program.fElements.size(); i++) {
2418 if (program.fElements[i]->fKind == ProgramElement::kFunction_Kind) {
2419 FunctionDefinition& f = (FunctionDefinition&) *program.fElements[i];
2420 fFunctionMap[f.fDeclaration] = this->nextId();
2421 }
2422 }
2423 for (size_t i = 0; i < program.fElements.size(); i++) {
2424 if (program.fElements[i]->fKind == ProgramElement::kInterfaceBlock_Kind) {
2425 InterfaceBlock& intf = (InterfaceBlock&) *program.fElements[i];
2426 SpvId id = this->writeInterfaceBlock(intf);
2427 if ((intf.fVariable->fModifiers.fFlags & Modifiers::kIn_Flag) ||
2428 (intf.fVariable->fModifiers.fFlags & Modifiers::kOut_Flag)) {
2429 interfaceVars.push_back(id);
dogben 2016/06/26 03:57:56 Doesn't this end up adding the same id twice, once
2430 }
2431 }
2432 }
2433 for (size_t i = 0; i < program.fElements.size(); i++) {
2434 if (program.fElements[i]->fKind == ProgramElement::kVar_Kind) {
2435 this->writeGlobalVars(((VarDeclaration&) *program.fElements[i]), bod y);
2436 }
2437 }
2438 for (size_t i = 0; i < program.fElements.size(); i++) {
2439 if (program.fElements[i]->fKind == ProgramElement::kFunction_Kind) {
2440 this->writeFunction(((FunctionDefinition&) *program.fElements[i]), b ody);
2441 }
2442 }
2443 std::shared_ptr<FunctionDeclaration> main = nullptr;
2444 for (auto entry : fFunctionMap) {
dogben 2016/06/26 03:57:55 nit: const ref
2445 if (entry.first->fName == "main") {
dogben 2016/06/26 03:57:56 nit: wrong indentation
2446 main = entry.first;
2447 }
2448 }
2449 ASSERT(main);
2450 for (auto entry : fVariableMap) {
dogben 2016/06/26 03:57:56 nit: const ref
2451 std::shared_ptr<Variable> var = entry.first;
2452 if (var->fStorage == Variable::kGlobal_Storage &&
2453 ((var->fModifiers.fFlags & Modifiers::kIn_Flag) ||
2454 (var->fModifiers.fFlags & Modifiers::kOut_Flag))) {
2455 interfaceVars.push_back(entry.second);
2456 }
2457 }
2458 this->writeCapabilities(out);
2459 this->writeInstruction(SpvOpExtInstImport, fGLSLExtendedInstructions, "GLSL. std.450", out);
2460 this->writeInstruction(SpvOpMemoryModel, SpvAddressingModelLogical, SpvMemor yModelGLSL450, out);
2461 this->writeOpCode(SpvOpEntryPoint, (SpvId) (3 + (strlen(main->fName.c_str()) + 4) / 4) +
2462 (int32_t) interfaceVars.size(), out);
2463 switch (program.fKind) {
2464 case Program::kVertex_Kind:
2465 this->writeWord(SpvExecutionModelVertex, out);
2466 break;
2467 case Program::kFragment_Kind:
2468 this->writeWord(SpvExecutionModelFragment, out);
2469 break;
2470 }
2471 this->writeWord(fFunctionMap[main], out);
2472 this->writeString(main->fName.c_str(), out);
2473 for (int var : interfaceVars) {
2474 this->writeWord(var, out);
2475 }
2476 if (program.fKind == Program::kFragment_Kind) {
2477 this->writeInstruction(SpvOpExecutionMode,
2478 fFunctionMap[main],
2479 SpvExecutionModeOriginUpperLeft,
2480 out);
2481 }
2482 for (size_t i = 0; i < program.fElements.size(); i++) {
2483 if (program.fElements[i]->fKind == ProgramElement::kExtension_Kind) {
2484 this->writeInstruction(SpvOpSourceExtension,
2485 ((Extension&) *program.fElements[i]).fName.c_ str(),
2486 out);
2487 }
2488 }
2489
2490 out << fNameBuffer.str();
2491 out << fDecorationBuffer.str();
2492 out << fConstantBuffer.str();
2493 out << fExternalFunctionsBuffer.str();
dogben 2016/06/26 03:57:56 fExternalFunctionsBuffer doesn't seem to be used a
2494 out << body.str();
2495 }
dogben 2016/06/26 03:57:55 nit: Maybe assert that fGlobalInitializersBuffer a
2496
2497 void SPIRVCodeGenerator::generateCode(Program& program, std::ostream& out) {
2498 this->writeWord(SpvMagicNumber, out);
2499 this->writeWord(SpvVersion, out);
2500 this->writeWord(SKSL_MAGIC, out);
2501 std::stringstream buffer;
2502 this->writeInstructions(program, buffer);
2503 this->writeWord(fIdCount, out);
2504 this->writeWord(0, out); // reserved, always zero
2505 out << buffer.str();
2506 }
2507
2508 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698