Pass descriptor sets to SPIR-V compilation

The at draw time currently bound descriptors are passed down to the
SPIR-V code generation so that we can read the sampler parameters and
image view parameters.

An important exception is compute shaders, which are currently
compiled before the invoke calls.

Also still TODO is taking the parameters into account during routine
lookup in the cache.

This change also eliminates the now unused 'enableMask' from
PixelProgram and VertexProgram.

Bug b/129523279

Change-Id: I1ea75ec5a7b83783a1efacb238143a419afa5bda
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/28446
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Device/Context.hpp b/src/Device/Context.hpp
index 581871f..ba9837a 100644
--- a/src/Device/Context.hpp
+++ b/src/Device/Context.hpp
@@ -30,7 +30,7 @@
 	class DescriptorSet;
 	class ImageView;
 	class PipelineLayout;
-} // namespace vk
+}
 
 namespace sw
 {
diff --git a/src/Device/PixelProcessor.cpp b/src/Device/PixelProcessor.cpp
index df7f9e6..7fc41a2 100644
--- a/src/Device/PixelProcessor.cpp
+++ b/src/Device/PixelProcessor.cpp
@@ -349,7 +349,7 @@
 
 		if(!routine)
 		{
-			QuadRasterizer *generator = new PixelProgram(state, context->pipelineLayout, context->pixelShader);
+			QuadRasterizer *generator = new PixelProgram(state, context->pipelineLayout, context->pixelShader, context->descriptorSets);
 			generator->generate();
 			routine = (*generator)("PixelRoutine_%0.8X", state.shaderID);
 			delete generator;
diff --git a/src/Device/VertexProcessor.cpp b/src/Device/VertexProcessor.cpp
index 9805e40..e5d0859 100644
--- a/src/Device/VertexProcessor.cpp
+++ b/src/Device/VertexProcessor.cpp
@@ -142,7 +142,7 @@
 
 		if(!routine)   // Create one
 		{
-			VertexRoutine *generator = new VertexProgram(state, context->pipelineLayout, context->vertexShader);
+			VertexRoutine *generator = new VertexProgram(state, context->pipelineLayout, context->vertexShader, context->descriptorSets);
 			generator->generate();
 			routine = (*generator)("VertexRoutine_%0.8X", state.shaderID);
 			delete generator;
diff --git a/src/Pipeline/ComputeProgram.cpp b/src/Pipeline/ComputeProgram.cpp
index fbaa2ac..50445b7 100644
--- a/src/Pipeline/ComputeProgram.cpp
+++ b/src/Pipeline/ComputeProgram.cpp
@@ -24,11 +24,12 @@
 
 namespace sw
 {
-	ComputeProgram::ComputeProgram(SpirvShader const *shader, vk::PipelineLayout const *pipelineLayout)
+	ComputeProgram::ComputeProgram(SpirvShader const *shader, vk::PipelineLayout const *pipelineLayout, const vk::DescriptorSet::Bindings &descriptorSets)
 		: data(Arg<0>()),
 		  routine(pipelineLayout),
 		  shader(shader),
-		  pipelineLayout(pipelineLayout)
+		  pipelineLayout(pipelineLayout),
+		  descriptorSets(descriptorSets)
 	{
 	}
 
@@ -157,7 +158,7 @@
 			});
 
 			// Process numLanes of the workgroup.
-			shader->emit(&routine, activeLaneMask);
+			shader->emit(&routine, activeLaneMask, descriptorSets);
 		}
 	}
 
diff --git a/src/Pipeline/ComputeProgram.hpp b/src/Pipeline/ComputeProgram.hpp
index e8265bc0..ab50592 100644
--- a/src/Pipeline/ComputeProgram.hpp
+++ b/src/Pipeline/ComputeProgram.hpp
@@ -39,7 +39,7 @@
 	class ComputeProgram : public Function<Void(Pointer<Byte>)>
 	{
 	public:
-		ComputeProgram(SpirvShader const *spirvShader, vk::PipelineLayout const *pipelineLayout);
+		ComputeProgram(SpirvShader const *spirvShader, vk::PipelineLayout const *pipelineLayout, const vk::DescriptorSet::Bindings &descriptorSets);
 
 		virtual ~ComputeProgram();
 
@@ -74,6 +74,7 @@
 		SpirvRoutine routine;
 		SpirvShader const * const shader;
 		vk::PipelineLayout const * const pipelineLayout;
+		const vk::DescriptorSet::Bindings &descriptorSets;
 	};
 
 } // namespace sw
