Start untangling sw::Context from the rendering code

Remove sw::Context members from the processor classes and removed
many related functions. Also, the Renderer::draw() function now takes
a const sw::Context object in, so it is no longer legal to modify
sw::Context object within the Renderer::draw() function.

Bug b/132280877

Change-Id: I890b5ba7db2306c02a96ec3e10496aa35c51bbe2
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/30950
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Chris Forbes <chrisforbes@google.com>
diff --git a/src/Device/Context.cpp b/src/Device/Context.cpp
index ce4fc3e..b2d6734 100644
--- a/src/Device/Context.cpp
+++ b/src/Device/Context.cpp
@@ -242,29 +242,29 @@
 		return modified;
 	}
 
-	bool Context::depthWriteActive()
+	bool Context::depthWriteActive() const
 	{
 		if(!depthBufferActive()) return false;
 
 		return depthWriteEnable;
 	}
 
-	bool Context::alphaTestActive()
+	bool Context::alphaTestActive() const
 	{
 		return transparencyAntialiasing != TRANSPARENCY_NONE;
 	}
 
-	bool Context::depthBufferActive()
+	bool Context::depthBufferActive() const
 	{
 		return depthBuffer && depthBufferEnable;
 	}
 
-	bool Context::stencilActive()
+	bool Context::stencilActive() const
 	{
 		return stencilBuffer && stencilEnable;
 	}
 
