• 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 #ifndef sw_SpirvShader_hpp
16 #define sw_SpirvShader_hpp
17 
18 #include "SamplerCore.hpp"
19 #include "ShaderCore.hpp"
20 #include "SpirvID.hpp"
21 #include "Device/Config.hpp"
22 #include "Device/Sampler.hpp"
23 #include "System/Debug.hpp"
24 #include "System/Types.hpp"
25 #include "Vulkan/VkConfig.h"
26 #include "Vulkan/VkDescriptorSet.hpp"
27 
28 #include <spirv/unified1/spirv.hpp>
29 
30 #include <array>
31 #include <atomic>
32 #include <cstdint>
33 #include <cstring>
34 #include <deque>
35 #include <functional>
36 #include <memory>
37 #include <string>
38 #include <type_traits>
39 #include <unordered_map>
40 #include <unordered_set>
41 #include <vector>
42 
43 #undef Yield  // b/127920555
44 
45 namespace vk {
46 
47 class PipelineLayout;
48 class ImageView;
49 class Sampler;
50 class RenderPass;
51 struct SampledImageDescriptor;
52 
53 namespace dbg {
54 class Context;
55 }  // namespace dbg
56 
57 }  // namespace vk
58 
59 namespace sw {
60 
61 // Forward declarations.
62 class SpirvRoutine;
63 
64 // Incrementally constructed complex bundle of rvalues
65 // Effectively a restricted vector, supporting only:
66 // - allocation to a (runtime-known) fixed size
67 // - in-place construction of elements
68 // - const operator[]
69 class Intermediate
70 {
71 public:
Intermediate(uint32_t size)72 	Intermediate(uint32_t size)
73 	    : scalar(new rr::Value *[size])
74 	    , size(size)
75 	{
76 		memset(scalar, 0, sizeof(rr::Value *) * size);
77 	}
78 
~Intermediate()79 	~Intermediate()
80 	{
81 		delete[] scalar;
82 	}
83 
move(uint32_t i,RValue<SIMD::Float> && scalar)84 	void move(uint32_t i, RValue<SIMD::Float> &&scalar) { emplace(i, scalar.value); }
move(uint32_t i,RValue<SIMD::Int> && scalar)85 	void move(uint32_t i, RValue<SIMD::Int> &&scalar) { emplace(i, scalar.value); }
move(uint32_t i,RValue<SIMD::UInt> && scalar)86 	void move(uint32_t i, RValue<SIMD::UInt> &&scalar) { emplace(i, scalar.value); }
87 
move(uint32_t i,const RValue<SIMD::Float> & scalar)88 	void move(uint32_t i, const RValue<SIMD::Float> &scalar) { emplace(i, scalar.value); }
move(uint32_t i,const RValue<SIMD::Int> & scalar)89 	void move(uint32_t i, const RValue<SIMD::Int> &scalar) { emplace(i, scalar.value); }
move(uint32_t i,const RValue<SIMD::UInt> & scalar)90 	void move(uint32_t i, const RValue<SIMD::UInt> &scalar) { emplace(i, scalar.value); }
91 
92 	// Value retrieval functions.
Float(uint32_t i) const93 	RValue<SIMD::Float> Float(uint32_t i) const
94 	{
95 		ASSERT(i < size);
96 		ASSERT(scalar[i] != nullptr);
97 		return As<SIMD::Float>(scalar[i]);  // TODO(b/128539387): RValue<SIMD::Float>(scalar)
98 	}
99 
Int(uint32_t i) const100 	RValue<SIMD::Int> Int(uint32_t i) const
101 	{
102 		ASSERT(i < size);
103 		ASSERT(scalar[i] != nullptr);
104 		return As<SIMD::Int>(scalar[i]);  // TODO(b/128539387): RValue<SIMD::Int>(scalar)
105 	}
106 
UInt(uint32_t i) const107 	RValue<SIMD::UInt> UInt(uint32_t i) const
108 	{
109 		ASSERT(i < size);
110 		ASSERT(scalar[i] != nullptr);
111 		return As<SIMD::UInt>(scalar[i]);  // TODO(b/128539387): RValue<SIMD::UInt>(scalar)
112 	}
113 
114 	// No copy/move construction or assignment
115 	Intermediate(Intermediate const &) = delete;
116 	Intermediate(Intermediate &&) = delete;
117 	Intermediate &operator=(Intermediate const &) = delete;
118 	Intermediate &operator=(Intermediate &&) = delete;
119 
120 private:
emplace(uint32_t i,rr::Value * value)121 	void emplace(uint32_t i, rr::Value *value)
122 	{
123 		ASSERT(i < size);
124 		ASSERT(scalar[i] == nullptr);
125 		scalar[i] = value;
126 	}
127 
128 	rr::Value **const scalar;
129 	uint32_t size;
130 };
131 
132 class SpirvShader
133 {
134 public:
135 	using InsnStore = std::vector<uint32_t>;
136 	InsnStore insns;
137 
138 	using ImageSampler = void(void *texture, void *sampler, void *uvsIn, void *texelOut, void *constants);
139 
140 	enum class YieldResult
141 	{
142 		ControlBarrier,
143 	};
144 
145 	/* Pseudo-iterator over SPIRV instructions, designed to support range-based-for. */
146 	class InsnIterator
147 	{
148 		InsnStore::const_iterator iter;
149 
150 	public:
opcode() const151 		spv::Op opcode() const
152 		{
153 			return static_cast<spv::Op>(*iter & spv::OpCodeMask);
154 		}
155 
wordCount() const156 		uint32_t wordCount() const
157 		{
158 			return *iter >> spv::WordCountShift;
159 		}
160 
word(uint32_t n) const161 		uint32_t word(uint32_t n) const
162 		{
163 			ASSERT(n < wordCount());
164 			return iter[n];
165 		}
166 
wordPointer(uint32_t n) const167 		uint32_t const *wordPointer(uint32_t n) const
168 		{
169 			ASSERT(n < wordCount());
170 			return &iter[n];
171 		}
172 
string(uint32_t n) const173 		const char *string(uint32_t n) const
174 		{
175 			return reinterpret_cast<const char *>(wordPointer(n));
176 		}
177 
operator ==(InsnIterator const & other) const178 		bool operator==(InsnIterator const &other) const
179 		{
180 			return iter == other.iter;
181 		}
182 
operator !=(InsnIterator const & other) const183 		bool operator!=(InsnIterator const &other) const
184 		{
185 			return iter != other.iter;
186 		}
187 
operator *() const188 		InsnIterator operator*() const
189 		{
190 			return *this;
191 		}
192 
operator ++()193 		InsnIterator &operator++()
194 		{
195 			iter += wordCount();
196 			return *this;
197 		}
198 
operator ++(int)199 		InsnIterator const operator++(int)
200 		{
201 			InsnIterator ret{ *this };
202 			iter += wordCount();
203 			return ret;
204 		}
205 
206 		InsnIterator(InsnIterator const &other) = default;
207 
208 		InsnIterator() = default;
209 
InsnIterator(InsnStore::const_iterator iter)210 		explicit InsnIterator(InsnStore::const_iterator iter)
211 		    : iter{ iter }
212 		{
213 		}
214 	};
215 
216 	/* range-based-for interface */
begin() const217 	InsnIterator begin() const
218 	{
219 		return InsnIterator{ insns.cbegin() + 5 };
220 	}
221 
end() const222 	InsnIterator end() const
223 	{
224 		return InsnIterator{ insns.cend() };
225 	}
226 
227 	class Type
228 	{
229 	public:
230 		using ID = SpirvID<Type>;
231 
opcode() const232 		spv::Op opcode() const { return definition.opcode(); }
233 
234 		InsnIterator definition;
235 		spv::StorageClass storageClass = static_cast<spv::StorageClass>(-1);
236 		uint32_t sizeInComponents = 0;
237 		bool isBuiltInBlock = false;
238 
239 		// Inner element type for pointers, arrays, vectors and matrices.
240 		ID element;
241 	};
242 
243 	class Object
244 	{
245 	public:
246 		using ID = SpirvID<Object>;
247 
opcode() const248 		spv::Op opcode() const { return definition.opcode(); }
249 
250 		InsnIterator definition;
251 		Type::ID type;
252 		std::unique_ptr<uint32_t[]> constantValue = nullptr;
253 
254 		enum class Kind
255 		{
256 			// Invalid default kind.
257 			// If we get left with an object in this state, the module was
258 			// broken.
259 			Unknown,
260 
261 			// TODO: Better document this kind.
262 			// A shader interface variable pointer.
263 			// Pointer with uniform address across all lanes.
264 			// Pointer held by SpirvRoutine::pointers
265 			InterfaceVariable,
266 
267 			// Constant value held by Object::constantValue.
268 			Constant,
269 
270 			// Value held by SpirvRoutine::intermediates.
271 			Intermediate,
272 
273 			// Pointer held by SpirvRoutine::pointers
274 			Pointer,
275 
276 			// A pointer to a vk::DescriptorSet*.
277 			// Pointer held by SpirvRoutine::pointers.
278 			DescriptorSet,
279 		};
280 
281 		Kind kind = Kind::Unknown;
282 	};
283 
284 	// Block is an interval of SPIR-V instructions, starting with the
285 	// opening OpLabel, and ending with a termination instruction.
286 	class Block
287 	{
288 	public:
289 		using ID = SpirvID<Block>;
290 		using Set = std::unordered_set<ID>;
291 
292 		// Edge represents the graph edge between two blocks.
293 		struct Edge
294 		{
295 			ID from;
296 			ID to;
297 
operator ==sw::SpirvShader::Block::Edge298 			bool operator==(const Edge &other) const { return from == other.from && to == other.to; }
299 
300 			struct Hash
301 			{
operator ()sw::SpirvShader::Block::Edge::Hash302 				std::size_t operator()(const Edge &edge) const noexcept
303 				{
304 					return std::hash<uint32_t>()(edge.from.value() * 31 + edge.to.value());
305 				}
306 			};
307 		};
308 
309 		Block() = default;
310 		Block(const Block &other) = default;
311 		explicit Block(InsnIterator begin, InsnIterator end);
312 
313 		/* range-based-for interface */
begin() const314 		inline InsnIterator begin() const { return begin_; }
end() const315 		inline InsnIterator end() const { return end_; }
316 
317 		enum Kind
318 		{
319 			Simple,                         // OpBranch or other simple terminator.
320 			StructuredBranchConditional,    // OpSelectionMerge + OpBranchConditional
321 			UnstructuredBranchConditional,  // OpBranchConditional
322 			StructuredSwitch,               // OpSelectionMerge + OpSwitch
323 			UnstructuredSwitch,             // OpSwitch
324 			Loop,                           // OpLoopMerge + [OpBranchConditional | OpBranch]
325 		};
326 
327 		Kind kind = Simple;
328 		InsnIterator mergeInstruction;   // Structured control flow merge instruction.
329 		InsnIterator branchInstruction;  // Branch instruction.
330 		ID mergeBlock;                   // Structured flow merge block.
331 		ID continueTarget;               // Loop continue block.
332 		Set ins;                         // Blocks that branch into this block.
333 		Set outs;                        // Blocks that this block branches to.
334 		bool isLoopMerge = false;
335 
336 	private:
337 		InsnIterator begin_;
338 		InsnIterator end_;
339 	};
340 
341 	class Function
342 	{
343 	public:
344 		using ID = SpirvID<Function>;
345 
346 		// Walks all reachable the blocks starting from id adding them to
347 		// reachable.
348 		void TraverseReachableBlocks(Block::ID id, Block::Set &reachable) const;
349 
350 		// AssignBlockFields() performs the following for all reachable blocks:
351 		// * Assigns Block::ins with the identifiers of all blocks that contain
352 		//   this block in their Block::outs.
353 		// * Sets Block::isLoopMerge to true if the block is the merge of a
354 		//   another loop block.
355 		void AssignBlockFields();
356 
357 		// ForeachBlockDependency calls f with each dependency of the given
358 		// block. A dependency is an incoming block that is not a loop-back
359 		// edge.
360 		void ForeachBlockDependency(Block::ID blockId, std::function<void(Block::ID)> f) const;
361 
362 		// ExistsPath returns true if there's a direct or indirect flow from
363 		// the 'from' block to the 'to' block that does not pass through
364 		// notPassingThrough.
365 		bool ExistsPath(Block::ID from, Block::ID to, Block::ID notPassingThrough) const;
366 
getBlock(Block::ID id) const367 		Block const &getBlock(Block::ID id) const
368 		{
369 			auto it = blocks.find(id);
370 			ASSERT_MSG(it != blocks.end(), "Unknown block %d", id.value());
371 			return it->second;
372 		}
373 
374 		Block::ID entry;          // function entry point block.
375 		HandleMap<Block> blocks;  // blocks belonging to this function.
376 		Type::ID type;            // type of the function.
377 		Type::ID result;          // return type.
378 	};
379 
380 	using String = std::string;
381 	using StringID = SpirvID<std::string>;
382 
383 	class Extension
384 	{
385 	public:
386 		using ID = SpirvID<Extension>;
387 
388 		enum Name
389 		{
390 			Unknown,
391 			GLSLstd450,
392 			OpenCLDebugInfo100
393 		};
394 
395 		Name name;
396 	};
397 
398 	struct TypeOrObject
399 	{};  // Dummy struct to represent a Type or Object.
400 
401 	// TypeOrObjectID is an identifier that represents a Type or an Object,
402 	// and supports implicit casting to and from Type::ID or Object::ID.
403 	class TypeOrObjectID : public SpirvID<TypeOrObject>
404 	{
405 	public:
406 		using Hash = std::hash<SpirvID<TypeOrObject>>;
407 
TypeOrObjectID(uint32_t id)408 		inline TypeOrObjectID(uint32_t id)
409 		    : SpirvID(id)
410 		{}
TypeOrObjectID(Type::ID id)411 		inline TypeOrObjectID(Type::ID id)
412 		    : SpirvID(id.value())
413 		{}
TypeOrObjectID(Object::ID id)414 		inline TypeOrObjectID(Object::ID id)
415 		    : SpirvID(id.value())
416 		{}
operator Type::ID() const417 		inline operator Type::ID() const { return Type::ID(value()); }
operator Object::ID() const418 		inline operator Object::ID() const { return Object::ID(value()); }
419 	};
420 
421 	// OpImageSample variants
422 	enum Variant
423 	{
424 		None,  // No Dref or Proj. Also used by OpImageFetch and OpImageQueryLod.
425 		Dref,
426 		Proj,
427 		ProjDref,
428 		VARIANT_LAST = ProjDref
429 	};
430 
431 	// Compact representation of image instruction parameters that is passed to the
432 	// trampoline function for retrieving/generating the corresponding sampling routine.
433 	struct ImageInstruction
434 	{
ImageInstructionsw::SpirvShader::ImageInstruction435 		ImageInstruction(Variant variant, SamplerMethod samplerMethod)
436 		    : parameters(0)
437 		{
438 			this->variant = variant;
439 			this->samplerMethod = samplerMethod;
440 		}
441 
442 		// Unmarshal from raw 32-bit data
ImageInstructionsw::SpirvShader::ImageInstruction443 		ImageInstruction(uint32_t parameters)
444 		    : parameters(parameters)
445 		{}
446 
getSamplerFunctionsw::SpirvShader::ImageInstruction447 		SamplerFunction getSamplerFunction() const
448 		{
449 			return { static_cast<SamplerMethod>(samplerMethod), offset != 0, sample != 0 };
450 		}
451 
isDrefsw::SpirvShader::ImageInstruction452 		bool isDref() const
453 		{
454 			return (variant == Dref) || (variant == ProjDref);
455 		}
456 
isProjsw::SpirvShader::ImageInstruction457 		bool isProj() const
458 		{
459 			return (variant == Proj) || (variant == ProjDref);
460 		}
461 
462 		union
463 		{
464 			struct
465 			{
466 				uint32_t variant : BITS(VARIANT_LAST);
467 				uint32_t samplerMethod : BITS(SAMPLER_METHOD_LAST);
468 				uint32_t gatherComponent : 2;
469 
470 				// Parameters are passed to the sampling routine in this order:
471 				uint32_t coordinates : 3;  // 1-4 (does not contain projection component)
472 				                           //	uint32_t dref : 1;              // Indicated by Variant::ProjDref|Dref
473 				                           //	uint32_t lodOrBias : 1;         // Indicated by SamplerMethod::Lod|Bias|Fetch
474 				uint32_t grad : 2;         // 0-3 components (for each of dx / dy)
475 				uint32_t offset : 2;       // 0-3 components
476 				uint32_t sample : 1;       // 0-1 scalar integer
477 			};
478 
479 			uint32_t parameters;
480 		};
481 	};
482 
483 	static_assert(sizeof(ImageInstruction) == sizeof(uint32_t), "ImageInstruction must be 32-bit");
484 
485 	// This method is for retrieving an ID that uniquely identifies the
486 	// shader entry point represented by this object.
getSerialID() const487 	uint64_t getSerialID() const
488 	{
489 		return ((uint64_t)entryPoint.value() << 32) | codeSerialID;
490 	}
491 
492 	SpirvShader(uint32_t codeSerialID,
493 	            VkShaderStageFlagBits stage,
494 	            const char *entryPointName,
495 	            InsnStore const &insns,
496 	            const vk::RenderPass *renderPass,
497 	            uint32_t subpassIndex,
498 	            bool robustBufferAccess,
499 	            const std::shared_ptr<vk::dbg::Context> &dbgctx);
500 
501 	~SpirvShader();
502 
503 	struct Modes
504 	{
505 		bool EarlyFragmentTests : 1;
506 		bool DepthReplacing : 1;
507 		bool DepthGreater : 1;
508 		bool DepthLess : 1;
509 		bool DepthUnchanged : 1;
510 		bool ContainsKill : 1;
511 		bool ContainsControlBarriers : 1;
512 		bool NeedsCentroid : 1;
513 
514 		// Compute workgroup dimensions
515 		int WorkgroupSizeX = 1, WorkgroupSizeY = 1, WorkgroupSizeZ = 1;
516 	};
517 
getModes() const518 	Modes const &getModes() const
519 	{
520 		return modes;
521 	}
522 
523 	struct Capabilities
524 	{
525 		bool Matrix : 1;
526 		bool Shader : 1;
527 		bool ClipDistance : 1;
528 		bool CullDistance : 1;
529 		bool InputAttachment : 1;
530 		bool Sampled1D : 1;
531 		bool Image1D : 1;
532 		bool ImageCubeArray : 1;
533 		bool SampledBuffer : 1;
534 		bool SampledCubeArray : 1;
535 		bool ImageBuffer : 1;
536 		bool StorageImageExtendedFormats : 1;
537 		bool ImageQuery : 1;
538 		bool DerivativeControl : 1;
539 		bool GroupNonUniform : 1;
540 		bool GroupNonUniformVote : 1;
541 		bool GroupNonUniformBallot : 1;
542 		bool GroupNonUniformShuffle : 1;
543 		bool GroupNonUniformShuffleRelative : 1;
544 		bool GroupNonUniformArithmetic : 1;
545 		bool DeviceGroup : 1;
546 		bool MultiView : 1;
547 		bool StencilExportEXT : 1;
548 	};
549 
getUsedCapabilities() const550 	Capabilities const &getUsedCapabilities() const
551 	{
552 		return capabilities;
553 	}
554 
555 	// getNumOutputClipDistances() returns the number of ClipDistances
556 	// outputted by this shader.
getNumOutputClipDistances() const557 	unsigned int getNumOutputClipDistances() const
558 	{
559 		if(getUsedCapabilities().ClipDistance)
560 		{
561 			auto it = outputBuiltins.find(spv::BuiltInClipDistance);
562 			if(it != outputBuiltins.end())
563 			{
564 				return it->second.SizeInComponents;
565 			}
566 		}
567 		return 0;
568 	}
569 
570 	// getNumOutputCullDistances() returns the number of CullDistances
571 	// outputted by this shader.
getNumOutputCullDistances() const572 	unsigned int getNumOutputCullDistances() const
573 	{
574 		if(getUsedCapabilities().CullDistance)
575 		{
576 			auto it = outputBuiltins.find(spv::BuiltInCullDistance);
577 			if(it != outputBuiltins.end())
578 			{
579 				return it->second.SizeInComponents;
580 			}
581 		}
582 		return 0;
583 	}
584 
585 	enum AttribType : unsigned char
586 	{
587 		ATTRIBTYPE_FLOAT,
588 		ATTRIBTYPE_INT,
589 		ATTRIBTYPE_UINT,
590 		ATTRIBTYPE_UNUSED,
591 
592 		ATTRIBTYPE_LAST = ATTRIBTYPE_UINT
593 	};
594 
hasBuiltinInput(spv::BuiltIn b) const595 	bool hasBuiltinInput(spv::BuiltIn b) const
596 	{
597 		return inputBuiltins.find(b) != inputBuiltins.end();
598 	}
599 
hasBuiltinOutput(spv::BuiltIn b) const600 	bool hasBuiltinOutput(spv::BuiltIn b) const
601 	{
602 		return outputBuiltins.find(b) != outputBuiltins.end();
603 	}
604 
605 	struct Decorations
606 	{
607 		int32_t Location = -1;
608 		int32_t Component = 0;
609 		spv::BuiltIn BuiltIn = static_cast<spv::BuiltIn>(-1);
610 		int32_t Offset = -1;
611 		int32_t ArrayStride = -1;
612 		int32_t MatrixStride = 1;
613 
614 		bool HasLocation : 1;
615 		bool HasComponent : 1;
616 		bool HasBuiltIn : 1;
617 		bool HasOffset : 1;
618 		bool HasArrayStride : 1;
619 		bool HasMatrixStride : 1;
620 		bool HasRowMajor : 1;  // whether RowMajor bit is valid.
621 
622 		bool Flat : 1;
623 		bool Centroid : 1;
624 		bool NoPerspective : 1;
625 		bool Block : 1;
626 		bool BufferBlock : 1;
627 		bool RelaxedPrecision : 1;
628 		bool RowMajor : 1;      // RowMajor if true; ColMajor if false
629 		bool InsideMatrix : 1;  // pseudo-decoration for whether we're inside a matrix.
630 
Decorationssw::SpirvShader::Decorations631 		Decorations()
632 		    : Location{ -1 }
633 		    , Component{ 0 }
634 		    , BuiltIn{ static_cast<spv::BuiltIn>(-1) }
635 		    , Offset{ -1 }
636 		    , ArrayStride{ -1 }
637 		    , MatrixStride{ -1 }
638 		    , HasLocation{ false }
639 		    , HasComponent{ false }
640 		    , HasBuiltIn{ false }
641 		    , HasOffset{ false }
642 		    , HasArrayStride{ false }
643 		    , HasMatrixStride{ false }
644 		    , HasRowMajor{ false }
645 		    , Flat{ false }
646 		    , Centroid{ false }
647 		    , NoPerspective{ false }
648 		    , Block{ false }
649 		    , BufferBlock{ false }
650 		    , RelaxedPrecision{ false }
651 		    , RowMajor{ false }
652 		    , InsideMatrix{ false }
653 		{
654 		}
655 
656 		Decorations(Decorations const &) = default;
657 
658 		void Apply(Decorations const &src);
659 
660 		void Apply(spv::Decoration decoration, uint32_t arg);
661 	};
662 
663 	std::unordered_map<TypeOrObjectID, Decorations, TypeOrObjectID::Hash> decorations;
664 	std::unordered_map<Type::ID, std::vector<Decorations>> memberDecorations;
665 
666 	struct DescriptorDecorations
667 	{
668 		int32_t DescriptorSet = -1;
669 		int32_t Binding = -1;
670 		int32_t InputAttachmentIndex = -1;
671 
672 		void Apply(DescriptorDecorations const &src);
673 	};
674 
675 	std::unordered_map<Object::ID, DescriptorDecorations> descriptorDecorations;
676 	std::vector<VkFormat> inputAttachmentFormats;
677 
678 	struct InterfaceComponent
679 	{
680 		AttribType Type;
681 
682 		union
683 		{
684 			struct
685 			{
686 				bool Flat : 1;
687 				bool Centroid : 1;
688 				bool NoPerspective : 1;
689 			};
690 
691 			uint8_t DecorationBits;
692 		};
693 
InterfaceComponentsw::SpirvShader::InterfaceComponent694 		InterfaceComponent()
695 		    : Type{ ATTRIBTYPE_UNUSED }
696 		    , DecorationBits{ 0 }
697 		{
698 		}
699 	};
700 
701 	struct BuiltinMapping
702 	{
703 		Object::ID Id;
704 		uint32_t FirstComponent;
705 		uint32_t SizeInComponents;
706 	};
707 
708 	struct WorkgroupMemory
709 	{
710 		// allocates a new variable of size bytes with the given identifier.
allocatesw::SpirvShader::WorkgroupMemory711 		inline void allocate(Object::ID id, uint32_t size)
712 		{
713 			uint32_t offset = totalSize;
714 			auto it = offsets.emplace(id, offset);
715 			ASSERT_MSG(it.second, "WorkgroupMemory already has an allocation for object %d", int(id.value()));
716 			totalSize += size;
717 		}
718 		// returns the byte offset of the variable with the given identifier.
offsetOfsw::SpirvShader::WorkgroupMemory719 		inline uint32_t offsetOf(Object::ID id) const
720 		{
721 			auto it = offsets.find(id);
722 			ASSERT_MSG(it != offsets.end(), "WorkgroupMemory has no allocation for object %d", int(id.value()));
723 			return it->second;
724 		}
725 		// returns the total allocated size in bytes.
sizesw::SpirvShader::WorkgroupMemory726 		inline uint32_t size() const { return totalSize; }
727 
728 	private:
729 		uint32_t totalSize = 0;                            // in bytes
730 		std::unordered_map<Object::ID, uint32_t> offsets;  // in bytes
731 	};
732 
733 	std::vector<InterfaceComponent> inputs;
734 	std::vector<InterfaceComponent> outputs;
735 
736 	void emitProlog(SpirvRoutine *routine) const;
737 	void emit(SpirvRoutine *routine, RValue<SIMD::Int> const &activeLaneMask, RValue<SIMD::Int> const &storesAndAtomicsMask, const vk::DescriptorSet::Bindings &descriptorSets) const;
738 	void emitEpilog(SpirvRoutine *routine) const;
739 
740 	using BuiltInHash = std::hash<std::underlying_type<spv::BuiltIn>::type>;
741 	std::unordered_map<spv::BuiltIn, BuiltinMapping, BuiltInHash> inputBuiltins;
742 	std::unordered_map<spv::BuiltIn, BuiltinMapping, BuiltInHash> outputBuiltins;
743 	WorkgroupMemory workgroupMemory;
744 
745 private:
746 	const uint32_t codeSerialID;
747 	Modes modes = {};
748 	Capabilities capabilities = {};
749 	HandleMap<Type> types;
750 	HandleMap<Object> defs;
751 	HandleMap<Function> functions;
752 	std::unordered_map<StringID, String> strings;
753 	HandleMap<Extension> extensionsByID;
754 	std::unordered_set<Extension::Name> extensionsImported;
755 	Function::ID entryPoint;
756 
757 	const bool robustBufferAccess = true;
758 	spv::ExecutionModel executionModel = spv::ExecutionModelMax;  // Invalid prior to OpEntryPoint parsing.
759 
760 	// DeclareType creates a Type for the given OpTypeX instruction, storing
761 	// it into the types map. It is called from the analysis pass (constructor).
762 	void DeclareType(InsnIterator insn);
763 
764 	void ProcessExecutionMode(InsnIterator it);
765 
766 	uint32_t ComputeTypeSize(InsnIterator insn);
767 	void ApplyDecorationsForId(Decorations *d, TypeOrObjectID id) const;
768 	void ApplyDecorationsForIdMember(Decorations *d, Type::ID id, uint32_t member) const;
769 	void ApplyDecorationsForAccessChain(Decorations *d, DescriptorDecorations *dd, Object::ID baseId, uint32_t numIndexes, uint32_t const *indexIds) const;
770 
771 	// Creates an Object for the instruction's result in 'defs'.
772 	void DefineResult(const InsnIterator &insn);
773 
774 	// Processes the OpenCL.Debug.100 instruction for the initial definition
775 	// pass of the SPIR-V.
776 	void DefineOpenCLDebugInfo100(const InsnIterator &insn);
777 
778 	// Returns true if data in the given storage class is word-interleaved
779 	// by each SIMD vector lane, otherwise data is stored linerally.
780 	//
781 	// Each lane addresses a single word, picked by a base pointer and an
782 	// integer offset.
783 	//
784 	// A word is currently 32 bits (single float, int32_t, uint32_t).
785 	// A lane is a single element of a SIMD vector register.
786 	//
787 	// Storage interleaved by lane - (IsStorageInterleavedByLane() == true):
788 	// ---------------------------------------------------------------------
789 	//
790 	// Address = PtrBase + sizeof(Word) * (SIMD::Width * LaneOffset + LaneIndex)
791 	//
792 	// Assuming SIMD::Width == 4:
793 	//
794 	//                   Lane[0]  |  Lane[1]  |  Lane[2]  |  Lane[3]
795 	//                 ===========+===========+===========+==========
796 	//  LaneOffset=0: |  Word[0]  |  Word[1]  |  Word[2]  |  Word[3]
797 	// ---------------+-----------+-----------+-----------+----------
798 	//  LaneOffset=1: |  Word[4]  |  Word[5]  |  Word[6]  |  Word[7]
799 	// ---------------+-----------+-----------+-----------+----------
800 	//  LaneOffset=2: |  Word[8]  |  Word[9]  |  Word[a]  |  Word[b]
801 	// ---------------+-----------+-----------+-----------+----------
802 	//  LaneOffset=3: |  Word[c]  |  Word[d]  |  Word[e]  |  Word[f]
803 	//
804 	//
805 	// Linear storage - (IsStorageInterleavedByLane() == false):
806 	// ---------------------------------------------------------
807 	//
808 	// Address = PtrBase + sizeof(Word) * LaneOffset
809 	//
810 	//                   Lane[0]  |  Lane[1]  |  Lane[2]  |  Lane[3]
811 	//                 ===========+===========+===========+==========
812 	//  LaneOffset=0: |  Word[0]  |  Word[0]  |  Word[0]  |  Word[0]
813 	// ---------------+-----------+-----------+-----------+----------
814 	//  LaneOffset=1: |  Word[1]  |  Word[1]  |  Word[1]  |  Word[1]
815 	// ---------------+-----------+-----------+-----------+----------
816 	//  LaneOffset=2: |  Word[2]  |  Word[2]  |  Word[2]  |  Word[2]
817 	// ---------------+-----------+-----------+-----------+----------
818 	//  LaneOffset=3: |  Word[3]  |  Word[3]  |  Word[3]  |  Word[3]
819 	//
820 	static bool IsStorageInterleavedByLane(spv::StorageClass storageClass);
821 	static bool IsExplicitLayout(spv::StorageClass storageClass);
822 
823 	static sw::SIMD::Pointer InterleaveByLane(sw::SIMD::Pointer p);
824 
825 	// Output storage buffers and images should not be affected by helper invocations
826 	static bool StoresInHelperInvocation(spv::StorageClass storageClass);
827 
828 	using InterfaceVisitor = std::function<void(Decorations const, AttribType)>;
829 
830 	void VisitInterface(Object::ID id, const InterfaceVisitor &v) const;
831 
832 	int VisitInterfaceInner(Type::ID id, Decorations d, const InterfaceVisitor &v) const;
833 
834 	// MemoryElement describes a scalar element within a structure, and is
835 	// used by the callback function of VisitMemoryObject().
836 	struct MemoryElement
837 	{
838 		uint32_t index;    // index of the scalar element
839 		uint32_t offset;   // offset (in bytes) from the base of the object
840 		const Type &type;  // element type
841 	};
842 
843 	using MemoryVisitor = std::function<void(const MemoryElement &)>;
844 
845 	// VisitMemoryObject() walks a type tree in an explicitly laid out
846 	// storage class, calling the MemoryVisitor for each scalar element
847 	// within the
848 	void VisitMemoryObject(Object::ID id, const MemoryVisitor &v) const;
849 
850 	// VisitMemoryObjectInner() is internally called by VisitMemoryObject()
851 	void VisitMemoryObjectInner(Type::ID id, Decorations d, uint32_t &index, uint32_t offset, const MemoryVisitor &v) const;
852 
853 	Object &CreateConstant(InsnIterator it);
854 
855 	void ProcessInterfaceVariable(Object &object);
856 
857 	// EmitState holds control-flow state for the emit() pass.
858 	class EmitState
859 	{
860 	public:
EmitState(SpirvRoutine * routine,Function::ID function,RValue<SIMD::Int> activeLaneMask,RValue<SIMD::Int> storesAndAtomicsMask,const vk::DescriptorSet::Bindings & descriptorSets,bool robustBufferAccess,spv::ExecutionModel executionModel)861 		EmitState(SpirvRoutine *routine,
862 		          Function::ID function,
863 		          RValue<SIMD::Int> activeLaneMask,
864 		          RValue<SIMD::Int> storesAndAtomicsMask,
865 		          const vk::DescriptorSet::Bindings &descriptorSets,
866 		          bool robustBufferAccess,
867 		          spv::ExecutionModel executionModel)
868 		    : routine(routine)
869 		    , function(function)
870 		    , activeLaneMaskValue(activeLaneMask.value)
871 		    , storesAndAtomicsMaskValue(storesAndAtomicsMask.value)
872 		    , descriptorSets(descriptorSets)
873 		    , robustBufferAccess(robustBufferAccess)
874 		    , executionModel(executionModel)
875 		{
876 			ASSERT(executionModelToStage(executionModel) != VkShaderStageFlagBits(0));  // Must parse OpEntryPoint before emitting.
877 		}
878 
activeLaneMask() const879 		RValue<SIMD::Int> activeLaneMask() const
880 		{
881 			ASSERT(activeLaneMaskValue != nullptr);
882 			return RValue<SIMD::Int>(activeLaneMaskValue);
883 		}
884 
storesAndAtomicsMask() const885 		RValue<SIMD::Int> storesAndAtomicsMask() const
886 		{
887 			ASSERT(storesAndAtomicsMaskValue != nullptr);
888 			return RValue<SIMD::Int>(storesAndAtomicsMaskValue);
889 		}
890 
891 		// Add a new active lane mask edge from the current block to out.
892 		// The edge mask value will be (mask AND activeLaneMaskValue).
893 		// If multiple active lane masks are added for the same edge, then
894 		// they will be ORed together.
895 		void addOutputActiveLaneMaskEdge(Block::ID out, RValue<SIMD::Int> mask);
896 
897 		// Add a new active lane mask for the edge from -> to.
898 		// If multiple active lane masks are added for the same edge, then
899 		// they will be ORed together.
900 		void addActiveLaneMaskEdge(Block::ID from, Block::ID to, RValue<SIMD::Int> mask);
901 
902 		SpirvRoutine *routine = nullptr;                 // The current routine being built.
903 		Function::ID function;                           // The current function being built.
904 		Block::ID block;                                 // The current block being built.
905 		rr::Value *activeLaneMaskValue = nullptr;        // The current active lane mask.
906 		rr::Value *storesAndAtomicsMaskValue = nullptr;  // The current atomics mask.
907 		Block::Set visited;                              // Blocks already built.
908 		std::unordered_map<Block::Edge, RValue<SIMD::Int>, Block::Edge::Hash> edgeActiveLaneMasks;
909 		std::deque<Block::ID> *pending;
910 
911 		const vk::DescriptorSet::Bindings &descriptorSets;
912 
913 		OutOfBoundsBehavior getOutOfBoundsBehavior(spv::StorageClass storageClass) const;
914 
createIntermediate(Object::ID id,uint32_t size)915 		Intermediate &createIntermediate(Object::ID id, uint32_t size)
916 		{
917 			auto it = intermediates.emplace(std::piecewise_construct,
918 			                                std::forward_as_tuple(id),
919 			                                std::forward_as_tuple(size));
920 			ASSERT_MSG(it.second, "Intermediate %d created twice", id.value());
921 			return it.first->second;
922 		}
923 
getIntermediate(Object::ID id) const924 		Intermediate const &getIntermediate(Object::ID id) const
925 		{
926 			auto it = intermediates.find(id);
927 			ASSERT_MSG(it != intermediates.end(), "Unknown intermediate %d", id.value());
928 			return it->second;
929 		}
930 
createPointer(Object::ID id,SIMD::Pointer ptr)931 		void createPointer(Object::ID id, SIMD::Pointer ptr)
932 		{
933 			bool added = pointers.emplace(id, ptr).second;
934 			ASSERT_MSG(added, "Pointer %d created twice", id.value());
935 		}
936 
getPointer(Object::ID id) const937 		SIMD::Pointer const &getPointer(Object::ID id) const
938 		{
939 			auto it = pointers.find(id);
940 			ASSERT_MSG(it != pointers.end(), "Unknown pointer %d", id.value());
941 			return it->second;
942 		}
943 
944 	private:
945 		std::unordered_map<Object::ID, Intermediate> intermediates;
946 		std::unordered_map<Object::ID, SIMD::Pointer> pointers;
947 
948 		const bool robustBufferAccess = true;  // Emit robustBufferAccess safe code.
949 		const spv::ExecutionModel executionModel = spv::ExecutionModelMax;
950 	};
951 
952 	// EmitResult is an enumerator of result values from the Emit functions.
953 	enum class EmitResult
954 	{
955 		Continue,    // No termination instructions.
956 		Terminator,  // Reached a termination instruction.
957 	};
958 
959 	// Generic wrapper over either per-lane intermediate value, or a constant.
960 	// Constants are transparently widened to per-lane values in operator[].
961 	// This is appropriate in most cases -- if we're not going to do something
962 	// significantly different based on whether the value is uniform across lanes.
963 	class GenericValue
964 	{
965 		SpirvShader::Object const &obj;
966 		Intermediate const *intermediate;
967 
968 	public:
969 		GenericValue(SpirvShader const *shader, EmitState const *state, SpirvShader::Object::ID objId);
970 
Float(uint32_t i) const971 		RValue<SIMD::Float> Float(uint32_t i) const
972 		{
973 			if(intermediate)
974 			{
975 				return intermediate->Float(i);
976 			}
977 
978 			// Constructing a constant SIMD::Float is not guaranteed to preserve the data's exact
979 			// bit pattern, but SPIR-V provides 32-bit words representing "the bit pattern for the constant".
980 			// Thus we must first construct an integer constant, and bitcast to float.
981 			ASSERT(obj.kind == SpirvShader::Object::Kind::Constant);
982 			auto constantValue = reinterpret_cast<uint32_t *>(obj.constantValue.get());
983 			return As<SIMD::Float>(SIMD::UInt(constantValue[i]));
984 		}
985 
Int(uint32_t i) const986 		RValue<SIMD::Int> Int(uint32_t i) const
987 		{
988 			if(intermediate)
989 			{
990 				return intermediate->Int(i);
991 			}
992 			ASSERT(obj.kind == SpirvShader::Object::Kind::Constant);
993 			auto constantValue = reinterpret_cast<int *>(obj.constantValue.get());
994 			return SIMD::Int(constantValue[i]);
995 		}
996 
UInt(uint32_t i) const997 		RValue<SIMD::UInt> UInt(uint32_t i) const
998 		{
999 			if(intermediate)
1000 			{
1001 				return intermediate->UInt(i);
1002 			}
1003 			ASSERT(obj.kind == SpirvShader::Object::Kind::Constant);
1004 			auto constantValue = reinterpret_cast<uint32_t *>(obj.constantValue.get());
1005 			return SIMD::UInt(constantValue[i]);
1006 		}
1007 
1008 		SpirvShader::Type::ID const type;
1009 	};
1010 
getType(Type::ID id) const1011 	Type const &getType(Type::ID id) const
1012 	{
1013 		auto it = types.find(id);
1014 		ASSERT_MSG(it != types.end(), "Unknown type %d", id.value());
1015 		return it->second;
1016 	}
1017 
getObject(Object::ID id) const1018 	Object const &getObject(Object::ID id) const
1019 	{
1020 		auto it = defs.find(id);
1021 		ASSERT_MSG(it != defs.end(), "Unknown object %d", id.value());
1022 		return it->second;
1023 	}
1024 
getFunction(Function::ID id) const1025 	Function const &getFunction(Function::ID id) const
1026 	{
1027 		auto it = functions.find(id);
1028 		ASSERT_MSG(it != functions.end(), "Unknown function %d", id.value());
1029 		return it->second;
1030 	}
1031 
getString(StringID id) const1032 	String const &getString(StringID id) const
1033 	{
1034 		auto it = strings.find(id);
1035 		ASSERT_MSG(it != strings.end(), "Unknown string %d", id.value());
1036 		return it->second;
1037 	}
1038 
getExtension(Extension::ID id) const1039 	Extension const &getExtension(Extension::ID id) const
1040 	{
1041 		auto it = extensionsByID.find(id);
1042 		ASSERT_MSG(it != extensionsByID.end(), "Unknown extension %d", id.value());
1043 		return it->second;
1044 	}
1045 
1046 	// Returns a SIMD::Pointer to the underlying data for the given pointer
1047 	// object.
1048 	// Handles objects of the following kinds:
1049 	//  • DescriptorSet
1050 	//  • DivergentPointer
1051 	//  • InterfaceVariable
1052 	//  • NonDivergentPointer
1053 	// Calling GetPointerToData with objects of any other kind will assert.
1054 	SIMD::Pointer GetPointerToData(Object::ID id, int arrayIndex, EmitState const *state) const;
1055 
1056 	SIMD::Pointer WalkExplicitLayoutAccessChain(Object::ID id, uint32_t numIndexes, uint32_t const *indexIds, EmitState const *state) const;
1057 	SIMD::Pointer WalkAccessChain(Object::ID id, uint32_t numIndexes, uint32_t const *indexIds, EmitState const *state) const;
1058 
1059 	// Returns the *component* offset in the literal for the given access chain.
1060 	uint32_t WalkLiteralAccessChain(Type::ID id, uint32_t numIndexes, uint32_t const *indexes) const;
1061 
1062 	// Lookup the active lane mask for the edge from -> to.
1063 	// If from is unreachable, then a mask of all zeros is returned.
1064 	// Asserts if from is reachable and the edge does not exist.
1065 	RValue<SIMD::Int> GetActiveLaneMaskEdge(EmitState *state, Block::ID from, Block::ID to) const;
1066 
1067 	// Updates the current active lane mask.
1068 	void SetActiveLaneMask(RValue<SIMD::Int> mask, EmitState *state) const;
1069 
1070 	// Emit all the unvisited blocks (except for ignore) in DFS order,
1071 	// starting with id.
1072 	void EmitBlocks(Block::ID id, EmitState *state, Block::ID ignore = 0) const;
1073 	void EmitNonLoop(EmitState *state) const;
1074 	void EmitLoop(EmitState *state) const;
1075 
1076 	void EmitInstructions(InsnIterator begin, InsnIterator end, EmitState *state) const;
1077 	EmitResult EmitInstruction(InsnIterator insn, EmitState *state) const;
1078 
1079 	// Emit pass instructions:
1080 	EmitResult EmitVariable(InsnIterator insn, EmitState *state) const;
1081 	EmitResult EmitLoad(InsnIterator insn, EmitState *state) const;
1082 	EmitResult EmitStore(InsnIterator insn, EmitState *state) const;
1083 	EmitResult EmitAccessChain(InsnIterator insn, EmitState *state) const;
1084 	EmitResult EmitCompositeConstruct(InsnIterator insn, EmitState *state) const;
1085 	EmitResult EmitCompositeInsert(InsnIterator insn, EmitState *state) const;
1086 	EmitResult EmitCompositeExtract(InsnIterator insn, EmitState *state) const;
1087 	EmitResult EmitVectorShuffle(InsnIterator insn, EmitState *state) const;
1088 	EmitResult EmitVectorTimesScalar(InsnIterator insn, EmitState *state) const;
1089 	EmitResult EmitMatrixTimesVector(InsnIterator insn, EmitState *state) const;
1090 	EmitResult EmitVectorTimesMatrix(InsnIterator insn, EmitState *state) const;
1091 	EmitResult EmitMatrixTimesMatrix(InsnIterator insn, EmitState *state) const;
1092 	EmitResult EmitOuterProduct(InsnIterator insn, EmitState *state) const;
1093 	EmitResult EmitTranspose(InsnIterator insn, EmitState *state) const;
1094 	EmitResult EmitVectorExtractDynamic(InsnIterator insn, EmitState *state) const;
1095 	EmitResult EmitVectorInsertDynamic(InsnIterator insn, EmitState *state) const;
1096 	EmitResult EmitUnaryOp(InsnIterator insn, EmitState *state) const;
1097 	EmitResult EmitBinaryOp(InsnIterator insn, EmitState *state) const;
1098 	EmitResult EmitDot(InsnIterator insn, EmitState *state) const;
1099 	EmitResult EmitSelect(InsnIterator insn, EmitState *state) const;
1100 	EmitResult EmitExtendedInstruction(InsnIterator insn, EmitState *state) const;
1101 	EmitResult EmitExtGLSLstd450(InsnIterator insn, EmitState *state) const;
1102 	EmitResult EmitOpenCLDebugInfo100(InsnIterator insn, EmitState *state) const;
1103 	EmitResult EmitLine(InsnIterator insn, EmitState *state) const;
1104 	EmitResult EmitAny(InsnIterator insn, EmitState *state) const;
1105 	EmitResult EmitAll(InsnIterator insn, EmitState *state) const;
1106 	EmitResult EmitBranch(InsnIterator insn, EmitState *state) const;
1107 	EmitResult EmitBranchConditional(InsnIterator insn, EmitState *state) const;
1108 	EmitResult EmitSwitch(InsnIterator insn, EmitState *state) const;
1109 	EmitResult EmitUnreachable(InsnIterator insn, EmitState *state) const;
1110 	EmitResult EmitReturn(InsnIterator insn, EmitState *state) const;
1111 	EmitResult EmitKill(InsnIterator insn, EmitState *state) const;
1112 	EmitResult EmitFunctionCall(InsnIterator insn, EmitState *state) const;
1113 	EmitResult EmitPhi(InsnIterator insn, EmitState *state) const;
1114 	EmitResult EmitImageSampleImplicitLod(Variant variant, InsnIterator insn, EmitState *state) const;
1115 	EmitResult EmitImageSampleExplicitLod(Variant variant, InsnIterator insn, EmitState *state) const;
1116 	EmitResult EmitImageGather(Variant variant, InsnIterator insn, EmitState *state) const;
1117 	EmitResult EmitImageFetch(InsnIterator insn, EmitState *state) const;
1118 	EmitResult EmitImageSample(ImageInstruction instruction, InsnIterator insn, EmitState *state) const;
1119 	EmitResult EmitImageQuerySizeLod(InsnIterator insn, EmitState *state) const;
1120 	EmitResult EmitImageQuerySize(InsnIterator insn, EmitState *state) const;
1121 	EmitResult EmitImageQueryLod(InsnIterator insn, EmitState *state) const;
1122 	EmitResult EmitImageQueryLevels(InsnIterator insn, EmitState *state) const;
1123 	EmitResult EmitImageQuerySamples(InsnIterator insn, EmitState *state) const;
1124 	EmitResult EmitImageRead(InsnIterator insn, EmitState *state) const;
1125 	EmitResult EmitImageWrite(InsnIterator insn, EmitState *state) const;
1126 	EmitResult EmitImageTexelPointer(InsnIterator insn, EmitState *state) const;
1127 	EmitResult EmitAtomicOp(InsnIterator insn, EmitState *state) const;
1128 	EmitResult EmitAtomicCompareExchange(InsnIterator insn, EmitState *state) const;
1129 	EmitResult EmitSampledImageCombineOrSplit(InsnIterator insn, EmitState *state) const;
1130 	EmitResult EmitCopyObject(InsnIterator insn, EmitState *state) const;
1131 	EmitResult EmitCopyMemory(InsnIterator insn, EmitState *state) const;
1132 	EmitResult EmitControlBarrier(InsnIterator insn, EmitState *state) const;
1133 	EmitResult EmitMemoryBarrier(InsnIterator insn, EmitState *state) const;
1134 	EmitResult EmitGroupNonUniform(InsnIterator insn, EmitState *state) const;
1135 	EmitResult EmitArrayLength(InsnIterator insn, EmitState *state) const;
1136 
1137 	void GetImageDimensions(EmitState const *state, Type const &resultTy, Object::ID imageId, Object::ID lodId, Intermediate &dst) const;
1138 	SIMD::Pointer GetTexelAddress(EmitState const *state, SIMD::Pointer base, GenericValue const &coordinate, Type const &imageType, Pointer<Byte> descriptor, int texelSize, Object::ID sampleId, bool useStencilAspect) const;
1139 	uint32_t GetConstScalarInt(Object::ID id) const;
1140 	void EvalSpecConstantOp(InsnIterator insn);
1141 	void EvalSpecConstantUnaryOp(InsnIterator insn);
1142 	void EvalSpecConstantBinaryOp(InsnIterator insn);
1143 
1144 	// LoadPhi loads the phi values from the alloca storage and places the
1145 	// load values into the intermediate with the phi's result id.
1146 	void LoadPhi(InsnIterator insn, EmitState *state) const;
1147 
1148 	// StorePhi updates the phi's alloca storage value using the incoming
1149 	// values from blocks that are both in the OpPhi instruction and in
1150 	// filter.
1151 	void StorePhi(Block::ID blockID, InsnIterator insn, EmitState *state, std::unordered_set<SpirvShader::Block::ID> const &filter) const;
1152 
1153 	// Emits a rr::Fence for the given MemorySemanticsMask.
1154 	void Fence(spv::MemorySemanticsMask semantics) const;
1155 
1156 	// Helper for calling rr::Yield with res cast to an rr::Int.
1157 	void Yield(YieldResult res) const;
1158 
1159 	// OpcodeName() returns the name of the opcode op.
1160 	// If NDEBUG is defined, then OpcodeName() will only return the numerical code.
1161 	static std::string OpcodeName(spv::Op op);
1162 	static std::memory_order MemoryOrder(spv::MemorySemanticsMask memorySemantics);
1163 
1164 	// IsStatement() returns true if the given opcode actually performs
1165 	// work (as opposed to declaring a type, defining a function start / end,
1166 	// etc).
1167 	static bool IsStatement(spv::Op op);
1168 
1169 	// Helper as we often need to take dot products as part of doing other things.
1170 	SIMD::Float Dot(unsigned numComponents, GenericValue const &x, GenericValue const &y) const;
1171 
1172 	// Splits x into a floating-point significand in the range [0.5, 1.0)
1173 	// and an integral exponent of two, such that:
1174 	//   x = significand * 2^exponent
1175 	// Returns the pair <significand, exponent>
1176 	std::pair<SIMD::Float, SIMD::Int> Frexp(RValue<SIMD::Float> val) const;
1177 
1178 	static ImageSampler *getImageSampler(uint32_t instruction, vk::SampledImageDescriptor const *imageDescriptor, const vk::Sampler *sampler);
1179 	static std::shared_ptr<rr::Routine> emitSamplerRoutine(ImageInstruction instruction, const Sampler &samplerState);
1180 
1181 	// TODO(b/129523279): Eliminate conversion and use vk::Sampler members directly.
1182 	static sw::FilterType convertFilterMode(const vk::Sampler *sampler);
1183 	static sw::MipmapType convertMipmapMode(const vk::Sampler *sampler);
1184 	static sw::AddressingMode convertAddressingMode(int coordinateIndex, const vk::Sampler *sampler, VkImageViewType imageViewType);
1185 
1186 	// Returns 0 when invalid.
1187 	static VkShaderStageFlagBits executionModelToStage(spv::ExecutionModel model);
1188 
1189 	// Debugger API functions. When ENABLE_VK_DEBUGGER is not defined, these
1190 	// are all no-ops.
1191 
1192 	// dbgInit() initializes the debugger code generation.
1193 	// All other dbgXXX() functions are no-op until this is called.
1194 	void dbgInit(const std::shared_ptr<vk::dbg::Context> &dbgctx);
1195 
1196 	// dbgTerm() terminates the debugger code generation.
1197 	void dbgTerm();
1198 
1199 	// dbgCreateFile() generates a synthetic file containing the disassembly
1200 	// of the SPIR-V shader. This is the file displayed in the debug
1201 	// session.
1202 	void dbgCreateFile();
1203 
1204 	// dbgBeginEmit() sets up the debugging state for the shader.
1205 	void dbgBeginEmit(EmitState *state) const;
1206 
1207 	// dbgEndEmit() tears down the debugging state for the shader.
1208 	void dbgEndEmit(EmitState *state) const;
1209 
1210 	// dbgBeginEmitInstruction() updates the current debugger location for
1211 	// the given instruction.
1212 	void dbgBeginEmitInstruction(InsnIterator insn, EmitState *state) const;
1213 
1214 	// dbgEndEmitInstruction() creates any new debugger variables for the
1215 	// instruction that just completed.
1216 	void dbgEndEmitInstruction(InsnIterator insn, EmitState *state) const;
1217 
1218 	// dbgExposeIntermediate() exposes the intermediate with the given ID to
1219 	// the debugger.
1220 	void dbgExposeIntermediate(Object::ID id, EmitState *state) const;
1221 
1222 	// dbgUpdateActiveLaneMask() updates the active lane masks to the
1223 	// debugger.
1224 	void dbgUpdateActiveLaneMask(RValue<SIMD::Int> mask, EmitState *state) const;
1225 
1226 	// dbgDeclareResult() associates resultId as the result of the given
1227 	// instruction.
1228 	void dbgDeclareResult(const InsnIterator &insn, Object::ID resultId) const;
1229 
1230 	// Impl holds forward declaration structs and pointers to state for the
1231 	// private implementations in the corresponding SpirvShaderXXX.cpp files.
1232 	// This allows access to the private members of the SpirvShader, without
1233 	// littering the header with implementation details.
1234 	struct Impl
1235 	{
1236 		struct Debugger;
1237 		struct Group;
1238 		Debugger *debugger = nullptr;
1239 	};
1240 	Impl impl;
1241 };
1242 
1243 class SpirvRoutine
1244 {
1245 public:
1246 	SpirvRoutine(vk::PipelineLayout const *pipelineLayout);
1247 
1248 	using Variable = Array<SIMD::Float>;
1249 
1250 	struct SamplerCache
1251 	{
1252 		Pointer<Byte> imageDescriptor = nullptr;
1253 		Pointer<Byte> sampler;
1254 		Pointer<Byte> function;
1255 	};
1256 
1257 	vk::PipelineLayout const *const pipelineLayout;
1258 
1259 	std::unordered_map<SpirvShader::Object::ID, Variable> variables;
1260 	std::unordered_map<SpirvShader::Object::ID, SamplerCache> samplerCache;
1261 	Variable inputs = Variable{ MAX_INTERFACE_COMPONENTS };
1262 	Variable outputs = Variable{ MAX_INTERFACE_COMPONENTS };
1263 
1264 	Pointer<Byte> workgroupMemory;
1265 	Pointer<Pointer<Byte>> descriptorSets;
1266 	Pointer<Int> descriptorDynamicOffsets;
1267 	Pointer<Byte> pushConstants;
1268 	Pointer<Byte> constants;
1269 	Int killMask = Int{ 0 };
1270 
1271 	// Shader invocation state.
1272 	// Not all of these variables are used for every type of shader, and some
1273 	// are only used when debugging. See b/146486064 for more information.
1274 	// Give careful consideration to the runtime performance loss before adding
1275 	// more state here.
1276 	SIMD::Int windowSpacePosition[2];
1277 	Int viewID;  // slice offset into input attachments for multiview, even if the shader doesn't use ViewIndex
1278 	Int instanceID;
1279 	SIMD::Int vertexIndex;
1280 	std::array<SIMD::Float, 4> fragCoord;
1281 	std::array<SIMD::Float, 4> pointCoord;
1282 	SIMD::Int helperInvocation;
1283 	Int4 numWorkgroups;
1284 	Int4 workgroupID;
1285 	Int4 workgroupSize;
1286 	Int subgroupsPerWorkgroup;
1287 	Int invocationsPerSubgroup;
1288 	Int subgroupIndex;
1289 	SIMD::Int localInvocationIndex;
1290 	std::array<SIMD::Int, 3> localInvocationID;
1291 	std::array<SIMD::Int, 3> globalInvocationID;
1292 
1293 	Pointer<Byte> dbgState;  // Pointer to a debugger state.
1294 
createVariable(SpirvShader::Object::ID id,uint32_t size)1295 	void createVariable(SpirvShader::Object::ID id, uint32_t size)
1296 	{
1297 		bool added = variables.emplace(id, Variable(size)).second;
1298 		ASSERT_MSG(added, "Variable %d created twice", id.value());
1299 	}
1300 
getVariable(SpirvShader::Object::ID id)1301 	Variable &getVariable(SpirvShader::Object::ID id)
1302 	{
1303 		auto it = variables.find(id);
1304 		ASSERT_MSG(it != variables.end(), "Unknown variables %d", id.value());
1305 		return it->second;
1306 	}
1307 
1308 	// setImmutableInputBuiltins() sets all the immutable input builtins,
1309 	// common for all shader types.
1310 	void setImmutableInputBuiltins(SpirvShader const *shader);
1311 
1312 	// setInputBuiltin() calls f() with the builtin and value if the shader
1313 	// uses the input builtin, otherwise the call is a no-op.
1314 	// F is a function with the signature:
1315 	// void(const SpirvShader::BuiltinMapping& builtin, Array<SIMD::Float>& value)
1316 	template<typename F>
setInputBuiltin(SpirvShader const * shader,spv::BuiltIn id,F && f)1317 	inline void setInputBuiltin(SpirvShader const *shader, spv::BuiltIn id, F &&f)
1318 	{
1319 		auto it = shader->inputBuiltins.find(id);
1320 		if(it != shader->inputBuiltins.end())
1321 		{
1322 			const auto &builtin = it->second;
1323 			f(builtin, getVariable(builtin.Id));
1324 		}
1325 	}
1326 
1327 private:
1328 	// The phis are only accessible to SpirvShader as they are only used and
1329 	// exist between calls to SpirvShader::emitProlog() and
1330 	// SpirvShader::emitEpilog().
1331 	friend class SpirvShader;
1332 
1333 	std::unordered_map<SpirvShader::Object::ID, Variable> phis;
1334 };
1335 
1336 }  // namespace sw
1337 
1338 #endif  // sw_SpirvShader_hpp
1339