diff --git a/src/Pipeline/PixelProgram.cpp b/src/Pipeline/PixelProgram.cpp
index 45b5348..9eb0ab4 100644
--- a/src/Pipeline/PixelProgram.cpp
+++ b/src/Pipeline/PixelProgram.cpp
@@ -29,14 +29,12 @@
 
 	void PixelProgram::applyShader(Int cMask[4])
 	{
-		enableIndex = 0;
-
 		routine.descriptorSets = data + OFFSET(DrawData, descriptorSets);
 		routine.descriptorDynamicOffsets = data + OFFSET(DrawData, descriptorDynamicOffsets);
 		routine.pushConstants = data + OFFSET(DrawData, pushConstants);
 
 		auto activeLaneMask = SIMD::Int(0xFFFFFFFF); // TODO: Control this.
-		spirvShader->emit(&routine, activeLaneMask);
+		spirvShader->emit(&routine, activeLaneMask, descriptorSets);
 		spirvShader->emitEpilog(&routine);
 
 		for(int i = 0; i < RENDERTARGETS; i++)
@@ -232,12 +230,6 @@
 		}
 	}
 
-	Int4 PixelProgram::enableMask()
-	{
-		Int4 enable = true ? Int4(enableStack[enableIndex]) : Int4(0xFFFFFFFF);
-		return enable;
-	}
-
 	Float4 PixelProgram::linearToSRGB(const Float4 &x)   // Approximates x^(1.0/2.2)
 	{
 		Float4 sqrtx = Rcp_pp(RcpSqrt_pp(x));
diff --git a/src/Pipeline/PixelProgram.hpp b/src/Pipeline/PixelProgram.hpp
index 71c46df..98fa19d 100644
--- a/src/Pipeline/PixelProgram.hpp
+++ b/src/Pipeline/PixelProgram.hpp
@@ -26,8 +26,9 @@
 		PixelProgram(
 				const PixelProcessor::State &state,
 				vk::PipelineLayout const *pipelineLayout,
-				SpirvShader const *spirvShader) :
-			PixelRoutine(state, pipelineLayout, spirvShader)
+				SpirvShader const *spirvShader,
+				const vk::DescriptorSet::Bindings &descriptorSets) :
+			PixelRoutine(state, pipelineLayout, spirvShader, descriptorSets)
 		{
 		}
 
@@ -43,15 +44,9 @@
 		// Color outputs
 		Vector4f c[RENDERTARGETS];
 
-		// Per pixel based on conditions reached
-		Int enableIndex;
-		Array<Int4, 1 + 24> enableStack;
-
 		// Raster operations
 		void clampColor(Vector4f oC[RENDERTARGETS]);
 
-		Int4 enableMask();
-
 		Float4 linearToSRGB(const Float4 &x);
 	};
 }
diff --git a/src/Pipeline/PixelRoutine.cpp b/src/Pipeline/PixelRoutine.cpp
index 2857fb3..b2f669a 100644
--- a/src/Pipeline/PixelRoutine.cpp
+++ b/src/Pipeline/PixelRoutine.cpp
@@ -35,9 +35,11 @@
 	PixelRoutine::PixelRoutine(
 			const PixelProcessor::State &state,
 			vk::PipelineLayout const *pipelineLayout,
-			SpirvShader const *spirvShader)
+			SpirvShader const *spirvShader,
+			const vk::DescriptorSet::Bindings &descriptorSets)
 		: QuadRasterizer(state, spirvShader),
-		  routine(pipelineLayout)
+		  routine(pipelineLayout),
+		  descriptorSets(descriptorSets)
 	{
 		spirvShader->emitProlog(&routine);
 
diff --git a/src/Pipeline/PixelRoutine.hpp b/src/Pipeline/PixelRoutine.hpp
index e7a3079..e4d8eee 100644
--- a/src/Pipeline/PixelRoutine.hpp
+++ b/src/Pipeline/PixelRoutine.hpp
@@ -27,7 +27,8 @@
 	public:
 		PixelRoutine(const PixelProcessor::State &state,
 			vk::PipelineLayout const *pipelineLayout,
-			SpirvShader const *spirvShader);
+			SpirvShader const *spirvShader,
+			const vk::DescriptorSet::Bindings &descriptorSets);
 
 		virtual ~PixelRoutine();
 