-	bool Context::alphaBlendActive()
+	bool Context::alphaBlendActive() const
 	{
 		if(!alphaBlendEnable)
 		{
@@ -282,7 +282,7 @@
 		return colorBlend || alphaBlend;
 	}
 
-	VkBlendFactor Context::sourceBlendFactor()
+	VkBlendFactor Context::sourceBlendFactor() const
 	{
 		if(!alphaBlendEnable) return VK_BLEND_FACTOR_ONE;
 
@@ -303,7 +303,7 @@
 		return sourceBlendFactorState;
 	}
 
-	VkBlendFactor Context::destBlendFactor()
+	VkBlendFactor Context::destBlendFactor() const
 	{
 		if(!alphaBlendEnable) return VK_BLEND_FACTOR_ONE;
 
@@ -324,7 +324,7 @@
 		return destBlendFactorState;
 	}
 
-	VkBlendOp Context::blendOperation()
+	VkBlendOp Context::blendOperation() const
 	{
 		if(!alphaBlendEnable) return VK_BLEND_OP_SRC_EXT;
 
@@ -436,7 +436,7 @@
 		return blendOperationState;
 	}
 
-	VkBlendFactor Context::sourceBlendFactorAlpha()
+	VkBlendFactor Context::sourceBlendFactorAlpha() const
 	{
 		if(!separateAlphaBlendEnable)
 		{
@@ -462,7 +462,7 @@
 		}
 	}
 
-	VkBlendFactor Context::destBlendFactorAlpha()
+	VkBlendFactor Context::destBlendFactorAlpha() const
 	{
 		if(!separateAlphaBlendEnable)
 		{
@@ -488,7 +488,7 @@
 		}
 	}
 
-	VkBlendOp Context::blendOperationAlpha()
+	VkBlendOp Context::blendOperationAlpha() const
 	{
 		if(!separateAlphaBlendEnable)
 		{
@@ -605,7 +605,7 @@
 		}
 	}
 
-	bool Context::perspectiveActive()
+	bool Context::perspectiveActive() const
 	{
 		if(!colorUsed())
 		{
@@ -625,7 +625,7 @@
 		return true;
 	}
 
-	VkFormat Context::renderTargetInternalFormat(int index)
+	VkFormat Context::renderTargetInternalFormat(int index) const
 	{
 		if(renderTarget[index])
 		{
@@ -637,7 +637,7 @@
 		}
 	}
 
-	bool Context::colorWriteActive()
+	bool Context::colorWriteActive() const
 	{
 		for (int i = 0; i < RENDERTARGETS; i++)
 		{
@@ -650,7 +650,7 @@
 		return false;
 	}
 
-	int Context::colorWriteActive(int index)
+	int Context::colorWriteActive(int index) const
 	{
 		if(!renderTarget[index] || renderTarget[index]->getFormat() == VK_FORMAT_UNDEFINED)
 		{
@@ -666,7 +666,7 @@
 		return colorWriteMask[index];
 	}
 
-	bool Context::colorUsed()
+	bool Context::colorUsed() const
 	{
 		return colorWriteActive() || alphaTestActive() || (pixelShader && pixelShader->getModes().ContainsKill);
 	}
diff --git a/src/Device/Context.hpp b/src/Device/Context.hpp
index 7700440..6e9408e 100644
--- a/src/Device/Context.hpp
+++ b/src/Device/Context.hpp
@@ -116,21 +116,21 @@
 		bool setColorWriteMask(int index, int colorWriteMask);
 		bool setWriteSRGB(bool sRGB);
 
-		bool depthWriteActive();
-		bool alphaTestActive();
-		bool depthBufferActive();
-		bool stencilActive();
+		bool depthWriteActive() const;
+		bool alphaTestActive() const;
+		bool depthBufferActive() const;
+		bool stencilActive() const;
 
-		bool perspectiveActive();
+		bool perspectiveActive() const;
 
-		bool alphaBlendActive();
-		VkBlendFactor sourceBlendFactor();
-		VkBlendFactor destBlendFactor();
-		VkBlendOp blendOperation();
+		bool alphaBlendActive() const;
+		VkBlendFactor sourceBlendFactor() const;
+		VkBlendFactor destBlendFactor() const;
+		VkBlendOp blendOperation() const;
 
-		VkBlendFactor sourceBlendFactorAlpha();
-		VkBlendFactor destBlendFactorAlpha();
-		VkBlendOp blendOperationAlpha();
+		VkBlendFactor sourceBlendFactorAlpha() const;
+		VkBlendFactor destBlendFactorAlpha() const;
+		VkBlendOp blendOperationAlpha() const;
 
 		VkPrimitiveTopology topology;
 
@@ -146,10 +146,10 @@
 		float depthBias;
 		float slopeDepthBias;
 
-		VkFormat renderTargetInternalFormat(int index);
-		bool colorWriteActive();
-		int colorWriteActive(int index);
-		bool colorUsed();
+		VkFormat renderTargetInternalFormat(int index) const;
+		bool colorWriteActive() const;
+		int colorWriteActive(int index) const;
+		bool colorUsed() const;
 
 		vk::DescriptorSet::Bindings descriptorSets = {};
 		vk::DescriptorSet::DynamicOffsets descriptorDynamicOffsets = {};
diff --git a/src/Device/PixelProcessor.cpp b/src/Device/PixelProcessor.cpp
index 073b40e..71ec36f 100644
--- a/src/Device/PixelProcessor.cpp
+++ b/src/Device/PixelProcessor.cpp
@@ -57,7 +57,7 @@
 		return memcmp(static_cast<const States*>(this), static_cast<const States*>(&state), sizeof(States)) == 0;
 	}
 
-	PixelProcessor::PixelProcessor(Context *context) : context(context)
+	PixelProcessor::PixelProcessor()
 	{
 		routineCache = nullptr;
 		setRoutineCacheSize(1024);
@@ -69,47 +69,6 @@
 		routineCache = nullptr;
 	}
 
-	void PixelProcessor::setRenderTarget(int index, vk::ImageView* renderTarget)
-	{
-		context->renderTarget[index] = renderTarget;
-	}
-
-	void PixelProcessor::setDepthBuffer(vk::ImageView *depthBuffer)
-	{
-		context->depthBuffer = depthBuffer;
-	}
-
-	void PixelProcessor::setStencilBuffer(vk::ImageView *stencilBuffer)
-	{
-		context->stencilBuffer = stencilBuffer;
-	}
-
-	void PixelProcessor::setDepthBufferEnable(bool depthBufferEnable)
-	{
-		context->setDepthBufferEnable(depthBufferEnable);
-	}
-
-	void PixelProcessor::setDepthCompare(VkCompareOp depthCompareMode)
-	{
-		context->depthCompareMode = depthCompareMode;
-	}
-
-	void PixelProcessor::setDepthWriteEnable(bool depthWriteEnable)
-	{
-		context->depthWriteEnable = depthWriteEnable;
-	}
-
-	void PixelProcessor::setCullMode(CullMode cullMode, bool frontFacingCCW)
-	{
-		context->cullMode = cullMode;
-		context->frontFacingCCW = frontFacingCCW;
-	}
-
-	void PixelProcessor::setColorWriteMask(int index, int rgbaMask)
-	{
-		context->setColorWriteMask(index, rgbaMask);
-	}
-
 	void PixelProcessor::setBlendConstant(const Color<float> &blendConstant)
 	{
 		// FIXME: Compact into generic function   // FIXME: Clamp
@@ -205,63 +164,18 @@
 		factor.invBlendConstant4F[3][3] = 1 - blendConstant.a;
 	}
 
-	void PixelProcessor::setAlphaBlendEnable(bool alphaBlendEnable)
-	{
-		context->setAlphaBlendEnable(alphaBlendEnable);
-	}
-
-	void PixelProcessor::setSourceBlendFactor(VkBlendFactor sourceBlendFactor)
-	{
-		context->setSourceBlendFactor(sourceBlendFactor);
-	}
-
-	void PixelProcessor::setDestBlendFactor(VkBlendFactor destBlendFactor)
-	{
-		context->setDestBlendFactor(destBlendFactor);
-	}
-
-	void PixelProcessor::setBlendOperation(VkBlendOp blendOperation)
-	{
-		context->setBlendOperation(blendOperation);
-	}
-
-	void PixelProcessor::setSeparateAlphaBlendEnable(bool separateAlphaBlendEnable)
-	{
-		context->setSeparateAlphaBlendEnable(separateAlphaBlendEnable);
-	}
-
-	void PixelProcessor::setSourceBlendFactorAlpha(VkBlendFactor sourceBlendFactorAlpha)
-	{
-		context->setSourceBlendFactorAlpha(sourceBlendFactorAlpha);
-	}
-
-	void PixelProcessor::setDestBlendFactorAlpha(VkBlendFactor destBlendFactorAlpha)
-	{
-		context->setDestBlendFactorAlpha(destBlendFactorAlpha);
-	}
-
-	void PixelProcessor::setBlendOperationAlpha(VkBlendOp blendOperationAlpha)
-	{
-		context->setBlendOperationAlpha(blendOperationAlpha);
-	}
-
 	void PixelProcessor::setPerspectiveCorrection(bool perspectiveEnable)
 	{
 		perspectiveCorrection = perspectiveEnable;
 	}
 
-	void PixelProcessor::setOcclusionEnabled(bool enable)
-	{
-		context->occlusionEnabled = enable;
-	}
-
 	void PixelProcessor::setRoutineCacheSize(int cacheSize)
 	{
 		delete routineCache;
 		routineCache = new RoutineCache<State>(clamp(cacheSize, 1, 65536));
 	}
 
-	const PixelProcessor::State PixelProcessor::update() const
+	const PixelProcessor::State PixelProcessor::update(const Context* context) const
 	{
 		State state;
 
@@ -330,13 +244,16 @@
 		return state;
 	}
 
-	Routine *PixelProcessor::routine(const State &state)
+	Routine *PixelProcessor::routine(const State &state,
+		vk::PipelineLayout const *pipelineLayout,
+		SpirvShader const *pixelShader,
+		const vk::DescriptorSet::Bindings &descriptorSets)
 	{
 		Routine *routine = routineCache->query(state);
 
 		if(!routine)
 		{
-			QuadRasterizer *generator = new PixelProgram(state, context->pipelineLayout, context->pixelShader, context->descriptorSets);
+			QuadRasterizer *generator = new PixelProgram(state, pipelineLayout, pixelShader, descriptorSets);
 			generator->generate();
 			routine = (*generator)("PixelRoutine_%0.8X", state.shaderID);
 			delete generator;
diff --git a/src/Device/PixelProcessor.hpp b/src/Device/PixelProcessor.hpp
index cf0eb5e..14d88d3 100644
--- a/src/Device/PixelProcessor.hpp
+++ b/src/Device/PixelProcessor.hpp
@@ -120,47 +120,24 @@
 	public:
 		typedef void (*RoutinePointer)(const Primitive *primitive, int count, int thread, DrawData *draw);
 
-		PixelProcessor(Context *context);
+		PixelProcessor();
 
 		virtual ~PixelProcessor();
 
-		void setRenderTarget(int index, vk::ImageView *renderTarget);
-		void setDepthBuffer(vk::ImageView *depthBuffer);
-		void setStencilBuffer(vk::ImageView *stencilBuffer);
-
-		void setDepthBufferEnable(bool depthBufferEnable);
-		void setDepthCompare(VkCompareOp depthCompareMode);
-		void setDepthWriteEnable(bool depthWriteEnable);
-		void setCullMode(CullMode cullMode, bool frontFacingCCW);
-		void setColorWriteMask(int index, int rgbaMask);
-
 		void setBlendConstant(const Color<float> &blendConstant);
 
-		void setAlphaBlendEnable(bool alphaBlendEnable);
-		void setSourceBlendFactor(VkBlendFactor sourceBlendFactor);
-		void setDestBlendFactor(VkBlendFactor destBlendFactor);
-		void setBlendOperation(VkBlendOp blendOperation);
-
-		void setSeparateAlphaBlendEnable(bool separateAlphaBlendEnable);
-		void setSourceBlendFactorAlpha(VkBlendFactor sourceBlendFactorAlpha);
-		void setDestBlendFactorAlpha(VkBlendFactor destBlendFactorAlpha);
-		void setBlendOperationAlpha(VkBlendOp blendOperationAlpha);
-
 		void setPerspectiveCorrection(bool perspectiveCorrection);
 
-		void setOcclusionEnabled(bool enable);
-
 	protected:
-		const State update() const;
-		Routine *routine(const State &state);
+		const State update(const Context* context) const;
+		Routine *routine(const State &state, vk::PipelineLayout const *pipelineLayout,
+		                 SpirvShader const *pixelShader, const vk::DescriptorSet::Bindings &descriptorSets);
 		void setRoutineCacheSize(int routineCacheSize);
 
 		// Other semi-constants
 		Factor factor;
 
 	private:
-		Context *const context;
-
 		RoutineCache<State> *routineCache;
 	};
 }
diff --git a/src/Device/Renderer.cpp b/src/Device/Renderer.cpp
index 9c602e0..3a5a02f 100644
--- a/src/Device/Renderer.cpp
+++ b/src/Device/Renderer.cpp
@@ -199,13 +199,11 @@
 		deallocate(data);
 	}
 
-	Renderer::Renderer(Context *context, Conventions conventions, bool exactColorRounding) : VertexProcessor(context), PixelProcessor(context), SetupProcessor(context), context(context), viewport()
+	Renderer::Renderer(Conventions conventions, bool exactColorRounding)
 	{
 		setGlobalRenderingSettings(conventions, exactColorRounding);
 
-		setRenderTarget(0, nullptr);
 		clipper = new Clipper;
-		blitter = new Blitter;
 
 		#if PERF_HUD
 			resetTimers();
@@ -269,9 +267,6 @@
 		delete clipper;
 		clipper = nullptr;
 
-		delete blitter;
-		blitter = nullptr;
-
 		delete resumeApp;
 		resumeApp = nullptr;
 
@@ -297,7 +292,20 @@
 		sw::deallocate(mem);
 	}
 
-	void Renderer::draw(VkPrimitiveTopology topology, VkIndexType indexType, unsigned int count, int baseVertex, vk::Fence* fence, bool update)
+	bool Renderer::hasQueryOfType(VkQueryType type) const
+	{
+		for(auto query : queries)
+		{
+			if(query->type == type)
+			{
+				return true;
+			}
+		}
+
+		return false;
+	}
+
+	void Renderer::draw(const sw::Context* context, VkIndexType indexType, unsigned int count, int baseVertex, vk::Fence* fence, bool update)
 	{
 		#ifndef NDEBUG
 			if(count < minPrimitives || count > maxPrimitives)
@@ -306,39 +314,26 @@
 			}
 		#endif
 
-		context->topology = topology;
-
 		updateConfiguration();
 
 		int ms = context->sampleCount;
-		context->multiSampleMask = context->sampleMask & ((unsigned)0xFFFFFFFF >> (32 - ms));
 
 		if(!context->multiSampleMask)
 		{
 			return;
 		}
 
-		context->occlusionEnabled = false;
-		for(auto query : queries)
-		{
-			if(query->type == VK_QUERY_TYPE_OCCLUSION)
-			{
-				context->occlusionEnabled = true;
-				break;
-			}
-		}
-
 		sync->lock(sw::PRIVATE);
 
 		if(update)
 		{
-			vertexState = VertexProcessor::update(topology);
-			setupState = SetupProcessor::update();
-			pixelState = PixelProcessor::update();
+			vertexState = VertexProcessor::update(context);
+			setupState = SetupProcessor::update(context);
+			pixelState = PixelProcessor::update(context);
 
-			vertexRoutine = VertexProcessor::routine(vertexState);
+			vertexRoutine = VertexProcessor::routine(vertexState, context->pipelineLayout, context->vertexShader, context->descriptorSets);
 			setupRoutine = SetupProcessor::routine(setupState);
-			pixelRoutine = PixelProcessor::routine(pixelState);
+			pixelRoutine = PixelProcessor::routine(pixelState, context->pipelineLayout, context->pixelShader, context->descriptorSets);
 		}
 
 		int batch = batchSize / ms;
@@ -392,7 +387,7 @@
 			}
 		}
 
