• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "SpirvShader.hpp"
16 
17 #include "System/Debug.hpp"
18 #include "Vulkan/VkPipelineLayout.hpp"
19 #include "Vulkan/VkRenderPass.hpp"
20 
21 #include "marl/defer.h"
22 
23 #include <spirv/unified1/spirv.hpp>
24 
25 namespace sw {
26 
SpirvShader(uint32_t codeSerialID,VkShaderStageFlagBits pipelineStage,const char * entryPointName,InsnStore const & insns,const vk::RenderPass * renderPass,uint32_t subpassIndex,bool robustBufferAccess,const std::shared_ptr<vk::dbg::Context> & dbgctx)27 SpirvShader::SpirvShader(
28     uint32_t codeSerialID,
29     VkShaderStageFlagBits pipelineStage,
30     const char *entryPointName,
31     InsnStore const &insns,
32     const vk::RenderPass *renderPass,
33     uint32_t subpassIndex,
34     bool robustBufferAccess,
35     const std::shared_ptr<vk::dbg::Context> &dbgctx)
36     : insns{ insns }
37     , inputs{ MAX_INTERFACE_COMPONENTS }
38     , outputs{ MAX_INTERFACE_COMPONENTS }
39     , codeSerialID(codeSerialID)
40     , robustBufferAccess(robustBufferAccess)
41 {
42 	ASSERT(insns.size() > 0);
43 
44 	if(dbgctx)
45 	{
46 		dbgInit(dbgctx);
47 	}
48 
49 	if(renderPass)
50 	{
51 		// capture formats of any input attachments present
52 		auto subpass = renderPass->getSubpass(subpassIndex);
53 		inputAttachmentFormats.reserve(subpass.inputAttachmentCount);
54 		for(auto i = 0u; i < subpass.inputAttachmentCount; i++)
55 		{
56 			auto attachmentIndex = subpass.pInputAttachments[i].attachment;
57 			inputAttachmentFormats.push_back(attachmentIndex != VK_ATTACHMENT_UNUSED
58 			                                     ? renderPass->getAttachment(attachmentIndex).format
59 			                                     : VK_FORMAT_UNDEFINED);
60 		}
61 	}
62 
63 	// Simplifying assumptions (to be satisfied by earlier transformations)
64 	// - The only input/output OpVariables present are those used by the entrypoint
65 
66 	Function::ID currentFunction;
67 	Block::ID currentBlock;
68 	InsnIterator blockStart;
69 
70 	for(auto insn : *this)
71 	{
72 		spv::Op opcode = insn.opcode();
73 
74 		switch(opcode)
75 		{
76 			case spv::OpEntryPoint:
77 			{
78 				executionModel = spv::ExecutionModel(insn.word(1));
79 				auto id = Function::ID(insn.word(2));
80 				auto name = insn.string(3);
81 				auto stage = executionModelToStage(executionModel);
82 				if(stage == pipelineStage && strcmp(name, entryPointName) == 0)
83 				{
84 					ASSERT_MSG(entryPoint == 0, "Duplicate entry point with name '%s' and stage %d", name, int(stage));
85 					entryPoint = id;
86 				}
87 				break;
88 			}
89 
90 			case spv::OpExecutionMode:
91 				ProcessExecutionMode(insn);
92 				break;
93 
94 			case spv::OpDecorate:
95 			{
96 				TypeOrObjectID targetId = insn.word(1);
97 				auto decoration = static_cast<spv::Decoration>(insn.word(2));
98 				uint32_t value = insn.wordCount() > 3 ? insn.word(3) : 0;
99 
100 				decorations[targetId].Apply(decoration, value);
101 
102 				switch(decoration)
103 				{
104 					case spv::DecorationDescriptorSet:
105 						descriptorDecorations[targetId].DescriptorSet = value;
106 						break;
107 					case spv::DecorationBinding:
108 						descriptorDecorations[targetId].Binding = value;
109 						break;
110 					case spv::DecorationInputAttachmentIndex:
111 						descriptorDecorations[targetId].InputAttachmentIndex = value;
112 						break;
113 					default:
114 						// Only handling descriptor decorations here.
115 						break;
116 				}
117 
118 				if(decoration == spv::DecorationCentroid)
119 					modes.NeedsCentroid = true;
120 				break;
121 			}
122 
123 			case spv::OpMemberDecorate:
124 			{
125 				Type::ID targetId = insn.word(1);
126 				auto memberIndex = insn.word(2);
127 				auto decoration = static_cast<spv::Decoration>(insn.word(3));
128 				uint32_t value = insn.wordCount() > 4 ? insn.word(4) : 0;
129 
130 				auto &d = memberDecorations[targetId];
131 				if(memberIndex >= d.size())
132 					d.resize(memberIndex + 1);  // on demand; exact size would require another pass...
133 
134 				d[memberIndex].Apply(decoration, value);
135 
136 				if(decoration == spv::DecorationCentroid)
137 					modes.NeedsCentroid = true;
138 				break;
139 			}
140 
141 			case spv::OpDecorationGroup:
142 				// Nothing to do here. We don't need to record the definition of the group; we'll just have
143 				// the bundle of decorations float around. If we were to ever walk the decorations directly,
144 				// we might think about introducing this as a real Object.
145 				break;
146 
147 			case spv::OpGroupDecorate:
148 			{
149 				uint32_t group = insn.word(1);
150 				auto const &groupDecorations = decorations[group];
151 				auto const &descriptorGroupDecorations = descriptorDecorations[group];
152 				for(auto i = 2u; i < insn.wordCount(); i++)
153 				{
154 					// Remaining operands are targets to apply the group to.
155 					uint32_t target = insn.word(i);
156 					decorations[target].Apply(groupDecorations);
157 					descriptorDecorations[target].Apply(descriptorGroupDecorations);
158 				}
159 
160 				break;
161 			}
162 
163 			case spv::OpGroupMemberDecorate:
164 			{
165 				auto const &srcDecorations = decorations[insn.word(1)];
166 				for(auto i = 2u; i < insn.wordCount(); i += 2)
167 				{
168 					// remaining operands are pairs of <id>, literal for members to apply to.
169 					auto &d = memberDecorations[insn.word(i)];
170 					auto memberIndex = insn.word(i + 1);
171 					if(memberIndex >= d.size())
172 						d.resize(memberIndex + 1);  // on demand resize, see above...
173 					d[memberIndex].Apply(srcDecorations);
174 				}
175 				break;
176 			}
177 
178 			case spv::OpLabel:
179 			{
180 				ASSERT(currentBlock.value() == 0);
181 				currentBlock = Block::ID(insn.word(1));
182 				blockStart = insn;
183 				break;
184 			}
185 
186 			// Branch Instructions (subset of Termination Instructions):
187 			case spv::OpBranch:
188 			case spv::OpBranchConditional:
189 			case spv::OpSwitch:
190 			case spv::OpReturn:
191 			// fallthrough
192 
193 			// Termination instruction:
194 			case spv::OpKill:
195 			case spv::OpUnreachable:
196 			{
197 				ASSERT(currentBlock.value() != 0);
198 				ASSERT(currentFunction.value() != 0);
199 
200 				auto blockEnd = insn;
201 				blockEnd++;
202 				functions[currentFunction].blocks[currentBlock] = Block(blockStart, blockEnd);
203 				currentBlock = Block::ID(0);
204 
205 				if(opcode == spv::OpKill)
206 				{
207 					modes.ContainsKill = true;
208 				}
209 				break;
210 			}
211 
212 			case spv::OpLoopMerge:
213 			case spv::OpSelectionMerge:
214 				break;  // Nothing to do in analysis pass.
215 
216 			case spv::OpTypeVoid:
217 			case spv::OpTypeBool:
218 			case spv::OpTypeInt:
219 			case spv::OpTypeFloat:
220 			case spv::OpTypeVector:
221 			case spv::OpTypeMatrix:
222 			case spv::OpTypeImage:
223 			case spv::OpTypeSampler:
224 			case spv::OpTypeSampledImage:
225 			case spv::OpTypeArray:
226 			case spv::OpTypeRuntimeArray:
227 			case spv::OpTypeStruct:
228 			case spv::OpTypePointer:
229 			case spv::OpTypeFunction:
230 				DeclareType(insn);
231 				break;
232 
233 			case spv::OpVariable:
234 			{
235 				Type::ID typeId = insn.word(1);
236 				Object::ID resultId = insn.word(2);
237 				auto storageClass = static_cast<spv::StorageClass>(insn.word(3));
238 
239 				auto &object = defs[resultId];
240 				object.kind = Object::Kind::Pointer;
241 				object.definition = insn;
242 				object.type = typeId;
243 
244 				ASSERT(getType(typeId).definition.opcode() == spv::OpTypePointer);
245 				ASSERT(getType(typeId).storageClass == storageClass);
246 
247 				switch(storageClass)
248 				{
249 					case spv::StorageClassInput:
250 					case spv::StorageClassOutput:
251 						ProcessInterfaceVariable(object);
252 						break;
253 
254 					case spv::StorageClassUniform:
255 					case spv::StorageClassStorageBuffer:
256 						object.kind = Object::Kind::DescriptorSet;
257 						break;
258 
259 					case spv::StorageClassPushConstant:
260 					case spv::StorageClassPrivate:
261 					case spv::StorageClassFunction:
262 					case spv::StorageClassUniformConstant:
263 						break;  // Correctly handled.
264 
265 					case spv::StorageClassWorkgroup:
266 					{
267 						auto &elTy = getType(getType(typeId).element);
268 						auto sizeInBytes = elTy.sizeInComponents * static_cast<uint32_t>(sizeof(float));
269 						workgroupMemory.allocate(resultId, sizeInBytes);
270 						object.kind = Object::Kind::Pointer;
271 						break;
272 					}
273 					case spv::StorageClassAtomicCounter:
274 					case spv::StorageClassImage:
275 						UNSUPPORTED("StorageClass %d not yet supported", (int)storageClass);
276 						break;
277 
278 					case spv::StorageClassCrossWorkgroup:
279 						UNSUPPORTED("SPIR-V OpenCL Execution Model (StorageClassCrossWorkgroup)");
280 						break;
281 
282 					case spv::StorageClassGeneric:
283 						UNSUPPORTED("SPIR-V GenericPointer Capability (StorageClassGeneric)");
284 						break;
285 
286 					default:
287 						UNREACHABLE("Unexpected StorageClass %d", storageClass);  // See Appendix A of the Vulkan spec.
288 						break;
289 				}
290 				break;
291 			}
292 
293 			case spv::OpConstant:
294 			case spv::OpSpecConstant:
295 				CreateConstant(insn).constantValue[0] = insn.word(3);
296 				break;
297 			case spv::OpConstantFalse:
298 			case spv::OpSpecConstantFalse:
299 				CreateConstant(insn).constantValue[0] = 0;  // Represent Boolean false as zero.
300 				break;
301 			case spv::OpConstantTrue:
302 			case spv::OpSpecConstantTrue:
303 				CreateConstant(insn).constantValue[0] = ~0u;  // Represent Boolean true as all bits set.
304 				break;
305 			case spv::OpConstantNull:
306 			case spv::OpUndef:
307 			{
308 				// TODO: consider a real LLVM-level undef. For now, zero is a perfectly good value.
309 				// OpConstantNull forms a constant of arbitrary type, all zeros.
310 				auto &object = CreateConstant(insn);
311 				auto &objectTy = getType(object.type);
312 				for(auto i = 0u; i < objectTy.sizeInComponents; i++)
313 				{
314 					object.constantValue[i] = 0;
315 				}
316 				break;
317 			}
318 			case spv::OpConstantComposite:
319 			case spv::OpSpecConstantComposite:
320 			{
321 				auto &object = CreateConstant(insn);
322 				auto offset = 0u;
323 				for(auto i = 0u; i < insn.wordCount() - 3; i++)
324 				{
325 					auto &constituent = getObject(insn.word(i + 3));
326 					auto &constituentTy = getType(constituent.type);
327 					for(auto j = 0u; j < constituentTy.sizeInComponents; j++)
328 					{
329 						object.constantValue[offset++] = constituent.constantValue[j];
330 					}
331 				}
332 
333 				auto objectId = Object::ID(insn.word(2));
334 				auto decorationsIt = decorations.find(objectId);
335 				if(decorationsIt != decorations.end() &&
336 				   decorationsIt->second.BuiltIn == spv::BuiltInWorkgroupSize)
337 				{
338 					// https://www.khronos.org/registry/vulkan/specs/1.1/html/vkspec.html#interfaces-builtin-variables :
339 					// Decorating an object with the WorkgroupSize built-in
340 					// decoration will make that object contain the dimensions
341 					// of a local workgroup. If an object is decorated with the
342 					// WorkgroupSize decoration, this must take precedence over
343 					// any execution mode set for LocalSize.
344 					// The object decorated with WorkgroupSize must be declared
345 					// as a three-component vector of 32-bit integers.
346 					ASSERT(getType(object.type).sizeInComponents == 3);
347 					modes.WorkgroupSizeX = object.constantValue[0];
348 					modes.WorkgroupSizeY = object.constantValue[1];
349 					modes.WorkgroupSizeZ = object.constantValue[2];
350 				}
351 				break;
352 			}
353 			case spv::OpSpecConstantOp:
354 				EvalSpecConstantOp(insn);
355 				break;
356 
357 			case spv::OpCapability:
358 			{
359 				auto capability = static_cast<spv::Capability>(insn.word(1));
360 				switch(capability)
361 				{
362 					case spv::CapabilityMatrix: capabilities.Matrix = true; break;
363 					case spv::CapabilityShader: capabilities.Shader = true; break;
364 					case spv::CapabilityClipDistance: capabilities.ClipDistance = true; break;
365 					case spv::CapabilityCullDistance: capabilities.CullDistance = true; break;
366 					case spv::CapabilityInputAttachment: capabilities.InputAttachment = true; break;
367 					case spv::CapabilitySampled1D: capabilities.Sampled1D = true; break;
368 					case spv::CapabilityImage1D: capabilities.Image1D = true; break;
369 					case spv::CapabilityImageCubeArray: capabilities.ImageCubeArray = true; break;
370 					case spv::CapabilitySampledBuffer: capabilities.SampledBuffer = true; break;
371 					case spv::CapabilitySampledCubeArray: capabilities.SampledCubeArray = true; break;
372 					case spv::CapabilityImageBuffer: capabilities.ImageBuffer = true; break;
373 					case spv::CapabilityStorageImageExtendedFormats: capabilities.StorageImageExtendedFormats = true; break;
374 					case spv::CapabilityImageQuery: capabilities.ImageQuery = true; break;
375 					case spv::CapabilityDerivativeControl: capabilities.DerivativeControl = true; break;
376 					case spv::CapabilityGroupNonUniform: capabilities.GroupNonUniform = true; break;
377 					case spv::CapabilityGroupNonUniformVote: capabilities.GroupNonUniformVote = true; break;
378 					case spv::CapabilityGroupNonUniformArithmetic: capabilities.GroupNonUniformArithmetic = true; break;
379 					case spv::CapabilityGroupNonUniformBallot: capabilities.GroupNonUniformBallot = true; break;
380 					case spv::CapabilityGroupNonUniformShuffle: capabilities.GroupNonUniformShuffle = true; break;
381 					case spv::CapabilityGroupNonUniformShuffleRelative: capabilities.GroupNonUniformShuffleRelative = true; break;
382 					case spv::CapabilityDeviceGroup: capabilities.DeviceGroup = true; break;
383 					case spv::CapabilityMultiView: capabilities.MultiView = true; break;
384 					case spv::CapabilityStencilExportEXT: capabilities.StencilExportEXT = true; break;
385 					default:
386 						UNSUPPORTED("Unsupported capability %u", insn.word(1));
387 				}
388 				break;  // Various capabilities will be declared, but none affect our code generation at this point.
389 			}
390 
391 			case spv::OpMemoryModel:
392 				break;  // Memory model does not affect our code generation until we decide to do Vulkan Memory Model support.
393 
394 			case spv::OpFunction:
395 			{
396 				auto functionId = Function::ID(insn.word(2));
397 				ASSERT_MSG(currentFunction == 0, "Functions %d and %d overlap", currentFunction.value(), functionId.value());
398 				currentFunction = functionId;
399 				auto &function = functions[functionId];
400 				function.result = Type::ID(insn.word(1));
401 				function.type = Type::ID(insn.word(4));
402 				// Scan forward to find the function's label.
403 				for(auto it = insn; it != end() && function.entry == 0; it++)
404 				{
405 					switch(it.opcode())
406 					{
407 						case spv::OpFunction:
408 						case spv::OpFunctionParameter:
409 							break;
410 						case spv::OpLabel:
411 							function.entry = Block::ID(it.word(1));
412 							break;
413 						default:
414 							WARN("Unexpected opcode '%s' following OpFunction", OpcodeName(it.opcode()).c_str());
415 					}
416 				}
417 				ASSERT_MSG(function.entry != 0, "Function<%d> has no label", currentFunction.value());
418 				break;
419 			}
420 
421 			case spv::OpFunctionEnd:
422 				currentFunction = 0;
423 				break;
424 
425 			case spv::OpExtInstImport:
426 			{
427 				static constexpr std::pair<const char *, Extension::Name> extensionsByName[] = {
428 					{ "GLSL.std.450", Extension::GLSLstd450 },
429 					{ "OpenCL.DebugInfo.100", Extension::OpenCLDebugInfo100 },
430 				};
431 				static constexpr auto extensionCount = sizeof(extensionsByName) / sizeof(extensionsByName[0]);
432 
433 				auto id = Extension::ID(insn.word(1));
434 				auto name = insn.string(2);
435 				auto ext = Extension{ Extension::Unknown };
436 				for(size_t i = 0; i < extensionCount; i++)
437 				{
438 					if(0 == strcmp(name, extensionsByName[i].first))
439 					{
440 						ext = Extension{ extensionsByName[i].second };
441 						break;
442 					}
443 				}
444 				if(ext.name == Extension::Unknown)
445 				{
446 					UNSUPPORTED("SPIR-V Extension: %s", name);
447 					break;
448 				}
449 				extensionsByID.emplace(id, ext);
450 				extensionsImported.emplace(ext.name);
451 				break;
452 			}
453 			case spv::OpName:
454 			case spv::OpMemberName:
455 			case spv::OpSource:
456 			case spv::OpSourceContinued:
457 			case spv::OpSourceExtension:
458 			case spv::OpLine:
459 			case spv::OpNoLine:
460 			case spv::OpModuleProcessed:
461 				// No semantic impact
462 				break;
463 
464 			case spv::OpString:
465 				strings.emplace(insn.word(1), insn.string(2));
466 				break;
467 
468 			case spv::OpFunctionParameter:
469 				// These should have all been removed by preprocessing passes. If we see them here,
470 				// our assumptions are wrong and we will probably generate wrong code.
471 				UNREACHABLE("%s should have already been lowered.", OpcodeName(opcode).c_str());
472 				break;
473 
474 			case spv::OpFunctionCall:
475 				// TODO(b/141246700): Add full support for spv::OpFunctionCall
476 				break;
477 
478 			case spv::OpFConvert:
479 				UNSUPPORTED("SPIR-V Float16 or Float64 Capability (OpFConvert)");
480 				break;
481 
482 			case spv::OpSConvert:
483 				UNSUPPORTED("SPIR-V Int16 or Int64 Capability (OpSConvert)");
484 				break;
485 
486 			case spv::OpUConvert:
487 				UNSUPPORTED("SPIR-V Int16 or Int64 Capability (OpUConvert)");
488 				break;
489 
490 			case spv::OpLoad:
491 			case spv::OpAccessChain:
492 			case spv::OpInBoundsAccessChain:
493 			case spv::OpSampledImage:
494 			case spv::OpImage:
495 			{
496 				// Propagate the descriptor decorations to the result.
497 				Object::ID resultId = insn.word(2);
498 				Object::ID pointerId = insn.word(3);
499 				const auto &d = descriptorDecorations.find(pointerId);
500 
501 				if(d != descriptorDecorations.end())
502 				{
503 					descriptorDecorations[resultId] = d->second;
504 				}
505 
506 				DefineResult(insn);
507 
508 				if(opcode == spv::OpAccessChain || opcode == spv::OpInBoundsAccessChain)
509 				{
510 					Decorations dd{};
511 					ApplyDecorationsForAccessChain(&dd, &descriptorDecorations[resultId], pointerId, insn.wordCount() - 4, insn.wordPointer(4));
512 					// Note: offset is the one thing that does *not* propagate, as the access chain accounts for it.
513 					dd.HasOffset = false;
514 					decorations[resultId].Apply(dd);
515 				}
516 			}
517 			break;
518 
519 			case spv::OpCompositeConstruct:
520 			case spv::OpCompositeInsert:
521 			case spv::OpCompositeExtract:
522 			case spv::OpVectorShuffle:
523 			case spv::OpVectorTimesScalar:
524 			case spv::OpMatrixTimesScalar:
525 			case spv::OpMatrixTimesVector:
526 			case spv::OpVectorTimesMatrix:
527 			case spv::OpMatrixTimesMatrix:
528 			case spv::OpOuterProduct:
529 			case spv::OpTranspose:
530 			case spv::OpVectorExtractDynamic:
531 			case spv::OpVectorInsertDynamic:
532 			// Unary ops
533 			case spv::OpNot:
534 			case spv::OpBitFieldInsert:
535 			case spv::OpBitFieldSExtract:
536 			case spv::OpBitFieldUExtract:
537 			case spv::OpBitReverse:
538 			case spv::OpBitCount:
539 			case spv::OpSNegate:
540 			case spv::OpFNegate:
541 			case spv::OpLogicalNot:
542 			case spv::OpQuantizeToF16:
543 			// Binary ops
544 			case spv::OpIAdd:
545 			case spv::OpISub:
546 			case spv::OpIMul:
547 			case spv::OpSDiv:
548 			case spv::OpUDiv:
549 			case spv::OpFAdd:
550 			case spv::OpFSub:
551 			case spv::OpFMul:
552 			case spv::OpFDiv:
553 			case spv::OpFMod:
554 			case spv::OpFRem:
555 			case spv::OpFOrdEqual:
556 			case spv::OpFUnordEqual:
557 			case spv::OpFOrdNotEqual:
558 			case spv::OpFUnordNotEqual:
559 			case spv::OpFOrdLessThan:
560 			case spv::OpFUnordLessThan:
561 			case spv::OpFOrdGreaterThan:
562 			case spv::OpFUnordGreaterThan:
563 			case spv::OpFOrdLessThanEqual:
564 			case spv::OpFUnordLessThanEqual:
565 			case spv::OpFOrdGreaterThanEqual:
566 			case spv::OpFUnordGreaterThanEqual:
567 			case spv::OpSMod:
568 			case spv::OpSRem:
569 			case spv::OpUMod:
570 			case spv::OpIEqual:
571 			case spv::OpINotEqual:
572 			case spv::OpUGreaterThan:
573 			case spv::OpSGreaterThan:
574 			case spv::OpUGreaterThanEqual:
575 			case spv::OpSGreaterThanEqual:
576 			case spv::OpULessThan:
577 			case spv::OpSLessThan:
578 			case spv::OpULessThanEqual:
579 			case spv::OpSLessThanEqual:
580 			case spv::OpShiftRightLogical:
581 			case spv::OpShiftRightArithmetic:
582 			case spv::OpShiftLeftLogical:
583 			case spv::OpBitwiseOr:
584 			case spv::OpBitwiseXor:
585 			case spv::OpBitwiseAnd:
586 			case spv::OpLogicalOr:
587 			case spv::OpLogicalAnd:
588 			case spv::OpLogicalEqual:
589 			case spv::OpLogicalNotEqual:
590 			case spv::OpUMulExtended:
591 			case spv::OpSMulExtended:
592 			case spv::OpIAddCarry:
593 			case spv::OpISubBorrow:
594 			case spv::OpDot:
595 			case spv::OpConvertFToU:
596 			case spv::OpConvertFToS:
597 			case spv::OpConvertSToF:
598 			case spv::OpConvertUToF:
599 			case spv::OpBitcast:
600 			case spv::OpSelect:
601 			case spv::OpIsInf:
602 			case spv::OpIsNan:
603 			case spv::OpAny:
604 			case spv::OpAll:
605 			case spv::OpDPdx:
606 			case spv::OpDPdxCoarse:
607 			case spv::OpDPdy:
608 			case spv::OpDPdyCoarse:
609 			case spv::OpFwidth:
610 			case spv::OpFwidthCoarse:
611 			case spv::OpDPdxFine:
612 			case spv::OpDPdyFine:
613 			case spv::OpFwidthFine:
614 			case spv::OpAtomicLoad:
615 			case spv::OpAtomicIAdd:
616 			case spv::OpAtomicISub:
617 			case spv::OpAtomicSMin:
618 			case spv::OpAtomicSMax:
619 			case spv::OpAtomicUMin:
620 			case spv::OpAtomicUMax:
621 			case spv::OpAtomicAnd:
622 			case spv::OpAtomicOr:
623 			case spv::OpAtomicXor:
624 			case spv::OpAtomicIIncrement:
625 			case spv::OpAtomicIDecrement:
626 			case spv::OpAtomicExchange:
627 			case spv::OpAtomicCompareExchange:
628 			case spv::OpPhi:
629 			case spv::OpImageSampleImplicitLod:
630 			case spv::OpImageSampleExplicitLod:
631 			case spv::OpImageSampleDrefImplicitLod:
632 			case spv::OpImageSampleDrefExplicitLod:
633 			case spv::OpImageSampleProjImplicitLod:
634 			case spv::OpImageSampleProjExplicitLod:
635 			case spv::OpImageSampleProjDrefImplicitLod:
636 			case spv::OpImageSampleProjDrefExplicitLod:
637 			case spv::OpImageGather:
638 			case spv::OpImageDrefGather:
639 			case spv::OpImageFetch:
640 			case spv::OpImageQuerySizeLod:
641 			case spv::OpImageQuerySize:
642 			case spv::OpImageQueryLod:
643 			case spv::OpImageQueryLevels:
644 			case spv::OpImageQuerySamples:
645 			case spv::OpImageRead:
646 			case spv::OpImageTexelPointer:
647 			case spv::OpGroupNonUniformElect:
648 			case spv::OpGroupNonUniformAll:
649 			case spv::OpGroupNonUniformAny:
650 			case spv::OpGroupNonUniformAllEqual:
651 			case spv::OpGroupNonUniformBroadcast:
652 			case spv::OpGroupNonUniformBroadcastFirst:
653 			case spv::OpGroupNonUniformBallot:
654 			case spv::OpGroupNonUniformInverseBallot:
655 			case spv::OpGroupNonUniformBallotBitExtract:
656 			case spv::OpGroupNonUniformBallotBitCount:
657 			case spv::OpGroupNonUniformBallotFindLSB:
658 			case spv::OpGroupNonUniformBallotFindMSB:
659 			case spv::OpGroupNonUniformShuffle:
660 			case spv::OpGroupNonUniformShuffleXor:
661 			case spv::OpGroupNonUniformShuffleUp:
662 			case spv::OpGroupNonUniformShuffleDown:
663 			case spv::OpGroupNonUniformIAdd:
664 			case spv::OpGroupNonUniformFAdd:
665 			case spv::OpGroupNonUniformIMul:
666 			case spv::OpGroupNonUniformFMul:
667 			case spv::OpGroupNonUniformSMin:
668 			case spv::OpGroupNonUniformUMin:
669 			case spv::OpGroupNonUniformFMin:
670 			case spv::OpGroupNonUniformSMax:
671 			case spv::OpGroupNonUniformUMax:
672 			case spv::OpGroupNonUniformFMax:
673 			case spv::OpGroupNonUniformBitwiseAnd:
674 			case spv::OpGroupNonUniformBitwiseOr:
675 			case spv::OpGroupNonUniformBitwiseXor:
676 			case spv::OpGroupNonUniformLogicalAnd:
677 			case spv::OpGroupNonUniformLogicalOr:
678 			case spv::OpGroupNonUniformLogicalXor:
679 			case spv::OpCopyObject:
680 			case spv::OpArrayLength:
681 				// Instructions that yield an intermediate value or divergent pointer
682 				DefineResult(insn);
683 				break;
684 
685 			case spv::OpExtInst:
686 				switch(getExtension(insn.word(3)).name)
687 				{
688 					case Extension::GLSLstd450:
689 						DefineResult(insn);
690 						break;
691 					case Extension::OpenCLDebugInfo100:
692 						DefineOpenCLDebugInfo100(insn);
693 						break;
694 					default:
695 						UNREACHABLE("Unexpected Extension name %d", int(getExtension(insn.word(3)).name));
696 						break;
697 				}
698 				break;
699 
700 			case spv::OpStore:
701 			case spv::OpAtomicStore:
702 			case spv::OpImageWrite:
703 			case spv::OpCopyMemory:
704 			case spv::OpMemoryBarrier:
705 				// Don't need to do anything during analysis pass
706 				break;
707 
708 			case spv::OpControlBarrier:
709 				modes.ContainsControlBarriers = true;
710 				break;
711 
712 			case spv::OpExtension:
713 			{
714 				auto ext = insn.string(1);
715 				// Part of core SPIR-V 1.3. Vulkan 1.1 implementations must also accept the pre-1.3
716 				// extension per Appendix A, `Vulkan Environment for SPIR-V`.
717 				if(!strcmp(ext, "SPV_KHR_storage_buffer_storage_class")) break;
718 				if(!strcmp(ext, "SPV_KHR_shader_draw_parameters")) break;
719 				if(!strcmp(ext, "SPV_KHR_16bit_storage")) break;
720 				if(!strcmp(ext, "SPV_KHR_variable_pointers")) break;
721 				if(!strcmp(ext, "SPV_KHR_device_group")) break;
722 				if(!strcmp(ext, "SPV_KHR_multiview")) break;
723 				if(!strcmp(ext, "SPV_EXT_shader_stencil_export")) break;
724 				UNSUPPORTED("SPIR-V Extension: %s", ext);
725 				break;
726 			}
727 
728 			default:
729 				UNSUPPORTED("%s", OpcodeName(opcode).c_str());
730 		}
731 	}
732 
733 	ASSERT_MSG(entryPoint != 0, "Entry point '%s' not found", entryPointName);
734 	for(auto &it : functions)
735 	{
736 		it.second.AssignBlockFields();
737 	}
738 
739 	dbgCreateFile();
740 }
741 
~SpirvShader()742 SpirvShader::~SpirvShader()
743 {
744 	dbgTerm();
745 }
746 
DeclareType(InsnIterator insn)747 void SpirvShader::DeclareType(InsnIterator insn)
748 {
749 	Type::ID resultId = insn.word(1);
750 
751 	auto &type = types[resultId];
752 	type.definition = insn;
753 	type.sizeInComponents = ComputeTypeSize(insn);
754 
755 	// A structure is a builtin block if it has a builtin
756 	// member. All members of such a structure are builtins.
757 	switch(insn.opcode())
758 	{
759 		case spv::OpTypeStruct:
760 		{
761 			auto d = memberDecorations.find(resultId);
762 			if(d != memberDecorations.end())
763 			{
764 				for(auto &m : d->second)
765 				{
766 					if(m.HasBuiltIn)
767 					{
768 						type.isBuiltInBlock = true;
769 						break;
770 					}
771 				}
772 			}
773 			break;
774 		}
775 		case spv::OpTypePointer:
776 		{
777 			Type::ID elementTypeId = insn.word(3);
778 			type.element = elementTypeId;
779 			type.isBuiltInBlock = getType(elementTypeId).isBuiltInBlock;
780 			type.storageClass = static_cast<spv::StorageClass>(insn.word(2));
781 			break;
782 		}
783 		case spv::OpTypeVector:
784 		case spv::OpTypeMatrix:
785 		case spv::OpTypeArray:
786 		case spv::OpTypeRuntimeArray:
787 		{
788 			Type::ID elementTypeId = insn.word(2);
789 			type.element = elementTypeId;
790 			break;
791 		}
792 		default:
793 			break;
794 	}
795 }
796 
CreateConstant(InsnIterator insn)797 SpirvShader::Object &SpirvShader::CreateConstant(InsnIterator insn)
798 {
799 	Type::ID typeId = insn.word(1);
800 	Object::ID resultId = insn.word(2);
801 	auto &object = defs[resultId];
802 	auto &objectTy = getType(typeId);
803 	object.type = typeId;
804 	object.kind = Object::Kind::Constant;
805 	object.definition = insn;
806 	object.constantValue = std::unique_ptr<uint32_t[]>(new uint32_t[objectTy.sizeInComponents]);
807 	return object;
808 }
809 
ProcessInterfaceVariable(Object & object)810 void SpirvShader::ProcessInterfaceVariable(Object &object)
811 {
812 	auto &objectTy = getType(object.type);
813 	ASSERT(objectTy.storageClass == spv::StorageClassInput || objectTy.storageClass == spv::StorageClassOutput);
814 
815 	ASSERT(objectTy.opcode() == spv::OpTypePointer);
816 	auto pointeeTy = getType(objectTy.element);
817 
818 	auto &builtinInterface = (objectTy.storageClass == spv::StorageClassInput) ? inputBuiltins : outputBuiltins;
819 	auto &userDefinedInterface = (objectTy.storageClass == spv::StorageClassInput) ? inputs : outputs;
820 
821 	ASSERT(object.opcode() == spv::OpVariable);
822 	Object::ID resultId = object.definition.word(2);
823 
824 	if(objectTy.isBuiltInBlock)
825 	{
826 		// walk the builtin block, registering each of its members separately.
827 		auto m = memberDecorations.find(objectTy.element);
828 		ASSERT(m != memberDecorations.end());  // otherwise we wouldn't have marked the type chain
829 		auto &structType = pointeeTy.definition;
830 		auto offset = 0u;
831 		auto word = 2u;
832 		for(auto &member : m->second)
833 		{
834 			auto &memberType = getType(structType.word(word));
835 
836 			if(member.HasBuiltIn)
837 			{
838 				builtinInterface[member.BuiltIn] = { resultId, offset, memberType.sizeInComponents };
839 			}
840 
841 			offset += memberType.sizeInComponents;
842 			++word;
843 		}
844 		return;
845 	}
846 
847 	auto d = decorations.find(resultId);
848 	if(d != decorations.end() && d->second.HasBuiltIn)
849 	{
850 		builtinInterface[d->second.BuiltIn] = { resultId, 0, pointeeTy.sizeInComponents };
851 	}
852 	else
853 	{
854 		object.kind = Object::Kind::InterfaceVariable;
855 		VisitInterface(resultId,
856 		               [&userDefinedInterface](Decorations const &d, AttribType type) {
857 			               // Populate a single scalar slot in the interface from a collection of decorations and the intended component type.
858 			               auto scalarSlot = (d.Location << 2) | d.Component;
859 			               ASSERT(scalarSlot >= 0 &&
860 			                      scalarSlot < static_cast<int32_t>(userDefinedInterface.size()));
861 
862 			               auto &slot = userDefinedInterface[scalarSlot];
863 			               slot.Type = type;
864 			               slot.Flat = d.Flat;
865 			               slot.NoPerspective = d.NoPerspective;
866 			               slot.Centroid = d.Centroid;
867 		               });
868 	}
869 }
870 
ProcessExecutionMode(InsnIterator insn)871 void SpirvShader::ProcessExecutionMode(InsnIterator insn)
872 {
873 	auto mode = static_cast<spv::ExecutionMode>(insn.word(2));
874 	switch(mode)
875 	{
876 		case spv::ExecutionModeEarlyFragmentTests:
877 			modes.EarlyFragmentTests = true;
878 			break;
879 		case spv::ExecutionModeDepthReplacing:
880 			modes.DepthReplacing = true;
881 			break;
882 		case spv::ExecutionModeDepthGreater:
883 			modes.DepthGreater = true;
884 			break;
885 		case spv::ExecutionModeDepthLess:
886 			modes.DepthLess = true;
887 			break;
888 		case spv::ExecutionModeDepthUnchanged:
889 			modes.DepthUnchanged = true;
890 			break;
891 		case spv::ExecutionModeLocalSize:
892 			modes.WorkgroupSizeX = insn.word(3);
893 			modes.WorkgroupSizeY = insn.word(4);
894 			modes.WorkgroupSizeZ = insn.word(5);
895 			break;
896 		case spv::ExecutionModeOriginUpperLeft:
897 			// This is always the case for a Vulkan shader. Do nothing.
898 			break;
899 		default:
900 			UNREACHABLE("Execution mode: %d", int(mode));
901 	}
902 }
903 
ComputeTypeSize(InsnIterator insn)904 uint32_t SpirvShader::ComputeTypeSize(InsnIterator insn)
905 {
906 	// Types are always built from the bottom up (with the exception of forward ptrs, which
907 	// don't appear in Vulkan shaders. Therefore, we can always assume our component parts have
908 	// already been described (and so their sizes determined)
909 	switch(insn.opcode())
910 	{
911 		case spv::OpTypeVoid:
912 		case spv::OpTypeSampler:
913 		case spv::OpTypeImage:
914 		case spv::OpTypeSampledImage:
915 		case spv::OpTypeFunction:
916 		case spv::OpTypeRuntimeArray:
917 			// Objects that don't consume any space.
918 			// Descriptor-backed objects currently only need exist at compile-time.
919 			// Runtime arrays don't appear in places where their size would be interesting
920 			return 0;
921 
922 		case spv::OpTypeBool:
923 		case spv::OpTypeFloat:
924 		case spv::OpTypeInt:
925 			// All the fundamental types are 1 component. If we ever add support for 8/16/64-bit components,
926 			// we might need to change this, but only 32 bit components are required for Vulkan 1.1.
927 			return 1;
928 
929 		case spv::OpTypeVector:
930 		case spv::OpTypeMatrix:
931 			// Vectors and matrices both consume element count * element size.
932 			return getType(insn.word(2)).sizeInComponents * insn.word(3);
933 
934 		case spv::OpTypeArray:
935 		{
936 			// Element count * element size. Array sizes come from constant ids.
937 			auto arraySize = GetConstScalarInt(insn.word(3));
938 			return getType(insn.word(2)).sizeInComponents * arraySize;
939 		}
940 
941 		case spv::OpTypeStruct:
942 		{
943 			uint32_t size = 0;
944 			for(uint32_t i = 2u; i < insn.wordCount(); i++)
945 			{
946 				size += getType(insn.word(i)).sizeInComponents;
947 			}
948 			return size;
949 		}
950 
951 		case spv::OpTypePointer:
952 			// Runtime representation of a pointer is a per-lane index.
953 			// Note: clients are expected to look through the pointer if they want the pointee size instead.
954 			return 1;
955 
956 		default:
957 			UNREACHABLE("%s", OpcodeName(insn.opcode()).c_str());
958 			return 0;
959 	}
960 }
961 
VisitInterfaceInner(Type::ID id,Decorations d,const InterfaceVisitor & f) const962 int SpirvShader::VisitInterfaceInner(Type::ID id, Decorations d, const InterfaceVisitor &f) const
963 {
964 	// Recursively walks variable definition and its type tree, taking into account
965 	// any explicit Location or Component decorations encountered; where explicit
966 	// Locations or Components are not specified, assigns them sequentially.
967 	// Collected decorations are carried down toward the leaves and across
968 	// siblings; Effect of decorations intentionally does not flow back up the tree.
969 	//
970 	// F is a functor to be called with the effective decoration set for every component.
971 	//
972 	// Returns the next available location, and calls f().
973 
974 	// This covers the rules in Vulkan 1.1 spec, 14.1.4 Location Assignment.
975 
976 	ApplyDecorationsForId(&d, id);
977 
978 	auto const &obj = getType(id);
979 	switch(obj.opcode())
980 	{
981 		case spv::OpTypePointer:
982 			return VisitInterfaceInner(obj.definition.word(3), d, f);
983 		case spv::OpTypeMatrix:
984 			for(auto i = 0u; i < obj.definition.word(3); i++, d.Location++)
985 			{
986 				// consumes same components of N consecutive locations
987 				VisitInterfaceInner(obj.definition.word(2), d, f);
988 			}
989 			return d.Location;
990 		case spv::OpTypeVector:
991 			for(auto i = 0u; i < obj.definition.word(3); i++, d.Component++)
992 			{
993 				// consumes N consecutive components in the same location
994 				VisitInterfaceInner(obj.definition.word(2), d, f);
995 			}
996 			return d.Location + 1;
997 		case spv::OpTypeFloat:
998 			f(d, ATTRIBTYPE_FLOAT);
999 			return d.Location + 1;
1000 		case spv::OpTypeInt:
1001 			f(d, obj.definition.word(3) ? ATTRIBTYPE_INT : ATTRIBTYPE_UINT);
1002 			return d.Location + 1;
1003 		case spv::OpTypeBool:
1004 			f(d, ATTRIBTYPE_UINT);
1005 			return d.Location + 1;
1006 		case spv::OpTypeStruct:
1007 		{
1008 			// iterate over members, which may themselves have Location/Component decorations
1009 			for(auto i = 0u; i < obj.definition.wordCount() - 2; i++)
1010 			{
1011 				ApplyDecorationsForIdMember(&d, id, i);
1012 				d.Location = VisitInterfaceInner(obj.definition.word(i + 2), d, f);
1013 				d.Component = 0;  // Implicit locations always have component=0
1014 			}
1015 			return d.Location;
1016 		}
1017 		case spv::OpTypeArray:
1018 		{
1019 			auto arraySize = GetConstScalarInt(obj.definition.word(3));
1020 			for(auto i = 0u; i < arraySize; i++)
1021 			{
1022 				d.Location = VisitInterfaceInner(obj.definition.word(2), d, f);
1023 			}
1024 			return d.Location;
1025 		}
1026 		default:
1027 			// Intentionally partial; most opcodes do not participate in type hierarchies
1028 			return 0;
1029 	}
1030 }
1031 
VisitInterface(Object::ID id,const InterfaceVisitor & f) const1032 void SpirvShader::VisitInterface(Object::ID id, const InterfaceVisitor &f) const
1033 {
1034 	// Walk a variable definition and call f for each component in it.
1035 	Decorations d{};
1036 	ApplyDecorationsForId(&d, id);
1037 
1038 	auto def = getObject(id).definition;
1039 	ASSERT(def.opcode() == spv::OpVariable);
1040 	VisitInterfaceInner(def.word(1), d, f);
1041 }
1042 
ApplyDecorationsForAccessChain(Decorations * d,DescriptorDecorations * dd,Object::ID baseId,uint32_t numIndexes,uint32_t const * indexIds) const1043 void SpirvShader::ApplyDecorationsForAccessChain(Decorations *d, DescriptorDecorations *dd, Object::ID baseId, uint32_t numIndexes, uint32_t const *indexIds) const
1044 {
1045 	ApplyDecorationsForId(d, baseId);
1046 	auto &baseObject = getObject(baseId);
1047 	ApplyDecorationsForId(d, baseObject.type);
1048 	auto typeId = getType(baseObject.type).element;
1049 
1050 	for(auto i = 0u; i < numIndexes; i++)
1051 	{
1052 		ApplyDecorationsForId(d, typeId);
1053 		auto &type = getType(typeId);
1054 		switch(type.opcode())
1055 		{
1056 			case spv::OpTypeStruct:
1057 			{
1058 				int memberIndex = GetConstScalarInt(indexIds[i]);
1059 				ApplyDecorationsForIdMember(d, typeId, memberIndex);
1060 				typeId = type.definition.word(2u + memberIndex);
1061 				break;
1062 			}
1063 			case spv::OpTypeArray:
1064 			case spv::OpTypeRuntimeArray:
1065 				if(dd->InputAttachmentIndex >= 0)
1066 				{
1067 					dd->InputAttachmentIndex += GetConstScalarInt(indexIds[i]);
1068 				}
1069 				typeId = type.element;
1070 				break;
1071 			case spv::OpTypeVector:
1072 				typeId = type.element;
1073 				break;
1074 			case spv::OpTypeMatrix:
1075 				typeId = type.element;
1076 				d->InsideMatrix = true;
1077 				break;
1078 			default:
1079 				UNREACHABLE("%s", OpcodeName(type.definition.opcode()).c_str());
1080 		}
1081 	}
1082 }
1083 
WalkExplicitLayoutAccessChain(Object::ID baseId,uint32_t numIndexes,uint32_t const * indexIds,EmitState const * state) const1084 SIMD::Pointer SpirvShader::WalkExplicitLayoutAccessChain(Object::ID baseId, uint32_t numIndexes, uint32_t const *indexIds, EmitState const *state) const
1085 {
1086 	// Produce a offset into external memory in sizeof(float) units
1087 
1088 	auto &baseObject = getObject(baseId);
1089 	Type::ID typeId = getType(baseObject.type).element;
1090 	Decorations d = {};
1091 	ApplyDecorationsForId(&d, baseObject.type);
1092 
1093 	uint32_t arrayIndex = 0;
1094 	if(baseObject.kind == Object::Kind::DescriptorSet)
1095 	{
1096 		auto type = getType(typeId).definition.opcode();
1097 		if(type == spv::OpTypeArray || type == spv::OpTypeRuntimeArray)
1098 		{
1099 			ASSERT(getObject(indexIds[0]).kind == Object::Kind::Constant);
1100 			arrayIndex = GetConstScalarInt(indexIds[0]);
1101 
1102 			numIndexes--;
1103 			indexIds++;
1104 			typeId = getType(typeId).element;
1105 		}
1106 	}
1107 
1108 	auto ptr = GetPointerToData(baseId, arrayIndex, state);
1109 
1110 	int constantOffset = 0;
1111 
1112 	for(auto i = 0u; i < numIndexes; i++)
1113 	{
1114 		auto &type = getType(typeId);
1115 		ApplyDecorationsForId(&d, typeId);
1116 
1117 		switch(type.definition.opcode())
1118 		{
1119 			case spv::OpTypeStruct:
1120 			{
1121 				int memberIndex = GetConstScalarInt(indexIds[i]);
1122 				ApplyDecorationsForIdMember(&d, typeId, memberIndex);
1123 				ASSERT(d.HasOffset);
1124 				constantOffset += d.Offset;
1125 				typeId = type.definition.word(2u + memberIndex);
1126 				break;
1127 			}
1128 			case spv::OpTypeArray:
1129 			case spv::OpTypeRuntimeArray:
1130 			{
1131 				// TODO: b/127950082: Check bounds.
1132 				ASSERT(d.HasArrayStride);
1133 				auto &obj = getObject(indexIds[i]);
1134 				if(obj.kind == Object::Kind::Constant)
1135 				{
1136 					constantOffset += d.ArrayStride * GetConstScalarInt(indexIds[i]);
1137 				}
1138 				else
1139 				{
1140 					ptr += SIMD::Int(d.ArrayStride) * state->getIntermediate(indexIds[i]).Int(0);
1141 				}
1142 				typeId = type.element;
1143 				break;
1144 			}
1145 			case spv::OpTypeMatrix:
1146 			{
1147 				// TODO: b/127950082: Check bounds.
1148 				ASSERT(d.HasMatrixStride);
1149 				d.InsideMatrix = true;
1150 				auto columnStride = (d.HasRowMajor && d.RowMajor) ? static_cast<int32_t>(sizeof(float)) : d.MatrixStride;
1151 				auto &obj = getObject(indexIds[i]);
1152 				if(obj.kind == Object::Kind::Constant)
1153 				{
1154 					constantOffset += columnStride * GetConstScalarInt(indexIds[i]);
1155 				}
1156 				else
1157 				{
1158 					ptr += SIMD::Int(columnStride) * state->getIntermediate(indexIds[i]).Int(0);
1159 				}
1160 				typeId = type.element;
1161 				break;
1162 			}
1163 			case spv::OpTypeVector:
1164 			{
1165 				auto elemStride = (d.InsideMatrix && d.HasRowMajor && d.RowMajor) ? d.MatrixStride : static_cast<int32_t>(sizeof(float));
1166 				auto &obj = getObject(indexIds[i]);
1167 				if(obj.kind == Object::Kind::Constant)
1168 				{
1169 					constantOffset += elemStride * GetConstScalarInt(indexIds[i]);
1170 				}
1171 				else
1172 				{
1173 					ptr += SIMD::Int(elemStride) * state->getIntermediate(indexIds[i]).Int(0);
1174 				}
1175 				typeId = type.element;
1176 				break;
1177 			}
1178 			default:
1179 				UNREACHABLE("%s", OpcodeName(type.definition.opcode()).c_str());
1180 		}
1181 	}
1182 
1183 	ptr += constantOffset;
1184 	return ptr;
1185 }
1186 
WalkAccessChain(Object::ID baseId,uint32_t numIndexes,uint32_t const * indexIds,EmitState const * state) const1187 SIMD::Pointer SpirvShader::WalkAccessChain(Object::ID baseId, uint32_t numIndexes, uint32_t const *indexIds, EmitState const *state) const
1188 {
1189 	// TODO: avoid doing per-lane work in some cases if we can?
1190 	auto routine = state->routine;
1191 	auto &baseObject = getObject(baseId);
1192 	Type::ID typeId = getType(baseObject.type).element;
1193 
1194 	auto ptr = state->getPointer(baseId);
1195 
1196 	int constantOffset = 0;
1197 
1198 	for(auto i = 0u; i < numIndexes; i++)
1199 	{
1200 		auto &type = getType(typeId);
1201 		switch(type.opcode())
1202 		{
1203 			case spv::OpTypeStruct:
1204 			{
1205 				int memberIndex = GetConstScalarInt(indexIds[i]);
1206 				int offsetIntoStruct = 0;
1207 				for(auto j = 0; j < memberIndex; j++)
1208 				{
1209 					auto memberType = type.definition.word(2u + j);
1210 					offsetIntoStruct += getType(memberType).sizeInComponents * sizeof(float);
1211 				}
1212 				constantOffset += offsetIntoStruct;
1213 				typeId = type.definition.word(2u + memberIndex);
1214 				break;
1215 			}
1216 
1217 			case spv::OpTypeVector:
1218 			case spv::OpTypeMatrix:
1219 			case spv::OpTypeArray:
1220 			case spv::OpTypeRuntimeArray:
1221 			{
1222 				// TODO: b/127950082: Check bounds.
1223 				if(getType(baseObject.type).storageClass == spv::StorageClassUniformConstant)
1224 				{
1225 					// indexing into an array of descriptors.
1226 					auto &obj = getObject(indexIds[i]);
1227 					if(obj.kind != Object::Kind::Constant)
1228 					{
1229 						UNSUPPORTED("SPIR-V SampledImageArrayDynamicIndexing Capability");
1230 					}
1231 
1232 					auto d = descriptorDecorations.at(baseId);
1233 					ASSERT(d.DescriptorSet >= 0);
1234 					ASSERT(d.Binding >= 0);
1235 					auto setLayout = routine->pipelineLayout->getDescriptorSetLayout(d.DescriptorSet);
1236 					auto stride = static_cast<uint32_t>(setLayout->getBindingStride(d.Binding));
1237 					ptr.base += stride * GetConstScalarInt(indexIds[i]);
1238 				}
1239 				else
1240 				{
1241 					auto stride = getType(type.element).sizeInComponents * static_cast<uint32_t>(sizeof(float));
1242 					auto &obj = getObject(indexIds[i]);
1243 					if(obj.kind == Object::Kind::Constant)
1244 					{
1245 						ptr += stride * GetConstScalarInt(indexIds[i]);
1246 					}
1247 					else
1248 					{
1249 						ptr += SIMD::Int(stride) * state->getIntermediate(indexIds[i]).Int(0);
1250 					}
1251 				}
1252 				typeId = type.element;
1253 				break;
1254 			}
1255 
1256 			default:
1257 				UNREACHABLE("%s", OpcodeName(type.opcode()).c_str());
1258 		}
1259 	}
1260 
1261 	if(constantOffset != 0)
1262 	{
1263 		ptr += constantOffset;
1264 	}
1265 	return ptr;
1266 }
1267 
WalkLiteralAccessChain(Type::ID typeId,uint32_t numIndexes,uint32_t const * indexes) const1268 uint32_t SpirvShader::WalkLiteralAccessChain(Type::ID typeId, uint32_t numIndexes, uint32_t const *indexes) const
1269 {
1270 	uint32_t componentOffset = 0;
1271 
1272 	for(auto i = 0u; i < numIndexes; i++)
1273 	{
1274 		auto &type = getType(typeId);
1275 		switch(type.opcode())
1276 		{
1277 			case spv::OpTypeStruct:
1278 			{
1279 				int memberIndex = indexes[i];
1280 				int offsetIntoStruct = 0;
1281 				for(auto j = 0; j < memberIndex; j++)
1282 				{
1283 					auto memberType = type.definition.word(2u + j);
1284 					offsetIntoStruct += getType(memberType).sizeInComponents;
1285 				}
1286 				componentOffset += offsetIntoStruct;
1287 				typeId = type.definition.word(2u + memberIndex);
1288 				break;
1289 			}
1290 
1291 			case spv::OpTypeVector:
1292 			case spv::OpTypeMatrix:
1293 			case spv::OpTypeArray:
1294 			{
1295 				auto elementType = type.definition.word(2);
1296 				auto stride = getType(elementType).sizeInComponents;
1297 				componentOffset += stride * indexes[i];
1298 				typeId = elementType;
1299 				break;
1300 			}
1301 
1302 			default:
1303 				UNREACHABLE("%s", OpcodeName(type.opcode()).c_str());
1304 		}
1305 	}
1306 
1307 	return componentOffset;
1308 }
1309 
Apply(spv::Decoration decoration,uint32_t arg)1310 void SpirvShader::Decorations::Apply(spv::Decoration decoration, uint32_t arg)
1311 {
1312 	switch(decoration)
1313 	{
1314 		case spv::DecorationLocation:
1315 			HasLocation = true;
1316 			Location = static_cast<int32_t>(arg);
1317 			break;
1318 		case spv::DecorationComponent:
1319 			HasComponent = true;
1320 			Component = arg;
1321 			break;
1322 		case spv::DecorationBuiltIn:
1323 			HasBuiltIn = true;
1324 			BuiltIn = static_cast<spv::BuiltIn>(arg);
1325 			break;
1326 		case spv::DecorationFlat:
1327 			Flat = true;
1328 			break;
1329 		case spv::DecorationNoPerspective:
1330 			NoPerspective = true;
1331 			break;
1332 		case spv::DecorationCentroid:
1333 			Centroid = true;
1334 			break;
1335 		case spv::DecorationBlock:
1336 			Block = true;
1337 			break;
1338 		case spv::DecorationBufferBlock:
1339 			BufferBlock = true;
1340 			break;
1341 		case spv::DecorationOffset:
1342 			HasOffset = true;
1343 			Offset = static_cast<int32_t>(arg);
1344 			break;
1345 		case spv::DecorationArrayStride:
1346 			HasArrayStride = true;
1347 			ArrayStride = static_cast<int32_t>(arg);
1348 			break;
1349 		case spv::DecorationMatrixStride:
1350 			HasMatrixStride = true;
1351 			MatrixStride = static_cast<int32_t>(arg);
1352 			break;
1353 		case spv::DecorationRelaxedPrecision:
1354 			RelaxedPrecision = true;
1355 			break;
1356 		case spv::DecorationRowMajor:
1357 			HasRowMajor = true;
1358 			RowMajor = true;
1359 			break;
1360 		case spv::DecorationColMajor:
1361 			HasRowMajor = true;
1362 			RowMajor = false;
1363 		default:
1364 			// Intentionally partial, there are many decorations we just don't care about.
1365 			break;
1366 	}
1367 }
1368 
Apply(const sw::SpirvShader::Decorations & src)1369 void SpirvShader::Decorations::Apply(const sw::SpirvShader::Decorations &src)
1370 {
1371 	// Apply a decoration group to this set of decorations
1372 	if(src.HasBuiltIn)
1373 	{
1374 		HasBuiltIn = true;
1375 		BuiltIn = src.BuiltIn;
1376 	}
1377 
1378 	if(src.HasLocation)
1379 	{
1380 		HasLocation = true;
1381 		Location = src.Location;
1382 	}
1383 
1384 	if(src.HasComponent)
1385 	{
1386 		HasComponent = true;
1387 		Component = src.Component;
1388 	}
1389 
1390 	if(src.HasOffset)
1391 	{
1392 		HasOffset = true;
1393 		Offset = src.Offset;
1394 	}
1395 
1396 	if(src.HasArrayStride)
1397 	{
1398 		HasArrayStride = true;
1399 		ArrayStride = src.ArrayStride;
1400 	}
1401 
1402 	if(src.HasMatrixStride)
1403 	{
1404 		HasMatrixStride = true;
1405 		MatrixStride = src.MatrixStride;
1406 	}
1407 
1408 	if(src.HasRowMajor)
1409 	{
1410 		HasRowMajor = true;
1411 		RowMajor = src.RowMajor;
1412 	}
1413 
1414 	Flat |= src.Flat;
1415 	NoPerspective |= src.NoPerspective;
1416 	Centroid |= src.Centroid;
1417 	Block |= src.Block;
1418 	BufferBlock |= src.BufferBlock;
1419 	RelaxedPrecision |= src.RelaxedPrecision;
1420 	InsideMatrix |= src.InsideMatrix;
1421 }
1422 
Apply(const sw::SpirvShader::DescriptorDecorations & src)1423 void SpirvShader::DescriptorDecorations::Apply(const sw::SpirvShader::DescriptorDecorations &src)
1424 {
1425 	if(src.DescriptorSet >= 0)
1426 	{
1427 		DescriptorSet = src.DescriptorSet;
1428 	}
1429 
1430 	if(src.Binding >= 0)
1431 	{
1432 		Binding = src.Binding;
1433 	}
1434 
1435 	if(src.InputAttachmentIndex >= 0)
1436 	{
1437 		InputAttachmentIndex = src.InputAttachmentIndex;
1438 	}
1439 }
1440 
ApplyDecorationsForId(Decorations * d,TypeOrObjectID id) const1441 void SpirvShader::ApplyDecorationsForId(Decorations *d, TypeOrObjectID id) const
1442 {
1443 	auto it = decorations.find(id);
1444 	if(it != decorations.end())
1445 		d->Apply(it->second);
1446 }
1447 
ApplyDecorationsForIdMember(Decorations * d,Type::ID id,uint32_t member) const1448 void SpirvShader::ApplyDecorationsForIdMember(Decorations *d, Type::ID id, uint32_t member) const
1449 {
1450 	auto it = memberDecorations.find(id);
1451 	if(it != memberDecorations.end() && member < it->second.size())
1452 	{
1453 		d->Apply(it->second[member]);
1454 	}
1455 }
1456 
DefineResult(const InsnIterator & insn)1457 void SpirvShader::DefineResult(const InsnIterator &insn)
1458 {
1459 	Type::ID typeId = insn.word(1);
1460 	Object::ID resultId = insn.word(2);
1461 	auto &object = defs[resultId];
1462 	object.type = typeId;
1463 
1464 	switch(getType(typeId).opcode())
1465 	{
1466 		case spv::OpTypePointer:
1467 		case spv::OpTypeImage:
1468 		case spv::OpTypeSampledImage:
1469 		case spv::OpTypeSampler:
1470 			object.kind = Object::Kind::Pointer;
1471 			break;
1472 
1473 		default:
1474 			object.kind = Object::Kind::Intermediate;
1475 	}
1476 
1477 	object.definition = insn;
1478 	dbgDeclareResult(insn, resultId);
1479 }
1480 
getOutOfBoundsBehavior(spv::StorageClass storageClass) const1481 OutOfBoundsBehavior SpirvShader::EmitState::getOutOfBoundsBehavior(spv::StorageClass storageClass) const
1482 {
1483 	switch(storageClass)
1484 	{
1485 		case spv::StorageClassUniform:
1486 		case spv::StorageClassStorageBuffer:
1487 			// Buffer resource access. robustBufferAccess feature applies.
1488 			return robustBufferAccess ? OutOfBoundsBehavior::RobustBufferAccess
1489 			                          : OutOfBoundsBehavior::UndefinedBehavior;
1490 
1491 		case spv::StorageClassImage:
1492 			return OutOfBoundsBehavior::UndefinedValue;  // "The value returned by a read of an invalid texel is undefined"
1493 
1494 		case spv::StorageClassInput:
1495 			if(executionModel == spv::ExecutionModelVertex)
1496 			{
1497 				// Vertex attributes follow robustBufferAccess rules.
1498 				return robustBufferAccess ? OutOfBoundsBehavior::RobustBufferAccess
1499 				                          : OutOfBoundsBehavior::UndefinedBehavior;
1500 			}
1501 			// Fall through to default case.
1502 		default:
1503 			// TODO(b/137183137): Optimize if the pointer resulted from OpInBoundsAccessChain.
1504 			// TODO(b/131224163): Optimize cases statically known to be within bounds.
1505 			return OutOfBoundsBehavior::UndefinedValue;
1506 	}
1507 
1508 	return OutOfBoundsBehavior::Nullify;
1509 }
1510 
1511 // emit-time
1512 
emitProlog(SpirvRoutine * routine) const1513 void SpirvShader::emitProlog(SpirvRoutine *routine) const
1514 {
1515 	for(auto insn : *this)
1516 	{
1517 		switch(insn.opcode())
1518 		{
1519 			case spv::OpVariable:
1520 			{
1521 				Type::ID resultPointerTypeId = insn.word(1);
1522 				auto resultPointerType = getType(resultPointerTypeId);
1523 				auto pointeeType = getType(resultPointerType.element);
1524 
1525 				if(pointeeType.sizeInComponents > 0)  // TODO: what to do about zero-slot objects?
1526 				{
1527 					Object::ID resultId = insn.word(2);
1528 					routine->createVariable(resultId, pointeeType.sizeInComponents);
1529 				}
1530 				break;
1531 			}
1532 			case spv::OpPhi:
1533 			{
1534 				auto type = getType(insn.word(1));
1535 				Object::ID resultId = insn.word(2);
1536 				routine->phis.emplace(resultId, SpirvRoutine::Variable(type.sizeInComponents));
1537 				break;
1538 			}
1539 
1540 			case spv::OpImageDrefGather:
1541 			case spv::OpImageFetch:
1542 			case spv::OpImageGather:
1543 			case spv::OpImageQueryLod:
1544 			case spv::OpImageSampleDrefExplicitLod:
1545 			case spv::OpImageSampleDrefImplicitLod:
1546 			case spv::OpImageSampleExplicitLod:
1547 			case spv::OpImageSampleImplicitLod:
1548 			case spv::OpImageSampleProjDrefExplicitLod:
1549 			case spv::OpImageSampleProjDrefImplicitLod:
1550 			case spv::OpImageSampleProjExplicitLod:
1551 			case spv::OpImageSampleProjImplicitLod:
1552 			{
1553 				Object::ID resultId = insn.word(2);
1554 				routine->samplerCache.emplace(resultId, SpirvRoutine::SamplerCache{});
1555 				break;
1556 			}
1557 
1558 			default:
1559 				// Nothing else produces interface variables, so can all be safely ignored.
1560 				break;
1561 		}
1562 	}
1563 }
1564 
emit(SpirvRoutine * routine,RValue<SIMD::Int> const & activeLaneMask,RValue<SIMD::Int> const & storesAndAtomicsMask,const vk::DescriptorSet::Bindings & descriptorSets) const1565 void SpirvShader::emit(SpirvRoutine *routine, RValue<SIMD::Int> const &activeLaneMask, RValue<SIMD::Int> const &storesAndAtomicsMask, const vk::DescriptorSet::Bindings &descriptorSets) const
1566 {
1567 	EmitState state(routine, entryPoint, activeLaneMask, storesAndAtomicsMask, descriptorSets, robustBufferAccess, executionModel);
1568 
1569 	dbgBeginEmit(&state);
1570 	defer(dbgEndEmit(&state));
1571 
1572 	// Emit everything up to the first label
1573 	// TODO: Separate out dispatch of block from non-block instructions?
1574 	for(auto insn : *this)
1575 	{
1576 		if(insn.opcode() == spv::OpLabel)
1577 		{
1578 			break;
1579 		}
1580 		EmitInstruction(insn, &state);
1581 	}
1582 
1583 	// Emit all the blocks starting from entryPoint.
1584 	EmitBlocks(getFunction(entryPoint).entry, &state);
1585 }
1586 
EmitInstructions(InsnIterator begin,InsnIterator end,EmitState * state) const1587 void SpirvShader::EmitInstructions(InsnIterator begin, InsnIterator end, EmitState *state) const
1588 {
1589 	for(auto insn = begin; insn != end; insn++)
1590 	{
1591 		auto res = EmitInstruction(insn, state);
1592 		switch(res)
1593 		{
1594 			case EmitResult::Continue:
1595 				continue;
1596 			case EmitResult::Terminator:
1597 				break;
1598 			default:
1599 				UNREACHABLE("Unexpected EmitResult %d", int(res));
1600 				break;
1601 		}
1602 	}
1603 }
1604 
EmitInstruction(InsnIterator insn,EmitState * state) const1605 SpirvShader::EmitResult SpirvShader::EmitInstruction(InsnIterator insn, EmitState *state) const
1606 {
1607 	dbgBeginEmitInstruction(insn, state);
1608 	defer(dbgEndEmitInstruction(insn, state));
1609 
1610 	auto opcode = insn.opcode();
1611 
1612 	switch(opcode)
1613 	{
1614 		case spv::OpTypeVoid:
1615 		case spv::OpTypeInt:
1616 		case spv::OpTypeFloat:
1617 		case spv::OpTypeBool:
1618 		case spv::OpTypeVector:
1619 		case spv::OpTypeArray:
1620 		case spv::OpTypeRuntimeArray:
1621 		case spv::OpTypeMatrix:
1622 		case spv::OpTypeStruct:
1623 		case spv::OpTypePointer:
1624 		case spv::OpTypeFunction:
1625 		case spv::OpTypeImage:
1626 		case spv::OpTypeSampledImage:
1627 		case spv::OpTypeSampler:
1628 		case spv::OpExecutionMode:
1629 		case spv::OpMemoryModel:
1630 		case spv::OpFunction:
1631 		case spv::OpFunctionEnd:
1632 		case spv::OpConstant:
1633 		case spv::OpConstantNull:
1634 		case spv::OpConstantTrue:
1635 		case spv::OpConstantFalse:
1636 		case spv::OpConstantComposite:
1637 		case spv::OpSpecConstant:
1638 		case spv::OpSpecConstantTrue:
1639 		case spv::OpSpecConstantFalse:
1640 		case spv::OpSpecConstantComposite:
1641 		case spv::OpSpecConstantOp:
1642 		case spv::OpUndef:
1643 		case spv::OpExtension:
1644 		case spv::OpCapability:
1645 		case spv::OpEntryPoint:
1646 		case spv::OpExtInstImport:
1647 		case spv::OpDecorate:
1648 		case spv::OpMemberDecorate:
1649 		case spv::OpGroupDecorate:
1650 		case spv::OpGroupMemberDecorate:
1651 		case spv::OpDecorationGroup:
1652 		case spv::OpName:
1653 		case spv::OpMemberName:
1654 		case spv::OpSource:
1655 		case spv::OpSourceContinued:
1656 		case spv::OpSourceExtension:
1657 		case spv::OpNoLine:
1658 		case spv::OpModuleProcessed:
1659 		case spv::OpString:
1660 			// Nothing to do at emit time. These are either fully handled at analysis time,
1661 			// or don't require any work at all.
1662 			return EmitResult::Continue;
1663 
1664 		case spv::OpLine:
1665 			return EmitLine(insn, state);
1666 
1667 		case spv::OpLabel:
1668 			return EmitResult::Continue;
1669 
1670 		case spv::OpVariable:
1671 			return EmitVariable(insn, state);
1672 
1673 		case spv::OpLoad:
1674 		case spv::OpAtomicLoad:
1675 			return EmitLoad(insn, state);
1676 
1677 		case spv::OpStore:
1678 		case spv::OpAtomicStore:
1679 			return EmitStore(insn, state);
1680 
1681 		case spv::OpAtomicIAdd:
1682 		case spv::OpAtomicISub:
1683 		case spv::OpAtomicSMin:
1684 		case spv::OpAtomicSMax:
1685 		case spv::OpAtomicUMin:
1686 		case spv::OpAtomicUMax:
1687 		case spv::OpAtomicAnd:
1688 		case spv::OpAtomicOr:
1689 		case spv::OpAtomicXor:
1690 		case spv::OpAtomicIIncrement:
1691 		case spv::OpAtomicIDecrement:
1692 		case spv::OpAtomicExchange:
1693 			return EmitAtomicOp(insn, state);
1694 
1695 		case spv::OpAtomicCompareExchange:
1696 			return EmitAtomicCompareExchange(insn, state);
1697 
1698 		case spv::OpAccessChain:
1699 		case spv::OpInBoundsAccessChain:
1700 			return EmitAccessChain(insn, state);
1701 
1702 		case spv::OpCompositeConstruct:
1703 			return EmitCompositeConstruct(insn, state);
1704 
1705 		case spv::OpCompositeInsert:
1706 			return EmitCompositeInsert(insn, state);
1707 
1708 		case spv::OpCompositeExtract:
1709 			return EmitCompositeExtract(insn, state);
1710 
1711 		case spv::OpVectorShuffle:
1712 			return EmitVectorShuffle(insn, state);
1713 
1714 		case spv::OpVectorExtractDynamic:
1715 			return EmitVectorExtractDynamic(insn, state);
1716 
1717 		case spv::OpVectorInsertDynamic:
1718 			return EmitVectorInsertDynamic(insn, state);
1719 
1720 		case spv::OpVectorTimesScalar:
1721 		case spv::OpMatrixTimesScalar:
1722 			return EmitVectorTimesScalar(insn, state);
1723 
1724 		case spv::OpMatrixTimesVector:
1725 			return EmitMatrixTimesVector(insn, state);
1726 
1727 		case spv::OpVectorTimesMatrix:
1728 			return EmitVectorTimesMatrix(insn, state);
1729 
1730 		case spv::OpMatrixTimesMatrix:
1731 			return EmitMatrixTimesMatrix(insn, state);
1732 
1733 		case spv::OpOuterProduct:
1734 			return EmitOuterProduct(insn, state);
1735 
1736 		case spv::OpTranspose:
1737 			return EmitTranspose(insn, state);
1738 
1739 		case spv::OpNot:
1740 		case spv::OpBitFieldInsert:
1741 		case spv::OpBitFieldSExtract:
1742 		case spv::OpBitFieldUExtract:
1743 		case spv::OpBitReverse:
1744 		case spv::OpBitCount:
1745 		case spv::OpSNegate:
1746 		case spv::OpFNegate:
1747 		case spv::OpLogicalNot:
1748 		case spv::OpConvertFToU:
1749 		case spv::OpConvertFToS:
1750 		case spv::OpConvertSToF:
1751 		case spv::OpConvertUToF:
1752 		case spv::OpBitcast:
1753 		case spv::OpIsInf:
1754 		case spv::OpIsNan:
1755 		case spv::OpDPdx:
1756 		case spv::OpDPdxCoarse:
1757 		case spv::OpDPdy:
1758 		case spv::OpDPdyCoarse:
1759 		case spv::OpFwidth:
1760 		case spv::OpFwidthCoarse:
1761 		case spv::OpDPdxFine:
1762 		case spv::OpDPdyFine:
1763 		case spv::OpFwidthFine:
1764 		case spv::OpQuantizeToF16:
1765 			return EmitUnaryOp(insn, state);
1766 
1767 		case spv::OpIAdd:
1768 		case spv::OpISub:
1769 		case spv::OpIMul:
1770 		case spv::OpSDiv:
1771 		case spv::OpUDiv:
1772 		case spv::OpFAdd:
1773 		case spv::OpFSub:
1774 		case spv::OpFMul:
1775 		case spv::OpFDiv:
1776 		case spv::OpFMod:
1777 		case spv::OpFRem:
1778 		case spv::OpFOrdEqual:
1779 		case spv::OpFUnordEqual:
1780 		case spv::OpFOrdNotEqual:
1781 		case spv::OpFUnordNotEqual:
1782 		case spv::OpFOrdLessThan:
1783 		case spv::OpFUnordLessThan:
1784 		case spv::OpFOrdGreaterThan:
1785 		case spv::OpFUnordGreaterThan:
1786 		case spv::OpFOrdLessThanEqual:
1787 		case spv::OpFUnordLessThanEqual:
1788 		case spv::OpFOrdGreaterThanEqual:
1789 		case spv::OpFUnordGreaterThanEqual:
1790 		case spv::OpSMod:
1791 		case spv::OpSRem:
1792 		case spv::OpUMod:
1793 		case spv::OpIEqual:
1794 		case spv::OpINotEqual:
1795 		case spv::OpUGreaterThan:
1796 		case spv::OpSGreaterThan:
1797 		case spv::OpUGreaterThanEqual:
1798 		case spv::OpSGreaterThanEqual:
1799 		case spv::OpULessThan:
1800 		case spv::OpSLessThan:
1801 		case spv::OpULessThanEqual:
1802 		case spv::OpSLessThanEqual:
1803 		case spv::OpShiftRightLogical:
1804 		case spv::OpShiftRightArithmetic:
1805 		case spv::OpShiftLeftLogical:
1806 		case spv::OpBitwiseOr:
1807 		case spv::OpBitwiseXor:
1808 		case spv::OpBitwiseAnd:
1809 		case spv::OpLogicalOr:
1810 		case spv::OpLogicalAnd:
1811 		case spv::OpLogicalEqual:
1812 		case spv::OpLogicalNotEqual:
1813 		case spv::OpUMulExtended:
1814 		case spv::OpSMulExtended:
1815 		case spv::OpIAddCarry:
1816 		case spv::OpISubBorrow:
1817 			return EmitBinaryOp(insn, state);
1818 
1819 		case spv::OpDot:
1820 			return EmitDot(insn, state);
1821 
1822 		case spv::OpSelect:
1823 			return EmitSelect(insn, state);
1824 
1825 		case spv::OpExtInst:
1826 			return EmitExtendedInstruction(insn, state);
1827 
1828 		case spv::OpAny:
1829 			return EmitAny(insn, state);
1830 
1831 		case spv::OpAll:
1832 			return EmitAll(insn, state);
1833 
1834 		case spv::OpBranch:
1835 			return EmitBranch(insn, state);
1836 
1837 		case spv::OpPhi:
1838 			return EmitPhi(insn, state);
1839 
1840 		case spv::OpSelectionMerge:
1841 		case spv::OpLoopMerge:
1842 			return EmitResult::Continue;
1843 
1844 		case spv::OpBranchConditional:
1845 			return EmitBranchConditional(insn, state);
1846 
1847 		case spv::OpSwitch:
1848 			return EmitSwitch(insn, state);
1849 
1850 		case spv::OpUnreachable:
1851 			return EmitUnreachable(insn, state);
1852 
1853 		case spv::OpReturn:
1854 			return EmitReturn(insn, state);
1855 
1856 		case spv::OpFunctionCall:
1857 			return EmitFunctionCall(insn, state);
1858 
1859 		case spv::OpKill:
1860 			return EmitKill(insn, state);
1861 
1862 		case spv::OpImageSampleImplicitLod:
1863 			return EmitImageSampleImplicitLod(None, insn, state);
1864 
1865 		case spv::OpImageSampleExplicitLod:
1866 			return EmitImageSampleExplicitLod(None, insn, state);
1867 
1868 		case spv::OpImageSampleDrefImplicitLod:
1869 			return EmitImageSampleImplicitLod(Dref, insn, state);
1870 
1871 		case spv::OpImageSampleDrefExplicitLod:
1872 			return EmitImageSampleExplicitLod(Dref, insn, state);
1873 
1874 		case spv::OpImageSampleProjImplicitLod:
1875 			return EmitImageSampleImplicitLod(Proj, insn, state);
1876 
1877 		case spv::OpImageSampleProjExplicitLod:
1878 			return EmitImageSampleExplicitLod(Proj, insn, state);
1879 
1880 		case spv::OpImageSampleProjDrefImplicitLod:
1881 			return EmitImageSampleImplicitLod(ProjDref, insn, state);
1882 
1883 		case spv::OpImageSampleProjDrefExplicitLod:
1884 			return EmitImageSampleExplicitLod(ProjDref, insn, state);
1885 
1886 		case spv::OpImageGather:
1887 			return EmitImageGather(None, insn, state);
1888 
1889 		case spv::OpImageDrefGather:
1890 			return EmitImageGather(Dref, insn, state);
1891 
1892 		case spv::OpImageFetch:
1893 			return EmitImageFetch(insn, state);
1894 
1895 		case spv::OpImageQuerySizeLod:
1896 			return EmitImageQuerySizeLod(insn, state);
1897 
1898 		case spv::OpImageQuerySize:
1899 			return EmitImageQuerySize(insn, state);
1900 
1901 		case spv::OpImageQueryLod:
1902 			return EmitImageQueryLod(insn, state);
1903 
1904 		case spv::OpImageQueryLevels:
1905 			return EmitImageQueryLevels(insn, state);
1906 
1907 		case spv::OpImageQuerySamples:
1908 			return EmitImageQuerySamples(insn, state);
1909 
1910 		case spv::OpImageRead:
1911 			return EmitImageRead(insn, state);
1912 
1913 		case spv::OpImageWrite:
1914 			return EmitImageWrite(insn, state);
1915 
1916 		case spv::OpImageTexelPointer:
1917 			return EmitImageTexelPointer(insn, state);
1918 
1919 		case spv::OpSampledImage:
1920 		case spv::OpImage:
1921 			return EmitSampledImageCombineOrSplit(insn, state);
1922 
1923 		case spv::OpCopyObject:
1924 			return EmitCopyObject(insn, state);
1925 
1926 		case spv::OpCopyMemory:
1927 			return EmitCopyMemory(insn, state);
1928 
1929 		case spv::OpControlBarrier:
1930 			return EmitControlBarrier(insn, state);
1931 
1932 		case spv::OpMemoryBarrier:
1933 			return EmitMemoryBarrier(insn, state);
1934 
1935 		case spv::OpGroupNonUniformElect:
1936 		case spv::OpGroupNonUniformAll:
1937 		case spv::OpGroupNonUniformAny:
1938 		case spv::OpGroupNonUniformAllEqual:
1939 		case spv::OpGroupNonUniformBroadcast:
1940 		case spv::OpGroupNonUniformBroadcastFirst:
1941 		case spv::OpGroupNonUniformBallot:
1942 		case spv::OpGroupNonUniformInverseBallot:
1943 		case spv::OpGroupNonUniformBallotBitExtract:
1944 		case spv::OpGroupNonUniformBallotBitCount:
1945 		case spv::OpGroupNonUniformBallotFindLSB:
1946 		case spv::OpGroupNonUniformBallotFindMSB:
1947 		case spv::OpGroupNonUniformShuffle:
1948 		case spv::OpGroupNonUniformShuffleXor:
1949 		case spv::OpGroupNonUniformShuffleUp:
1950 		case spv::OpGroupNonUniformShuffleDown:
1951 		case spv::OpGroupNonUniformIAdd:
1952 		case spv::OpGroupNonUniformFAdd:
1953 		case spv::OpGroupNonUniformIMul:
1954 		case spv::OpGroupNonUniformFMul:
1955 		case spv::OpGroupNonUniformSMin:
1956 		case spv::OpGroupNonUniformUMin:
1957 		case spv::OpGroupNonUniformFMin:
1958 		case spv::OpGroupNonUniformSMax:
1959 		case spv::OpGroupNonUniformUMax:
1960 		case spv::OpGroupNonUniformFMax:
1961 		case spv::OpGroupNonUniformBitwiseAnd:
1962 		case spv::OpGroupNonUniformBitwiseOr:
1963 		case spv::OpGroupNonUniformBitwiseXor:
1964 		case spv::OpGroupNonUniformLogicalAnd:
1965 		case spv::OpGroupNonUniformLogicalOr:
1966 		case spv::OpGroupNonUniformLogicalXor:
1967 			return EmitGroupNonUniform(insn, state);
1968 
1969 		case spv::OpArrayLength:
1970 			return EmitArrayLength(insn, state);
1971 
1972 		default:
1973 			UNREACHABLE("%s", OpcodeName(opcode).c_str());
1974 			break;
1975 	}
1976 
1977 	return EmitResult::Continue;
1978 }
1979 
EmitAccessChain(InsnIterator insn,EmitState * state) const1980 SpirvShader::EmitResult SpirvShader::EmitAccessChain(InsnIterator insn, EmitState *state) const
1981 {
1982 	Type::ID typeId = insn.word(1);
1983 	Object::ID resultId = insn.word(2);
1984 	Object::ID baseId = insn.word(3);
1985 	uint32_t numIndexes = insn.wordCount() - 4;
1986 	const uint32_t *indexes = insn.wordPointer(4);
1987 	auto &type = getType(typeId);
1988 	ASSERT(type.sizeInComponents == 1);
1989 	ASSERT(getObject(resultId).kind == Object::Kind::Pointer);
1990 
1991 	if(type.storageClass == spv::StorageClassPushConstant ||
1992 	   type.storageClass == spv::StorageClassUniform ||
1993 	   type.storageClass == spv::StorageClassStorageBuffer)
1994 	{
1995 		auto ptr = WalkExplicitLayoutAccessChain(baseId, numIndexes, indexes, state);
1996 		state->createPointer(resultId, ptr);
1997 	}
1998 	else
1999 	{
2000 		auto ptr = WalkAccessChain(baseId, numIndexes, indexes, state);
2001 		state->createPointer(resultId, ptr);
2002 	}
2003 
2004 	return EmitResult::Continue;
2005 }
2006 
EmitCompositeConstruct(InsnIterator insn,EmitState * state) const2007 SpirvShader::EmitResult SpirvShader::EmitCompositeConstruct(InsnIterator insn, EmitState *state) const
2008 {
2009 	auto &type = getType(insn.word(1));
2010 	auto &dst = state->createIntermediate(insn.word(2), type.sizeInComponents);
2011 	auto offset = 0u;
2012 
2013 	for(auto i = 0u; i < insn.wordCount() - 3; i++)
2014 	{
2015 		Object::ID srcObjectId = insn.word(3u + i);
2016 		auto &srcObject = getObject(srcObjectId);
2017 		auto &srcObjectTy = getType(srcObject.type);
2018 		GenericValue srcObjectAccess(this, state, srcObjectId);
2019 
2020 		for(auto j = 0u; j < srcObjectTy.sizeInComponents; j++)
2021 		{
2022 			dst.move(offset++, srcObjectAccess.Float(j));
2023 		}
2024 	}
2025 
2026 	return EmitResult::Continue;
2027 }
2028 
EmitCompositeInsert(InsnIterator insn,EmitState * state) const2029 SpirvShader::EmitResult SpirvShader::EmitCompositeInsert(InsnIterator insn, EmitState *state) const
2030 {
2031 	Type::ID resultTypeId = insn.word(1);
2032 	auto &type = getType(resultTypeId);
2033 	auto &dst = state->createIntermediate(insn.word(2), type.sizeInComponents);
2034 	auto &newPartObject = getObject(insn.word(3));
2035 	auto &newPartObjectTy = getType(newPartObject.type);
2036 	auto firstNewComponent = WalkLiteralAccessChain(resultTypeId, insn.wordCount() - 5, insn.wordPointer(5));
2037 
2038 	GenericValue srcObjectAccess(this, state, insn.word(4));
2039 	GenericValue newPartObjectAccess(this, state, insn.word(3));
2040 
2041 	// old components before
2042 	for(auto i = 0u; i < firstNewComponent; i++)
2043 	{
2044 		dst.move(i, srcObjectAccess.Float(i));
2045 	}
2046 	// new part
2047 	for(auto i = 0u; i < newPartObjectTy.sizeInComponents; i++)
2048 	{
2049 		dst.move(firstNewComponent + i, newPartObjectAccess.Float(i));
2050 	}
2051 	// old components after
2052 	for(auto i = firstNewComponent + newPartObjectTy.sizeInComponents; i < type.sizeInComponents; i++)
2053 	{
2054 		dst.move(i, srcObjectAccess.Float(i));
2055 	}
2056 
2057 	return EmitResult::Continue;
2058 }
2059 
EmitCompositeExtract(InsnIterator insn,EmitState * state) const2060 SpirvShader::EmitResult SpirvShader::EmitCompositeExtract(InsnIterator insn, EmitState *state) const
2061 {
2062 	auto &type = getType(insn.word(1));
2063 	auto &dst = state->createIntermediate(insn.word(2), type.sizeInComponents);
2064 	auto &compositeObject = getObject(insn.word(3));
2065 	Type::ID compositeTypeId = compositeObject.definition.word(1);
2066 	auto firstComponent = WalkLiteralAccessChain(compositeTypeId, insn.wordCount() - 4, insn.wordPointer(4));
2067 
2068 	GenericValue compositeObjectAccess(this, state, insn.word(3));
2069 	for(auto i = 0u; i < type.sizeInComponents; i++)
2070 	{
2071 		dst.move(i, compositeObjectAccess.Float(firstComponent + i));
2072 	}
2073 
2074 	return EmitResult::Continue;
2075 }
2076 
EmitVectorShuffle(InsnIterator insn,EmitState * state) const2077 SpirvShader::EmitResult SpirvShader::EmitVectorShuffle(InsnIterator insn, EmitState *state) const
2078 {
2079 	auto &type = getType(insn.word(1));
2080 	auto &dst = state->createIntermediate(insn.word(2), type.sizeInComponents);
2081 
2082 	// Note: number of components in result type, first half type, and second
2083 	// half type are all independent.
2084 	auto &firstHalfType = getType(getObject(insn.word(3)).type);
2085 
2086 	GenericValue firstHalfAccess(this, state, insn.word(3));
2087 	GenericValue secondHalfAccess(this, state, insn.word(4));
2088 
2089 	for(auto i = 0u; i < type.sizeInComponents; i++)
2090 	{
2091 		auto selector = insn.word(5 + i);
2092 		if(selector == static_cast<uint32_t>(-1))
2093 		{
2094 			// Undefined value. Until we decide to do real undef values, zero is as good
2095 			// a value as any
2096 			dst.move(i, RValue<SIMD::Float>(0.0f));
2097 		}
2098 		else if(selector < firstHalfType.sizeInComponents)
2099 		{
2100 			dst.move(i, firstHalfAccess.Float(selector));
2101 		}
2102 		else
2103 		{
2104 			dst.move(i, secondHalfAccess.Float(selector - firstHalfType.sizeInComponents));
2105 		}
2106 	}
2107 
2108 	return EmitResult::Continue;
2109 }
2110 
EmitVectorExtractDynamic(InsnIterator insn,EmitState * state) const2111 SpirvShader::EmitResult SpirvShader::EmitVectorExtractDynamic(InsnIterator insn, EmitState *state) const
2112 {
2113 	auto &type = getType(insn.word(1));
2114 	auto &dst = state->createIntermediate(insn.word(2), type.sizeInComponents);
2115 	auto &srcType = getType(getObject(insn.word(3)).type);
2116 
2117 	GenericValue src(this, state, insn.word(3));
2118 	GenericValue index(this, state, insn.word(4));
2119 
2120 	SIMD::UInt v = SIMD::UInt(0);
2121 
2122 	for(auto i = 0u; i < srcType.sizeInComponents; i++)
2123 	{
2124 		v |= CmpEQ(index.UInt(0), SIMD::UInt(i)) & src.UInt(i);
2125 	}
2126 
2127 	dst.move(0, v);
2128 	return EmitResult::Continue;
2129 }
2130 
EmitVectorInsertDynamic(InsnIterator insn,EmitState * state) const2131 SpirvShader::EmitResult SpirvShader::EmitVectorInsertDynamic(InsnIterator insn, EmitState *state) const
2132 {
2133 	auto &type = getType(insn.word(1));
2134 	auto &dst = state->createIntermediate(insn.word(2), type.sizeInComponents);
2135 
2136 	GenericValue src(this, state, insn.word(3));
2137 	GenericValue component(this, state, insn.word(4));
2138 	GenericValue index(this, state, insn.word(5));
2139 
2140 	for(auto i = 0u; i < type.sizeInComponents; i++)
2141 	{
2142 		SIMD::UInt mask = CmpEQ(SIMD::UInt(i), index.UInt(0));
2143 		dst.move(i, (src.UInt(i) & ~mask) | (component.UInt(0) & mask));
2144 	}
2145 	return EmitResult::Continue;
2146 }
2147 
EmitSelect(InsnIterator insn,EmitState * state) const2148 SpirvShader::EmitResult SpirvShader::EmitSelect(InsnIterator insn, EmitState *state) const
2149 {
2150 	auto &type = getType(insn.word(1));
2151 	auto &dst = state->createIntermediate(insn.word(2), type.sizeInComponents);
2152 	auto cond = GenericValue(this, state, insn.word(3));
2153 	auto condIsScalar = (getType(cond.type).sizeInComponents == 1);
2154 	auto lhs = GenericValue(this, state, insn.word(4));
2155 	auto rhs = GenericValue(this, state, insn.word(5));
2156 
2157 	for(auto i = 0u; i < type.sizeInComponents; i++)
2158 	{
2159 		auto sel = cond.Int(condIsScalar ? 0 : i);
2160 		dst.move(i, (sel & lhs.Int(i)) | (~sel & rhs.Int(i)));  // TODO: IfThenElse()
2161 	}
2162 
2163 	return EmitResult::Continue;
2164 }
2165 
EmitAny(InsnIterator insn,EmitState * state) const2166 SpirvShader::EmitResult SpirvShader::EmitAny(InsnIterator insn, EmitState *state) const
2167 {
2168 	auto &type = getType(insn.word(1));
2169 	ASSERT(type.sizeInComponents == 1);
2170 	auto &dst = state->createIntermediate(insn.word(2), type.sizeInComponents);
2171 	auto &srcType = getType(getObject(insn.word(3)).type);
2172 	auto src = GenericValue(this, state, insn.word(3));
2173 
2174 	SIMD::UInt result = src.UInt(0);
2175 
2176 	for(auto i = 1u; i < srcType.sizeInComponents; i++)
2177 	{
2178 		result |= src.UInt(i);
2179 	}
2180 
2181 	dst.move(0, result);
2182 	return EmitResult::Continue;
2183 }
2184 
EmitAll(InsnIterator insn,EmitState * state) const2185 SpirvShader::EmitResult SpirvShader::EmitAll(InsnIterator insn, EmitState *state) const
2186 {
2187 	auto &type = getType(insn.word(1));
2188 	ASSERT(type.sizeInComponents == 1);
2189 	auto &dst = state->createIntermediate(insn.word(2), type.sizeInComponents);
2190 	auto &srcType = getType(getObject(insn.word(3)).type);
2191 	auto src = GenericValue(this, state, insn.word(3));
2192 
2193 	SIMD::UInt result = src.UInt(0);
2194 
2195 	for(auto i = 1u; i < srcType.sizeInComponents; i++)
2196 	{
2197 		result &= src.UInt(i);
2198 	}
2199 
2200 	dst.move(0, result);
2201 	return EmitResult::Continue;
2202 }
2203 
EmitAtomicOp(InsnIterator insn,EmitState * state) const2204 SpirvShader::EmitResult SpirvShader::EmitAtomicOp(InsnIterator insn, EmitState *state) const
2205 {
2206 	auto &resultType = getType(Type::ID(insn.word(1)));
2207 	Object::ID resultId = insn.word(2);
2208 	Object::ID semanticsId = insn.word(5);
2209 	auto memorySemantics = static_cast<spv::MemorySemanticsMask>(getObject(semanticsId).constantValue[0]);
2210 	auto memoryOrder = MemoryOrder(memorySemantics);
2211 	// Where no value is provided (increment/decrement) use an implicit value of 1.
2212 	auto value = (insn.wordCount() == 7) ? GenericValue(this, state, insn.word(6)).UInt(0) : RValue<SIMD::UInt>(1);
2213 	auto &dst = state->createIntermediate(resultId, resultType.sizeInComponents);
2214 	auto ptr = state->getPointer(insn.word(3));
2215 	auto ptrOffsets = ptr.offsets();
2216 
2217 	SIMD::UInt x(0);
2218 	auto mask = state->activeLaneMask() & state->storesAndAtomicsMask();
2219 	for(int j = 0; j < SIMD::Width; j++)
2220 	{
2221 		If(Extract(mask, j) != 0)
2222 		{
2223 			auto offset = Extract(ptrOffsets, j);
2224 			auto laneValue = Extract(value, j);
2225 			UInt v;
2226 			switch(insn.opcode())
2227 			{
2228 				case spv::OpAtomicIAdd:
2229 				case spv::OpAtomicIIncrement:
2230 					v = AddAtomic(Pointer<UInt>(&ptr.base[offset]), laneValue, memoryOrder);
2231 					break;
2232 				case spv::OpAtomicISub:
2233 				case spv::OpAtomicIDecrement:
2234 					v = SubAtomic(Pointer<UInt>(&ptr.base[offset]), laneValue, memoryOrder);
2235 					break;
2236 				case spv::OpAtomicAnd:
2237 					v = AndAtomic(Pointer<UInt>(&ptr.base[offset]), laneValue, memoryOrder);
2238 					break;
2239 				case spv::OpAtomicOr:
2240 					v = OrAtomic(Pointer<UInt>(&ptr.base[offset]), laneValue, memoryOrder);
2241 					break;
2242 				case spv::OpAtomicXor:
2243 					v = XorAtomic(Pointer<UInt>(&ptr.base[offset]), laneValue, memoryOrder);
2244 					break;
2245 				case spv::OpAtomicSMin:
2246 					v = As<UInt>(MinAtomic(Pointer<Int>(&ptr.base[offset]), As<Int>(laneValue), memoryOrder));
2247 					break;
2248 				case spv::OpAtomicSMax:
2249 					v = As<UInt>(MaxAtomic(Pointer<Int>(&ptr.base[offset]), As<Int>(laneValue), memoryOrder));
2250 					break;
2251 				case spv::OpAtomicUMin:
2252 					v = MinAtomic(Pointer<UInt>(&ptr.base[offset]), laneValue, memoryOrder);
2253 					break;
2254 				case spv::OpAtomicUMax:
2255 					v = MaxAtomic(Pointer<UInt>(&ptr.base[offset]), laneValue, memoryOrder);
2256 					break;
2257 				case spv::OpAtomicExchange:
2258 					v = ExchangeAtomic(Pointer<UInt>(&ptr.base[offset]), laneValue, memoryOrder);
2259 					break;
2260 				default:
2261 					UNREACHABLE("%s", OpcodeName(insn.opcode()).c_str());
2262 					break;
2263 			}
2264 			x = Insert(x, v, j);
2265 		}
2266 	}
2267 
2268 	dst.move(0, x);
2269 	return EmitResult::Continue;
2270 }
2271 
EmitAtomicCompareExchange(InsnIterator insn,EmitState * state) const2272 SpirvShader::EmitResult SpirvShader::EmitAtomicCompareExchange(InsnIterator insn, EmitState *state) const
2273 {
2274 	// Separate from EmitAtomicOp due to different instruction encoding
2275 	auto &resultType = getType(Type::ID(insn.word(1)));
2276 	Object::ID resultId = insn.word(2);
2277 
2278 	auto memorySemanticsEqual = static_cast<spv::MemorySemanticsMask>(getObject(insn.word(5)).constantValue[0]);
2279 	auto memoryOrderEqual = MemoryOrder(memorySemanticsEqual);
2280 	auto memorySemanticsUnequal = static_cast<spv::MemorySemanticsMask>(getObject(insn.word(6)).constantValue[0]);
2281 	auto memoryOrderUnequal = MemoryOrder(memorySemanticsUnequal);
2282 
2283 	auto value = GenericValue(this, state, insn.word(7));
2284 	auto comparator = GenericValue(this, state, insn.word(8));
2285 	auto &dst = state->createIntermediate(resultId, resultType.sizeInComponents);
2286 	auto ptr = state->getPointer(insn.word(3));
2287 	auto ptrOffsets = ptr.offsets();
2288 
2289 	SIMD::UInt x(0);
2290 	auto mask = state->activeLaneMask() & state->storesAndAtomicsMask();
2291 	for(int j = 0; j < SIMD::Width; j++)
2292 	{
2293 		If(Extract(mask, j) != 0)
2294 		{
2295 			auto offset = Extract(ptrOffsets, j);
2296 			auto laneValue = Extract(value.UInt(0), j);
2297 			auto laneComparator = Extract(comparator.UInt(0), j);
2298 			UInt v = CompareExchangeAtomic(Pointer<UInt>(&ptr.base[offset]), laneValue, laneComparator, memoryOrderEqual, memoryOrderUnequal);
2299 			x = Insert(x, v, j);
2300 		}
2301 	}
2302 
2303 	dst.move(0, x);
2304 	return EmitResult::Continue;
2305 }
2306 
EmitCopyObject(InsnIterator insn,EmitState * state) const2307 SpirvShader::EmitResult SpirvShader::EmitCopyObject(InsnIterator insn, EmitState *state) const
2308 {
2309 	auto ty = getType(insn.word(1));
2310 	auto &dst = state->createIntermediate(insn.word(2), ty.sizeInComponents);
2311 	auto src = GenericValue(this, state, insn.word(3));
2312 	for(uint32_t i = 0; i < ty.sizeInComponents; i++)
2313 	{
2314 		dst.move(i, src.Int(i));
2315 	}
2316 	return EmitResult::Continue;
2317 }
2318 
EmitArrayLength(InsnIterator insn,EmitState * state) const2319 SpirvShader::EmitResult SpirvShader::EmitArrayLength(InsnIterator insn, EmitState *state) const
2320 {
2321 	auto resultTyId = Type::ID(insn.word(1));
2322 	auto resultId = Object::ID(insn.word(2));
2323 	auto structPtrId = Object::ID(insn.word(3));
2324 	auto arrayFieldIdx = insn.word(4);
2325 
2326 	auto &resultType = getType(resultTyId);
2327 	ASSERT(resultType.sizeInComponents == 1);
2328 	ASSERT(resultType.definition.opcode() == spv::OpTypeInt);
2329 
2330 	auto &structPtrTy = getType(getObject(structPtrId).type);
2331 	auto &structTy = getType(structPtrTy.element);
2332 	auto arrayId = Type::ID(structTy.definition.word(2 + arrayFieldIdx));
2333 
2334 	auto &result = state->createIntermediate(resultId, 1);
2335 	auto structBase = GetPointerToData(structPtrId, 0, state);
2336 
2337 	Decorations structDecorations = {};
2338 	ApplyDecorationsForIdMember(&structDecorations, structPtrTy.element, arrayFieldIdx);
2339 	ASSERT(structDecorations.HasOffset);
2340 
2341 	auto arrayBase = structBase + structDecorations.Offset;
2342 	auto arraySizeInBytes = SIMD::Int(arrayBase.limit()) - arrayBase.offsets();
2343 
2344 	Decorations arrayDecorations = {};
2345 	ApplyDecorationsForId(&arrayDecorations, arrayId);
2346 	ASSERT(arrayDecorations.HasArrayStride);
2347 	auto arrayLength = arraySizeInBytes / SIMD::Int(arrayDecorations.ArrayStride);
2348 
2349 	result.move(0, SIMD::Int(arrayLength));
2350 
2351 	return EmitResult::Continue;
2352 }
2353 
EmitExtendedInstruction(InsnIterator insn,EmitState * state) const2354 SpirvShader::EmitResult SpirvShader::EmitExtendedInstruction(InsnIterator insn, EmitState *state) const
2355 {
2356 	auto ext = getExtension(insn.word(3));
2357 	switch(ext.name)
2358 	{
2359 		case Extension::GLSLstd450:
2360 			return EmitExtGLSLstd450(insn, state);
2361 		case Extension::OpenCLDebugInfo100:
2362 			return EmitOpenCLDebugInfo100(insn, state);
2363 		default:
2364 			UNREACHABLE("Unknown Extension::Name<%d>", int(ext.name));
2365 	}
2366 	return EmitResult::Continue;
2367 }
2368 
GetConstScalarInt(Object::ID id) const2369 uint32_t SpirvShader::GetConstScalarInt(Object::ID id) const
2370 {
2371 	auto &scopeObj = getObject(id);
2372 	ASSERT(scopeObj.kind == Object::Kind::Constant);
2373 	ASSERT(getType(scopeObj.type).sizeInComponents == 1);
2374 	return scopeObj.constantValue[0];
2375 }
2376 
emitEpilog(SpirvRoutine * routine) const2377 void SpirvShader::emitEpilog(SpirvRoutine *routine) const
2378 {
2379 	for(auto insn : *this)
2380 	{
2381 		switch(insn.opcode())
2382 		{
2383 			case spv::OpVariable:
2384 			{
2385 				Object::ID resultId = insn.word(2);
2386 				auto &object = getObject(resultId);
2387 				auto &objectTy = getType(object.type);
2388 				if(object.kind == Object::Kind::InterfaceVariable && objectTy.storageClass == spv::StorageClassOutput)
2389 				{
2390 					auto &dst = routine->getVariable(resultId);
2391 					int offset = 0;
2392 					VisitInterface(resultId,
2393 					               [&](Decorations const &d, AttribType type) {
2394 						               auto scalarSlot = d.Location << 2 | d.Component;
2395 						               routine->outputs[scalarSlot] = dst[offset++];
2396 					               });
2397 				}
2398 				break;
2399 			}
2400 			default:
2401 				break;
2402 		}
2403 	}
2404 
2405 	// Clear phis that are no longer used. This serves two purposes:
2406 	// (1) The phi rr::Variables are destructed, preventing pointless
2407 	//     materialization.
2408 	// (2) Frees memory that will never be used again.
2409 	routine->phis.clear();
2410 }
2411 
executionModelToStage(spv::ExecutionModel model)2412 VkShaderStageFlagBits SpirvShader::executionModelToStage(spv::ExecutionModel model)
2413 {
2414 	switch(model)
2415 	{
2416 		case spv::ExecutionModelVertex: return VK_SHADER_STAGE_VERTEX_BIT;
2417 		// case spv::ExecutionModelTessellationControl:    return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
2418 		// case spv::ExecutionModelTessellationEvaluation: return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
2419 		// case spv::ExecutionModelGeometry:               return VK_SHADER_STAGE_GEOMETRY_BIT;
2420 		case spv::ExecutionModelFragment: return VK_SHADER_STAGE_FRAGMENT_BIT;
2421 		case spv::ExecutionModelGLCompute: return VK_SHADER_STAGE_COMPUTE_BIT;
2422 		// case spv::ExecutionModelKernel:                 return VkShaderStageFlagBits(0); // Not supported by vulkan.
2423 		// case spv::ExecutionModelTaskNV:                 return VK_SHADER_STAGE_TASK_BIT_NV;
2424 		// case spv::ExecutionModelMeshNV:                 return VK_SHADER_STAGE_MESH_BIT_NV;
2425 		// case spv::ExecutionModelRayGenerationNV:        return VK_SHADER_STAGE_RAYGEN_BIT_NV;
2426 		// case spv::ExecutionModelIntersectionNV:         return VK_SHADER_STAGE_INTERSECTION_BIT_NV;
2427 		// case spv::ExecutionModelAnyHitNV:               return VK_SHADER_STAGE_ANY_HIT_BIT_NV;
2428 		// case spv::ExecutionModelClosestHitNV:           return VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV;
2429 		// case spv::ExecutionModelMissNV:                 return VK_SHADER_STAGE_MISS_BIT_NV;
2430 		// case spv::ExecutionModelCallableNV:             return VK_SHADER_STAGE_CALLABLE_BIT_NV;
2431 		default:
2432 			UNSUPPORTED("ExecutionModel: %d", int(model));
2433 			return VkShaderStageFlagBits(0);
2434 	}
2435 }
2436 
GenericValue(SpirvShader const * shader,EmitState const * state,SpirvShader::Object::ID objId)2437 SpirvShader::GenericValue::GenericValue(SpirvShader const *shader, EmitState const *state, SpirvShader::Object::ID objId)
2438     : obj(shader->getObject(objId))
2439     , intermediate(obj.kind == SpirvShader::Object::Kind::Intermediate ? &state->getIntermediate(objId) : nullptr)
2440     , type(obj.type)
2441 {}
2442 
SpirvRoutine(vk::PipelineLayout const * pipelineLayout)2443 SpirvRoutine::SpirvRoutine(vk::PipelineLayout const *pipelineLayout)
2444     : pipelineLayout(pipelineLayout)
2445 {
2446 }
2447 
setImmutableInputBuiltins(SpirvShader const * shader)2448 void SpirvRoutine::setImmutableInputBuiltins(SpirvShader const *shader)
2449 {
2450 	setInputBuiltin(shader, spv::BuiltInSubgroupLocalInvocationId, [&](const SpirvShader::BuiltinMapping &builtin, Array<SIMD::Float> &value) {
2451 		ASSERT(builtin.SizeInComponents == 1);
2452 		value[builtin.FirstComponent] = As<SIMD::Float>(SIMD::Int(0, 1, 2, 3));
2453 	});
2454 
2455 	setInputBuiltin(shader, spv::BuiltInSubgroupEqMask, [&](const SpirvShader::BuiltinMapping &builtin, Array<SIMD::Float> &value) {
2456 		ASSERT(builtin.SizeInComponents == 4);
2457 		value[builtin.FirstComponent + 0] = As<SIMD::Float>(SIMD::Int(1, 2, 4, 8));
2458 		value[builtin.FirstComponent + 1] = As<SIMD::Float>(SIMD::Int(0, 0, 0, 0));
2459 		value[builtin.FirstComponent + 2] = As<SIMD::Float>(SIMD::Int(0, 0, 0, 0));
2460 		value[builtin.FirstComponent + 3] = As<SIMD::Float>(SIMD::Int(0, 0, 0, 0));
2461 	});
2462 
2463 	setInputBuiltin(shader, spv::BuiltInSubgroupGeMask, [&](const SpirvShader::BuiltinMapping &builtin, Array<SIMD::Float> &value) {
2464 		ASSERT(builtin.SizeInComponents == 4);
2465 		value[builtin.FirstComponent + 0] = As<SIMD::Float>(SIMD::Int(15, 14, 12, 8));
2466 		value[builtin.FirstComponent + 1] = As<SIMD::Float>(SIMD::Int(0, 0, 0, 0));
2467 		value[builtin.FirstComponent + 2] = As<SIMD::Float>(SIMD::Int(0, 0, 0, 0));
2468 		value[builtin.FirstComponent + 3] = As<SIMD::Float>(SIMD::Int(0, 0, 0, 0));
2469 	});
2470 
2471 	setInputBuiltin(shader, spv::BuiltInSubgroupGtMask, [&](const SpirvShader::BuiltinMapping &builtin, Array<SIMD::Float> &value) {
2472 		ASSERT(builtin.SizeInComponents == 4);
2473 		value[builtin.FirstComponent + 0] = As<SIMD::Float>(SIMD::Int(14, 12, 8, 0));
2474 		value[builtin.FirstComponent + 1] = As<SIMD::Float>(SIMD::Int(0, 0, 0, 0));
2475 		value[builtin.FirstComponent + 2] = As<SIMD::Float>(SIMD::Int(0, 0, 0, 0));
2476 		value[builtin.FirstComponent + 3] = As<SIMD::Float>(SIMD::Int(0, 0, 0, 0));
2477 	});
2478 
2479 	setInputBuiltin(shader, spv::BuiltInSubgroupLeMask, [&](const SpirvShader::BuiltinMapping &builtin, Array<SIMD::Float> &value) {
2480 		ASSERT(builtin.SizeInComponents == 4);
2481 		value[builtin.FirstComponent + 0] = As<SIMD::Float>(SIMD::Int(1, 3, 7, 15));
2482 		value[builtin.FirstComponent + 1] = As<SIMD::Float>(SIMD::Int(0, 0, 0, 0));
2483 		value[builtin.FirstComponent + 2] = As<SIMD::Float>(SIMD::Int(0, 0, 0, 0));
2484 		value[builtin.FirstComponent + 3] = As<SIMD::Float>(SIMD::Int(0, 0, 0, 0));
2485 	});
2486 
2487 	setInputBuiltin(shader, spv::BuiltInSubgroupLtMask, [&](const SpirvShader::BuiltinMapping &builtin, Array<SIMD::Float> &value) {
2488 		ASSERT(builtin.SizeInComponents == 4);
2489 		value[builtin.FirstComponent + 0] = As<SIMD::Float>(SIMD::Int(0, 1, 3, 7));
2490 		value[builtin.FirstComponent + 1] = As<SIMD::Float>(SIMD::Int(0, 0, 0, 0));
2491 		value[builtin.FirstComponent + 2] = As<SIMD::Float>(SIMD::Int(0, 0, 0, 0));
2492 		value[builtin.FirstComponent + 3] = As<SIMD::Float>(SIMD::Int(0, 0, 0, 0));
2493 	});
2494 
2495 	setInputBuiltin(shader, spv::BuiltInDeviceIndex, [&](const SpirvShader::BuiltinMapping &builtin, Array<SIMD::Float> &value) {
2496 		ASSERT(builtin.SizeInComponents == 1);
2497 		// Only a single physical device is supported.
2498 		value[builtin.FirstComponent] = As<SIMD::Float>(SIMD::Int(0, 0, 0, 0));
2499 	});
2500 }
2501 
2502 }  // namespace sw
2503