@@ -37,6 +38,7 @@
 		Float4 rhw;  // Reciprocal w
 
 		SpirvRoutine routine;
+		const vk::DescriptorSet::Bindings &descriptorSets;
 
 		// Depth output
 		Float4 oDepth;
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index 4aed978..0063dbc 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -19,6 +19,7 @@
 #include "Vulkan/VkDebug.hpp"
 #include "Vulkan/VkDescriptorSet.hpp"
 #include "Vulkan/VkPipelineLayout.hpp"
+#include "Vulkan/VkDescriptorSetLayout.hpp"
 #include "Device/Config.hpp"
 
 #include <spirv/unified1/spirv.hpp>
@@ -1371,11 +1372,9 @@
 		}
 	}
 
-	void SpirvShader::emit(SpirvRoutine *routine, RValue<SIMD::Int> const &activeLaneMask) const
+	void SpirvShader::emit(SpirvRoutine *routine, RValue<SIMD::Int> const &activeLaneMask, const vk::DescriptorSet::Bindings &descriptorSets) const
 	{
-		EmitState state;
-		state.setActiveLaneMask(activeLaneMask);
-		state.routine = routine;
+		EmitState state(routine, activeLaneMask, descriptorSets);
 
 		// Emit everything up to the first label
 		// TODO: Separate out dispatch of block from non-block instructions?
diff --git a/src/Pipeline/SpirvShader.hpp b/src/Pipeline/SpirvShader.hpp
index 28709da..1527c9a 100644
--- a/src/Pipeline/SpirvShader.hpp
+++ b/src/Pipeline/SpirvShader.hpp
@@ -20,6 +20,7 @@
 #include "System/Types.hpp"
 #include "Vulkan/VkDebug.hpp"
 #include "Vulkan/VkConfig.h"
+#include "Vulkan/VkDescriptorSet.hpp"
 #include "Device/Config.hpp"
 
 #include <spirv/unified1/spirv.hpp>
@@ -480,7 +481,7 @@
 		std::vector<InterfaceComponent> outputs;
 
 		void emitProlog(SpirvRoutine *routine) const;
-		void emit(SpirvRoutine *routine, RValue<SIMD::Int> const &activeLaneMask) const;
+		void emit(SpirvRoutine *routine, RValue<SIMD::Int> const &activeLaneMask, const vk::DescriptorSet::Bindings &descriptorSets) const;
 		void emitEpilog(SpirvRoutine *routine) const;
 
 		using BuiltInHash = std::hash<std::underlying_type<spv::BuiltIn>::type>;
@@ -610,6 +611,13 @@
 		class EmitState
 		{
 		public:
+			EmitState(SpirvRoutine *routine, RValue<SIMD::Int> activeLaneMask, const vk::DescriptorSet::Bindings &descriptorSets)
+				: routine(routine),
+				  activeLaneMaskValue(activeLaneMask.value),
+				  descriptorSets(descriptorSets)
+			{
+			}
+
 			RValue<SIMD::Int> activeLaneMask() const
 			{
 				ASSERT(activeLaneMaskValue != nullptr);
@@ -638,6 +646,8 @@
 			Block::Set visited; // Blocks already built.
 			std::unordered_map<Block::Edge, RValue<SIMD::Int>, Block::Edge::Hash> edgeActiveLaneMasks;
 			std::queue<Block::ID> *pending;
+
+			const vk::DescriptorSet::Bindings &descriptorSets;
 		};
 
 		// EmitResult is an enumerator of result values from the Emit functions.
diff --git a/src/Pipeline/VertexProgram.cpp b/src/Pipeline/VertexProgram.cpp
index f5ea229..6ea04f2 100644
--- a/src/Pipeline/VertexProgram.cpp
+++ b/src/Pipeline/VertexProgram.cpp
@@ -27,16 +27,11 @@
 	VertexProgram::VertexProgram(
 			const VertexProcessor::State &state,
 			vk::PipelineLayout const *pipelineLayout,
-			SpirvShader const *spirvShader)
-		: VertexRoutine(state, pipelineLayout, spirvShader)
+			SpirvShader const *spirvShader,
+			const vk::DescriptorSet::Bindings &descriptorSets)
+		: VertexRoutine(state, pipelineLayout, spirvShader),
+		  descriptorSets(descriptorSets)
 	{
-		ifDepth = 0;
-		loopRepDepth = 0;
-		currentLabel = -1;
-		whileTest = false;
-
-		enableStack[0] = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
-
 		auto it = spirvShader->inputBuiltins.find(spv::BuiltInInstanceIndex);
 		if (it != spirvShader->inputBuiltins.end())
 		{
@@ -57,10 +52,6 @@
 
 	void VertexProgram::program(UInt &index)
 	{
-		//	shader->print("VertexShader-%0.8X.txt", state.shaderID);
-
-		enableIndex = 0;
-
 		auto it = spirvShader->inputBuiltins.find(spv::BuiltInVertexIndex);
 		if (it != spirvShader->inputBuiltins.end())
 		{
@@ -70,20 +61,8 @@
 		}
 
 		auto activeLaneMask = SIMD::Int(0xFFFFFFFF); // TODO: Control this.
-		spirvShader->emit(&routine, activeLaneMask);
-
-		if(currentLabel != -1)
-		{
-			Nucleus::setInsertBlock(returnBlock);
-		}
+		spirvShader->emit(&routine, activeLaneMask, descriptorSets);
 
 		spirvShader->emitEpilog(&routine);
 	}
-
-	Int4 VertexProgram::enableMask()
-	{
-		Int4 enable = true ? Int4(enableStack[enableIndex]) : Int4(0xFFFFFFFF);
-		return enable;
-	}
-
 }
diff --git a/src/Pipeline/VertexProgram.hpp b/src/Pipeline/VertexProgram.hpp
index 5fe1252..2b4657f 100644
--- a/src/Pipeline/VertexProgram.hpp
+++ b/src/Pipeline/VertexProgram.hpp
@@ -32,31 +32,15 @@
 		VertexProgram(
 			const VertexProcessor::State &state,
 			vk::PipelineLayout const *pipelineLayout,
-			SpirvShader const *spirvShader);
+			SpirvShader const *spirvShader,
+			const vk::DescriptorSet::Bindings &descriptorSets);
 
 		virtual ~VertexProgram();
 
 	private:
-		Int enableIndex;
-		Array<Int4, 1 + 24> enableStack;
-
 		void program(UInt &index) override;
-		RValue<Pointer<Byte>> uniformAddress(int bufferIndex, unsigned int index);
-		RValue<Pointer<Byte>> uniformAddress(int bufferIndex, unsigned int index, Int &offset);
-		Int4 enableMask();
 
-		int ifDepth;
-		int loopRepDepth;
-		int currentLabel;
-		bool whileTest;
-
-		BasicBlock *ifFalseBlock[24 + 24];
-		BasicBlock *loopRepTestBlock[4];
-		BasicBlock *loopRepEndBlock[4];
-		BasicBlock *labelBlock[2048];
-		std::vector<BasicBlock*> callRetBlock[2048];
-		BasicBlock *returnBlock;
-		bool isConditionalIf[24 + 24];
+		const vk::DescriptorSet::Bindings &descriptorSets;
 	};
 }
 
diff --git a/src/Vulkan/VkPipeline.cpp b/src/Vulkan/VkPipeline.cpp
index 50b83f4..b9b8610 100644
--- a/src/Vulkan/VkPipeline.cpp
+++ b/src/Vulkan/VkPipeline.cpp
@@ -505,10 +505,10 @@
 
 	ASSERT(shader == nullptr);
 
-	// FIXME (b/119409619): use allocator.
+	// FIXME(b/119409619): use allocator.
 	shader = new sw::SpirvShader(code);
-
-	sw::ComputeProgram program(shader, layout);
+	vk::DescriptorSet::Bindings descriptorSets;  // FIXME(b/129523279): Delay code generation until invoke time.
+	sw::ComputeProgram program(shader, layout, descriptorSets);
 
 	program.generate();