-		draw->topology = topology;
+		draw->topology = context->topology;
 		draw->indexType = indexType;
 		draw->batchSize = batch;
 
@@ -1396,46 +1391,6 @@
 		}
 	}
 
-	void Renderer::setMultiSampleMask(unsigned int mask)
-	{
-		context->sampleMask = mask;
-	}
-
-	void Renderer::setTransparencyAntialiasing(TransparencyAntialiasing transparencyAntialiasing)
-	{
-		sw::transparencyAntialiasing = transparencyAntialiasing;
-	}
-
-	void Renderer::setLineWidth(float width)
-	{
-		context->lineWidth = width;
-	}
-
-	void Renderer::setDepthBias(float bias)
-	{
-		context->depthBias = bias;
-	}
-
-	void Renderer::setSlopeDepthBias(float slopeBias)
-	{
-		context->slopeDepthBias = slopeBias;
-	}
-
-	void Renderer::setRasterizerDiscard(bool rasterizerDiscard)
-	{
-		context->rasterizerDiscard = rasterizerDiscard;
-	}
-
-	void Renderer::setPixelShader(const SpirvShader *shader)
-	{
-		context->pixelShader = shader;
-	}
-
-	void Renderer::setVertexShader(const SpirvShader *shader)
-	{
-		context->vertexShader = shader;
-	}
-
 	void Renderer::addQuery(vk::Query *query)
 	{
 		queries.push_back(query);
@@ -1446,11 +1401,11 @@
 		queries.remove(query);
 	}
 
-	void Renderer::advanceInstanceAttributes()
+	void Renderer::advanceInstanceAttributes(Stream* inputs)
 	{
 		for(uint32_t i = 0; i < vk::MAX_VERTEX_INPUT_BINDINGS; i++)
 		{
-			auto &attrib = context->input[i];
+			auto &attrib = inputs[i];
 			if (attrib.count && attrib.instanceStride)
 			{
 				// Under the casts: attrib.buffer += attrib.instanceStride
@@ -1491,11 +1446,6 @@
 		}
 	#endif
 
-	void Renderer::setContext(const sw::Context& context)
-	{
-		*(this->context) = context;
-	}
-
 	void Renderer::setViewport(const VkViewport &viewport)
 	{
 		this->viewport = viewport;
diff --git a/src/Device/Renderer.hpp b/src/Device/Renderer.hpp
index 86d6ad1..2c8c3be 100644
--- a/src/Device/Renderer.hpp
+++ b/src/Device/Renderer.hpp
@@ -193,30 +193,16 @@
 		};
 
 	public:
-		Renderer(Context *context, Conventions conventions, bool exactColorRounding);
+		Renderer(Conventions conventions, bool exactColorRounding);
 
 		virtual ~Renderer();
 
 		void *operator new(size_t size);
 		void operator delete(void * mem);
 
-		void draw(VkPrimitiveTopology topology, VkIndexType indexType, unsigned int count, int baseVertex, vk::Fence* fence, bool update = true);
+		bool hasQueryOfType(VkQueryType type) const;
 
-		void setContext(const sw::Context& context);
-
-		void setMultiSampleMask(unsigned int mask);
-		void setTransparencyAntialiasing(TransparencyAntialiasing transparencyAntialiasing);
-
-		void setLineWidth(float width);
-
-		void setDepthBias(float bias);
-		void setSlopeDepthBias(float slopeBias);
-
-		void setRasterizerDiscard(bool rasterizerDiscard);
-
-		// Programmable pipelines
-		void setPixelShader(const SpirvShader *shader);
-		void setVertexShader(const SpirvShader *shader);
+		void draw(const sw::Context* context, VkIndexType indexType, unsigned int count, int baseVertex, vk::Fence* fence, bool update = true);
 
 		// Viewport & Clipper
 		void setViewport(const VkViewport &viewport);
@@ -225,7 +211,7 @@
 		void addQuery(vk::Query *query);
 		void removeQuery(vk::Query *query);
 
-		void advanceInstanceAttributes();
+		void advanceInstanceAttributes(Stream* inputs);
 
 		void synchronize();
 
@@ -262,9 +248,7 @@
 		void initializeThreads();
 		void terminateThreads();
 
-		Context *context;
 		Clipper *clipper;
-		Blitter *blitter;
 		VkViewport viewport;
 		VkRect2D scissor;
 		int clipFlags;
diff --git a/src/Device/SetupProcessor.cpp b/src/Device/SetupProcessor.cpp
index 7af4d3a..eb5a7e5 100644
--- a/src/Device/SetupProcessor.cpp
+++ b/src/Device/SetupProcessor.cpp
@@ -57,7 +57,7 @@
 		return memcmp(static_cast<const States*>(this), static_cast<const States*>(&state), sizeof(States)) == 0;
 	}
 
-	SetupProcessor::SetupProcessor(Context *context) : context(context)
+	SetupProcessor::SetupProcessor()
 	{
 		routineCache = nullptr;
 		setRoutineCacheSize(1024);
@@ -69,7 +69,7 @@
 		routineCache = nullptr;
 	}
 
-	SetupProcessor::State SetupProcessor::update() const
+	SetupProcessor::State SetupProcessor::update(const sw::Context* context) const
 	{
 		State state;
 
diff --git a/src/Device/SetupProcessor.hpp b/src/Device/SetupProcessor.hpp
index d5b40f6..de52927 100644
--- a/src/Device/SetupProcessor.hpp
+++ b/src/Device/SetupProcessor.hpp
@@ -64,19 +64,17 @@
 
 		typedef bool (*RoutinePointer)(Primitive *primitive, const Triangle *triangle, const Polygon *polygon, const DrawData *draw);
 
-		SetupProcessor(Context *context);
+		SetupProcessor();
 
 		~SetupProcessor();
 
 	protected:
-		State update() const;
+		State update(const sw::Context* context) const;
 		Routine *routine(const State &state);
 
 		void setRoutineCacheSize(int cacheSize);
 
 	private:
-		Context *const context;
-
 		RoutineCache<State> *routineCache;
 	};
 }
diff --git a/src/Device/VertexProcessor.cpp b/src/Device/VertexProcessor.cpp
index e5d0859..db62f62 100644
--- a/src/Device/VertexProcessor.cpp
+++ b/src/Device/VertexProcessor.cpp
@@ -61,7 +61,7 @@
 		return memcmp(static_cast<const States*>(this), static_cast<const States*>(&state), sizeof(States)) == 0;
 	}
 
-	VertexProcessor::VertexProcessor(Context *context) : context(context)
+	VertexProcessor::VertexProcessor()
 	{
 		routineCache = nullptr;
 		setRoutineCacheSize(1024);
@@ -73,37 +73,19 @@
 		routineCache = nullptr;
 	}
 
-	void VertexProcessor::setInputStream(int index, const Stream &stream)
-	{
-		context->input[index] = stream;
-	}
-
-	void VertexProcessor::resetInputStreams()
-	{
-		for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
-		{
-			context->input[i].defaults();
-		}
-	}
-
-	void VertexProcessor::setInstanceID(int instanceID)
-	{
-		context->instanceID = instanceID;
-	}
-
 	void VertexProcessor::setRoutineCacheSize(int cacheSize)
 	{
 		delete routineCache;
 		routineCache = new RoutineCache<State>(clamp(cacheSize, 1, 65536));
 	}
 
-	const VertexProcessor::State VertexProcessor::update(VkPrimitiveTopology topology)
+	const VertexProcessor::State VertexProcessor::update(const sw::Context* context)
 	{
 		State state;
 
 		state.shaderID = context->vertexShader->getSerialID();
 
-		switch(topology)
+		switch(context->topology)
 		{
 		case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
 			state.verticesPerPrimitive = 1;
@@ -118,7 +100,7 @@
 			state.verticesPerPrimitive = 3;
 			break;
 		default:
-			UNIMPLEMENTED("topology %d", int(topology));
+			UNIMPLEMENTED("topology %d", int(context->topology));
 		}
 
 		for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
@@ -136,13 +118,16 @@
 		return state;
 	}
 
-	Routine *VertexProcessor::routine(const State &state)
+	Routine *VertexProcessor::routine(const State &state,
+	                                  vk::PipelineLayout const *pipelineLayout,
+	                                  SpirvShader const *vertexShader,
+	                                  const vk::DescriptorSet::Bindings &descriptorSets)
 	{
 		Routine *routine = routineCache->query(state);
 
 		if(!routine)   // Create one
 		{
-			VertexRoutine *generator = new VertexProgram(state, context->pipelineLayout, context->vertexShader, context->descriptorSets);
+			VertexRoutine *generator = new VertexProgram(state, pipelineLayout, vertexShader, descriptorSets);
 			generator->generate();
 			routine = (*generator)("VertexRoutine_%0.8X", state.shaderID);
 			delete generator;
diff --git a/src/Device/VertexProcessor.hpp b/src/Device/VertexProcessor.hpp
index dedcf97..b5d7353 100644
--- a/src/Device/VertexProcessor.hpp
+++ b/src/Device/VertexProcessor.hpp
@@ -80,24 +80,18 @@
 
 		typedef void (*RoutinePointer)(Vertex *output, unsigned int *batch, VertexTask *vertexTask, DrawData *draw);
 
-		VertexProcessor(Context *context);
+		VertexProcessor();
 
 		virtual ~VertexProcessor();
 
-		void setInputStream(int index, const Stream &stream);
-		void resetInputStreams();
-
-		void setInstanceID(int instanceID);
-
 	protected:
-		const State update(VkPrimitiveTopology topology);
-		Routine *routine(const State &state);
+		const State update(const sw::Context* context);
+		Routine *routine(const State &state, vk::PipelineLayout const *pipelineLayout,
+		                 SpirvShader const *vertexShader, const vk::DescriptorSet::Bindings &descriptorSets);
 
 		void setRoutineCacheSize(int cacheSize);
 
 	private:
-		Context *const context;
-
 		RoutineCache<State> *routineCache;
 	};
 }
diff --git a/src/Vulkan/VkCommandBuffer.cpp b/src/Vulkan/VkCommandBuffer.cpp
index bb34b9b..f161e9e 100644
--- a/src/Vulkan/VkCommandBuffer.cpp
+++ b/src/Vulkan/VkCommandBuffer.cpp
@@ -417,7 +417,7 @@
 	}
 }
 
-void CommandBuffer::ExecutionState::bindAttachments()
+void CommandBuffer::ExecutionState::bindAttachments(sw::Context& context)
 {
 	// Binds all the attachments for the current subpass
 	// Ideally this would be performed by BeginRenderPass and NextSubpass, but
@@ -429,8 +429,7 @@
 		auto attachmentReference = renderPass->getCurrentSubpass().pColorAttachments[i];
 		if (attachmentReference.attachment != VK_ATTACHMENT_UNUSED)
 		{
-			auto attachment = renderPassFramebuffer->getAttachment(attachmentReference.attachment);
-			renderer->setRenderTarget(i, attachment);
+			context.renderTarget[i] = renderPassFramebuffer->getAttachment(attachmentReference.attachment);
 		}
 	}
 
@@ -440,11 +439,11 @@
 		auto attachment = renderPassFramebuffer->getAttachment(attachmentReference->attachment);
 		if (attachment->hasDepthAspect())
 		{
-			renderer->setDepthBuffer(attachment);
+			context.depthBuffer = attachment;
 		}
 		if (attachment->hasStencilAspect())
 		{
-			renderer->setStencilBuffer(attachment);
+			context.stencilBuffer = attachment;
 		}
 	}
 }
@@ -516,17 +515,17 @@
 			context.backStencil.reference = executionState.dynamicState.reference[1];
 		}
 
-		executionState.renderer->setContext(context);
+		executionState.bindAttachments(context);
 
-		executionState.bindAttachments();
+		context.multiSampleMask = context.sampleMask & ((unsigned)0xFFFFFFFF >> (32 - context.sampleCount));
+		context.occlusionEnabled = executionState.renderer->hasQueryOfType(VK_QUERY_TYPE_OCCLUSION);
 
 		const uint32_t primitiveCount = pipeline->computePrimitiveCount(count);
 		for(uint32_t instance = firstInstance; instance != firstInstance + instanceCount; instance++)
 		{
-			executionState.renderer->setInstanceID(instance);
-			executionState.renderer->draw(context.topology, executionState.indexType, primitiveCount, vertexOffset,
-			                              executionState.fence);
-			executionState.renderer->advanceInstanceAttributes();
+			context.instanceID = instance;
+			executionState.renderer->draw(&context, executionState.indexType, primitiveCount, vertexOffset, executionState.fence);
+			executionState.renderer->advanceInstanceAttributes(context.input);
 		}
 	}
 };
diff --git a/src/Vulkan/VkCommandBuffer.hpp b/src/Vulkan/VkCommandBuffer.hpp
index f13ee23..40ea76f 100644
--- a/src/Vulkan/VkCommandBuffer.hpp
+++ b/src/Vulkan/VkCommandBuffer.hpp
@@ -166,7 +166,7 @@
 		VertexInputBinding indexBufferBinding;
 		VkIndexType indexType;
 
-		void bindAttachments();
+		void bindAttachments(sw::Context& context);
 		void bindVertexInputs(sw::Context& context, int firstVertex, int firstInstance);
 	};
 
diff --git a/src/Vulkan/VkQueue.cpp b/src/Vulkan/VkQueue.cpp
index db545d2..3f79c7f 100644
--- a/src/Vulkan/VkQueue.cpp
+++ b/src/Vulkan/VkQueue.cpp
@@ -75,8 +75,7 @@
 
 Queue::Queue()
 {
-	context.reset(new sw::Context());
-	renderer.reset(new sw::Renderer(context.get(), sw::OpenGL, true));
+	renderer.reset(new sw::Renderer(sw::OpenGL, true));
 
 	queueThread = std::thread(TaskLoop, this);
 }
@@ -93,7 +92,6 @@
 	garbageCollect();
 
 	renderer.reset(nullptr);
-	context.reset(nullptr);
 }
 
 VkResult Queue::submit(uint32_t submitCount, const VkSubmitInfo* pSubmits, VkFence fence)
diff --git a/src/Vulkan/VkQueue.hpp b/src/Vulkan/VkQueue.hpp
index f9664b7..9dda990 100644
--- a/src/Vulkan/VkQueue.hpp
+++ b/src/Vulkan/VkQueue.hpp
@@ -151,7 +151,6 @@
 	void garbageCollect();
 	void submitQueue(const Task& task);
 
-	std::unique_ptr<sw::Context> context;
 	std::unique_ptr<sw::Renderer> renderer;
 	Chan<Task> pending;
 	Chan<VkSubmitInfo*> toDelete;