Replace Shader,VertexShader,PixelShader with SpirvShader

Also deletes tons of fixed-function-centric stuff that will never be
used by the Vulkan backend. Very little of the SPIRV integration
actually does anything interesting yet (we don't generate code) but this
wires on the new shader representation.

Bug: b/120799499

Change-Id: Ib76e2086113098aebd526a0da461689d4344e8c2
Reviewed-on: https://swiftshader-review.googlesource.com/c/23090
Tested-by: Chris Forbes <chrisforbes@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Device/Context.cpp b/src/Device/Context.cpp
index 9e5835a..6f12455 100644
--- a/src/Device/Context.cpp
+++ b/src/Device/Context.cpp
@@ -16,10 +16,9 @@
 
 #include "Primitive.hpp"
 #include "Surface.hpp"
-#include "Pipeline/PixelShader.hpp"
-#include "Pipeline/VertexShader.hpp"
 #include "System/Memory.hpp"
 #include "Vulkan/VkDebug.hpp"
+#include "Pipeline/SpirvShader.hpp"
 
 #include <string.h>
 
@@ -27,7 +26,6 @@
 {
 	extern bool perspectiveCorrection;
 
-	bool halfIntegerCoordinates = false;     // Pixel centers are not at integer coordinates
 	bool booleanFaceRegister = false;
 	bool fullPixelPositionRegister = false;
 	bool leadingVertexFirst = false;         // Flat shading uses first vertex, else last
@@ -724,16 +722,6 @@
 		return true;
 	}
 
-	unsigned short Context::pixelShaderModel() const
-	{
-		return pixelShader ? pixelShader->getShaderModel() : 0x0000;
-	}
-
-	unsigned short Context::vertexShaderModel() const
-	{
-		return vertexShader ? vertexShader->getShaderModel() : 0x0000;
-	}
-
 	int Context::getMultiSampleCount() const
 	{
 		return renderTarget[0] ? renderTarget[0]->getMultiSampleCount() : 1;
@@ -774,6 +762,6 @@
 
 	bool Context::colorUsed()
 	{
-		return colorWriteActive() || alphaTestActive() || (pixelShader && pixelShader->containsKill());
+		return colorWriteActive() || alphaTestActive() || (pixelShader && pixelShader->getModes().ContainsKill);
 	}
 }
diff --git a/src/Device/Context.hpp b/src/Device/Context.hpp
index 790e4ca..fc998df 100644
--- a/src/Device/Context.hpp
+++ b/src/Device/Context.hpp
@@ -27,6 +27,7 @@
 	class Surface;
 	class PixelShader;
 	class VertexShader;
+	class SpirvShader;
 	struct Triangle;
 	struct Primitive;
 	struct Vertex;
@@ -153,9 +154,6 @@
 
 		VkLogicOp colorLogicOp();
 
-		unsigned short pixelShaderModel() const;
-		unsigned short vertexShaderModel() const;
-
 		int getMultiSampleCount() const;
 
 		DrawType drawType;
@@ -208,8 +206,8 @@
 		unsigned int stencilBufferLayer;
 
 		// Shaders
-		const PixelShader *pixelShader;
-		const VertexShader *vertexShader;
+		const SpirvShader *pixelShader;
+		const SpirvShader *vertexShader;
 
 		// Instancing
 		int instanceID;
diff --git a/src/Device/PixelProcessor.cpp b/src/Device/PixelProcessor.cpp
index 13168b8..6579a75 100644
--- a/src/Device/PixelProcessor.cpp
+++ b/src/Device/PixelProcessor.cpp
@@ -17,7 +17,6 @@
 #include "Surface.hpp"
 #include "Primitive.hpp"
 #include "Pipeline/PixelProgram.hpp"
-#include "Pipeline/PixelShader.hpp"
 #include "Pipeline/Constants.hpp"
 #include "Vulkan/VkDebug.hpp"
 
@@ -634,8 +633,7 @@
 			state.shaderID = 0;
 		}
 
-		state.depthOverride = context->pixelShader && context->pixelShader->depthOverride();
-		state.shaderContainsKill = context->pixelShader ? context->pixelShader->containsKill() : false;
+		state.depthOverride = context->pixelShader ? context->pixelShader->getModes().DepthReplacing : false;
 
 		if(context->alphaTestActive())
 		{
@@ -704,61 +702,50 @@
 
 		if(state.multiSample > 1 && context->pixelShader)
 		{
-			state.centroid = context->pixelShader->containsCentroid();
+			state.centroid = false;//context->pixelShader->containsCentroid();
 		}
 
 		state.frontFaceCCW = context->frontFacingCCW;
 
-
-		for(unsigned int i = 0; i < 16; i++)
-		{
-			if(context->pixelShader)
-			{
-				if(context->pixelShader->usesSampler(i))
-				{
-					state.sampler[i] = context->sampler[i].samplerState();
-				}
-			}
-		}
-
 		const bool point = context->isDrawPoint();
 
-		for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
-		{
-			for(int component = 0; component < 4; component++)
-			{
-				const Shader::Semantic &semantic = context->pixelShader->getInput(interpolant, component);
-
-				if(semantic.active())
-				{
-					bool flat = point;
-
-					switch(semantic.usage)
-					{
-					case Shader::USAGE_TEXCOORD: flat = false;                  break;
-					case Shader::USAGE_COLOR:    flat = semantic.flat || point; break;
-					}
-
-					state.interpolant[interpolant].component |= 1 << component;
-
-					if(flat)
-					{
-						state.interpolant[interpolant].flat |= 1 << component;
-					}
-				}
-			}
-		}
-
-		if(state.centroid)
-		{
-			for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
-			{
-				for(int component = 0; component < 4; component++)
-				{
-					state.interpolant[interpolant].centroid = context->pixelShader->getInput(interpolant, 0).centroid;
-				}
-			}
-		}
+		/* TODO: bring back interpolants by some mechanism */
+//		for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
+//		{
+//			for(int component = 0; component < 4; component++)
+//			{
+//				const Shader::Semantic &semantic = context->pixelShader->getInput(interpolant, component);
+//
+//				if(semantic.active())
+//				{
+//					bool flat = point;
+//
+//					switch(semantic.usage)
+//					{
+//					case Shader::USAGE_TEXCOORD: flat = false;                  break;
+//					case Shader::USAGE_COLOR:    flat = semantic.flat || point; break;
+//					}
+//
+//					state.interpolant[interpolant].component |= 1 << component;
+//
+//					if(flat)
+//					{
+//						state.interpolant[interpolant].flat |= 1 << component;
+//					}
+//				}
+//			}
+//		}
+//
+//		if(state.centroid)
+//		{
+//			for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
+//			{
+//				for(int component = 0; component < 4; component++)
+//				{
+//					state.interpolant[interpolant].centroid = context->pixelShader->getInput(interpolant, 0).centroid;
+//				}
+//			}
+//		}
 
 		state.hash = state.computeHash();
 
@@ -771,7 +758,6 @@
 
 		if(!routine)
 		{
-			const bool integerPipeline = (context->pixelShaderModel() <= 0x0104);
 			QuadRasterizer *generator = new PixelProgram(state, context->pixelShader);
 			generator->generate();
 			routine = (*generator)("PixelRoutine_%0.8X", state.shaderID);
diff --git a/src/Device/PixelProcessor.hpp b/src/Device/PixelProcessor.hpp
index 1b0e04b..ae3472b 100644
--- a/src/Device/PixelProcessor.hpp
+++ b/src/Device/PixelProcessor.hpp
@@ -35,7 +35,6 @@
 			int shaderID;
 
 			bool depthOverride                        : 1;   // TODO: Eliminate by querying shader.
-			bool shaderContainsKill                   : 1;   // TODO: Eliminate by querying shader.
 
 			VkCompareOp depthCompareMode              : BITS(VK_COMPARE_OP_END_RANGE);
 			VkCompareOp alphaCompareMode              : BITS(VK_COMPARE_OP_END_RANGE);
diff --git a/src/Device/QuadRasterizer.cpp b/src/Device/QuadRasterizer.cpp
index 90d560d..237c9e3 100644
--- a/src/Device/QuadRasterizer.cpp
+++ b/src/Device/QuadRasterizer.cpp
@@ -28,7 +28,7 @@
 
 	extern int clusterCount;
 
-	QuadRasterizer::QuadRasterizer(const PixelProcessor::State &state, const PixelShader *pixelShader) : state(state), shader(pixelShader)
+	QuadRasterizer::QuadRasterizer(const PixelProcessor::State &state, SpirvShader const *spirvShader) : state(state), spirvShader{spirvShader}
 	{
 	}
 
@@ -340,11 +340,11 @@
 
 	bool QuadRasterizer::interpolateZ() const
 	{
-		return state.depthTestActive || (shader && shader->isVPosDeclared() && fullPixelPositionRegister);
+		return state.depthTestActive || (spirvShader && spirvShader->hasBuiltinInput(spv::BuiltInPosition));
 	}
 
 	bool QuadRasterizer::interpolateW() const
 	{
-		return state.perspective || (shader && shader->isVPosDeclared() && fullPixelPositionRegister);
+		return state.perspective || (spirvShader && spirvShader->hasBuiltinInput(spv::BuiltInPosition));
 	}
 }
diff --git a/src/Device/QuadRasterizer.hpp b/src/Device/QuadRasterizer.hpp
index e702f8a..b04deb9 100644
--- a/src/Device/QuadRasterizer.hpp
+++ b/src/Device/QuadRasterizer.hpp
@@ -17,7 +17,7 @@
 
 #include "Rasterizer.hpp"
 #include "Pipeline/ShaderCore.hpp"
-#include "Pipeline/PixelShader.hpp"
+#include "Pipeline/SpirvShader.hpp"
 #include "System/Types.hpp"
 
 namespace sw
@@ -25,7 +25,7 @@
 	class QuadRasterizer : public Rasterizer
 	{
 	public:
-		QuadRasterizer(const PixelProcessor::State &state, const PixelShader *shader);
+		QuadRasterizer(const PixelProcessor::State &state, SpirvShader const *spirvShader);
 		virtual ~QuadRasterizer();
 
 		void generate();
@@ -51,7 +51,7 @@
 		Float4 interpolate(Float4 &x, Float4 &D, Float4 &rhw, Pointer<Byte> planeEquation, bool flat, bool perspective, bool clamp);
 
 		const PixelProcessor::State &state;
-		const PixelShader *const shader;
+		const SpirvShader *const spirvShader;
 
 	private:
 		void rasterize(Int &yMin, Int &yMax);
diff --git a/src/Device/Renderer.cpp b/src/Device/Renderer.cpp
index bee130a..aa62cee 100644
--- a/src/Device/Renderer.cpp
+++ b/src/Device/Renderer.cpp
@@ -30,6 +30,7 @@
 #include "System/Math.hpp"
 #include "System/Timer.hpp"
 #include "Vulkan/VkDebug.hpp"
+#include "Pipeline/SpirvShader.hpp"
 
 #undef max
 
@@ -42,7 +43,6 @@
 
 namespace sw
 {
-	extern bool halfIntegerCoordinates;     // Pixel centers are not at integer coordinates
 	extern bool booleanFaceRegister;
 	extern bool fullPixelPositionRegister;
 	extern bool leadingVertexFirst;         // Flat shading uses first vertex, else last
@@ -77,7 +77,6 @@
 
 		if(!initialized)
 		{
-			sw::halfIntegerCoordinates = conventions.halfIntegerCoordinates;
 			sw::booleanFaceRegister = conventions.booleanFaceRegister;
 			sw::fullPixelPositionRegister = conventions.fullPixelPositionRegister;
 			sw::leadingVertexFirst = conventions.leadingVertexFirst;
@@ -98,14 +97,6 @@
 	{
 		queries = 0;
 
-		vsDirtyConstF = VERTEX_UNIFORM_VECTORS + 1;
-		vsDirtyConstI = 16;
-		vsDirtyConstB = 16;
-
-		psDirtyConstF = FRAGMENT_UNIFORM_VECTORS;
-		psDirtyConstI = 16;
-		psDirtyConstB = 16;
-
 		references = -1;
 
 		data = (DrawData*)allocate(sizeof(DrawData));
@@ -294,14 +285,10 @@
 		if(queries.size() != 0)
 		{
 			draw->queries = new std::list<Query*>();
-			bool includePrimitivesWrittenQueries = vertexState.transformFeedbackQueryEnabled && vertexState.transformFeedbackEnabled;
 			for(auto &query : queries)
 			{
-				if(includePrimitivesWrittenQueries || (query->type != Query::TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN))
-				{
-					++query->reference; // Atomic
-					draw->queries->push_back(query);
-				}
+				++query->reference; // Atomic
+				draw->queries->push_back(query);
 			}
 		}
 
@@ -358,24 +345,6 @@
 
 		if(context->pixelShader)
 		{
-			if(draw->psDirtyConstF)
-			{
-				memcpy(&data->ps.c, PixelProcessor::c, sizeof(float4) * draw->psDirtyConstF);
-				draw->psDirtyConstF = 0;
-			}
-
-			if(draw->psDirtyConstI)
-			{
-				memcpy(&data->ps.i, PixelProcessor::i, sizeof(int4) * draw->psDirtyConstI);
-				draw->psDirtyConstI = 0;
-			}
-
-			if(draw->psDirtyConstB)
-			{
-				memcpy(&data->ps.b, PixelProcessor::b, sizeof(bool) * draw->psDirtyConstB);
-				draw->psDirtyConstB = 0;
-			}
-
 			PixelProcessor::lockUniformBuffers(data->ps.u, draw->pUniformBuffers);
 		}
 		else
@@ -397,31 +366,12 @@
 			}
 		}
 
-		if(draw->vsDirtyConstF)
-		{
-			memcpy(&data->vs.c, VertexProcessor::c, sizeof(float4) * draw->vsDirtyConstF);
-			draw->vsDirtyConstF = 0;
-		}
-
-		if(draw->vsDirtyConstI)
-		{
-			memcpy(&data->vs.i, VertexProcessor::i, sizeof(int4) * draw->vsDirtyConstI);
-			draw->vsDirtyConstI = 0;
-		}
-
-		if(draw->vsDirtyConstB)
-		{
-			memcpy(&data->vs.b, VertexProcessor::b, sizeof(bool) * draw->vsDirtyConstB);
-			draw->vsDirtyConstB = 0;
-		}
-
-		if(context->vertexShader->isInstanceIdDeclared())
+		if(context->vertexShader->hasBuiltinInput(spv::BuiltInInstanceId))
 		{
 			data->instanceID = context->instanceID;
 		}
 
 		VertexProcessor::lockUniformBuffers(data->vs.u, draw->vUniformBuffers);
-		VertexProcessor::lockTransformFeedbackBuffers(data->vs.t, data->vs.reg, data->vs.row, data->vs.col, data->vs.str, draw->transformFeedbackBuffers);
 
 		if(pixelState.stencilActive)
 		{
@@ -965,14 +915,6 @@
 					}
 				}
 
-				for(int i = 0; i < MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS; i++)
-				{
-					if(draw.transformFeedbackBuffers[i])
-					{
-						draw.transformFeedbackBuffers[i]->unlock();
-					}
-				}
-
 				draw.vertexRoutine->unbind();
 				draw.setupRoutine->unbind();
 				draw.pixelRoutine->unbind();
@@ -1723,92 +1665,6 @@
 		}
 	}
 
-	void Renderer::loadConstants(const VertexShader *vertexShader)
-	{
-		size_t count = vertexShader->getLength();
-
-		for(size_t i = 0; i < count; i++)
-		{
-			const Shader::Instruction *instruction = vertexShader->getInstruction(i);
-
-			if(instruction->opcode == Shader::OPCODE_DEF)
-			{
-				int index = instruction->dst.index;
-				float value[4];
-
-				value[0] = instruction->src[0].value[0];
-				value[1] = instruction->src[0].value[1];
-				value[2] = instruction->src[0].value[2];
-				value[3] = instruction->src[0].value[3];
-
-				setVertexShaderConstantF(index, value);
-			}
-			else if(instruction->opcode == Shader::OPCODE_DEFI)
-			{
-				int index = instruction->dst.index;
-				int integer[4];
-
-				integer[0] = instruction->src[0].integer[0];
-				integer[1] = instruction->src[0].integer[1];
-				integer[2] = instruction->src[0].integer[2];
-				integer[3] = instruction->src[0].integer[3];
-
-				setVertexShaderConstantI(index, integer);
-			}
-			else if(instruction->opcode == Shader::OPCODE_DEFB)
-			{
-				int index = instruction->dst.index;
-				int boolean = instruction->src[0].boolean[0];
-
-				setVertexShaderConstantB(index, &boolean);
-			}
-		}
-	}
-
-	void Renderer::loadConstants(const PixelShader *pixelShader)
-	{
-		if(!pixelShader) return;
-
-		size_t count = pixelShader->getLength();
-
-		for(size_t i = 0; i < count; i++)
-		{
-			const Shader::Instruction *instruction = pixelShader->getInstruction(i);
-
-			if(instruction->opcode == Shader::OPCODE_DEF)
-			{
-				int index = instruction->dst.index;
-				float value[4];
-
-				value[0] = instruction->src[0].value[0];
-				value[1] = instruction->src[0].value[1];
-				value[2] = instruction->src[0].value[2];
-				value[3] = instruction->src[0].value[3];
-
-				setPixelShaderConstantF(index, value);
-			}
-			else if(instruction->opcode == Shader::OPCODE_DEFI)
-			{
-				int index = instruction->dst.index;
-				int integer[4];
-
-				integer[0] = instruction->src[0].integer[0];
-				integer[1] = instruction->src[0].integer[1];
-				integer[2] = instruction->src[0].integer[2];
-				integer[3] = instruction->src[0].integer[3];
-
-				setPixelShaderConstantI(index, integer);
-			}
-			else if(instruction->opcode == Shader::OPCODE_DEFB)
-			{
-				int index = instruction->dst.index;
-				int boolean = instruction->src[0].boolean[0];
-
-				setPixelShaderConstantB(index, &boolean);
-			}
-		}
-	}
-
 	void Renderer::setIndexBuffer(Resource *indexBuffer)
 	{
 		context->indexBuffer = indexBuffer;
@@ -2131,120 +1987,14 @@
 		context->rasterizerDiscard = rasterizerDiscard;
 	}
 
-	void Renderer::setPixelShader(const PixelShader *shader)
+	void Renderer::setPixelShader(const SpirvShader *shader)
 	{
 		context->pixelShader = shader;
-
-		loadConstants(shader);
 	}
 
-	void Renderer::setVertexShader(const VertexShader *shader)
+	void Renderer::setVertexShader(const SpirvShader *shader)
 	{
 		context->vertexShader = shader;
-
-		loadConstants(shader);
-	}
-
-	void Renderer::setPixelShaderConstantF(unsigned int index, const float value[4], unsigned int count)
-	{
-		for(unsigned int i = 0; i < DRAW_COUNT; i++)
-		{
-			if(drawCall[i]->psDirtyConstF < index + count)
-			{
-				drawCall[i]->psDirtyConstF = index + count;
-			}
-		}
-
-		for(unsigned int i = 0; i < count; i++)
-		{
-			PixelProcessor::setFloatConstant(index + i, value);
-			value += 4;
-		}
-	}
-
-	void Renderer::setPixelShaderConstantI(unsigned int index, const int value[4], unsigned int count)
-	{
-		for(unsigned int i = 0; i < DRAW_COUNT; i++)
-		{
-			if(drawCall[i]->psDirtyConstI < index + count)
-			{
-				drawCall[i]->psDirtyConstI = index + count;
-			}
-		}
-
-		for(unsigned int i = 0; i < count; i++)
-		{
-			PixelProcessor::setIntegerConstant(index + i, value);
-			value += 4;
-		}
-	}
-
-	void Renderer::setPixelShaderConstantB(unsigned int index, const int *boolean, unsigned int count)
-	{
-		for(unsigned int i = 0; i < DRAW_COUNT; i++)
-		{
-			if(drawCall[i]->psDirtyConstB < index + count)
-			{
-				drawCall[i]->psDirtyConstB = index + count;
-			}
-		}
-
-		for(unsigned int i = 0; i < count; i++)
-		{
-			PixelProcessor::setBooleanConstant(index + i, *boolean);
-			boolean++;
-		}
-	}
-
-	void Renderer::setVertexShaderConstantF(unsigned int index, const float value[4], unsigned int count)
-	{
-		for(unsigned int i = 0; i < DRAW_COUNT; i++)
-		{
-			if(drawCall[i]->vsDirtyConstF < index + count)
-			{
-				drawCall[i]->vsDirtyConstF = index + count;
-			}
-		}
-
-		for(unsigned int i = 0; i < count; i++)
-		{
-			VertexProcessor::setFloatConstant(index + i, value);
-			value += 4;
-		}
-	}
-
-	void Renderer::setVertexShaderConstantI(unsigned int index, const int value[4], unsigned int count)
-	{
-		for(unsigned int i = 0; i < DRAW_COUNT; i++)
-		{
-			if(drawCall[i]->vsDirtyConstI < index + count)
-			{
-				drawCall[i]->vsDirtyConstI = index + count;
-			}
-		}
-
-		for(unsigned int i = 0; i < count; i++)
-		{
-			VertexProcessor::setIntegerConstant(index + i, value);
-			value += 4;
-		}
-	}
-
-	void Renderer::setVertexShaderConstantB(unsigned int index, const int *boolean, unsigned int count)
-	{
-		for(unsigned int i = 0; i < DRAW_COUNT; i++)
-		{
-			if(drawCall[i]->vsDirtyConstB < index + count)
-			{
-				drawCall[i]->vsDirtyConstB = index + count;
-			}
-		}
-
-		for(unsigned int i = 0; i < count; i++)
-		{
-			VertexProcessor::setBooleanConstant(index + i, *boolean);
-			boolean++;
-		}
 	}
 
 	void Renderer::addQuery(Query *query)
diff --git a/src/Device/Renderer.hpp b/src/Device/Renderer.hpp
index b5e4077..6bcc1a2 100644
--- a/src/Device/Renderer.hpp
+++ b/src/Device/Renderer.hpp
@@ -294,16 +294,8 @@
 		void setRasterizerDiscard(bool rasterizerDiscard);
 
 		// Programmable pipelines
-		void setPixelShader(const PixelShader *shader);
-		void setVertexShader(const VertexShader *shader);
-
-		void setPixelShaderConstantF(unsigned int index, const float value[4], unsigned int count = 1);
-		void setPixelShaderConstantI(unsigned int index, const int value[4], unsigned int count = 1);
-		void setPixelShaderConstantB(unsigned int index, const int *boolean, unsigned int count = 1);
-
-		void setVertexShaderConstantF(unsigned int index, const float value[4], unsigned int count = 1);
-		void setVertexShaderConstantI(unsigned int index, const int value[4], unsigned int count = 1);
-		void setVertexShaderConstantB(unsigned int index, const int *boolean, unsigned int count = 1);
+		void setPixelShader(const SpirvShader *shader);
+		void setVertexShader(const SpirvShader *shader);
 
 		// Viewport & Clipper
 		void setViewport(const VkViewport &viewport);
@@ -311,12 +303,6 @@
 		void setClipFlags(int flags);
 		void setClipPlane(unsigned int index, const float plane[4]);
 
-		// Partial transform
-		void setModelMatrix(const Matrix &M, int i = 0);
-		void setViewMatrix(const Matrix &V);
-		void setBaseMatrix(const Matrix &B);
-		void setProjectionMatrix(const Matrix &P);
-
 		void addQuery(Query *query);
 		void removeQuery(Query *query);
 
@@ -357,9 +343,6 @@
 		void initializeThreads();
 		void terminateThreads();
 
-		void loadConstants(const VertexShader *vertexShader);
-		void loadConstants(const PixelShader *pixelShader);
-
 		Context *context;
 		Clipper *clipper;
 		Blitter *blitter;
@@ -459,15 +442,6 @@
 		Resource *texture[TOTAL_IMAGE_UNITS];
 		Resource* pUniformBuffers[MAX_UNIFORM_BUFFER_BINDINGS];
 		Resource* vUniformBuffers[MAX_UNIFORM_BUFFER_BINDINGS];
-		Resource* transformFeedbackBuffers[MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS];
-
-		unsigned int vsDirtyConstF;
-		unsigned int vsDirtyConstI;
-		unsigned int vsDirtyConstB;
-
-		unsigned int psDirtyConstF;
-		unsigned int psDirtyConstI;
-		unsigned int psDirtyConstB;
 
 		std::list<Query*> *queries;
 
diff --git a/src/Device/SetupProcessor.cpp b/src/Device/SetupProcessor.cpp
index a638a0d..800d320 100644
--- a/src/Device/SetupProcessor.cpp
+++ b/src/Device/SetupProcessor.cpp
@@ -21,6 +21,7 @@
 #include "Pipeline/SetupRoutine.hpp"
 #include "Pipeline/Constants.hpp"
 #include "Vulkan/VkDebug.hpp"
+#include "Pipeline/SpirvShader.hpp"
 
 namespace sw
 {
@@ -73,7 +74,7 @@
 	{
 		State state;
 
-		bool vPosZW = (context->pixelShader && context->pixelShader->isVPosDeclared() && fullPixelPositionRegister);
+		bool vPosZW = (context->pixelShader && context->pixelShader->hasBuiltinInput(spv::BuiltInPosition));
 
 		state.isDrawPoint = context->isDrawPoint();
 		state.isDrawLine = context->isDrawLine();
@@ -84,7 +85,7 @@
 		state.cullMode = context->cullMode;
 		state.twoSidedStencil = context->stencilActive() && context->twoSidedStencil;
 		state.slopeDepthBias = context->slopeDepthBias != 0.0f;
-		state.vFace = context->pixelShader && context->pixelShader->isVFaceDeclared();
+		state.vFace = context->pixelShader && context->pixelShader->hasBuiltinInput(spv::BuiltInFrontFacing);
 
 		state.positionRegister = Pos;
 		state.pointSizeRegister = Unused;
@@ -92,8 +93,9 @@
 		state.multiSample = context->getMultiSampleCount();
 		state.rasterizerDiscard = context->rasterizerDiscard;
 
-		state.positionRegister = context->vertexShader->getPositionRegister();
-		state.pointSizeRegister = context->vertexShader->getPointSizeRegister();
+		//TODO: route properly
+		state.positionRegister = 0;//context->vertexShader->getPositionRegister();
+		state.pointSizeRegister = 1;//context->vertexShader->getPointSizeRegister();
 
 		for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
 		{
@@ -107,37 +109,37 @@
 
 		const bool point = context->isDrawPoint();
 
-		for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
-		{
-			for(int component = 0; component < 4; component++)
-			{
-				const Shader::Semantic& semantic = context->pixelShader->getInput(interpolant, component);
-
-				if(semantic.active())
-				{
-					int input = interpolant;
-					for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++)
-					{
-						if(semantic == context->vertexShader->getOutput(i, component))
-						{
-							input = i;
-							break;
-						}
-					}
-
-					bool flat = point;
-
-					switch(semantic.usage)
-					{
-					case Shader::USAGE_TEXCOORD: flat = false;                  break;
-					case Shader::USAGE_COLOR:    flat = semantic.flat || point; break;
-					}
-
-					state.gradient[interpolant][component].attribute = input;
-					state.gradient[interpolant][component].flat = flat;
-				}
-			}
-		}
+//		for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
+//		{
+//			for(int component = 0; component < 4; component++)
+//			{
+//				const Shader::Semantic& semantic = context->pixelShader->getInput(interpolant, component);
+//
+//				if(semantic.active())
+//				{
+//					int input = interpolant;
+//					for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++)
+//					{
+//						if(semantic == context->vertexShader->getOutput(i, component))
+//						{
+//							input = i;
+//							break;
+//						}
+//					}
+//
+//					bool flat = point;
+//
+//					switch(semantic.usage)
+//					{
+//					case Shader::USAGE_TEXCOORD: flat = false;                  break;
+//					case Shader::USAGE_COLOR:    flat = semantic.flat || point; break;
+//					}
+//
+//					state.gradient[interpolant][component].attribute = input;
+//					state.gradient[interpolant][component].flat = flat;
+//				}
+//			}
+//		}
 
 		state.hash = state.computeHash();
 
diff --git a/src/Device/SetupProcessor.hpp b/src/Device/SetupProcessor.hpp
index 622a053..797c362 100644
--- a/src/Device/SetupProcessor.hpp
+++ b/src/Device/SetupProcessor.hpp
@@ -17,8 +17,6 @@
 
 #include "Context.hpp"
 #include "RoutineCache.hpp"
-#include "Pipeline/VertexShader.hpp"
-#include "Pipeline/PixelShader.hpp"
 #include "System/Types.hpp"
 
 namespace sw
diff --git a/src/Device/VertexProcessor.cpp b/src/Device/VertexProcessor.cpp
index deacc28..854c023 100644
--- a/src/Device/VertexProcessor.cpp
+++ b/src/Device/VertexProcessor.cpp
@@ -15,8 +15,6 @@
 #include "VertexProcessor.hpp"
 
 #include "Pipeline/VertexProgram.hpp"
-#include "Pipeline/VertexShader.hpp"
-#include "Pipeline/PixelShader.hpp"
 #include "Pipeline/Constants.hpp"
 #include "System/Math.hpp"
 #include "Vulkan/VkDebug.hpp"
@@ -63,16 +61,6 @@
 		return memcmp(static_cast<const States*>(this), static_cast<const States*>(&state), sizeof(States)) == 0;
 	}
 
-	VertexProcessor::TransformFeedbackInfo::TransformFeedbackInfo()
-	{
-		buffer = nullptr;
-		offset = 0;
-		reg = 0;
-		row = 0;
-		col = 0;
-		stride = 0;
-	}
-
 	VertexProcessor::UniformBufferInfo::UniformBufferInfo()
 	{
 		buffer = nullptr;
@@ -152,29 +140,6 @@
 		}
 	}
 
-	void VertexProcessor::setTransformFeedbackBuffer(int index, sw::Resource* buffer, int offset, unsigned int reg, unsigned int row, unsigned int col, unsigned int stride)
-	{
-		transformFeedbackInfo[index].buffer = buffer;
-		transformFeedbackInfo[index].offset = offset;
-		transformFeedbackInfo[index].reg = reg;
-		transformFeedbackInfo[index].row = row;
-		transformFeedbackInfo[index].col = col;
-		transformFeedbackInfo[index].stride = stride;
-	}
-
-	void VertexProcessor::lockTransformFeedbackBuffers(byte** t, unsigned int* v, unsigned int* r, unsigned int* c, unsigned int* s, sw::Resource* transformFeedbackBuffers[])
-	{
-		for(int i = 0; i < MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS; ++i)
-		{
-			t[i] = transformFeedbackInfo[i].buffer ? static_cast<byte*>(transformFeedbackInfo[i].buffer->lock(PUBLIC, PRIVATE)) + transformFeedbackInfo[i].offset : nullptr;
-			transformFeedbackBuffers[i] = transformFeedbackInfo[i].buffer;
-			v[i] = transformFeedbackInfo[i].reg;
-			r[i] = transformFeedbackInfo[i].row;
-			c[i] = transformFeedbackInfo[i].col;
-			s[i] = transformFeedbackInfo[i].stride;
-		}
-	}
-
 	void VertexProcessor::setInstanceID(int instanceID)
 	{
 		context->instanceID = instanceID;
@@ -370,16 +335,6 @@
 		this->pointSizeMax = pointSizeMax;
 	}
 
-	void VertexProcessor::setTransformFeedbackQueryEnabled(bool enable)
-	{
-		context->transformFeedbackQueryEnabled = enable;
-	}
-
-	void VertexProcessor::enableTransformFeedback(uint64_t enable)
-	{
-		context->transformFeedbackEnabled = enable;
-	}
-
 	void VertexProcessor::setRoutineCacheSize(int cacheSize)
 	{
 		delete routineCache;
@@ -391,49 +346,13 @@
 		State state;
 
 		state.shaderID = context->vertexShader->getSerialID();
-
-		state.fixedFunction = !context->vertexShader && context->pixelShaderModel() < 0x0300;
-		state.textureSampling = context->vertexShader ? context->vertexShader->containsTextureSampling() : false;
-		state.positionRegister = context->vertexShader ? context->vertexShader->getPositionRegister() : Pos;
-		state.pointSizeRegister = context->vertexShader ? context->vertexShader->getPointSizeRegister() : Pts;
-
 		state.multiSampling = context->getMultiSampleCount() > 1;
 
-		state.transformFeedbackQueryEnabled = context->transformFeedbackQueryEnabled;
-		state.transformFeedbackEnabled = context->transformFeedbackEnabled;
-
 		// Note: Quads aren't handled for verticesPerPrimitive, but verticesPerPrimitive is used for transform feedback,
 		//       which is an OpenGL ES 3.0 feature, and OpenGL ES 3.0 doesn't support quads as a primitive type.
 		DrawType type = static_cast<DrawType>(static_cast<unsigned int>(drawType) & 0xF);
 		state.verticesPerPrimitive = 1 + (type >= DRAW_LINELIST) + (type >= DRAW_TRIANGLELIST);
 
-		for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
-		{
-			state.input[i].type = context->input[i].type;
-			state.input[i].count = context->input[i].count;
-			state.input[i].normalized = context->input[i].normalized;
-			state.input[i].attribType = context->vertexShader ? context->vertexShader->getAttribType(i) : SpirvShader::ATTRIBTYPE_FLOAT;
-		}
-
-		for(unsigned int i = 0; i < VERTEX_TEXTURE_IMAGE_UNITS; i++)
-		{
-			if(context->vertexShader->usesSampler(i))
-			{
-				state.sampler[i] = context->sampler[TEXTURE_IMAGE_UNITS + i].samplerState();
-			}
-		}
-
-		if(context->vertexShader)   // FIXME: Also when pre-transformed?
-		{
-			for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++)
-			{
-				state.output[i].xWrite = context->vertexShader->getOutput(i, 0).active();
-				state.output[i].yWrite = context->vertexShader->getOutput(i, 1).active();
-				state.output[i].zWrite = context->vertexShader->getOutput(i, 2).active();
-				state.output[i].wWrite = context->vertexShader->getOutput(i, 3).active();
-			}
-		}
-
 		state.hash = state.computeHash();
 
 		return state;
diff --git a/src/Device/VertexProcessor.hpp b/src/Device/VertexProcessor.hpp
index 7a14864..51dbd5c 100644
--- a/src/Device/VertexProcessor.hpp
+++ b/src/Device/VertexProcessor.hpp
@@ -18,7 +18,6 @@
 #include "Matrix.hpp"
 #include "Context.hpp"
 #include "RoutineCache.hpp"
-#include "Pipeline/VertexShader.hpp"
 #include "Pipeline/SpirvShader.hpp"
 
 namespace sw
@@ -51,13 +50,9 @@
 
 			uint64_t shaderID;
 
-			bool fixedFunction             : 1;   // TODO: Eliminate by querying shader.
 			bool textureSampling           : 1;   // TODO: Eliminate by querying shader.
 			unsigned int positionRegister  : BITS(MAX_VERTEX_OUTPUTS);   // TODO: Eliminate by querying shader.
 			unsigned int pointSizeRegister : BITS(MAX_VERTEX_OUTPUTS);   // TODO: Eliminate by querying shader.
-
-			bool transformFeedbackQueryEnabled                : 1;
-			uint64_t transformFeedbackEnabled                 : 64;
 			unsigned char verticesPerPrimitive                : 2; // 1 (points), 2 (lines) or 3 (triangles)
 
 			bool multiSampling  : 1;
@@ -164,9 +159,6 @@
 		void setPointSizeMin(float pointSizeMin);
 		void setPointSizeMax(float pointSizeMax);
 
-		void setTransformFeedbackQueryEnabled(bool enable);
-		void enableTransformFeedback(uint64_t enable);
-
 	protected:
 		const State update(DrawType drawType);
 		Routine *routine(const State &state);
@@ -191,19 +183,6 @@
 		};
 		UniformBufferInfo uniformBufferInfo[MAX_UNIFORM_BUFFER_BINDINGS];
 
-		struct TransformFeedbackInfo
-		{
-			TransformFeedbackInfo();
-
-			Resource* buffer;
-			unsigned int offset;
-			unsigned int reg;
-			unsigned int row;
-			unsigned int col;
-			unsigned int stride;
-		};
-		TransformFeedbackInfo transformFeedbackInfo[MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS];
-
 		Context *const context;
 
 		RoutineCache<State> *routineCache;
diff --git a/src/Pipeline/PixelProgram.cpp b/src/Pipeline/PixelProgram.cpp
index 4ebe3e0..901e5ec 100644
--- a/src/Pipeline/PixelProgram.cpp
+++ b/src/Pipeline/PixelProgram.cpp
@@ -21,61 +21,18 @@
 namespace sw
 {
 	extern bool postBlendSRGB;
-	extern bool booleanFaceRegister;
-	extern bool halfIntegerCoordinates;     // Pixel centers are not at integer coordinates
-	extern bool fullPixelPositionRegister;
 
 	void PixelProgram::setBuiltins(Int &x, Int &y, Float4(&z)[4], Float4 &w)
 	{
-		if(shader->getShaderModel() >= 0x0300)
-		{
-			if(shader->isVPosDeclared())
-			{
-				if(!halfIntegerCoordinates)
-				{
-					vPos.x = Float4(Float(x)) + Float4(0, 1, 0, 1);
-					vPos.y = Float4(Float(y)) + Float4(0, 0, 1, 1);
-				}
-				else
-				{
-					vPos.x = Float4(Float(x)) + Float4(0.5f, 1.5f, 0.5f, 1.5f);
-					vPos.y = Float4(Float(y)) + Float4(0.5f, 0.5f, 1.5f, 1.5f);
-				}
-
-				if(fullPixelPositionRegister)
-				{
-					vPos.z = z[0]; // FIXME: Centroid?
-					vPos.w = w;    // FIXME: Centroid?
-				}
-			}
-
-			if(shader->isVFaceDeclared())
-			{
-				Float4 face = *Pointer<Float>(primitive + OFFSET(Primitive, area));
-
-				if(booleanFaceRegister)
-				{
-					face = As<Float4>(state.frontFaceCCW ? CmpNLT(face, Float4(0.0f)) : CmpLT(face, Float4(0.0f)));
-				}
-
-				vFace.x = face;
-				vFace.y = face;
-				vFace.z = face;
-				vFace.w = face;
-			}
-		}
+		// TODO: wire up builtins correctly
 	}
 
 	void PixelProgram::applyShader(Int cMask[4])
 	{
 		enableIndex = 0;
-		stackIndex = 0;
 
-		if(shader->containsLeaveInstruction())
-		{
-			enableLeave = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
-		}
-
+		// For our own sanity, ensure color outputs are written,
+		// even if the shader neglects to write them.
 		for(int i = 0; i < RENDERTARGETS; i++)
 		{
 			if(state.targetFormat[i] != VK_FORMAT_UNDEFINED)
@@ -84,487 +41,11 @@
 			}
 		}
 
-		// Create all call site return blocks up front
-		for(size_t i = 0; i < shader->getLength(); i++)
+		// TODO: Emit code for the actual shader here.
+
+		for(int i = 0; i < RENDERTARGETS; i++)
 		{
-			const Shader::Instruction *instruction = shader->getInstruction(i);
-			Shader::Opcode opcode = instruction->opcode;
-
-			if(opcode == Shader::OPCODE_CALL || opcode == Shader::OPCODE_CALLNZ)
-			{
-				const Dst &dst = instruction->dst;
-
-				ASSERT(callRetBlock[dst.label].size() == dst.callSite);
-				callRetBlock[dst.label].push_back(Nucleus::createBasicBlock());
-			}
-		}
-
-		bool broadcastColor0 = true;
-
-		for(size_t i = 0; i < shader->getLength(); i++)
-		{
-			const Shader::Instruction *instruction = shader->getInstruction(i);
-			Shader::Opcode opcode = instruction->opcode;
-
-			if(opcode == Shader::OPCODE_DCL || opcode == Shader::OPCODE_DEF || opcode == Shader::OPCODE_DEFI || opcode == Shader::OPCODE_DEFB)
-			{
-				continue;
-			}
-
-			const Dst &dst = instruction->dst;
-			const Src &src0 = instruction->src[0];
-			const Src &src1 = instruction->src[1];
-			const Src &src2 = instruction->src[2];
-			const Src &src3 = instruction->src[3];
-			const Src &src4 = instruction->src[4];
-
-			bool predicate = instruction->predicate;
-			Control control = instruction->control;
-			bool pp = dst.partialPrecision;
-			bool project = instruction->project;
-			bool bias = instruction->bias;
-
-			Vector4f d;
-			Vector4f s0;
-			Vector4f s1;
-			Vector4f s2;
-			Vector4f s3;
-			Vector4f s4;
-
-			if(opcode == Shader::OPCODE_TEXKILL)   // Takes destination as input
-			{
-				if(dst.type == Shader::PARAMETER_TEXTURE)
-				{
-					d.x = v[2 + dst.index].x;
-					d.y = v[2 + dst.index].y;
-					d.z = v[2 + dst.index].z;
-					d.w = v[2 + dst.index].w;
-				}
-				else
-				{
-					d = r[dst.index];
-				}
-			}
-
-			if(src0.type != Shader::PARAMETER_VOID) s0 = fetchRegister(src0);
-			if(src1.type != Shader::PARAMETER_VOID) s1 = fetchRegister(src1);
-			if(src2.type != Shader::PARAMETER_VOID) s2 = fetchRegister(src2);
-			if(src3.type != Shader::PARAMETER_VOID) s3 = fetchRegister(src3);
-			if(src4.type != Shader::PARAMETER_VOID) s4 = fetchRegister(src4);
-
-			switch(opcode)
-			{
-			case Shader::OPCODE_PS_2_0:                                                    break;
-			case Shader::OPCODE_PS_2_x:                                                    break;
-			case Shader::OPCODE_PS_3_0:                                                    break;
-			case Shader::OPCODE_DEF:                                                       break;
-			case Shader::OPCODE_DCL:                                                       break;
-			case Shader::OPCODE_NOP:                                                       break;
-			case Shader::OPCODE_MOV:        mov(d, s0);                                    break;
-			case Shader::OPCODE_NEG:        neg(d, s0);                                    break;
-			case Shader::OPCODE_INEG:       ineg(d, s0);                                   break;
-			case Shader::OPCODE_F2B:        f2b(d, s0);                                    break;
-			case Shader::OPCODE_B2F:        b2f(d, s0);                                    break;
-			case Shader::OPCODE_F2I:        f2i(d, s0);                                    break;
-			case Shader::OPCODE_I2F:        i2f(d, s0);                                    break;
-			case Shader::OPCODE_F2U:        f2u(d, s0);                                    break;
-			case Shader::OPCODE_U2F:        u2f(d, s0);                                    break;
-			case Shader::OPCODE_I2B:        i2b(d, s0);                                    break;
-			case Shader::OPCODE_B2I:        b2i(d, s0);                                    break;
-			case Shader::OPCODE_ADD:        add(d, s0, s1);                                break;
-			case Shader::OPCODE_IADD:       iadd(d, s0, s1);                               break;
-			case Shader::OPCODE_SUB:        sub(d, s0, s1);                                break;
-			case Shader::OPCODE_ISUB:       isub(d, s0, s1);                               break;
-			case Shader::OPCODE_MUL:        mul(d, s0, s1);                                break;
-			case Shader::OPCODE_IMUL:       imul(d, s0, s1);                               break;
-			case Shader::OPCODE_MAD:        mad(d, s0, s1, s2);                            break;
-			case Shader::OPCODE_IMAD:       imad(d, s0, s1, s2);                           break;
-			case Shader::OPCODE_DP1:        dp1(d, s0, s1);                                break;
-			case Shader::OPCODE_DP2:        dp2(d, s0, s1);                                break;
-			case Shader::OPCODE_DP2ADD:     dp2add(d, s0, s1, s2);                         break;
-			case Shader::OPCODE_DP3:        dp3(d, s0, s1);                                break;
-			case Shader::OPCODE_DP4:        dp4(d, s0, s1);                                break;
-			case Shader::OPCODE_DET2:       det2(d, s0, s1);                               break;
-			case Shader::OPCODE_DET3:       det3(d, s0, s1, s2);                           break;
-			case Shader::OPCODE_DET4:       det4(d, s0, s1, s2, s3);                       break;
-			case Shader::OPCODE_CMP0:       cmp0(d, s0, s1, s2);                           break;
-			case Shader::OPCODE_ICMP:       icmp(d, s0, s1, control);                      break;
-			case Shader::OPCODE_UCMP:       ucmp(d, s0, s1, control);                      break;
-			case Shader::OPCODE_SELECT:     select(d, s0, s1, s2);                         break;
-			case Shader::OPCODE_EXTRACT:    extract(d.x, s0, s1.x);                        break;
-			case Shader::OPCODE_INSERT:     insert(d, s0, s1.x, s2.x);                     break;
-			case Shader::OPCODE_FRC:        frc(d, s0);                                    break;
-			case Shader::OPCODE_TRUNC:      trunc(d, s0);                                  break;
-			case Shader::OPCODE_FLOOR:      floor(d, s0);                                  break;
-			case Shader::OPCODE_ROUND:      round(d, s0);                                  break;
-			case Shader::OPCODE_ROUNDEVEN:  roundEven(d, s0);                              break;
-			case Shader::OPCODE_CEIL:       ceil(d, s0);                                   break;
-			case Shader::OPCODE_EXP2X:      exp2x(d, s0, pp);                              break;
-			case Shader::OPCODE_EXP2:       exp2(d, s0, pp);                               break;
-			case Shader::OPCODE_LOG2X:      log2x(d, s0, pp);                              break;
-			case Shader::OPCODE_LOG2:       log2(d, s0, pp);                               break;
-			case Shader::OPCODE_EXP:        exp(d, s0, pp);                                break;
-			case Shader::OPCODE_LOG:        log(d, s0, pp);                                break;
-			case Shader::OPCODE_RCPX:       rcpx(d, s0, pp);                               break;
-			case Shader::OPCODE_DIV:        div(d, s0, s1);                                break;
-			case Shader::OPCODE_IDIV:       idiv(d, s0, s1);                               break;
-			case Shader::OPCODE_UDIV:       udiv(d, s0, s1);                               break;
-			case Shader::OPCODE_MOD:        mod(d, s0, s1);                                break;
-			case Shader::OPCODE_IMOD:       imod(d, s0, s1);                               break;
-			case Shader::OPCODE_UMOD:       umod(d, s0, s1);                               break;
-			case Shader::OPCODE_SHL:        shl(d, s0, s1);                                break;
-			case Shader::OPCODE_ISHR:       ishr(d, s0, s1);                               break;
-			case Shader::OPCODE_USHR:       ushr(d, s0, s1);                               break;
-			case Shader::OPCODE_RSQX:       rsqx(d, s0, pp);                               break;
-			case Shader::OPCODE_SQRT:       sqrt(d, s0, pp);                               break;
-			case Shader::OPCODE_RSQ:        rsq(d, s0, pp);                                break;
-			case Shader::OPCODE_LEN2:       len2(d.x, s0, pp);                             break;
-			case Shader::OPCODE_LEN3:       len3(d.x, s0, pp);                             break;
-			case Shader::OPCODE_LEN4:       len4(d.x, s0, pp);                             break;
-			case Shader::OPCODE_DIST1:      dist1(d.x, s0, s1, pp);                        break;
-			case Shader::OPCODE_DIST2:      dist2(d.x, s0, s1, pp);                        break;
-			case Shader::OPCODE_DIST3:      dist3(d.x, s0, s1, pp);                        break;
-			case Shader::OPCODE_DIST4:      dist4(d.x, s0, s1, pp);                        break;
-			case Shader::OPCODE_MIN:        min(d, s0, s1);                                break;
-			case Shader::OPCODE_IMIN:       imin(d, s0, s1);                               break;
-			case Shader::OPCODE_UMIN:       umin(d, s0, s1);                               break;
-			case Shader::OPCODE_MAX:        max(d, s0, s1);                                break;
-			case Shader::OPCODE_IMAX:       imax(d, s0, s1);                               break;
-			case Shader::OPCODE_UMAX:       umax(d, s0, s1);                               break;
-			case Shader::OPCODE_LRP:        lrp(d, s0, s1, s2);                            break;
-			case Shader::OPCODE_STEP:       step(d, s0, s1);                               break;
-			case Shader::OPCODE_SMOOTH:     smooth(d, s0, s1, s2);                         break;
-			case Shader::OPCODE_ISINF:      isinf(d, s0);                                  break;
-			case Shader::OPCODE_ISNAN:      isnan(d, s0);                                  break;
-			case Shader::OPCODE_FLOATBITSTOINT:
-			case Shader::OPCODE_FLOATBITSTOUINT:
-			case Shader::OPCODE_INTBITSTOFLOAT:
-			case Shader::OPCODE_UINTBITSTOFLOAT: d = s0;                                   break;
-			case Shader::OPCODE_PACKSNORM2x16:   packSnorm2x16(d, s0);                     break;
-			case Shader::OPCODE_PACKUNORM2x16:   packUnorm2x16(d, s0);                     break;
-			case Shader::OPCODE_PACKHALF2x16:    packHalf2x16(d, s0);                      break;
-			case Shader::OPCODE_UNPACKSNORM2x16: unpackSnorm2x16(d, s0);                   break;
-			case Shader::OPCODE_UNPACKUNORM2x16: unpackUnorm2x16(d, s0);                   break;
-			case Shader::OPCODE_UNPACKHALF2x16:  unpackHalf2x16(d, s0);                    break;
-			case Shader::OPCODE_POWX:       powx(d, s0, s1, pp);                           break;
-			case Shader::OPCODE_POW:        pow(d, s0, s1, pp);                            break;
-			case Shader::OPCODE_SGN:        sgn(d, s0);                                    break;
-			case Shader::OPCODE_ISGN:       isgn(d, s0);                                   break;
-			case Shader::OPCODE_CRS:        crs(d, s0, s1);                                break;
-			case Shader::OPCODE_FORWARD1:   forward1(d, s0, s1, s2);                       break;
-			case Shader::OPCODE_FORWARD2:   forward2(d, s0, s1, s2);                       break;
-			case Shader::OPCODE_FORWARD3:   forward3(d, s0, s1, s2);                       break;
-			case Shader::OPCODE_FORWARD4:   forward4(d, s0, s1, s2);                       break;
-			case Shader::OPCODE_REFLECT1:   reflect1(d, s0, s1);                           break;
-			case Shader::OPCODE_REFLECT2:   reflect2(d, s0, s1);                           break;
-			case Shader::OPCODE_REFLECT3:   reflect3(d, s0, s1);                           break;
-			case Shader::OPCODE_REFLECT4:   reflect4(d, s0, s1);                           break;
-			case Shader::OPCODE_REFRACT1:   refract1(d, s0, s1, s2.x);                     break;
-			case Shader::OPCODE_REFRACT2:   refract2(d, s0, s1, s2.x);                     break;
-			case Shader::OPCODE_REFRACT3:   refract3(d, s0, s1, s2.x);                     break;
-			case Shader::OPCODE_REFRACT4:   refract4(d, s0, s1, s2.x);                     break;
-			case Shader::OPCODE_NRM2:       nrm2(d, s0, pp);                               break;
-			case Shader::OPCODE_NRM3:       nrm3(d, s0, pp);                               break;
-			case Shader::OPCODE_NRM4:       nrm4(d, s0, pp);                               break;
-			case Shader::OPCODE_ABS:        abs(d, s0);                                    break;
-			case Shader::OPCODE_IABS:       iabs(d, s0);                                   break;
-			case Shader::OPCODE_SINCOS:     sincos(d, s0, pp);                             break;
-			case Shader::OPCODE_COS:        cos(d, s0, pp);                                break;
-			case Shader::OPCODE_SIN:        sin(d, s0, pp);                                break;
-			case Shader::OPCODE_TAN:        tan(d, s0, pp);                                break;
-			case Shader::OPCODE_ACOS:       acos(d, s0, pp);                               break;
-			case Shader::OPCODE_ASIN:       asin(d, s0, pp);                               break;
-			case Shader::OPCODE_ATAN:       atan(d, s0, pp);                               break;
-			case Shader::OPCODE_ATAN2:      atan2(d, s0, s1, pp);                          break;
-			case Shader::OPCODE_COSH:       cosh(d, s0, pp);                               break;
-			case Shader::OPCODE_SINH:       sinh(d, s0, pp);                               break;
-			case Shader::OPCODE_TANH:       tanh(d, s0, pp);                               break;
-			case Shader::OPCODE_ACOSH:      acosh(d, s0, pp);                              break;
-			case Shader::OPCODE_ASINH:      asinh(d, s0, pp);                              break;
-			case Shader::OPCODE_ATANH:      atanh(d, s0, pp);                              break;
-			case Shader::OPCODE_M4X4:       M4X4(d, s0, src1);                             break;
-			case Shader::OPCODE_M4X3:       M4X3(d, s0, src1);                             break;
-			case Shader::OPCODE_M3X4:       M3X4(d, s0, src1);                             break;
-			case Shader::OPCODE_M3X3:       M3X3(d, s0, src1);                             break;
-			case Shader::OPCODE_M3X2:       M3X2(d, s0, src1);                             break;
-			case Shader::OPCODE_TEX:        TEX(d, s0, src1, project, bias);               break;
-			case Shader::OPCODE_TEXLDD:     TEXGRAD(d, s0, src1, s2, s3);                  break;
-			case Shader::OPCODE_TEXLDL:     TEXLOD(d, s0, src1, s0.w);                     break;
-			case Shader::OPCODE_TEXLOD:     TEXLOD(d, s0, src1, s2.x);                     break;
-			case Shader::OPCODE_TEXSIZE:    TEXSIZE(d, s0.x, src1);                        break;
-			case Shader::OPCODE_TEXKILL:    TEXKILL(cMask, d, dst.mask);                   break;
-			case Shader::OPCODE_TEXOFFSET:  TEXOFFSET(d, s0, src1, s2);                    break;
-			case Shader::OPCODE_TEXLODOFFSET: TEXLODOFFSET(d, s0, src1, s2, s3.x);         break;
-			case Shader::OPCODE_TEXELFETCH: TEXELFETCH(d, s0, src1, s2.x);                 break;
-			case Shader::OPCODE_TEXELFETCHOFFSET: TEXELFETCHOFFSET(d, s0, src1, s2, s3.x); break;
-			case Shader::OPCODE_TEXGRAD:    TEXGRAD(d, s0, src1, s2, s3);                  break;
-			case Shader::OPCODE_TEXGRADOFFSET: TEXGRADOFFSET(d, s0, src1, s2, s3, s4);     break;
-			case Shader::OPCODE_TEXBIAS:    TEXBIAS(d, s0, src1, s2.x);                    break;
-			case Shader::OPCODE_TEXOFFSETBIAS: TEXOFFSETBIAS(d, s0, src1, s2, s3.x);       break;
-			case Shader::OPCODE_DISCARD:    DISCARD(cMask, instruction);                   break;
-			case Shader::OPCODE_DFDX:       DFDX(d, s0);                                   break;
-			case Shader::OPCODE_DFDY:       DFDY(d, s0);                                   break;
-			case Shader::OPCODE_FWIDTH:     FWIDTH(d, s0);                                 break;
-			case Shader::OPCODE_BREAK:      BREAK();                                       break;
-			case Shader::OPCODE_BREAKC:     BREAKC(s0, s1, control);                       break;
-			case Shader::OPCODE_BREAKP:     BREAKP(src0);                                  break;
-			case Shader::OPCODE_CONTINUE:   CONTINUE();                                    break;
-			case Shader::OPCODE_TEST:       TEST();                                        break;
-			case Shader::OPCODE_CALL:       CALL(dst.label, dst.callSite);                 break;
-			case Shader::OPCODE_CALLNZ:     CALLNZ(dst.label, dst.callSite, src0);         break;
-			case Shader::OPCODE_ELSE:       ELSE();                                        break;
-			case Shader::OPCODE_ENDIF:      ENDIF();                                       break;
-			case Shader::OPCODE_ENDLOOP:    ENDLOOP();                                     break;
-			case Shader::OPCODE_ENDREP:     ENDREP();                                      break;
-			case Shader::OPCODE_ENDWHILE:   ENDWHILE();                                    break;
-			case Shader::OPCODE_ENDSWITCH:  ENDSWITCH();                                   break;
-			case Shader::OPCODE_IF:         IF(src0);                                      break;
-			case Shader::OPCODE_IFC:        IFC(s0, s1, control);                          break;
-			case Shader::OPCODE_LABEL:      LABEL(dst.index);                              break;
-			case Shader::OPCODE_LOOP:       LOOP(src1);                                    break;
-			case Shader::OPCODE_REP:        REP(src0);                                     break;
-			case Shader::OPCODE_WHILE:      WHILE(src0);                                   break;
-			case Shader::OPCODE_SWITCH:     SWITCH();                                      break;
-			case Shader::OPCODE_RET:        RET();                                         break;
-			case Shader::OPCODE_LEAVE:      LEAVE();                                       break;
-			case Shader::OPCODE_CMP:        cmp(d, s0, s1, control);                       break;
-			case Shader::OPCODE_ALL:        all(d.x, s0);                                  break;
-			case Shader::OPCODE_ANY:        any(d.x, s0);                                  break;
-			case Shader::OPCODE_NOT:        bitwise_not(d, s0);                            break;
-			case Shader::OPCODE_OR:         bitwise_or(d, s0, s1);                         break;
-			case Shader::OPCODE_XOR:        bitwise_xor(d, s0, s1);                        break;
-			case Shader::OPCODE_AND:        bitwise_and(d, s0, s1);                        break;
-			case Shader::OPCODE_EQ:         equal(d, s0, s1);                              break;
-			case Shader::OPCODE_NE:         notEqual(d, s0, s1);                           break;
-			case Shader::OPCODE_END:                                                       break;
-			default:
-				ASSERT(false);
-			}
-
-			if(dst.type != Shader::PARAMETER_VOID && dst.type != Shader::PARAMETER_LABEL && opcode != Shader::OPCODE_TEXKILL && opcode != Shader::OPCODE_NOP)
-			{
-				if(dst.saturate)
-				{
-					if(dst.x) d.x = Max(d.x, Float4(0.0f));
-					if(dst.y) d.y = Max(d.y, Float4(0.0f));
-					if(dst.z) d.z = Max(d.z, Float4(0.0f));
-					if(dst.w) d.w = Max(d.w, Float4(0.0f));
-
-					if(dst.x) d.x = Min(d.x, Float4(1.0f));
-					if(dst.y) d.y = Min(d.y, Float4(1.0f));
-					if(dst.z) d.z = Min(d.z, Float4(1.0f));
-					if(dst.w) d.w = Min(d.w, Float4(1.0f));
-				}
-
-				if(instruction->isPredicated())
-				{
-					Vector4f pDst;   // FIXME: Rename
-
-					switch(dst.type)
-					{
-					case Shader::PARAMETER_TEMP:
-						if(dst.rel.type == Shader::PARAMETER_VOID)
-						{
-							if(dst.x) pDst.x = r[dst.index].x;
-							if(dst.y) pDst.y = r[dst.index].y;
-							if(dst.z) pDst.z = r[dst.index].z;
-							if(dst.w) pDst.w = r[dst.index].w;
-						}
-						else if(!dst.rel.dynamic)
-						{
-							Int a = dst.index + relativeAddress(dst.rel);
-
-							if(dst.x) pDst.x = r[a].x;
-							if(dst.y) pDst.y = r[a].y;
-							if(dst.z) pDst.z = r[a].z;
-							if(dst.w) pDst.w = r[a].w;
-						}
-						else
-						{
-							Int4 a = dst.index + dynamicAddress(dst.rel);
-
-							if(dst.x) pDst.x = r[a].x;
-							if(dst.y) pDst.y = r[a].y;
-							if(dst.z) pDst.z = r[a].z;
-							if(dst.w) pDst.w = r[a].w;
-						}
-						break;
-					case Shader::PARAMETER_COLOROUT:
-						if(dst.rel.type == Shader::PARAMETER_VOID)
-						{
-							if(dst.x) pDst.x = oC[dst.index].x;
-							if(dst.y) pDst.y = oC[dst.index].y;
-							if(dst.z) pDst.z = oC[dst.index].z;
-							if(dst.w) pDst.w = oC[dst.index].w;
-						}
-						else if(!dst.rel.dynamic)
-						{
-							Int a = dst.index + relativeAddress(dst.rel);
-
-							if(dst.x) pDst.x = oC[a].x;
-							if(dst.y) pDst.y = oC[a].y;
-							if(dst.z) pDst.z = oC[a].z;
-							if(dst.w) pDst.w = oC[a].w;
-						}
-						else
-						{
-							Int4 a = dst.index + dynamicAddress(dst.rel);
-
-							if(dst.x) pDst.x = oC[a].x;
-							if(dst.y) pDst.y = oC[a].y;
-							if(dst.z) pDst.z = oC[a].z;
-							if(dst.w) pDst.w = oC[a].w;
-						}
-						break;
-					case Shader::PARAMETER_PREDICATE:
-						if(dst.x) pDst.x = p0.x;
-						if(dst.y) pDst.y = p0.y;
-						if(dst.z) pDst.z = p0.z;
-						if(dst.w) pDst.w = p0.w;
-						break;
-					case Shader::PARAMETER_DEPTHOUT:
-						pDst.x = oDepth;
-						break;
-					default:
-						ASSERT(false);
-					}
-
-					Int4 enable = enableMask(instruction);
-
-					Int4 xEnable = enable;
-					Int4 yEnable = enable;
-					Int4 zEnable = enable;
-					Int4 wEnable = enable;
-
-					if(predicate)
-					{
-						unsigned char pSwizzle = instruction->predicateSwizzle;
-
-						Float4 xPredicate = p0[(pSwizzle >> 0) & 0x03];
-						Float4 yPredicate = p0[(pSwizzle >> 2) & 0x03];
-						Float4 zPredicate = p0[(pSwizzle >> 4) & 0x03];
-						Float4 wPredicate = p0[(pSwizzle >> 6) & 0x03];
-
-						if(!instruction->predicateNot)
-						{
-							if(dst.x) xEnable = xEnable & As<Int4>(xPredicate);
-							if(dst.y) yEnable = yEnable & As<Int4>(yPredicate);
-							if(dst.z) zEnable = zEnable & As<Int4>(zPredicate);
-							if(dst.w) wEnable = wEnable & As<Int4>(wPredicate);
-						}
-						else
-						{
-							if(dst.x) xEnable = xEnable & ~As<Int4>(xPredicate);
-							if(dst.y) yEnable = yEnable & ~As<Int4>(yPredicate);
-							if(dst.z) zEnable = zEnable & ~As<Int4>(zPredicate);
-							if(dst.w) wEnable = wEnable & ~As<Int4>(wPredicate);
-						}
-					}
-
-					if(dst.x) d.x = As<Float4>(As<Int4>(d.x) & xEnable);
-					if(dst.y) d.y = As<Float4>(As<Int4>(d.y) & yEnable);
-					if(dst.z) d.z = As<Float4>(As<Int4>(d.z) & zEnable);
-					if(dst.w) d.w = As<Float4>(As<Int4>(d.w) & wEnable);
-
-					if(dst.x) d.x = As<Float4>(As<Int4>(d.x) | (As<Int4>(pDst.x) & ~xEnable));
-					if(dst.y) d.y = As<Float4>(As<Int4>(d.y) | (As<Int4>(pDst.y) & ~yEnable));
-					if(dst.z) d.z = As<Float4>(As<Int4>(d.z) | (As<Int4>(pDst.z) & ~zEnable));
-					if(dst.w) d.w = As<Float4>(As<Int4>(d.w) | (As<Int4>(pDst.w) & ~wEnable));
-				}
-
-				switch(dst.type)
-				{
-				case Shader::PARAMETER_TEMP:
-					if(dst.rel.type == Shader::PARAMETER_VOID)
-					{
-						if(dst.x) r[dst.index].x = d.x;
-						if(dst.y) r[dst.index].y = d.y;
-						if(dst.z) r[dst.index].z = d.z;
-						if(dst.w) r[dst.index].w = d.w;
-					}
-					else if(!dst.rel.dynamic)
-					{
-						Int a = dst.index + relativeAddress(dst.rel);
-
-						if(dst.x) r[a].x = d.x;
-						if(dst.y) r[a].y = d.y;
-						if(dst.z) r[a].z = d.z;
-						if(dst.w) r[a].w = d.w;
-					}
-					else
-					{
-						Int4 a = dst.index + dynamicAddress(dst.rel);
-
-						if(dst.x) r.scatter_x(a, d.x);
-						if(dst.y) r.scatter_y(a, d.y);
-						if(dst.z) r.scatter_z(a, d.z);
-						if(dst.w) r.scatter_w(a, d.w);
-					}
-					break;
-				case Shader::PARAMETER_COLOROUT:
-					if(dst.rel.type == Shader::PARAMETER_VOID)
-					{
-						broadcastColor0 = (dst.index == 0) && broadcastColor0;
-
-						if(dst.x) oC[dst.index].x = d.x;
-						if(dst.y) oC[dst.index].y = d.y;
-						if(dst.z) oC[dst.index].z = d.z;
-						if(dst.w) oC[dst.index].w = d.w;
-					}
-					else if(!dst.rel.dynamic)
-					{
-						broadcastColor0 = false;
-						Int a = dst.index + relativeAddress(dst.rel);
-
-						if(dst.x) oC[a].x = d.x;
-						if(dst.y) oC[a].y = d.y;
-						if(dst.z) oC[a].z = d.z;
-						if(dst.w) oC[a].w = d.w;
-					}
-					else
-					{
-						broadcastColor0 = false;
-						Int4 a = dst.index + dynamicAddress(dst.rel);
-
-						if(dst.x) oC.scatter_x(a, d.x);
-						if(dst.y) oC.scatter_y(a, d.y);
-						if(dst.z) oC.scatter_z(a, d.z);
-						if(dst.w) oC.scatter_w(a, d.w);
-					}
-					break;
-				case Shader::PARAMETER_PREDICATE:
-					if(dst.x) p0.x = d.x;
-					if(dst.y) p0.y = d.y;
-					if(dst.z) p0.z = d.z;
-					if(dst.w) p0.w = d.w;
-					break;
-				case Shader::PARAMETER_DEPTHOUT:
-					oDepth = d.x;
-					break;
-				default:
-					ASSERT(false);
-				}
-			}
-		}
-
-		if(currentLabel != -1)
-		{
-			Nucleus::setInsertBlock(returnBlock);
-		}
-
-		if(broadcastColor0)
-		{
-			for(int i = 0; i < RENDERTARGETS; i++)
-			{
-				c[i] = oC[0];
-			}
-		}
-		else
-		{
-			for(int i = 0; i < RENDERTARGETS; i++)
-			{
-				c[i] = oC[i];
-			}
+			c[i] = oC[i];
 		}
 
 		clampColor(c);
@@ -704,56 +185,6 @@
 		}
 	}
 
-	Vector4f PixelProgram::sampleTexture(const Src &sampler, Vector4f &uvwq, Float4 &bias, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function)
-	{
-		Vector4f tmp;
-
-		if(sampler.type == Shader::PARAMETER_SAMPLER && sampler.rel.type == Shader::PARAMETER_VOID)
-		{
-			tmp = sampleTexture(sampler.index, uvwq, bias, dsx, dsy, offset, function);
-		}
-		else
-		{
-			Int index = As<Int>(Float(fetchRegister(sampler).x.x));
-
-			for(int i = 0; i < TEXTURE_IMAGE_UNITS; i++)
-			{
-				if(shader->usesSampler(i))
-				{
-					If(index == i)
-					{
-						tmp = sampleTexture(i, uvwq, bias, dsx, dsy, offset, function);
-						// FIXME: When the sampler states are the same, we could use one sampler and just index the texture
-					}
-				}
-			}
-		}
-
-		Vector4f c;
-		c.x = tmp[(sampler.swizzle >> 0) & 0x3];
-		c.y = tmp[(sampler.swizzle >> 2) & 0x3];
-		c.z = tmp[(sampler.swizzle >> 4) & 0x3];
-		c.w = tmp[(sampler.swizzle >> 6) & 0x3];
-
-		return c;
-	}
-
-	Vector4f PixelProgram::sampleTexture(int samplerIndex, Vector4f &uvwq, Float4 &bias, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function)
-	{
-		#if PERF_PROFILE
-			Long texTime = Ticks();
-		#endif
-
-		Pointer<Byte> texture = data + OFFSET(DrawData, mipmap) + samplerIndex * sizeof(Texture);
-		Vector4f c = SamplerCore(constants, state.sampler[samplerIndex]).sampleTexture(texture, uvwq.x, uvwq.y, uvwq.z, uvwq.w, bias, dsx, dsy, offset, function);
-
-		#if PERF_PROFILE
-			cycles[PERF_TEX] += Ticks() - texTime;
-		#endif
-
-		return c;
-	}
-
 	void PixelProgram::clampColor(Vector4f oC[RENDERTARGETS])
 	{
 		for(int index = 0; index < RENDERTARGETS; index++)
@@ -808,322 +239,12 @@
 		}
 	}
 
-	Int4 PixelProgram::enableMask(const Shader::Instruction *instruction)
+	Int4 PixelProgram::enableMask()
 	{
-		Int4 enable = instruction->analysisBranch ? Int4(enableStack[enableIndex]) : Int4(0xFFFFFFFF);
-
-		if(!whileTest)
-		{
-			if(shader->containsBreakInstruction() && instruction->analysisBreak)
-			{
-				enable &= enableBreak;
-			}
-
-			if(shader->containsContinueInstruction() && instruction->analysisContinue)
-			{
-				enable &= enableContinue;
-			}
-
-			if(shader->containsLeaveInstruction() && instruction->analysisLeave)
-			{
-				enable &= enableLeave;
-			}
-		}
-
+		Int4 enable = true ? Int4(enableStack[enableIndex]) : Int4(0xFFFFFFFF);
 		return enable;
 	}
 
-	Vector4f PixelProgram::fetchRegister(const Src &src, unsigned int offset)
-	{
-		Vector4f reg;
-		unsigned int i = src.index + offset;
-
-		switch(src.type)
-		{
-		case Shader::PARAMETER_TEMP:
-			if(src.rel.type == Shader::PARAMETER_VOID)
-			{
-				reg = r[i];
-			}
-			else if(!src.rel.dynamic)
-			{
-				reg = r[i + relativeAddress(src.rel, src.bufferIndex)];
-			}
-			else
-			{
-				reg = r[i + dynamicAddress(src.rel)];
-			}
-			break;
-		case Shader::PARAMETER_INPUT:
-			if(src.rel.type == Shader::PARAMETER_VOID)   // Not relative
-			{
-				reg = v[i];
-			}
-			else if(!src.rel.dynamic)
-			{
-				reg = v[i + relativeAddress(src.rel, src.bufferIndex)];
-			}
-			else
-			{
-				reg = v[i + dynamicAddress(src.rel)];
-			}
-			break;
-		case Shader::PARAMETER_CONST:
-			reg = readConstant(src, offset);
-			break;
-		case Shader::PARAMETER_TEXTURE:
-			reg = v[2 + i];
-			break;
-		case Shader::PARAMETER_MISCTYPE:
-			if(src.index == Shader::VPosIndex) reg = vPos;
-			if(src.index == Shader::VFaceIndex) reg = vFace;
-			break;
-		case Shader::PARAMETER_SAMPLER:
-			if(src.rel.type == Shader::PARAMETER_VOID)
-			{
-				reg.x = As<Float4>(Int4(i));
-			}
-			else if(src.rel.type == Shader::PARAMETER_TEMP)
-			{
-				reg.x = As<Float4>(Int4(i) + As<Int4>(r[src.rel.index].x));
-			}
-			return reg;
-		case Shader::PARAMETER_PREDICATE:   return reg; // Dummy
-		case Shader::PARAMETER_VOID:        return reg; // Dummy
-		case Shader::PARAMETER_FLOAT4LITERAL:
-			reg.x = Float4(src.value[0]);
-			reg.y = Float4(src.value[1]);
-			reg.z = Float4(src.value[2]);
-			reg.w = Float4(src.value[3]);
-			break;
-		case Shader::PARAMETER_CONSTINT:    return reg; // Dummy
-		case Shader::PARAMETER_CONSTBOOL:   return reg; // Dummy
-		case Shader::PARAMETER_LOOP:        return reg; // Dummy
-		case Shader::PARAMETER_COLOROUT:
-			if(src.rel.type == Shader::PARAMETER_VOID)   // Not relative
-			{
-				reg = oC[i];
-			}
-			else if(!src.rel.dynamic)
-			{
-				reg = oC[i + relativeAddress(src.rel, src.bufferIndex)];
-			}
-			else
-			{
-				reg = oC[i + dynamicAddress(src.rel)];
-			}
-			break;
-		case Shader::PARAMETER_DEPTHOUT:
-			reg.x = oDepth;
-			break;
-		default:
-			ASSERT(false);
-		}
-
-		const Float4 &x = reg[(src.swizzle >> 0) & 0x3];
-		const Float4 &y = reg[(src.swizzle >> 2) & 0x3];
-		const Float4 &z = reg[(src.swizzle >> 4) & 0x3];
-		const Float4 &w = reg[(src.swizzle >> 6) & 0x3];
-
-		Vector4f mod;
-
-		switch(src.modifier)
-		{
-		case Shader::MODIFIER_NONE:
-			mod.x = x;
-			mod.y = y;
-			mod.z = z;
-			mod.w = w;
-			break;
-		case Shader::MODIFIER_NEGATE:
-			mod.x = -x;
-			mod.y = -y;
-			mod.z = -z;
-			mod.w = -w;
-			break;
-		case Shader::MODIFIER_ABS:
-			mod.x = Abs(x);
-			mod.y = Abs(y);
-			mod.z = Abs(z);
-			mod.w = Abs(w);
-			break;
-		case Shader::MODIFIER_ABS_NEGATE:
-			mod.x = -Abs(x);
-			mod.y = -Abs(y);
-			mod.z = -Abs(z);
-			mod.w = -Abs(w);
-			break;
-		case Shader::MODIFIER_NOT:
-			mod.x = As<Float4>(As<Int4>(x) ^ Int4(0xFFFFFFFF));
-			mod.y = As<Float4>(As<Int4>(y) ^ Int4(0xFFFFFFFF));
-			mod.z = As<Float4>(As<Int4>(z) ^ Int4(0xFFFFFFFF));
-			mod.w = As<Float4>(As<Int4>(w) ^ Int4(0xFFFFFFFF));
-			break;
-		default:
-			ASSERT(false);
-		}
-
-		return mod;
-	}
-
-	RValue<Pointer<Byte>> PixelProgram::uniformAddress(int bufferIndex, unsigned int index)
-	{
-		if(bufferIndex == -1)
-		{
-			return data + OFFSET(DrawData, ps.c[index]);
-		}
-		else
-		{
-			return *Pointer<Pointer<Byte>>(data + OFFSET(DrawData, ps.u[bufferIndex])) + index;
-		}
-	}
-
-	RValue<Pointer<Byte>> PixelProgram::uniformAddress(int bufferIndex, unsigned int index, Int& offset)
-	{
-		return uniformAddress(bufferIndex, index) + offset * sizeof(float4);
-	}
-
-	Vector4f PixelProgram::readConstant(const Src &src, unsigned int offset)
-	{
-		Vector4f c;
-		unsigned int i = src.index + offset;
-
-		if(src.rel.type == Shader::PARAMETER_VOID)   // Not relative
-		{
-			c.x = c.y = c.z = c.w = *Pointer<Float4>(uniformAddress(src.bufferIndex, i));
-
-			c.x = c.x.xxxx;
-			c.y = c.y.yyyy;
-			c.z = c.z.zzzz;
-			c.w = c.w.wwww;
-
-			if(shader->containsDefineInstruction())   // Constant may be known at compile time
-			{
-				for(size_t j = 0; j < shader->getLength(); j++)
-				{
-					const Shader::Instruction &instruction = *shader->getInstruction(j);
-
-					if(instruction.opcode == Shader::OPCODE_DEF)
-					{
-						if(instruction.dst.index == i)
-						{
-							c.x = Float4(instruction.src[0].value[0]);
-							c.y = Float4(instruction.src[0].value[1]);
-							c.z = Float4(instruction.src[0].value[2]);
-							c.w = Float4(instruction.src[0].value[3]);
-
-							break;
-						}
-					}
-				}
-			}
-		}
-		else if(!src.rel.dynamic || src.rel.type == Shader::PARAMETER_LOOP)
-		{
-			Int a = relativeAddress(src.rel, src.bufferIndex);
-
-			c.x = c.y = c.z = c.w = *Pointer<Float4>(uniformAddress(src.bufferIndex, i, a));
-
-			c.x = c.x.xxxx;
-			c.y = c.y.yyyy;
-			c.z = c.z.zzzz;
-			c.w = c.w.wwww;
-		}
-		else
-		{
-			int component = src.rel.swizzle & 0x03;
-			Float4 a;
-
-			switch(src.rel.type)
-			{
-			case Shader::PARAMETER_TEMP:     a = r[src.rel.index][component]; break;
-			case Shader::PARAMETER_INPUT:    a = v[src.rel.index][component]; break;
-			case Shader::PARAMETER_OUTPUT:   a = oC[src.rel.index][component]; break;
-			case Shader::PARAMETER_CONST:    a = *Pointer<Float>(uniformAddress(src.bufferIndex, src.rel.index) + component * sizeof(float)); break;
-			case Shader::PARAMETER_MISCTYPE:
-				switch(src.rel.index)
-				{
-				case Shader::VPosIndex:  a = vPos.x;  break;
-				case Shader::VFaceIndex: a = vFace.x; break;
-				default: ASSERT(false);
-				}
-				break;
-			default: ASSERT(false);
-			}
-
-			Int4 index = Int4(i) + As<Int4>(a) * Int4(src.rel.scale);
-
-			index = Min(As<UInt4>(index), UInt4(VERTEX_UNIFORM_VECTORS));   // Clamp to constant register range, c[VERTEX_UNIFORM_VECTORS] = {0, 0, 0, 0}
-
-			Int index0 = Extract(index, 0);
-			Int index1 = Extract(index, 1);
-			Int index2 = Extract(index, 2);
-			Int index3 = Extract(index, 3);
-
-			c.x = *Pointer<Float4>(uniformAddress(src.bufferIndex, 0, index0), 16);
-			c.y = *Pointer<Float4>(uniformAddress(src.bufferIndex, 0, index1), 16);
-			c.z = *Pointer<Float4>(uniformAddress(src.bufferIndex, 0, index2), 16);
-			c.w = *Pointer<Float4>(uniformAddress(src.bufferIndex, 0, index3), 16);
-
-			transpose4x4(c.x, c.y, c.z, c.w);
-		}
-
-		return c;
-	}
-
-	Int PixelProgram::relativeAddress(const Shader::Relative &rel, int bufferIndex)
-	{
-		ASSERT(!rel.dynamic);
-
-		if(rel.type == Shader::PARAMETER_TEMP)
-		{
-			return As<Int>(Extract(r[rel.index].x, 0)) * rel.scale;
-		}
-		else if(rel.type == Shader::PARAMETER_INPUT)
-		{
-			return As<Int>(Extract(v[rel.index].x, 0)) * rel.scale;
-		}
-		else if(rel.type == Shader::PARAMETER_OUTPUT)
-		{
-			return As<Int>(Extract(oC[rel.index].x, 0)) * rel.scale;
-		}
-		else if(rel.type == Shader::PARAMETER_CONST)
-		{
-			return *Pointer<Int>(uniformAddress(bufferIndex, rel.index)) * rel.scale;
-		}
-		else if(rel.type == Shader::PARAMETER_LOOP)
-		{
-			return aL[loopDepth];
-		}
-		else ASSERT(false);
-
-		return 0;
-	}
-
-	Int4 PixelProgram::dynamicAddress(const Shader::Relative &rel)
-	{
-		int component = rel.swizzle & 0x03;
-		Float4 a;
-
-		switch(rel.type)
-		{
-		case Shader::PARAMETER_TEMP:     a = r[rel.index][component]; break;
-		case Shader::PARAMETER_INPUT:    a = v[rel.index][component]; break;
-		case Shader::PARAMETER_OUTPUT:   a = oC[rel.index][component]; break;
-		case Shader::PARAMETER_MISCTYPE:
-			switch(rel.index)
-			{
-			case Shader::VPosIndex:  a = vPos.x;  break;
-			case Shader::VFaceIndex: a = vFace.x; break;
-			default: ASSERT(false);
-			}
-			break;
-		default: ASSERT(false);
-		}
-
-		return As<Int4>(a) * Int4(rel.scale);
-	}
-
 	Float4 PixelProgram::linearToSRGB(const Float4 &x)   // Approximates x^(1.0/2.2)
 	{
 		Float4 sqrtx = Rcp_pp(RcpSqrt_pp(x));
@@ -1131,701 +252,4 @@
 
 		return Min(Max(sRGB, Float4(0.0f)), Float4(1.0f));
 	}
-
-	void PixelProgram::M3X2(Vector4f &dst, Vector4f &src0, const Src &src1)
-	{
-		Vector4f row0 = fetchRegister(src1, 0);
-		Vector4f row1 = fetchRegister(src1, 1);
-
-		dst.x = dot3(src0, row0);
-		dst.y = dot3(src0, row1);
-	}
-
-	void PixelProgram::M3X3(Vector4f &dst, Vector4f &src0, const Src &src1)
-	{
-		Vector4f row0 = fetchRegister(src1, 0);
-		Vector4f row1 = fetchRegister(src1, 1);
-		Vector4f row2 = fetchRegister(src1, 2);
-
-		dst.x = dot3(src0, row0);
-		dst.y = dot3(src0, row1);
-		dst.z = dot3(src0, row2);
-	}
-
-	void PixelProgram::M3X4(Vector4f &dst, Vector4f &src0, const Src &src1)
-	{
-		Vector4f row0 = fetchRegister(src1, 0);
-		Vector4f row1 = fetchRegister(src1, 1);
-		Vector4f row2 = fetchRegister(src1, 2);
-		Vector4f row3 = fetchRegister(src1, 3);
-
-		dst.x = dot3(src0, row0);
-		dst.y = dot3(src0, row1);
-		dst.z = dot3(src0, row2);
-		dst.w = dot3(src0, row3);
-	}
-
-	void PixelProgram::M4X3(Vector4f &dst, Vector4f &src0, const Src &src1)
-	{
-		Vector4f row0 = fetchRegister(src1, 0);
-		Vector4f row1 = fetchRegister(src1, 1);
-		Vector4f row2 = fetchRegister(src1, 2);
-
-		dst.x = dot4(src0, row0);
-		dst.y = dot4(src0, row1);
-		dst.z = dot4(src0, row2);
-	}
-
-	void PixelProgram::M4X4(Vector4f &dst, Vector4f &src0, const Src &src1)
-	{
-		Vector4f row0 = fetchRegister(src1, 0);
-		Vector4f row1 = fetchRegister(src1, 1);
-		Vector4f row2 = fetchRegister(src1, 2);
-		Vector4f row3 = fetchRegister(src1, 3);
-
-		dst.x = dot4(src0, row0);
-		dst.y = dot4(src0, row1);
-		dst.z = dot4(src0, row2);
-		dst.w = dot4(src0, row3);
-	}
-
-	void PixelProgram::TEX(Vector4f &dst, Vector4f &src0, const Src &src1, bool project, bool bias)
-	{
-		if(project)
-		{
-			Vector4f proj;
-			Float4 rw = reciprocal(src0.w);
-			proj.x = src0.x * rw;
-			proj.y = src0.y * rw;
-			proj.z = src0.z * rw;
-
-			dst = sampleTexture(src1, proj, src0.x, (src0), (src0), (src0), Implicit);
-		}
-		else
-		{
-			dst = sampleTexture(src1, src0, src0.x, (src0), (src0), (src0), bias ? Bias : Implicit);
-		}
-	}
-
-	void PixelProgram::TEXOFFSET(Vector4f &dst, Vector4f &src0, const Src &src1, Vector4f &offset)
-	{
-		dst = sampleTexture(src1, src0, (src0.x), (src0), (src0), offset, {Implicit, Offset});
-	}
-
-	void PixelProgram::TEXLODOFFSET(Vector4f &dst, Vector4f &src0, const Src &src1, Vector4f &offset, Float4 &lod)
-	{
-		dst = sampleTexture(src1, src0, lod, (src0), (src0), offset, {Lod, Offset});
-	}
-
-	void PixelProgram::TEXBIAS(Vector4f &dst, Vector4f &src0, const Src &src1, Float4 &bias)
-	{
-		dst = sampleTexture(src1, src0, bias, (src0), (src0), (src0), Bias);
-	}
-
-	void PixelProgram::TEXOFFSETBIAS(Vector4f &dst, Vector4f &src0, const Src &src1, Vector4f &offset, Float4 &bias)
-	{
-		dst = sampleTexture(src1, src0, bias, (src0), (src0), offset, {Bias, Offset});
-	}
-
-	void PixelProgram::TEXELFETCH(Vector4f &dst, Vector4f &src0, const Src& src1, Float4 &lod)
-	{
-		dst = sampleTexture(src1, src0, lod, (src0), (src0), (src0), Fetch);
-	}
-
-	void PixelProgram::TEXELFETCHOFFSET(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &offset, Float4 &lod)
-	{
-		dst = sampleTexture(src1, src0, lod, (src0), (src0), offset, {Fetch, Offset});
-	}
-
-	void PixelProgram::TEXGRAD(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &dsx, Vector4f &dsy)
-	{
-		dst = sampleTexture(src1, src0, (src0.x), dsx, dsy, (src0), Grad);
-	}
-
-	void PixelProgram::TEXGRADOFFSET(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &dsx, Vector4f &dsy, Vector4f &offset)
-	{
-		dst = sampleTexture(src1, src0, (src0.x), dsx, dsy, offset, {Grad, Offset});
-	}
-
-	void PixelProgram::TEXLOD(Vector4f &dst, Vector4f &src0, const Src &src1, Float4 &lod)
-	{
-		dst = sampleTexture(src1, src0, lod, (src0), (src0), (src0), Lod);
-	}
-
-	void PixelProgram::TEXSIZE(Vector4f &dst, Float4 &lod, const Src &src1)
-	{
-		bool uniformSampler = (src1.type == Shader::PARAMETER_SAMPLER && src1.rel.type == Shader::PARAMETER_VOID);
-		Int offset = uniformSampler ? src1.index * sizeof(Texture) : As<Int>(Float(fetchRegister(src1).x.x)) * sizeof(Texture);
-		Pointer<Byte> texture = data + OFFSET(DrawData, mipmap) + offset;
-
-		dst = SamplerCore::textureSize(texture, lod);
-	}
-
-	void PixelProgram::TEXKILL(Int cMask[4], Vector4f &src, unsigned char mask)
-	{
-		Int kill = -1;
-
-		if(mask & 0x1) kill &= SignMask(CmpNLT(src.x, Float4(0.0f)));
-		if(mask & 0x2) kill &= SignMask(CmpNLT(src.y, Float4(0.0f)));
-		if(mask & 0x4) kill &= SignMask(CmpNLT(src.z, Float4(0.0f)));
-		if(mask & 0x8) kill &= SignMask(CmpNLT(src.w, Float4(0.0f)));
-
-		// FIXME: Dynamic branching affects TEXKILL?
-		//	if(shader->containsDynamicBranching())
-		//	{
-		//		kill = ~SignMask(enableMask());
-		//	}
-
-		for(unsigned int q = 0; q < state.multiSample; q++)
-		{
-			cMask[q] &= kill;
-		}
-
-		// FIXME: Branch to end of shader if all killed?
-	}
-
-	void PixelProgram::DISCARD(Int cMask[4], const Shader::Instruction *instruction)
-	{
-		Int kill = 0;
-
-		if(shader->containsDynamicBranching())
-		{
-			kill = ~SignMask(enableMask(instruction));
-		}
-
-		for(unsigned int q = 0; q < state.multiSample; q++)
-		{
-			cMask[q] &= kill;
-		}
-
-		// FIXME: Branch to end of shader if all killed?
-	}
-
-	void PixelProgram::DFDX(Vector4f &dst, Vector4f &src)
-	{
-		dst.x = src.x.yyww - src.x.xxzz;
-		dst.y = src.y.yyww - src.y.xxzz;
-		dst.z = src.z.yyww - src.z.xxzz;
-		dst.w = src.w.yyww - src.w.xxzz;
-	}
-
-	void PixelProgram::DFDY(Vector4f &dst, Vector4f &src)
-	{
-		dst.x = src.x.zwzw - src.x.xyxy;
-		dst.y = src.y.zwzw - src.y.xyxy;
-		dst.z = src.z.zwzw - src.z.xyxy;
-		dst.w = src.w.zwzw - src.w.xyxy;
-	}
-
-	void PixelProgram::FWIDTH(Vector4f &dst, Vector4f &src)
-	{
-		// abs(dFdx(src)) + abs(dFdy(src));
-		dst.x = Abs(src.x.yyww - src.x.xxzz) + Abs(src.x.zwzw - src.x.xyxy);
-		dst.y = Abs(src.y.yyww - src.y.xxzz) + Abs(src.y.zwzw - src.y.xyxy);
-		dst.z = Abs(src.z.yyww - src.z.xxzz) + Abs(src.z.zwzw - src.z.xyxy);
-		dst.w = Abs(src.w.yyww - src.w.xxzz) + Abs(src.w.zwzw - src.w.xyxy);
-	}
-
-	void PixelProgram::BREAK()
-	{
-		enableBreak = enableBreak & ~enableStack[enableIndex];
-	}
-
-	void PixelProgram::BREAKC(Vector4f &src0, Vector4f &src1, Control control)
-	{
-		Int4 condition;
-
-		switch(control)
-		{
-		case Shader::CONTROL_GT: condition = CmpNLE(src0.x, src1.x); break;
-		case Shader::CONTROL_EQ: condition = CmpEQ(src0.x, src1.x);  break;
-		case Shader::CONTROL_GE: condition = CmpNLT(src0.x, src1.x); break;
-		case Shader::CONTROL_LT: condition = CmpLT(src0.x, src1.x);  break;
-		case Shader::CONTROL_NE: condition = CmpNEQ(src0.x, src1.x); break;
-		case Shader::CONTROL_LE: condition = CmpLE(src0.x, src1.x);  break;
-		default:
-			ASSERT(false);
-		}
-
-		BREAK(condition);
-	}
-
-	void PixelProgram::BREAKP(const Src &predicateRegister)   // FIXME: Factor out parts common with BREAKC
-	{
-		Int4 condition = As<Int4>(p0[predicateRegister.swizzle & 0x3]);
-
-		if(predicateRegister.modifier == Shader::MODIFIER_NOT)
-		{
-			condition = ~condition;
-		}
-
-		BREAK(condition);
-	}
-
-	void PixelProgram::BREAK(Int4 &condition)
-	{
-		condition &= enableStack[enableIndex];
-
-		enableBreak = enableBreak & ~condition;
-	}
-
-	void PixelProgram::CONTINUE()
-	{
-		enableContinue = enableContinue & ~enableStack[enableIndex];
-	}
-
-	void PixelProgram::TEST()
-	{
-		whileTest = true;
-	}
-
-	void PixelProgram::CALL(int labelIndex, int callSiteIndex)
-	{
-		if(!labelBlock[labelIndex])
-		{
-			labelBlock[labelIndex] = Nucleus::createBasicBlock();
-		}
-
-		if(callRetBlock[labelIndex].size() > 1)
-		{
-			callStack[stackIndex++] = UInt(callSiteIndex);
-		}
-
-		Int4 restoreLeave = enableLeave;
-
-		Nucleus::createBr(labelBlock[labelIndex]);
-		Nucleus::setInsertBlock(callRetBlock[labelIndex][callSiteIndex]);
-
-		enableLeave = restoreLeave;
-	}
-
-	void PixelProgram::CALLNZ(int labelIndex, int callSiteIndex, const Src &src)
-	{
-		if(src.type == Shader::PARAMETER_CONSTBOOL)
-		{
-			CALLNZb(labelIndex, callSiteIndex, src);
-		}
-		else if(src.type == Shader::PARAMETER_PREDICATE)
-		{
-			CALLNZp(labelIndex, callSiteIndex, src);
-		}
-		else ASSERT(false);
-	}
-
-	void PixelProgram::CALLNZb(int labelIndex, int callSiteIndex, const Src &boolRegister)
-	{
-		Bool condition = (*Pointer<Byte>(data + OFFSET(DrawData, ps.b[boolRegister.index])) != Byte(0));   // FIXME
-
-		if(boolRegister.modifier == Shader::MODIFIER_NOT)
-		{
-			condition = !condition;
-		}
-
-		if(!labelBlock[labelIndex])
-		{
-			labelBlock[labelIndex] = Nucleus::createBasicBlock();
-		}
-
-		if(callRetBlock[labelIndex].size() > 1)
-		{
-			callStack[stackIndex++] = UInt(callSiteIndex);
-		}
-
-		Int4 restoreLeave = enableLeave;
-
-		branch(condition, labelBlock[labelIndex], callRetBlock[labelIndex][callSiteIndex]);
-		Nucleus::setInsertBlock(callRetBlock[labelIndex][callSiteIndex]);
-
-		enableLeave = restoreLeave;
-	}
-
-	void PixelProgram::CALLNZp(int labelIndex, int callSiteIndex, const Src &predicateRegister)
-	{
-		Int4 condition = As<Int4>(p0[predicateRegister.swizzle & 0x3]);
-
-		if(predicateRegister.modifier == Shader::MODIFIER_NOT)
-		{
-			condition = ~condition;
-		}
-
-		condition &= enableStack[enableIndex];
-
-		if(!labelBlock[labelIndex])
-		{
-			labelBlock[labelIndex] = Nucleus::createBasicBlock();
-		}
-
-		if(callRetBlock[labelIndex].size() > 1)
-		{
-			callStack[stackIndex++] = UInt(callSiteIndex);
-		}
-
-		enableIndex++;
-		enableStack[enableIndex] = condition;
-		Int4 restoreLeave = enableLeave;
-
-		Bool notAllFalse = SignMask(condition) != 0;
-		branch(notAllFalse, labelBlock[labelIndex], callRetBlock[labelIndex][callSiteIndex]);
-		Nucleus::setInsertBlock(callRetBlock[labelIndex][callSiteIndex]);
-
-		enableIndex--;
-		enableLeave = restoreLeave;
-	}
-
-	void PixelProgram::ELSE()
-	{
-		ifDepth--;
-
-		BasicBlock *falseBlock = ifFalseBlock[ifDepth];
-		BasicBlock *endBlock = Nucleus::createBasicBlock();
-
-		if(isConditionalIf[ifDepth])
-		{
-			Int4 condition = ~enableStack[enableIndex] & enableStack[enableIndex - 1];
-			Bool notAllFalse = SignMask(condition) != 0;
-
-			branch(notAllFalse, falseBlock, endBlock);
-
-			enableStack[enableIndex] = ~enableStack[enableIndex] & enableStack[enableIndex - 1];
-		}
-		else
-		{
-			Nucleus::createBr(endBlock);
-			Nucleus::setInsertBlock(falseBlock);
-		}
-
-		ifFalseBlock[ifDepth] = endBlock;
-
-		ifDepth++;
-	}
-
-	void PixelProgram::ENDIF()
-	{
-		ifDepth--;
-
-		BasicBlock *endBlock = ifFalseBlock[ifDepth];
-
-		Nucleus::createBr(endBlock);
-		Nucleus::setInsertBlock(endBlock);
-
-		if(isConditionalIf[ifDepth])
-		{
-			enableIndex--;
-		}
-	}
-
-	void PixelProgram::ENDLOOP()
-	{
-		loopRepDepth--;
-
-		aL[loopDepth] = aL[loopDepth] + increment[loopDepth];   // FIXME: +=
-
-		BasicBlock *testBlock = loopRepTestBlock[loopRepDepth];
-		BasicBlock *endBlock = loopRepEndBlock[loopRepDepth];
-
-		Nucleus::createBr(testBlock);
-		Nucleus::setInsertBlock(endBlock);
-
-		loopDepth--;
-		enableBreak = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
-	}
-
-	void PixelProgram::ENDREP()
-	{
-		loopRepDepth--;
-
-		BasicBlock *testBlock = loopRepTestBlock[loopRepDepth];
-		BasicBlock *endBlock = loopRepEndBlock[loopRepDepth];
-
-		Nucleus::createBr(testBlock);
-		Nucleus::setInsertBlock(endBlock);
-
-		loopDepth--;
-		enableBreak = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
-	}
-
-	void PixelProgram::ENDWHILE()
-	{
-		loopRepDepth--;
-
-		BasicBlock *testBlock = loopRepTestBlock[loopRepDepth];
-		BasicBlock *endBlock = loopRepEndBlock[loopRepDepth];
-
-		Nucleus::createBr(testBlock);
-		Nucleus::setInsertBlock(endBlock);
-
-		enableIndex--;
-		whileTest = false;
-	}
-
-	void PixelProgram::ENDSWITCH()
-	{
-		loopRepDepth--;
-
-		BasicBlock *endBlock = loopRepEndBlock[loopRepDepth];
-
-		Nucleus::createBr(endBlock);
-		Nucleus::setInsertBlock(endBlock);
-	}
-
-	void PixelProgram::IF(const Src &src)
-	{
-		if(src.type == Shader::PARAMETER_CONSTBOOL)
-		{
-			IFb(src);
-		}
-		else if(src.type == Shader::PARAMETER_PREDICATE)
-		{
-			IFp(src);
-		}
-		else
-		{
-			Int4 condition = As<Int4>(fetchRegister(src).x);
-			IF(condition);
-		}
-	}
-
-	void PixelProgram::IFb(const Src &boolRegister)
-	{
-		ASSERT(ifDepth < 24 + 4);
-
-		Bool condition = (*Pointer<Byte>(data + OFFSET(DrawData, ps.b[boolRegister.index])) != Byte(0));   // FIXME
-
-		if(boolRegister.modifier == Shader::MODIFIER_NOT)
-		{
-			condition = !condition;
-		}
-
-		BasicBlock *trueBlock = Nucleus::createBasicBlock();
-		BasicBlock *falseBlock = Nucleus::createBasicBlock();
-
-		branch(condition, trueBlock, falseBlock);
-
-		isConditionalIf[ifDepth] = false;
-		ifFalseBlock[ifDepth] = falseBlock;
-
-		ifDepth++;
-	}
-
-	void PixelProgram::IFp(const Src &predicateRegister)
-	{
-		Int4 condition = As<Int4>(p0[predicateRegister.swizzle & 0x3]);
-
-		if(predicateRegister.modifier == Shader::MODIFIER_NOT)
-		{
-			condition = ~condition;
-		}
-
-		IF(condition);
-	}
-
-	void PixelProgram::IFC(Vector4f &src0, Vector4f &src1, Control control)
-	{
-		Int4 condition;
-
-		switch(control)
-		{
-		case Shader::CONTROL_GT: condition = CmpNLE(src0.x, src1.x); break;
-		case Shader::CONTROL_EQ: condition = CmpEQ(src0.x, src1.x);  break;
-		case Shader::CONTROL_GE: condition = CmpNLT(src0.x, src1.x); break;
-		case Shader::CONTROL_LT: condition = CmpLT(src0.x, src1.x);  break;
-		case Shader::CONTROL_NE: condition = CmpNEQ(src0.x, src1.x); break;
-		case Shader::CONTROL_LE: condition = CmpLE(src0.x, src1.x);  break;
-		default:
-			ASSERT(false);
-		}
-
-		IF(condition);
-	}
-
-	void PixelProgram::IF(Int4 &condition)
-	{
-		condition &= enableStack[enableIndex];
-
-		enableIndex++;
-		enableStack[enableIndex] = condition;
-
-		BasicBlock *trueBlock = Nucleus::createBasicBlock();
-		BasicBlock *falseBlock = Nucleus::createBasicBlock();
-
-		Bool notAllFalse = SignMask(condition) != 0;
-
-		branch(notAllFalse, trueBlock, falseBlock);
-
-		isConditionalIf[ifDepth] = true;
-		ifFalseBlock[ifDepth] = falseBlock;
-
-		ifDepth++;
-	}
-
-	void PixelProgram::LABEL(int labelIndex)
-	{
-		if(!labelBlock[labelIndex])
-		{
-			labelBlock[labelIndex] = Nucleus::createBasicBlock();
-		}
-
-		Nucleus::setInsertBlock(labelBlock[labelIndex]);
-		currentLabel = labelIndex;
-	}
-
-	void PixelProgram::LOOP(const Src &integerRegister)
-	{
-		loopDepth++;
-
-		iteration[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData, ps.i[integerRegister.index][0]));
-		aL[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData, ps.i[integerRegister.index][1]));
-		increment[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData, ps.i[integerRegister.index][2]));
-
-		//	If(increment[loopDepth] == 0)
-		//	{
-		//		increment[loopDepth] = 1;
-		//	}
-
-		BasicBlock *loopBlock = Nucleus::createBasicBlock();
-		BasicBlock *testBlock = Nucleus::createBasicBlock();
-		BasicBlock *endBlock = Nucleus::createBasicBlock();
-
-		loopRepTestBlock[loopRepDepth] = testBlock;
-		loopRepEndBlock[loopRepDepth] = endBlock;
-
-		// FIXME: jump(testBlock)
-		Nucleus::createBr(testBlock);
-		Nucleus::setInsertBlock(testBlock);
-
-		branch(iteration[loopDepth] > 0, loopBlock, endBlock);
-		Nucleus::setInsertBlock(loopBlock);
-
-		iteration[loopDepth] = iteration[loopDepth] - 1;   // FIXME: --
-
-		loopRepDepth++;
-	}
-
-	void PixelProgram::REP(const Src &integerRegister)
-	{
-		loopDepth++;
-
-		iteration[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData, ps.i[integerRegister.index][0]));
-		aL[loopDepth] = aL[loopDepth - 1];
-
-		BasicBlock *loopBlock = Nucleus::createBasicBlock();
-		BasicBlock *testBlock = Nucleus::createBasicBlock();
-		BasicBlock *endBlock = Nucleus::createBasicBlock();
-
-		loopRepTestBlock[loopRepDepth] = testBlock;
-		loopRepEndBlock[loopRepDepth] = endBlock;
-
-		// FIXME: jump(testBlock)
-		Nucleus::createBr(testBlock);
-		Nucleus::setInsertBlock(testBlock);
-
-		branch(iteration[loopDepth] > 0, loopBlock, endBlock);
-		Nucleus::setInsertBlock(loopBlock);
-
-		iteration[loopDepth] = iteration[loopDepth] - 1;   // FIXME: --
-
-		loopRepDepth++;
-	}
-
-	void PixelProgram::WHILE(const Src &temporaryRegister)
-	{
-		enableIndex++;
-
-		BasicBlock *loopBlock = Nucleus::createBasicBlock();
-		BasicBlock *testBlock = Nucleus::createBasicBlock();
-		BasicBlock *endBlock = Nucleus::createBasicBlock();
-
-		loopRepTestBlock[loopRepDepth] = testBlock;
-		loopRepEndBlock[loopRepDepth] = endBlock;
-
-		Int4 restoreBreak = enableBreak;
-		Int4 restoreContinue = enableContinue;
-
-		// TODO: jump(testBlock)
-		Nucleus::createBr(testBlock);
-		Nucleus::setInsertBlock(testBlock);
-		enableContinue = restoreContinue;
-
-		const Vector4f &src = fetchRegister(temporaryRegister);
-		Int4 condition = As<Int4>(src.x);
-		condition &= enableStack[enableIndex - 1];
-		if(shader->containsLeaveInstruction()) condition &= enableLeave;
-		if(shader->containsBreakInstruction()) condition &= enableBreak;
-		enableStack[enableIndex] = condition;
-
-		Bool notAllFalse = SignMask(condition) != 0;
-		branch(notAllFalse, loopBlock, endBlock);
-
-		Nucleus::setInsertBlock(endBlock);
-		enableBreak = restoreBreak;
-
-		Nucleus::setInsertBlock(loopBlock);
-
-		loopRepDepth++;
-	}
-
-	void PixelProgram::SWITCH()
-	{
-		BasicBlock *endBlock = Nucleus::createBasicBlock();
-
-		loopRepTestBlock[loopRepDepth] = nullptr;
-		loopRepEndBlock[loopRepDepth] = endBlock;
-
-		Int4 restoreBreak = enableBreak;
-
-		BasicBlock *currentBlock = Nucleus::getInsertBlock();
-
-		Nucleus::setInsertBlock(endBlock);
-		enableBreak = restoreBreak;
-
-		Nucleus::setInsertBlock(currentBlock);
-
-		loopRepDepth++;
-	}
-
-	void PixelProgram::RET()
-	{
-		if(currentLabel == -1)
-		{
-			returnBlock = Nucleus::createBasicBlock();
-			Nucleus::createBr(returnBlock);
-		}
-		else
-		{
-			BasicBlock *unreachableBlock = Nucleus::createBasicBlock();
-
-			if(callRetBlock[currentLabel].size() > 1)   // Pop the return destination from the call stack
-			{
-				// FIXME: Encapsulate
-				UInt index = callStack[--stackIndex];
-
-				Value *value = index.loadValue();
-				SwitchCases *switchCases = Nucleus::createSwitch(value, unreachableBlock, (int)callRetBlock[currentLabel].size());
-
-				for(unsigned int i = 0; i < callRetBlock[currentLabel].size(); i++)
-				{
-					Nucleus::addSwitchCase(switchCases, i, callRetBlock[currentLabel][i]);
-				}
-			}
-			else if(callRetBlock[currentLabel].size() == 1)   // Jump directly to the unique return destination
-			{
-				Nucleus::createBr(callRetBlock[currentLabel][0]);
-			}
-			else   // Function isn't called
-			{
-				Nucleus::createBr(unreachableBlock);
-			}
-
-			Nucleus::setInsertBlock(unreachableBlock);
-			Nucleus::createUnreachable();
-		}
-	}
-
-	void PixelProgram::LEAVE()
-	{
-		enableLeave = enableLeave & ~enableStack[enableIndex];
-
-		// FIXME: Return from function if all instances left
-		// FIXME: Use enableLeave in other control-flow constructs
-	}
 }
diff --git a/src/Pipeline/PixelProgram.hpp b/src/Pipeline/PixelProgram.hpp
index 240938d..3f15ba6 100644
--- a/src/Pipeline/PixelProgram.hpp
+++ b/src/Pipeline/PixelProgram.hpp
@@ -23,26 +23,9 @@
 	class PixelProgram : public PixelRoutine
 	{
 	public:
-		PixelProgram(const PixelProcessor::State &state, const PixelShader *shader) :
-			PixelRoutine(state, shader), r(shader->indirectAddressableTemporaries),
-			loopDepth(-1), ifDepth(0), loopRepDepth(0), currentLabel(-1), whileTest(false)
+		PixelProgram(const PixelProcessor::State &state, SpirvShader const *spirvShader) :
+			PixelRoutine(state, spirvShader)
 		{
-			for(int i = 0; i < 2048; ++i)
-			{
-				labelBlock[i] = 0;
-			}
-
-			enableStack[0] = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
-
-			if(shader->containsBreakInstruction())
-			{
-				enableBreak = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
-			}
-
-			if(shader->containsContinueInstruction())
-			{
-				enableContinue = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
-			}
 		}
 
 		virtual ~PixelProgram() {}
@@ -54,116 +37,20 @@
 		virtual void rasterOperation(Float4 &fog, Pointer<Byte> cBuffer[4], Int &x, Int sMask[4], Int zMask[4], Int cMask[4]);
 
 	private:
-		// Temporary registers
-		RegisterArray<NUM_TEMPORARY_REGISTERS> r;
-
 		// Color outputs
 		Vector4f c[RENDERTARGETS];
 		RegisterArray<RENDERTARGETS, true> oC;
 
-		// Shader variables
-		Vector4f vPos;
-		Vector4f vFace;
-
-		// DX9 specific variables
-		Vector4f p0;
-		Array<Int, 4> aL;
-		Array<Int, 4> increment;
-		Array<Int, 4> iteration;
-
-		Int loopDepth;    // FIXME: Add support for switch
-		Int stackIndex;   // FIXME: Inc/decrement callStack
-		Array<UInt, 16> callStack;
-
 		// Per pixel based on conditions reached
 		Int enableIndex;
 		Array<Int4, 1 + 24> enableStack;
-		Int4 enableBreak;
-		Int4 enableContinue;
-		Int4 enableLeave;
-
-		Vector4f sampleTexture(const Src &sampler, Vector4f &uvwq, Float4 &bias, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function);
-		Vector4f sampleTexture(int samplerIndex, Vector4f &uvwq, Float4 &bias, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function);
 
 		// Raster operations
 		void clampColor(Vector4f oC[RENDERTARGETS]);
 
-		Int4 enableMask(const Shader::Instruction *instruction);
-
-		Vector4f fetchRegister(const Src &src, unsigned int offset = 0);
-		Vector4f readConstant(const Src &src, unsigned int offset = 0);
-		RValue<Pointer<Byte>> uniformAddress(int bufferIndex, unsigned int index);
-		RValue<Pointer<Byte>> uniformAddress(int bufferIndex, unsigned int index, Int& offset);
-		Int relativeAddress(const Shader::Relative &rel, int bufferIndex = -1);
-		Int4 dynamicAddress(const Shader::Relative &rel);
+		Int4 enableMask();
 
 		Float4 linearToSRGB(const Float4 &x);
-
-		// Instructions
-		typedef Shader::Control Control;
-
-		void M3X2(Vector4f &dst, Vector4f &src0, const Src &src1);
-		void M3X3(Vector4f &dst, Vector4f &src0, const Src &src1);
-		void M3X4(Vector4f &dst, Vector4f &src0, const Src &src1);
-		void M4X3(Vector4f &dst, Vector4f &src0, const Src &src1);
-		void M4X4(Vector4f &dst, Vector4f &src0, const Src &src1);
-		void TEX(Vector4f &dst, Vector4f &src0, const Src &src1, bool project, bool bias);
-		void TEXLOD(Vector4f &dst, Vector4f &src0, const Src &src1, Float4 &lod);
-		void TEXBIAS(Vector4f &dst, Vector4f &src0, const Src &src1, Float4 &bias);
-		void TEXSIZE(Vector4f &dst, Float4 &lod, const Src &src1);
-		void TEXKILL(Int cMask[4], Vector4f &src, unsigned char mask);
-		void TEXOFFSET(Vector4f &dst, Vector4f &src0, const Src &src1, Vector4f &offset);
-		void TEXOFFSETBIAS(Vector4f &dst, Vector4f &src0, const Src &src1, Vector4f &offset, Float4 &bias);
-		void TEXLODOFFSET(Vector4f &dst, Vector4f &src0, const Src &src1, Vector4f &offset, Float4 &lod);
-		void TEXELFETCH(Vector4f &dst, Vector4f &src, const Src &, Float4 &lod);
-		void TEXELFETCHOFFSET(Vector4f &dst, Vector4f &src, const Src &, Vector4f &offset, Float4 &lod);
-		void TEXGRAD(Vector4f &dst, Vector4f &src0, const Src &src1, Vector4f &dsx, Vector4f &dsy);
-		void TEXGRADOFFSET(Vector4f &dst, Vector4f &src, const Src &, Vector4f &dsx, Vector4f &dsy, Vector4f &offset);
-		void DISCARD(Int cMask[4], const Shader::Instruction *instruction);
-		void DFDX(Vector4f &dst, Vector4f &src);
-		void DFDY(Vector4f &dst, Vector4f &src);
-		void FWIDTH(Vector4f &dst, Vector4f &src);
-		void BREAK();
-		void BREAKC(Vector4f &src0, Vector4f &src1, Control);
-		void BREAKP(const Src &predicateRegister);
-		void BREAK(Int4 &condition);
-		void CONTINUE();
-		void TEST();
-		void CALL(int labelIndex, int callSiteIndex);
-		void CALLNZ(int labelIndex, int callSiteIndex, const Src &src);
-		void CALLNZb(int labelIndex, int callSiteIndex, const Src &boolRegister);
-		void CALLNZp(int labelIndex, int callSiteIndex, const Src &predicateRegister);
-		void ELSE();
-		void ENDIF();
-		void ENDLOOP();
-		void ENDREP();
-		void ENDWHILE();
-		void ENDSWITCH();
-		void IF(const Src &src);
-		void IFb(const Src &boolRegister);
-		void IFp(const Src &predicateRegister);
-		void IFC(Vector4f &src0, Vector4f &src1, Control);
-		void IF(Int4 &condition);
-		void LABEL(int labelIndex);
-		void LOOP(const Src &integerRegister);
-		void REP(const Src &integerRegister);
-		void WHILE(const Src &temporaryRegister);
-		void SWITCH();
-		void RET();
-		void LEAVE();
-
-		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];
 	};
 }
 
diff --git a/src/Pipeline/PixelRoutine.cpp b/src/Pipeline/PixelRoutine.cpp
index 10fa8fb..09714aa 100644
--- a/src/Pipeline/PixelRoutine.cpp
+++ b/src/Pipeline/PixelRoutine.cpp
@@ -29,10 +29,10 @@
 	extern bool exactColorRounding;
 	extern bool forceClearRegisters;
 
-	PixelRoutine::PixelRoutine(const PixelProcessor::State &state, const PixelShader *shader)
-		: QuadRasterizer(state, shader), v(shader && shader->indirectAddressableInput)
+	PixelRoutine::PixelRoutine(const PixelProcessor::State &state, SpirvShader const *spirvShader)
+		: QuadRasterizer(state, spirvShader), v(true)	/* addressing */
 	{
-		if(!shader || shader->getShaderModel() < 0x0200 || forceClearRegisters)
+		if(forceClearRegisters)
 		{
 			for(int i = 0; i < MAX_FRAGMENT_INPUTS; i++)
 			{
@@ -142,6 +142,7 @@
 				}
 			}
 
+			// TODO: rethink what we want to do here for pull-mode interpolation
 			for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
 			{
 				for(int component = 0; component < 4; component++)
@@ -210,7 +211,7 @@
 
 				alphaPass = alphaTest(cMask);
 
-				if((shader && shader->containsKill()) || state.alphaTestActive())
+				if((spirvShader && spirvShader->getModes().ContainsKill) || state.alphaTestActive())
 				{
 					for(unsigned int q = 0; q < state.multiSample; q++)
 					{
@@ -394,7 +395,7 @@
 
 		Float4 Z = z;
 
-		if(shader && shader->depthOverride())
+		if(spirvShader && spirvShader->getModes().DepthReplacing)
 		{
 			if(complementaryDepthBuffer)
 			{
@@ -592,7 +593,7 @@
 
 		Float4 Z = z;
 
-		if(shader && shader->depthOverride())
+		if(spirvShader && spirvShader->getModes().DepthReplacing)
 		{
 			if(complementaryDepthBuffer)
 			{
@@ -2479,6 +2480,6 @@
 
 	bool PixelRoutine::colorUsed()
 	{
-		return state.colorWriteMask || state.alphaTestActive() || state.shaderContainsKill;
+		return state.colorWriteMask || state.alphaTestActive() || (spirvShader && spirvShader->getModes().ContainsKill);
 	}
 }
diff --git a/src/Pipeline/PixelRoutine.hpp b/src/Pipeline/PixelRoutine.hpp
index 288ccc7..0c2d8f3 100644
--- a/src/Pipeline/PixelRoutine.hpp
+++ b/src/Pipeline/PixelRoutine.hpp
@@ -25,7 +25,7 @@
 	class PixelRoutine : public sw::QuadRasterizer, public ShaderCore
 	{
 	public:
-		PixelRoutine(const PixelProcessor::State &state, const PixelShader *shader);
+		PixelRoutine(const PixelProcessor::State &state, SpirvShader const *spirvShader);
 
 		virtual ~PixelRoutine();
 
@@ -39,9 +39,6 @@
 		// Depth output
 		Float4 oDepth;
 
-		typedef Shader::SourceParameter Src;
-		typedef Shader::DestinationParameter Dst;
-
 		virtual void setBuiltins(Int &x, Int &y, Float4(&z)[4], Float4 &w) = 0;
 		virtual void applyShader(Int cMask[4]) = 0;
 		virtual Bool alphaTest(Int cMask[4]) = 0;
diff --git a/src/Pipeline/PixelShader.cpp b/src/Pipeline/PixelShader.cpp
deleted file mode 100644
index c15cbba..0000000
--- a/src/Pipeline/PixelShader.cpp
+++ /dev/null
@@ -1,746 +0,0 @@
-// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//    http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "PixelShader.hpp"
-
-#include "Vulkan/VkDebug.hpp"
-
-#include <string.h>
-
-namespace sw
-{
-	PixelShader::PixelShader(const PixelShader *ps) : Shader()
-	{
-		shaderModel = 0x0300;
-		vPosDeclared = false;
-		vFaceDeclared = false;
-		centroid = false;
-
-		if(ps)   // Make a copy
-		{
-			for(size_t i = 0; i < ps->getLength(); i++)
-			{
-				append(new sw::Shader::Instruction(*ps->getInstruction(i)));
-			}
-
-			memcpy(input, ps->input, sizeof(input));
-			vPosDeclared = ps->vPosDeclared;
-			vFaceDeclared = ps->vFaceDeclared;
-			usedSamplers = ps->usedSamplers;
-
-			optimize();
-			analyze();
-		}
-	}
-
-	PixelShader::PixelShader(const unsigned long *token) : Shader()
-	{
-		parse(token);
-
-		vPosDeclared = false;
-		vFaceDeclared = false;
-		centroid = false;
-
-		optimize();
-		analyze();
-	}
-
-	PixelShader::~PixelShader()
-	{
-	}
-
-	int PixelShader::validate(const unsigned long *const token)
-	{
-		if(!token)
-		{
-			return 0;
-		}
-
-		unsigned short version = (unsigned short)(token[0] & 0x0000FFFF);
-		// unsigned char minorVersion = (unsigned char)(token[0] & 0x000000FF);
-		unsigned char majorVersion = (unsigned char)((token[0] & 0x0000FF00) >> 8);
-		ShaderType shaderType = (ShaderType)((token[0] & 0xFFFF0000) >> 16);
-
-		if(shaderType != SHADER_PIXEL || majorVersion > 3)
-		{
-			return 0;
-		}
-
-		int instructionCount = 1;
-
-		for(int i = 0; token[i] != 0x0000FFFF; i++)
-		{
-			if((token[i] & 0x0000FFFF) == 0x0000FFFE)   // Comment token
-			{
-				int length = (token[i] & 0x7FFF0000) >> 16;
-
-				i += length;
-			}
-			else
-			{
-				Shader::Opcode opcode = (Shader::Opcode)(token[i] & 0x0000FFFF);
-
-				switch(opcode)
-				{
-				case Shader::OPCODE_RESERVED0:
-				case Shader::OPCODE_MOVA:
-					return 0;   // Unsupported operation
-				default:
-					instructionCount++;
-					break;
-				}
-
-				i += size(token[i], version);
-			}
-		}
-
-		return instructionCount;
-	}
-
-	bool PixelShader::depthOverride() const
-	{
-		return zOverride;
-	}
-
-	bool PixelShader::containsKill() const
-	{
-		return kill;
-	}
-
-	bool PixelShader::containsCentroid() const
-	{
-		return centroid;
-	}
-
-	bool PixelShader::usesDiffuse(int component) const
-	{
-		return input[0][component].active();
-	}
-
-	bool PixelShader::usesSpecular(int component) const
-	{
-		return input[1][component].active();
-	}
-
-	bool PixelShader::usesTexture(int coordinate, int component) const
-	{
-		return input[2 + coordinate][component].active();
-	}
-
-	void PixelShader::setInput(int inputIdx, int nbComponents, const sw::Shader::Semantic& semantic)
-	{
-		for(int i = 0; i < nbComponents; ++i)
-		{
-			input[inputIdx][i] = semantic;
-		}
-	}
-
-	const sw::Shader::Semantic& PixelShader::getInput(int inputIdx, int component) const
-	{
-		return input[inputIdx][component];
-	}
-
-	void PixelShader::analyze()
-	{
-		analyzeZOverride();
-		analyzeKill();
-		analyzeInterpolants();
-		analyzeDirtyConstants();
-		analyzeDynamicBranching();
-		analyzeSamplers();
-		analyzeCallSites();
-		analyzeIndirectAddressing();
-	}
-
-	void PixelShader::analyzeZOverride()
-	{
-		zOverride = false;
-
-		for(const auto &inst : instruction)
-		{
-			if(inst->opcode == Shader::OPCODE_TEXM3X2DEPTH ||
-			   inst->opcode == Shader::OPCODE_TEXDEPTH ||
-			   inst->dst.type == Shader::PARAMETER_DEPTHOUT)
-			{
-				zOverride = true;
-
-				break;
-			}
-		}
-	}
-
-	void PixelShader::analyzeKill()
-	{
-		kill = false;
-
-		for(const auto &inst : instruction)
-		{
-			if(inst->opcode == Shader::OPCODE_TEXKILL ||
-			   inst->opcode == Shader::OPCODE_DISCARD)
-			{
-				kill = true;
-
-				break;
-			}
-		}
-	}
-
-	void PixelShader::analyzeInterpolants()
-	{
-		if(shaderModel < 0x0300)
-		{
-			// Set default mapping; disable unused interpolants below
-			input[0][0] = Semantic(Shader::USAGE_COLOR, 0);
-			input[0][1] = Semantic(Shader::USAGE_COLOR, 0);
-			input[0][2] = Semantic(Shader::USAGE_COLOR, 0);
-			input[0][3] = Semantic(Shader::USAGE_COLOR, 0);
-
-			input[1][0] = Semantic(Shader::USAGE_COLOR, 1);
-			input[1][1] = Semantic(Shader::USAGE_COLOR, 1);
-			input[1][2] = Semantic(Shader::USAGE_COLOR, 1);
-			input[1][3] = Semantic(Shader::USAGE_COLOR, 1);
-
-			for(int i = 0; i < 8; i++)
-			{
-				input[2 + i][0] = Semantic(Shader::USAGE_TEXCOORD, i);
-				input[2 + i][1] = Semantic(Shader::USAGE_TEXCOORD, i);
-				input[2 + i][2] = Semantic(Shader::USAGE_TEXCOORD, i);
-				input[2 + i][3] = Semantic(Shader::USAGE_TEXCOORD, i);
-			}
-
-			Shader::SamplerType samplerType[16];
-
-			for(int i = 0; i < 16; i++)
-			{
-				samplerType[i] = Shader::SAMPLER_UNKNOWN;
-			}
-
-			for(const auto &inst : instruction)
-			{
-				if(inst->dst.type == Shader::PARAMETER_SAMPLER)
-				{
-					int sampler = inst->dst.index;
-
-					samplerType[sampler] = inst->samplerType;
-				}
-			}
-
-			bool interpolant[MAX_FRAGMENT_INPUTS][4] = {{false}};   // Interpolants in use
-
-			for(const auto &inst : instruction)
-			{
-				if(inst->dst.type == Shader::PARAMETER_TEXTURE)
-				{
-					int index = inst->dst.index + 2;
-
-					switch(inst->opcode)
-					{
-					case Shader::OPCODE_TEX:
-					case Shader::OPCODE_TEXBEM:
-					case Shader::OPCODE_TEXBEML:
-					case Shader::OPCODE_TEXCOORD:
-					case Shader::OPCODE_TEXDP3:
-					case Shader::OPCODE_TEXDP3TEX:
-					case Shader::OPCODE_TEXM3X2DEPTH:
-					case Shader::OPCODE_TEXM3X2PAD:
-					case Shader::OPCODE_TEXM3X2TEX:
-					case Shader::OPCODE_TEXM3X3:
-					case Shader::OPCODE_TEXM3X3PAD:
-					case Shader::OPCODE_TEXM3X3TEX:
-						interpolant[index][0] = true;
-						interpolant[index][1] = true;
-						interpolant[index][2] = true;
-						break;
-					case Shader::OPCODE_TEXKILL:
-						if(majorVersion < 2)
-						{
-							interpolant[index][0] = true;
-							interpolant[index][1] = true;
-							interpolant[index][2] = true;
-						}
-						else
-						{
-							interpolant[index][0] = true;
-							interpolant[index][1] = true;
-							interpolant[index][2] = true;
-							interpolant[index][3] = true;
-						}
-						break;
-					case Shader::OPCODE_TEXM3X3VSPEC:
-						interpolant[index][0] = true;
-						interpolant[index][1] = true;
-						interpolant[index][2] = true;
-						interpolant[index - 2][3] = true;
-						interpolant[index - 1][3] = true;
-						interpolant[index - 0][3] = true;
-						break;
-					case Shader::OPCODE_DCL:
-						break;   // Ignore
-					default:   // Arithmetic instruction
-						if(shaderModel >= 0x0104)
-						{
-							ASSERT(false);
-						}
-					}
-				}
-
-				for(int argument = 0; argument < 4; argument++)
-				{
-					if(inst->src[argument].type == Shader::PARAMETER_INPUT ||
-					   inst->src[argument].type == Shader::PARAMETER_TEXTURE)
-					{
-						int index = inst->src[argument].index;
-						int swizzle = inst->src[argument].swizzle;
-						int mask = inst->dst.mask;
-
-						if(inst->src[argument].type == Shader::PARAMETER_TEXTURE)
-						{
-							index += 2;
-						}
-
-						switch(inst->opcode)
-						{
-						case Shader::OPCODE_TEX:
-						case Shader::OPCODE_TEXLDD:
-						case Shader::OPCODE_TEXLDL:
-						case Shader::OPCODE_TEXLOD:
-						case Shader::OPCODE_TEXBIAS:
-						case Shader::OPCODE_TEXOFFSET:
-						case Shader::OPCODE_TEXOFFSETBIAS:
-						case Shader::OPCODE_TEXLODOFFSET:
-						case Shader::OPCODE_TEXELFETCH:
-						case Shader::OPCODE_TEXELFETCHOFFSET:
-						case Shader::OPCODE_TEXGRAD:
-						case Shader::OPCODE_TEXGRADOFFSET:
-							{
-								int sampler = inst->src[1].index;
-
-								switch(samplerType[sampler])
-								{
-								case Shader::SAMPLER_UNKNOWN:
-									if(shaderModel == 0x0104)
-									{
-										if((inst->src[0].swizzle & 0x30) == 0x20)   // .xyz
-										{
-											interpolant[index][0] = true;
-											interpolant[index][1] = true;
-											interpolant[index][2] = true;
-										}
-										else   // .xyw
-										{
-											interpolant[index][0] = true;
-											interpolant[index][1] = true;
-											interpolant[index][3] = true;
-										}
-									}
-									else
-									{
-										ASSERT(false);
-									}
-									break;
-								case Shader::SAMPLER_1D:
-									interpolant[index][0] = true;
-									break;
-								case Shader::SAMPLER_2D:
-									interpolant[index][0] = true;
-									interpolant[index][1] = true;
-									break;
-								case Shader::SAMPLER_CUBE:
-									interpolant[index][0] = true;
-									interpolant[index][1] = true;
-									interpolant[index][2] = true;
-									break;
-								case Shader::SAMPLER_VOLUME:
-									interpolant[index][0] = true;
-									interpolant[index][1] = true;
-									interpolant[index][2] = true;
-									break;
-								default:
-									ASSERT(false);
-								}
-
-								if(inst->bias)
-								{
-									interpolant[index][3] = true;
-								}
-
-								if(inst->project)
-								{
-									interpolant[index][3] = true;
-								}
-
-								if(shaderModel == 0x0104 && inst->opcode == Shader::OPCODE_TEX)
-								{
-									if(inst->src[0].modifier == Shader::MODIFIER_DZ)
-									{
-										interpolant[index][2] = true;
-									}
-
-									if(inst->src[0].modifier == Shader::MODIFIER_DW)
-									{
-										interpolant[index][3] = true;
-									}
-								}
-							}
-							break;
-						case Shader::OPCODE_M3X2:
-							if(mask & 0x1)
-							{
-								interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
-								interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
-								interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
-								interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
-							}
-
-							if(argument == 1)
-							{
-								if(mask & 0x2)
-								{
-									interpolant[index + 1][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
-									interpolant[index + 1][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
-									interpolant[index + 1][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
-									interpolant[index + 1][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
-								}
-							}
-							break;
-						case Shader::OPCODE_M3X3:
-							if(mask & 0x1)
-							{
-								interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
-								interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
-								interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
-								interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
-							}
-
-							if(argument == 1)
-							{
-								if(mask & 0x2)
-								{
-									interpolant[index + 1][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
-									interpolant[index + 1][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
-									interpolant[index + 1][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
-									interpolant[index + 1][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
-								}
-
-								if(mask & 0x4)
-								{
-									interpolant[index + 2][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
-									interpolant[index + 2][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
-									interpolant[index + 2][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
-									interpolant[index + 2][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
-								}
-							}
-							break;
-						case Shader::OPCODE_M3X4:
-							if(mask & 0x1)
-							{
-								interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
-								interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
-								interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
-								interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
-							}
-
-							if(argument == 1)
-							{
-								if(mask & 0x2)
-								{
-									interpolant[index + 1][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
-									interpolant[index + 1][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
-									interpolant[index + 1][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
-									interpolant[index + 1][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
-								}
-
-								if(mask & 0x4)
-								{
-									interpolant[index + 2][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
-									interpolant[index + 2][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
-									interpolant[index + 2][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
-									interpolant[index + 2][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
-								}
-
-								if(mask & 0x8)
-								{
-									interpolant[index + 3][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
-									interpolant[index + 3][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
-									interpolant[index + 3][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
-									interpolant[index + 3][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
-								}
-							}
-							break;
-						case Shader::OPCODE_M4X3:
-							if(mask & 0x1)
-							{
-								interpolant[index][0] |= swizzleContainsComponent(swizzle, 0);
-								interpolant[index][1] |= swizzleContainsComponent(swizzle, 1);
-								interpolant[index][2] |= swizzleContainsComponent(swizzle, 2);
-								interpolant[index][3] |= swizzleContainsComponent(swizzle, 3);
-							}
-
-							if(argument == 1)
-							{
-								if(mask & 0x2)
-								{
-									interpolant[index + 1][0] |= swizzleContainsComponent(swizzle, 0);
-									interpolant[index + 1][1] |= swizzleContainsComponent(swizzle, 1);
-									interpolant[index + 1][2] |= swizzleContainsComponent(swizzle, 2);
-									interpolant[index + 1][3] |= swizzleContainsComponent(swizzle, 3);
-								}
-
-								if(mask & 0x4)
-								{
-									interpolant[index + 2][0] |= swizzleContainsComponent(swizzle, 0);
-									interpolant[index + 2][1] |= swizzleContainsComponent(swizzle, 1);
-									interpolant[index + 2][2] |= swizzleContainsComponent(swizzle, 2);
-									interpolant[index + 2][3] |= swizzleContainsComponent(swizzle, 3);
-								}
-							}
-							break;
-						case Shader::OPCODE_M4X4:
-							if(mask & 0x1)
-							{
-								interpolant[index][0] |= swizzleContainsComponent(swizzle, 0);
-								interpolant[index][1] |= swizzleContainsComponent(swizzle, 1);
-								interpolant[index][2] |= swizzleContainsComponent(swizzle, 2);
-								interpolant[index][3] |= swizzleContainsComponent(swizzle, 3);
-							}
-
-							if(argument == 1)
-							{
-								if(mask & 0x2)
-								{
-									interpolant[index + 1][0] |= swizzleContainsComponent(swizzle, 0);
-									interpolant[index + 1][1] |= swizzleContainsComponent(swizzle, 1);
-									interpolant[index + 1][2] |= swizzleContainsComponent(swizzle, 2);
-									interpolant[index + 1][3] |= swizzleContainsComponent(swizzle, 3);
-								}
-
-								if(mask & 0x4)
-								{
-									interpolant[index + 2][0] |= swizzleContainsComponent(swizzle, 0);
-									interpolant[index + 2][1] |= swizzleContainsComponent(swizzle, 1);
-									interpolant[index + 2][2] |= swizzleContainsComponent(swizzle, 2);
-									interpolant[index + 2][3] |= swizzleContainsComponent(swizzle, 3);
-								}
-
-								if(mask & 0x8)
-								{
-									interpolant[index + 3][0] |= swizzleContainsComponent(swizzle, 0);
-									interpolant[index + 3][1] |= swizzleContainsComponent(swizzle, 1);
-									interpolant[index + 3][2] |= swizzleContainsComponent(swizzle, 2);
-									interpolant[index + 3][3] |= swizzleContainsComponent(swizzle, 3);
-								}
-							}
-							break;
-						case Shader::OPCODE_CRS:
-							if(mask & 0x1)
-							{
-								interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x6);
-								interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x6);
-								interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x6);
-								interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x6);
-							}
-
-							if(mask & 0x2)
-							{
-								interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x5);
-								interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x5);
-								interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x5);
-								interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x5);
-							}
-
-							if(mask & 0x4)
-							{
-								interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x3);
-								interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x3);
-								interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x3);
-								interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x3);
-							}
-							break;
-						case Shader::OPCODE_DP2ADD:
-							if(argument == 0 || argument == 1)
-							{
-								interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x3);
-								interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x3);
-								interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x3);
-								interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x3);
-							}
-							else   // argument == 2
-							{
-								interpolant[index][0] |= swizzleContainsComponent(swizzle, 0);
-								interpolant[index][1] |= swizzleContainsComponent(swizzle, 1);
-								interpolant[index][2] |= swizzleContainsComponent(swizzle, 2);
-								interpolant[index][3] |= swizzleContainsComponent(swizzle, 3);
-							}
-							break;
-						case Shader::OPCODE_DP3:
-							interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7);
-							interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7);
-							interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7);
-							interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7);
-							break;
-						case Shader::OPCODE_DP4:
-							interpolant[index][0] |= swizzleContainsComponent(swizzle, 0);
-							interpolant[index][1] |= swizzleContainsComponent(swizzle, 1);
-							interpolant[index][2] |= swizzleContainsComponent(swizzle, 2);
-							interpolant[index][3] |= swizzleContainsComponent(swizzle, 3);
-							break;
-						case Shader::OPCODE_SINCOS:
-						case Shader::OPCODE_EXP2X:
-						case Shader::OPCODE_LOG2X:
-						case Shader::OPCODE_POWX:
-						case Shader::OPCODE_RCPX:
-						case Shader::OPCODE_RSQX:
-							interpolant[index][0] |= swizzleContainsComponent(swizzle, 0);
-							interpolant[index][1] |= swizzleContainsComponent(swizzle, 1);
-							interpolant[index][2] |= swizzleContainsComponent(swizzle, 2);
-							interpolant[index][3] |= swizzleContainsComponent(swizzle, 3);
-							break;
-						case Shader::OPCODE_NRM3:
-							interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7 | mask);
-							interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7 | mask);
-							interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7 | mask);
-							interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7 | mask);
-							break;
-						case Shader::OPCODE_MOV:
-						case Shader::OPCODE_ADD:
-						case Shader::OPCODE_SUB:
-						case Shader::OPCODE_MUL:
-						case Shader::OPCODE_MAD:
-						case Shader::OPCODE_ABS:
-						case Shader::OPCODE_CMP0:
-						case Shader::OPCODE_CND:
-						case Shader::OPCODE_FRC:
-						case Shader::OPCODE_LRP:
-						case Shader::OPCODE_MAX:
-						case Shader::OPCODE_MIN:
-						case Shader::OPCODE_CMP:
-						case Shader::OPCODE_BREAKC:
-						case Shader::OPCODE_DFDX:
-						case Shader::OPCODE_DFDY:
-							interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, mask);
-							interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, mask);
-							interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, mask);
-							interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, mask);
-							break;
-						case Shader::OPCODE_TEXCOORD:
-							interpolant[index][0] = true;
-							interpolant[index][1] = true;
-							interpolant[index][2] = true;
-							interpolant[index][3] = true;
-							break;
-						case Shader::OPCODE_TEXDP3:
-						case Shader::OPCODE_TEXDP3TEX:
-						case Shader::OPCODE_TEXM3X2PAD:
-						case Shader::OPCODE_TEXM3X3PAD:
-						case Shader::OPCODE_TEXM3X2TEX:
-						case Shader::OPCODE_TEXM3X3SPEC:
-						case Shader::OPCODE_TEXM3X3VSPEC:
-						case Shader::OPCODE_TEXBEM:
-						case Shader::OPCODE_TEXBEML:
-						case Shader::OPCODE_TEXM3X2DEPTH:
-						case Shader::OPCODE_TEXM3X3:
-						case Shader::OPCODE_TEXM3X3TEX:
-							interpolant[index][0] = true;
-							interpolant[index][1] = true;
-							interpolant[index][2] = true;
-							break;
-						case Shader::OPCODE_TEXREG2AR:
-						case Shader::OPCODE_TEXREG2GB:
-						case Shader::OPCODE_TEXREG2RGB:
-							break;
-						default:
-						//	ASSERT(false);   // Refine component usage
-							interpolant[index][0] = true;
-							interpolant[index][1] = true;
-							interpolant[index][2] = true;
-							interpolant[index][3] = true;
-						}
-					}
-				}
-			}
-
-			for(int index = 0; index < MAX_FRAGMENT_INPUTS; index++)
-			{
-				for(int component = 0; component < 4; component++)
-				{
-					if(!interpolant[index][component])
-					{
-						input[index][component] = Semantic();
-					}
-				}
-			}
-		}
-		else   // Shader Model 3.0 input declaration; v# indexable
-		{
-			for(const auto &inst : instruction)
-			{
-				if(inst->opcode == Shader::OPCODE_DCL)
-				{
-					if(inst->dst.type == Shader::PARAMETER_INPUT)
-					{
-						unsigned char usage = inst->usage;
-						unsigned char index = inst->usageIndex;
-						unsigned char mask = inst->dst.mask;
-						unsigned char reg = inst->dst.index;
-
-						if(mask & 0x01) input[reg][0] = Semantic(usage, index);
-						if(mask & 0x02) input[reg][1] = Semantic(usage, index);
-						if(mask & 0x04) input[reg][2] = Semantic(usage, index);
-						if(mask & 0x08) input[reg][3] = Semantic(usage, index);
-					}
-					else if(inst->dst.type == Shader::PARAMETER_MISCTYPE)
-					{
-						unsigned char index = inst->dst.index;
-
-						if(index == Shader::VPosIndex)
-						{
-							vPosDeclared = true;
-						}
-						else if(index == Shader::VFaceIndex)
-						{
-							vFaceDeclared = true;
-						}
-						else ASSERT(false);
-					}
-				}
-			}
-		}
-
-		if(shaderModel >= 0x0200)
-		{
-			for(const auto &inst : instruction)
-			{
-				if(inst->opcode == Shader::OPCODE_DCL)
-				{
-					bool centroid = inst->dst.centroid;
-					unsigned char reg = inst->dst.index;
-
-					switch(inst->dst.type)
-					{
-					case Shader::PARAMETER_INPUT:
-						input[reg][0].centroid = centroid;
-						break;
-					case Shader::PARAMETER_TEXTURE:
-						input[2 + reg][0].centroid = centroid;
-						break;
-					default:
-						break;
-					}
-
-					this->centroid = this->centroid || centroid;
-				}
-			}
-		}
-	}
-}
diff --git a/src/Pipeline/PixelShader.hpp b/src/Pipeline/PixelShader.hpp
deleted file mode 100644
index 659c9f2..0000000
--- a/src/Pipeline/PixelShader.hpp
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//    http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef sw_PixelShader_hpp
-#define sw_PixelShader_hpp
-
-#include "Shader.hpp"
-#include "Device/Config.hpp"
-
-namespace sw
-{
-	class PixelShader : public Shader
-	{
-	public:
-		explicit PixelShader(const PixelShader *ps = 0);
-		explicit PixelShader(const unsigned long *token);
-
-		virtual ~PixelShader();
-
-		static int validate(const unsigned long *const token);   // Returns number of instructions if valid
-		bool depthOverride() const;
-		bool containsKill() const;
-		bool containsCentroid() const;
-		bool usesDiffuse(int component) const;
-		bool usesSpecular(int component) const;
-		bool usesTexture(int coordinate, int component) const;
-
-		void setInput(int inputIdx, int nbComponents, const Semantic& semantic);
-		const Semantic& getInput(int inputIdx, int component) const;
-
-		void declareVPos() { vPosDeclared = true; }
-		void declareVFace() { vFaceDeclared = true; }
-		bool isVPosDeclared() const { return vPosDeclared; }
-		bool isVFaceDeclared() const { return vFaceDeclared; }
-
-	private:
-		void analyze();
-		void analyzeZOverride();
-		void analyzeKill();
-		void analyzeInterpolants();
-
-		Semantic input[MAX_FRAGMENT_INPUTS][4];
-
-		bool vPosDeclared;
-		bool vFaceDeclared;
-		bool zOverride;
-		bool kill;
-		bool centroid;
-	};
-}
-
-#endif   // sw_PixelShader_hpp
diff --git a/src/Pipeline/Shader.cpp b/src/Pipeline/Shader.cpp
deleted file mode 100644
index a04e129..0000000
--- a/src/Pipeline/Shader.cpp
+++ /dev/null
@@ -1,1927 +0,0 @@
-// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//    http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "Shader.hpp"
-
-#include "VertexShader.hpp"
-#include "PixelShader.hpp"
-#include "System/Math.hpp"
-#include "Vulkan/VkDebug.hpp"
-
-#include <set>
-#include <fstream>
-#include <sstream>
-#include <stdarg.h>
-
-namespace sw
-{
-	volatile int Shader::serialCounter = 1;
-
-	Shader::Opcode Shader::OPCODE_DP(int i)
-	{
-		switch(i)
-		{
-		default: ASSERT(false);
-		case 1: return OPCODE_DP1;
-		case 2: return OPCODE_DP2;
-		case 3: return OPCODE_DP3;
-		case 4: return OPCODE_DP4;
-		}
-	}
-
-	Shader::Opcode Shader::OPCODE_LEN(int i)
-	{
-		switch(i)
-		{
-		default: ASSERT(false);
-		case 1: return OPCODE_ABS;
-		case 2: return OPCODE_LEN2;
-		case 3: return OPCODE_LEN3;
-		case 4: return OPCODE_LEN4;
-		}
-	}
-
-	Shader::Opcode Shader::OPCODE_DIST(int i)
-	{
-		switch(i)
-		{
-		default: ASSERT(false);
-		case 1: return OPCODE_DIST1;
-		case 2: return OPCODE_DIST2;
-		case 3: return OPCODE_DIST3;
-		case 4: return OPCODE_DIST4;
-		}
-	}
-
-	Shader::Opcode Shader::OPCODE_NRM(int i)
-	{
-		switch(i)
-		{
-		default: ASSERT(false);
-		case 1: return OPCODE_SGN;
-		case 2: return OPCODE_NRM2;
-		case 3: return OPCODE_NRM3;
-		case 4: return OPCODE_NRM4;
-		}
-	}
-
-	Shader::Opcode Shader::OPCODE_FORWARD(int i)
-	{
-		switch(i)
-		{
-		default: ASSERT(false);
-		case 1: return OPCODE_FORWARD1;
-		case 2: return OPCODE_FORWARD2;
-		case 3: return OPCODE_FORWARD3;
-		case 4: return OPCODE_FORWARD4;
-		}
-	}
-
-	Shader::Opcode Shader::OPCODE_REFLECT(int i)
-	{
-		switch(i)
-		{
-		default: ASSERT(false);
-		case 1: return OPCODE_REFLECT1;
-		case 2: return OPCODE_REFLECT2;
-		case 3: return OPCODE_REFLECT3;
-		case 4: return OPCODE_REFLECT4;
-		}
-	}
-
-	Shader::Opcode Shader::OPCODE_REFRACT(int i)
-	{
-		switch(i)
-		{
-		default: ASSERT(false);
-		case 1: return OPCODE_REFRACT1;
-		case 2: return OPCODE_REFRACT2;
-		case 3: return OPCODE_REFRACT3;
-		case 4: return OPCODE_REFRACT4;
-		}
-	}
-
-	Shader::Instruction::Instruction(Opcode opcode) : opcode(opcode), analysis(0)
-	{
-		control = CONTROL_RESERVED0;
-
-		predicate = false;
-		predicateNot = false;
-		predicateSwizzle = 0xE4;
-
-		coissue = false;
-		samplerType = SAMPLER_UNKNOWN;
-		usage = USAGE_POSITION;
-		usageIndex = 0;
-	}
-
-	Shader::Instruction::Instruction(const unsigned long *token, int size, unsigned char majorVersion) : analysis(0)
-	{
-		parseOperationToken(*token++, majorVersion);
-
-		samplerType = SAMPLER_UNKNOWN;
-		usage = USAGE_POSITION;
-		usageIndex = 0;
-
-		if(opcode == OPCODE_IF ||
-		   opcode == OPCODE_IFC ||
-		   opcode == OPCODE_LOOP ||
-		   opcode == OPCODE_REP ||
-		   opcode == OPCODE_BREAKC ||
-		   opcode == OPCODE_BREAKP)   // No destination operand
-		{
-			if(size > 0) parseSourceToken(0, token++, majorVersion);
-			if(size > 1) parseSourceToken(1, token++, majorVersion);
-			if(size > 2) parseSourceToken(2, token++, majorVersion);
-			if(size > 3) ASSERT(false);
-		}
-		else if(opcode == OPCODE_DCL)
-		{
-			parseDeclarationToken(*token++);
-			parseDestinationToken(token++, majorVersion);
-		}
-		else
-		{
-			if(size > 0)
-			{
-				parseDestinationToken(token, majorVersion);
-
-				if(dst.rel.type != PARAMETER_VOID && majorVersion >= 3)
-				{
-					token++;
-					size--;
-				}
-
-				token++;
-				size--;
-			}
-
-			if(predicate)
-			{
-				ASSERT(size != 0);
-
-				predicateNot = (Modifier)((*token & 0x0F000000) >> 24) == MODIFIER_NOT;
-				predicateSwizzle = (unsigned char)((*token & 0x00FF0000) >> 16);
-
-				token++;
-				size--;
-			}
-
-			for(int i = 0; size > 0; i++)
-			{
-				parseSourceToken(i, token, majorVersion);
-
-				token++;
-				size--;
-
-				if(src[i].rel.type != PARAMETER_VOID && majorVersion >= 2)
-				{
-					token++;
-					size--;
-				}
-			}
-		}
-	}
-
-	Shader::Instruction::~Instruction()
-	{
-	}
-
-	std::string Shader::Instruction::string(ShaderType shaderType, unsigned short version) const
-	{
-		std::string instructionString;
-
-		if(opcode != OPCODE_DCL)
-		{
-			instructionString += coissue ? "+ " : "";
-
-			if(predicate)
-			{
-				instructionString += predicateNot ? "(!p0" : "(p0";
-				instructionString += swizzleString(PARAMETER_PREDICATE, predicateSwizzle);
-				instructionString += ") ";
-			}
-
-			instructionString += operationString(version) + controlString() + dst.shiftString() + dst.modifierString();
-
-			if(dst.type != PARAMETER_VOID)
-			{
-				instructionString += " " + dst.string(shaderType, version) +
-				                           dst.relativeString() +
-				                           dst.maskString();
-			}
-
-			for(int i = 0; i < 4; i++)
-			{
-				if(src[i].type != PARAMETER_VOID)
-				{
-					instructionString += (dst.type != PARAMETER_VOID || i > 0) ? ", " : " ";
-					instructionString += src[i].preModifierString() +
-										 src[i].string(shaderType, version) +
-										 src[i].relativeString() +
-										 src[i].postModifierString() +
-										 src[i].swizzleString();
-				}
-			}
-		}
-		else   // DCL
-		{
-			instructionString += "dcl";
-
-			if(dst.type == PARAMETER_SAMPLER)
-			{
-				switch(samplerType)
-				{
-				case SAMPLER_UNKNOWN: instructionString += " ";        break;
-				case SAMPLER_1D:      instructionString += "_1d ";     break;
-				case SAMPLER_2D:      instructionString += "_2d ";     break;
-				case SAMPLER_CUBE:    instructionString += "_cube ";   break;
-				case SAMPLER_VOLUME:  instructionString += "_volume "; break;
-				default:
-					ASSERT(false);
-				}
-
-				instructionString += dst.string(shaderType, version);
-			}
-			else if(dst.type == PARAMETER_INPUT ||
-				    dst.type == PARAMETER_OUTPUT ||
-				    dst.type == PARAMETER_TEXTURE)
-			{
-				if(version >= 0x0300)
-				{
-					switch(usage)
-					{
-					case USAGE_POSITION:     instructionString += "_position";     break;
-					case USAGE_BLENDWEIGHT:  instructionString += "_blendweight";  break;
-					case USAGE_BLENDINDICES: instructionString += "_blendindices"; break;
-					case USAGE_NORMAL:       instructionString += "_normal";       break;
-					case USAGE_PSIZE:        instructionString += "_psize";        break;
-					case USAGE_TEXCOORD:     instructionString += "_texcoord";     break;
-					case USAGE_TANGENT:      instructionString += "_tangent";      break;
-					case USAGE_BINORMAL:     instructionString += "_binormal";     break;
-					case USAGE_TESSFACTOR:   instructionString += "_tessfactor";   break;
-					case USAGE_POSITIONT:    instructionString += "_positiont";    break;
-					case USAGE_COLOR:        instructionString += "_color";        break;
-					case USAGE_FOG:          instructionString += "_fog";          break;
-					case USAGE_DEPTH:        instructionString += "_depth";        break;
-					case USAGE_SAMPLE:       instructionString += "_sample";       break;
-					default:
-						ASSERT(false);
-					}
-
-					if(usageIndex > 0)
-					{
-						std::ostringstream buffer;
-
-						buffer << (int)usageIndex;
-
-						instructionString += buffer.str();
-					}
-				}
-				else ASSERT(dst.type != PARAMETER_OUTPUT);
-
-				instructionString += " ";
-
-				instructionString += dst.string(shaderType, version);
-				instructionString += dst.maskString();
-			}
-			else if(dst.type == PARAMETER_MISCTYPE)   // vPos and vFace
-			{
-				instructionString += " ";
-
-				instructionString += dst.string(shaderType, version);
-			}
-			else ASSERT(false);
-		}
-
-		return instructionString;
-	}
-
-	std::string Shader::DestinationParameter::modifierString() const
-	{
-		if(type == PARAMETER_VOID || type == PARAMETER_LABEL)
-		{
-			return "";
-		}
-
-		std::string modifierString;
-
-		if(saturate)
-		{
-			modifierString += "_sat";
-		}
-
-		if(partialPrecision)
-		{
-			modifierString += "_pp";
-		}
-
-		if(centroid)
-		{
-			modifierString += "_centroid";
-		}
-
-		return modifierString;
-	}
-
-	std::string Shader::DestinationParameter::shiftString() const
-	{
-		if(type == PARAMETER_VOID || type == PARAMETER_LABEL)
-		{
-			return "";
-		}
-
-		switch(shift)
-		{
-		case 0:		return "";
-		case 1:		return "_x2";
-		case 2:		return "_x4";
-		case 3:		return "_x8";
-		case -1:	return "_d2";
-		case -2:	return "_d4";
-		case -3:	return "_d8";
-		default:
-			return "";
-		//	ASSERT(false);   // FIXME
-		}
-	}
-
-	std::string Shader::DestinationParameter::maskString() const
-	{
-		if(type == PARAMETER_VOID || type == PARAMETER_LABEL)
-		{
-			return "";
-		}
-
-		switch(mask)
-		{
-		case 0x0:	return "";
-		case 0x1:	return ".x";
-		case 0x2:	return ".y";
-		case 0x3:	return ".xy";
-		case 0x4:	return ".z";
-		case 0x5:	return ".xz";
-		case 0x6:	return ".yz";
-		case 0x7:	return ".xyz";
-		case 0x8:	return ".w";
-		case 0x9:	return ".xw";
-		case 0xA:	return ".yw";
-		case 0xB:	return ".xyw";
-		case 0xC:	return ".zw";
-		case 0xD:	return ".xzw";
-		case 0xE:	return ".yzw";
-		case 0xF:	return "";
-		default:
-			ASSERT(false);
-		}
-
-		return "";
-	}
-
-	std::string Shader::SourceParameter::preModifierString() const
-	{
-		if(type == PARAMETER_VOID)
-		{
-			return "";
-		}
-
-		switch(modifier)
-		{
-		case MODIFIER_NONE:			return "";
-		case MODIFIER_NEGATE:		return "-";
-		case MODIFIER_BIAS:			return "";
-		case MODIFIER_BIAS_NEGATE:	return "-";
-		case MODIFIER_SIGN:			return "";
-		case MODIFIER_SIGN_NEGATE:	return "-";
-		case MODIFIER_COMPLEMENT:	return "1-";
-		case MODIFIER_X2:			return "";
-		case MODIFIER_X2_NEGATE:	return "-";
-		case MODIFIER_DZ:			return "";
-		case MODIFIER_DW:			return "";
-		case MODIFIER_ABS:			return "";
-		case MODIFIER_ABS_NEGATE:	return "-";
-		case MODIFIER_NOT:			return "!";
-		default:
-			ASSERT(false);
-		}
-
-		return "";
-	}
-
-	std::string Shader::Parameter::relativeString() const
-	{
-		if(type == PARAMETER_CONST || type == PARAMETER_INPUT || type == PARAMETER_OUTPUT || type == PARAMETER_TEMP)
-		{
-			if(rel.type == PARAMETER_VOID)
-			{
-				return "";
-			}
-			else if(rel.type == PARAMETER_ADDR)
-			{
-				switch(rel.swizzle & 0x03)
-				{
-				case 0: return "[a0.x]";
-				case 1: return "[a0.y]";
-				case 2: return "[a0.z]";
-				case 3: return "[a0.w]";
-				}
-			}
-			else if(rel.type == PARAMETER_TEMP)
-			{
-				std::ostringstream buffer;
-				buffer << rel.index;
-
-				switch(rel.swizzle & 0x03)
-				{
-				case 0: return "[r" + buffer.str() + ".x]";
-				case 1: return "[r" + buffer.str() + ".y]";
-				case 2: return "[r" + buffer.str() + ".z]";
-				case 3: return "[r" + buffer.str() + ".w]";
-				}
-			}
-			else if(rel.type == PARAMETER_LOOP)
-			{
-				return "[aL]";
-			}
-			else if(rel.type == PARAMETER_CONST)
-			{
-				std::ostringstream buffer;
-				buffer << rel.index;
-
-				switch(rel.swizzle & 0x03)
-				{
-				case 0: return "[c" + buffer.str() + ".x]";
-				case 1: return "[c" + buffer.str() + ".y]";
-				case 2: return "[c" + buffer.str() + ".z]";
-				case 3: return "[c" + buffer.str() + ".w]";
-				}
-			}
-			else ASSERT(false);
-		}
-
-		return "";
-	}
-
-	std::string Shader::SourceParameter::postModifierString() const
-	{
-		if(type == PARAMETER_VOID)
-		{
-			return "";
-		}
-
-		switch(modifier)
-		{
-		case MODIFIER_NONE:			return "";
-		case MODIFIER_NEGATE:		return "";
-		case MODIFIER_BIAS:			return "_bias";
-		case MODIFIER_BIAS_NEGATE:	return "_bias";
-		case MODIFIER_SIGN:			return "_bx2";
-		case MODIFIER_SIGN_NEGATE:	return "_bx2";
-		case MODIFIER_COMPLEMENT:	return "";
-		case MODIFIER_X2:			return "_x2";
-		case MODIFIER_X2_NEGATE:	return "_x2";
-		case MODIFIER_DZ:			return "_dz";
-		case MODIFIER_DW:			return "_dw";
-		case MODIFIER_ABS:			return "_abs";
-		case MODIFIER_ABS_NEGATE:	return "_abs";
-		case MODIFIER_NOT:			return "";
-		default:
-			ASSERT(false);
-		}
-
-		return "";
-	}
-
-	std::string Shader::SourceParameter::string(ShaderType shaderType, unsigned short version) const
-	{
-		if(type == PARAMETER_CONST && bufferIndex >= 0)
-		{
-			std::ostringstream buffer;
-			buffer << bufferIndex;
-
-			std::ostringstream offset;
-			offset << index;
-
-			return "cb" + buffer.str() + "[" + offset.str() + "]";
-		}
-		else
-		{
-			return Parameter::string(shaderType, version);
-		}
-	}
-
-	std::string Shader::SourceParameter::swizzleString() const
-	{
-		return Instruction::swizzleString(type, swizzle);
-	}
-
-	void Shader::Instruction::parseOperationToken(unsigned long token, unsigned char majorVersion)
-	{
-		if((token & 0xFFFF0000) == 0xFFFF0000 || (token & 0xFFFF0000) == 0xFFFE0000)   // Version token
-		{
-			opcode = (Opcode)token;
-
-			control = CONTROL_RESERVED0;
-			predicate = false;
-			coissue = false;
-		}
-		else
-		{
-			opcode = (Opcode)(token & 0x0000FFFF);
-			control = (Control)((token & 0x00FF0000) >> 16);
-
-			int size = (token & 0x0F000000) >> 24;
-
-			predicate = (token & 0x10000000) != 0x00000000;
-			coissue = (token & 0x40000000) != 0x00000000;
-
-			if(majorVersion < 2)
-			{
-				if(size != 0)
-				{
-					ASSERT(false);   // Reserved
-				}
-			}
-
-			if(majorVersion < 2)
-			{
-				if(predicate)
-				{
-					ASSERT(false);
-				}
-			}
-
-			if((token & 0x20000000) != 0x00000000)
-			{
-				ASSERT(false);   // Reserved
-			}
-
-			if(majorVersion >= 2)
-			{
-				if(coissue)
-				{
-					ASSERT(false);   // Reserved
-				}
-			}
-
-			if((token & 0x80000000) != 0x00000000)
-			{
-				ASSERT(false);
-			}
-		}
-	}
-
-	void Shader::Instruction::parseDeclarationToken(unsigned long token)
-	{
-		samplerType = (SamplerType)((token & 0x78000000) >> 27);
-		usage = (Usage)(token & 0x0000001F);
-		usageIndex = (unsigned char)((token & 0x000F0000) >> 16);
-	}
-
-	void Shader::Instruction::parseDestinationToken(const unsigned long *token, unsigned char majorVersion)
-	{
-		dst.index = (unsigned short)(token[0] & 0x000007FF);
-		dst.type = (ParameterType)(((token[0] & 0x00001800) >> 8) | ((token[0] & 0x70000000) >> 28));
-
-		// TODO: Check type and index range
-
-		bool relative = (token[0] & 0x00002000) != 0x00000000;
-		dst.rel.type = relative ? PARAMETER_ADDR : PARAMETER_VOID;
-		dst.rel.swizzle = 0x00;
-		dst.rel.scale = 1;
-
-		if(relative && majorVersion >= 3)
-		{
-			dst.rel.type = (ParameterType)(((token[1] & 0x00001800) >> 8) | ((token[1] & 0x70000000) >> 28));
-			dst.rel.swizzle = (unsigned char)((token[1] & 0x00FF0000) >> 16);
-		}
-		else if(relative) ASSERT(false);   // Reserved
-
-		if((token[0] & 0x0000C000) != 0x00000000)
-		{
-			ASSERT(false);   // Reserved
-		}
-
-		dst.mask = (unsigned char)((token[0] & 0x000F0000) >> 16);
-		dst.saturate = (token[0] & 0x00100000) != 0;
-		dst.partialPrecision = (token[0] & 0x00200000) != 0;
-		dst.centroid = (token[0] & 0x00400000) != 0;
-		dst.shift = (signed char)((token[0] & 0x0F000000) >> 20) >> 4;
-
-		if(majorVersion >= 2)
-		{
-			if(dst.shift)
-			{
-				ASSERT(false);   // Reserved
-			}
-		}
-
-		if((token[0] & 0x80000000) != 0x80000000)
-		{
-			ASSERT(false);
-		}
-	}
-
-	void Shader::Instruction::parseSourceToken(int i, const unsigned long *token, unsigned char majorVersion)
-	{
-		// Defaults
-		src[i].index = 0;
-		src[i].type = PARAMETER_VOID;
-		src[i].modifier = MODIFIER_NONE;
-		src[i].swizzle = 0xE4;
-		src[i].rel.type = PARAMETER_VOID;
-		src[i].rel.swizzle = 0x00;
-		src[i].rel.scale = 1;
-
-		switch(opcode)
-		{
-		case OPCODE_DEF:
-			src[0].type = PARAMETER_FLOAT4LITERAL;
-			src[0].value[i] = *(float*)token;
-			break;
-		case OPCODE_DEFB:
-			src[0].type = PARAMETER_BOOL1LITERAL;
-			src[0].boolean[0] = *(int*)token;
-			break;
-		case OPCODE_DEFI:
-			src[0].type = PARAMETER_INT4LITERAL;
-			src[0].integer[i] = *(int*)token;
-			break;
-		default:
-			src[i].index = (unsigned short)(token[0] & 0x000007FF);
-			src[i].type = (ParameterType)(((token[0] & 0x00001800) >> 8) | ((token[0] & 0x70000000) >> 28));
-
-			// FIXME: Check type and index range
-
-			bool relative = (token[0] & 0x00002000) != 0x00000000;
-			src[i].rel.type = relative ? PARAMETER_ADDR : PARAMETER_VOID;
-
-			if((token[0] & 0x0000C000) != 0x00000000)
-			{
-				if(opcode != OPCODE_DEF &&
-				   opcode != OPCODE_DEFI &&
-				   opcode != OPCODE_DEFB)
-				{
-					ASSERT(false);
-				}
-			}
-
-			src[i].swizzle = (unsigned char)((token[0] & 0x00FF0000) >> 16);
-			src[i].modifier = (Modifier)((token[0] & 0x0F000000) >> 24);
-
-			if((token[0] & 0x80000000) != 0x80000000)
-			{
-				if(opcode != OPCODE_DEF &&
-				   opcode != OPCODE_DEFI &&
-				   opcode != OPCODE_DEFB)
-				{
-					ASSERT(false);
-				}
-			}
-
-			if(relative && majorVersion >= 2)
-			{
-				src[i].rel.type = (ParameterType)(((token[1] & 0x00001800) >> 8) | ((token[1] & 0x70000000) >> 28));
-				src[i].rel.swizzle = (unsigned char)((token[1] & 0x00FF0000) >> 16);
-			}
-		}
-	}
-
-	std::string Shader::Instruction::swizzleString(ParameterType type, unsigned char swizzle)
-	{
-		if(type == PARAMETER_VOID || type == PARAMETER_LABEL || swizzle == 0xE4)
-		{
-			return "";
-		}
-
-		int x = (swizzle & 0x03) >> 0;
-		int y = (swizzle & 0x0C) >> 2;
-		int z = (swizzle & 0x30) >> 4;
-		int w = (swizzle & 0xC0) >> 6;
-
-		std::string swizzleString = ".";
-
-		switch(x)
-		{
-		case 0: swizzleString += "x"; break;
-		case 1: swizzleString += "y"; break;
-		case 2: swizzleString += "z"; break;
-		case 3: swizzleString += "w"; break;
-		}
-
-		if(!(x == y && y == z && z == w))
-		{
-			switch(y)
-			{
-			case 0: swizzleString += "x"; break;
-			case 1: swizzleString += "y"; break;
-			case 2: swizzleString += "z"; break;
-			case 3: swizzleString += "w"; break;
-			}
-
-			if(!(y == z && z == w))
-			{
-				switch(z)
-				{
-				case 0: swizzleString += "x"; break;
-				case 1: swizzleString += "y"; break;
-				case 2: swizzleString += "z"; break;
-				case 3: swizzleString += "w"; break;
-				}
-
-				if(!(z == w))
-				{
-					switch(w)
-					{
-					case 0: swizzleString += "x"; break;
-					case 1: swizzleString += "y"; break;
-					case 2: swizzleString += "z"; break;
-					case 3: swizzleString += "w"; break;
-					}
-				}
-			}
-		}
-
-		return swizzleString;
-	}
-
-	std::string Shader::Instruction::operationString(unsigned short version) const
-	{
-		switch(opcode)
-		{
-		case OPCODE_NULL:            return "null";
-		case OPCODE_NOP:             return "nop";
-		case OPCODE_MOV:             return "mov";
-		case OPCODE_ADD:             return "add";
-		case OPCODE_IADD:            return "iadd";
-		case OPCODE_SUB:             return "sub";
-		case OPCODE_ISUB:            return "isub";
-		case OPCODE_MAD:             return "mad";
-		case OPCODE_IMAD:            return "imad";
-		case OPCODE_MUL:             return "mul";
-		case OPCODE_IMUL:            return "imul";
-		case OPCODE_RCPX:            return "rcpx";
-		case OPCODE_DIV:             return "div";
-		case OPCODE_IDIV:            return "idiv";
-		case OPCODE_UDIV:            return "udiv";
-		case OPCODE_MOD:             return "mod";
-		case OPCODE_IMOD:            return "imod";
-		case OPCODE_UMOD:            return "umod";
-		case OPCODE_SHL:             return "shl";
-		case OPCODE_ISHR:            return "ishr";
-		case OPCODE_USHR:            return "ushr";
-		case OPCODE_RSQX:            return "rsqx";
-		case OPCODE_SQRT:            return "sqrt";
-		case OPCODE_RSQ:             return "rsq";
-		case OPCODE_LEN2:            return "len2";
-		case OPCODE_LEN3:            return "len3";
-		case OPCODE_LEN4:            return "len4";
-		case OPCODE_DIST1:           return "dist1";
-		case OPCODE_DIST2:           return "dist2";
-		case OPCODE_DIST3:           return "dist3";
-		case OPCODE_DIST4:           return "dist4";
-		case OPCODE_DP3:             return "dp3";
-		case OPCODE_DP4:             return "dp4";
-		case OPCODE_DET2:            return "det2";
-		case OPCODE_DET3:            return "det3";
-		case OPCODE_DET4:            return "det4";
-		case OPCODE_MIN:             return "min";
-		case OPCODE_IMIN:            return "imin";
-		case OPCODE_UMIN:            return "umin";
-		case OPCODE_MAX:             return "max";
-		case OPCODE_IMAX:            return "imax";
-		case OPCODE_UMAX:            return "umax";
-		case OPCODE_SLT:             return "slt";
-		case OPCODE_SGE:             return "sge";
-		case OPCODE_EXP2X:           return "exp2x";
-		case OPCODE_LOG2X:           return "log2x";
-		case OPCODE_LIT:             return "lit";
-		case OPCODE_ATT:             return "att";
-		case OPCODE_LRP:             return "lrp";
-		case OPCODE_STEP:            return "step";
-		case OPCODE_SMOOTH:          return "smooth";
-		case OPCODE_FLOATBITSTOINT:  return "floatBitsToInt";
-		case OPCODE_FLOATBITSTOUINT: return "floatBitsToUInt";
-		case OPCODE_INTBITSTOFLOAT:  return "intBitsToFloat";
-		case OPCODE_UINTBITSTOFLOAT: return "uintBitsToFloat";
-		case OPCODE_PACKSNORM2x16:   return "packSnorm2x16";
-		case OPCODE_PACKUNORM2x16:   return "packUnorm2x16";
-		case OPCODE_PACKHALF2x16:    return "packHalf2x16";
-		case OPCODE_UNPACKSNORM2x16: return "unpackSnorm2x16";
-		case OPCODE_UNPACKUNORM2x16: return "unpackUnorm2x16";
-		case OPCODE_UNPACKHALF2x16:  return "unpackHalf2x16";
-		case OPCODE_FRC:             return "frc";
-		case OPCODE_M4X4:            return "m4x4";
-		case OPCODE_M4X3:            return "m4x3";
-		case OPCODE_M3X4:            return "m3x4";
-		case OPCODE_M3X3:            return "m3x3";
-		case OPCODE_M3X2:            return "m3x2";
-		case OPCODE_CALL:            return "call";
-		case OPCODE_CALLNZ:          return "callnz";
-		case OPCODE_LOOP:            return "loop";
-		case OPCODE_RET:             return "ret";
-		case OPCODE_ENDLOOP:         return "endloop";
-		case OPCODE_LABEL:           return "label";
-		case OPCODE_DCL:             return "dcl";
-		case OPCODE_POWX:            return "powx";
-		case OPCODE_CRS:             return "crs";
-		case OPCODE_SGN:             return "sgn";
-		case OPCODE_ISGN:            return "isgn";
-		case OPCODE_ABS:             return "abs";
-		case OPCODE_IABS:            return "iabs";
-		case OPCODE_NRM2:            return "nrm2";
-		case OPCODE_NRM3:            return "nrm3";
-		case OPCODE_NRM4:            return "nrm4";
-		case OPCODE_SINCOS:          return "sincos";
-		case OPCODE_REP:             return "rep";
-		case OPCODE_ENDREP:          return "endrep";
-		case OPCODE_IF:              return "if";
-		case OPCODE_IFC:             return "ifc";
-		case OPCODE_ELSE:            return "else";
-		case OPCODE_ENDIF:           return "endif";
-		case OPCODE_BREAK:           return "break";
-		case OPCODE_BREAKC:          return "breakc";
-		case OPCODE_MOVA:            return "mova";
-		case OPCODE_DEFB:            return "defb";
-		case OPCODE_DEFI:            return "defi";
-		case OPCODE_TEXCOORD:        return "texcoord";
-		case OPCODE_TEXKILL:         return "texkill";
-		case OPCODE_DISCARD:         return "discard";
-		case OPCODE_TEX:
-			if(version < 0x0104)     return "tex";
-			else                     return "texld";
-		case OPCODE_TEXBEM:          return "texbem";
-		case OPCODE_TEXBEML:         return "texbeml";
-		case OPCODE_TEXREG2AR:       return "texreg2ar";
-		case OPCODE_TEXREG2GB:       return "texreg2gb";
-		case OPCODE_TEXM3X2PAD:      return "texm3x2pad";
-		case OPCODE_TEXM3X2TEX:      return "texm3x2tex";
-		case OPCODE_TEXM3X3PAD:      return "texm3x3pad";
-		case OPCODE_TEXM3X3TEX:      return "texm3x3tex";
-		case OPCODE_RESERVED0:       return "reserved0";
-		case OPCODE_TEXM3X3SPEC:     return "texm3x3spec";
-		case OPCODE_TEXM3X3VSPEC:    return "texm3x3vspec";
-		case OPCODE_EXPP:            return "expp";
-		case OPCODE_LOGP:            return "logp";
-		case OPCODE_CND:             return "cnd";
-		case OPCODE_DEF:             return "def";
-		case OPCODE_TEXREG2RGB:      return "texreg2rgb";
-		case OPCODE_TEXDP3TEX:       return "texdp3tex";
-		case OPCODE_TEXM3X2DEPTH:    return "texm3x2depth";
-		case OPCODE_TEXDP3:          return "texdp3";
-		case OPCODE_TEXM3X3:         return "texm3x3";
-		case OPCODE_TEXDEPTH:        return "texdepth";
-		case OPCODE_CMP0:            return "cmp0";
-		case OPCODE_ICMP:            return "icmp";
-		case OPCODE_UCMP:            return "ucmp";
-		case OPCODE_SELECT:          return "select";
-		case OPCODE_EXTRACT:         return "extract";
-		case OPCODE_INSERT:          return "insert";
-		case OPCODE_BEM:             return "bem";
-		case OPCODE_DP2ADD:          return "dp2add";
-		case OPCODE_DFDX:            return "dFdx";
-		case OPCODE_DFDY:            return "dFdy";
-		case OPCODE_FWIDTH:          return "fwidth";
-		case OPCODE_TEXLDD:          return "texldd";
-		case OPCODE_CMP:             return "cmp";
-		case OPCODE_TEXLDL:          return "texldl";
-		case OPCODE_TEXBIAS:         return "texbias";
-		case OPCODE_TEXOFFSET:       return "texoffset";
-		case OPCODE_TEXOFFSETBIAS:   return "texoffsetbias";
-		case OPCODE_TEXLODOFFSET:    return "texlodoffset";
-		case OPCODE_TEXELFETCH:      return "texelfetch";
-		case OPCODE_TEXELFETCHOFFSET: return "texelfetchoffset";
-		case OPCODE_TEXGRAD:         return "texgrad";
-		case OPCODE_TEXGRADOFFSET:   return "texgradoffset";
-		case OPCODE_BREAKP:          return "breakp";
-		case OPCODE_TEXSIZE:         return "texsize";
-		case OPCODE_PHASE:           return "phase";
-		case OPCODE_COMMENT:         return "comment";
-		case OPCODE_END:             return "end";
-		case OPCODE_PS_1_0:          return "ps_1_0";
-		case OPCODE_PS_1_1:          return "ps_1_1";
-		case OPCODE_PS_1_2:          return "ps_1_2";
-		case OPCODE_PS_1_3:          return "ps_1_3";
-		case OPCODE_PS_1_4:          return "ps_1_4";
-		case OPCODE_PS_2_0:          return "ps_2_0";
-		case OPCODE_PS_2_x:          return "ps_2_x";
-		case OPCODE_PS_3_0:          return "ps_3_0";
-		case OPCODE_VS_1_0:          return "vs_1_0";
-		case OPCODE_VS_1_1:          return "vs_1_1";
-		case OPCODE_VS_2_0:          return "vs_2_0";
-		case OPCODE_VS_2_x:          return "vs_2_x";
-		case OPCODE_VS_2_sw:         return "vs_2_sw";
-		case OPCODE_VS_3_0:          return "vs_3_0";
-		case OPCODE_VS_3_sw:         return "vs_3_sw";
-		case OPCODE_WHILE:           return "while";
-		case OPCODE_ENDWHILE:        return "endwhile";
-		case OPCODE_COS:             return "cos";
-		case OPCODE_SIN:             return "sin";
-		case OPCODE_TAN:             return "tan";
-		case OPCODE_ACOS:            return "acos";
-		case OPCODE_ASIN:            return "asin";
-		case OPCODE_ATAN:            return "atan";
-		case OPCODE_ATAN2:           return "atan2";
-		case OPCODE_COSH:            return "cosh";
-		case OPCODE_SINH:            return "sinh";
-		case OPCODE_TANH:            return "tanh";
-		case OPCODE_ACOSH:           return "acosh";
-		case OPCODE_ASINH:           return "asinh";
-		case OPCODE_ATANH:           return "atanh";
-		case OPCODE_DP1:             return "dp1";
-		case OPCODE_DP2:             return "dp2";
-		case OPCODE_TRUNC:           return "trunc";
-		case OPCODE_FLOOR:           return "floor";
-		case OPCODE_ROUND:           return "round";
-		case OPCODE_ROUNDEVEN:       return "roundEven";
-		case OPCODE_CEIL:            return "ceil";
-		case OPCODE_EXP2:            return "exp2";
-		case OPCODE_LOG2:            return "log2";
-		case OPCODE_EXP:             return "exp";
-		case OPCODE_LOG:             return "log";
-		case OPCODE_POW:             return "pow";
-		case OPCODE_F2B:             return "f2b";
-		case OPCODE_B2F:             return "b2f";
-		case OPCODE_F2I:             return "f2i";
-		case OPCODE_I2F:             return "i2f";
-		case OPCODE_F2U:             return "f2u";
-		case OPCODE_U2F:             return "u2f";
-		case OPCODE_B2I:             return "b2i";
-		case OPCODE_I2B:             return "i2b";
-		case OPCODE_ALL:             return "all";
-		case OPCODE_ANY:             return "any";
-		case OPCODE_NEG:             return "neg";
-		case OPCODE_INEG:            return "ineg";
-		case OPCODE_ISNAN:           return "isnan";
-		case OPCODE_ISINF:           return "isinf";
-		case OPCODE_NOT:             return "not";
-		case OPCODE_OR:              return "or";
-		case OPCODE_XOR:             return "xor";
-		case OPCODE_AND:             return "and";
-		case OPCODE_EQ:              return "eq";
-		case OPCODE_NE:              return "neq";
-		case OPCODE_FORWARD1:        return "forward1";
-		case OPCODE_FORWARD2:        return "forward2";
-		case OPCODE_FORWARD3:        return "forward3";
-		case OPCODE_FORWARD4:        return "forward4";
-		case OPCODE_REFLECT1:        return "reflect1";
-		case OPCODE_REFLECT2:        return "reflect2";
-		case OPCODE_REFLECT3:        return "reflect3";
-		case OPCODE_REFLECT4:        return "reflect4";
-		case OPCODE_REFRACT1:        return "refract1";
-		case OPCODE_REFRACT2:        return "refract2";
-		case OPCODE_REFRACT3:        return "refract3";
-		case OPCODE_REFRACT4:        return "refract4";
-		case OPCODE_LEAVE:           return "leave";
-		case OPCODE_CONTINUE:        return "continue";
-		case OPCODE_TEST:            return "test";
-		case OPCODE_SWITCH:          return "switch";
-		case OPCODE_ENDSWITCH:       return "endswitch";
-		default:
-			ASSERT(false);
-		}
-
-		return "<unknown>";
-	}
-
-	std::string Shader::Instruction::controlString() const
-	{
-		if(opcode != OPCODE_LOOP && opcode != OPCODE_BREAKC && opcode != OPCODE_IFC && opcode != OPCODE_CMP)
-		{
-			if(project) return "p";
-
-			if(bias) return "b";
-
-			// FIXME: LOD
-		}
-
-		switch(control)
-		{
-		case 1: return "_gt";
-		case 2: return "_eq";
-		case 3: return "_ge";
-		case 4: return "_lt";
-		case 5: return "_ne";
-		case 6: return "_le";
-		default:
-			return "";
-		//	ASSERT(false);   // FIXME
-		}
-	}
-
-	std::string Shader::Parameter::string(ShaderType shaderType, unsigned short version) const
-	{
-		std::ostringstream buffer;
-
-		if(type == PARAMETER_FLOAT4LITERAL)
-		{
-			buffer << '{' << value[0] << ", " << value[1] << ", " << value[2] << ", " << value[3] << '}';
-
-			return buffer.str();
-		}
-		else if(type != PARAMETER_RASTOUT && !(type == PARAMETER_ADDR && shaderType == SHADER_VERTEX) && type != PARAMETER_LOOP && type != PARAMETER_PREDICATE && type != PARAMETER_MISCTYPE)
-		{
-			buffer << index;
-
-			return typeString(shaderType, version) + buffer.str();
-		}
-		else
-		{
-			return typeString(shaderType, version);
-		}
-	}
-
-	std::string Shader::Parameter::typeString(ShaderType shaderType, unsigned short version) const
-	{
-		switch(type)
-		{
-		case PARAMETER_TEMP:			return "r";
-		case PARAMETER_INPUT:			return "v";
-		case PARAMETER_CONST:			return "c";
-		case PARAMETER_TEXTURE:
-	//	case PARAMETER_ADDR:
-			if(shaderType == SHADER_PIXEL)	return "t";
-			else							return "a0";
-		case PARAMETER_RASTOUT:
-			if(index == 0)              return "oPos";
-			else if(index == 1)         return "oFog";
-			else if(index == 2)         return "oPts";
-			else                        ASSERT(false);
-		case PARAMETER_ATTROUT:			return "oD";
-		case PARAMETER_TEXCRDOUT:
-	//	case PARAMETER_OUTPUT:			return "";
-			if(version < 0x0300)		return "oT";
-			else						return "o";
-		case PARAMETER_CONSTINT:		return "i";
-		case PARAMETER_COLOROUT:		return "oC";
-		case PARAMETER_DEPTHOUT:		return "oDepth";
-		case PARAMETER_SAMPLER:			return "s";
-	//	case PARAMETER_CONST2:			return "";
-	//	case PARAMETER_CONST3:			return "";
-	//	case PARAMETER_CONST4:			return "";
-		case PARAMETER_CONSTBOOL:		return "b";
-		case PARAMETER_LOOP:			return "aL";
-	//	case PARAMETER_TEMPFLOAT16:		return "";
-		case PARAMETER_MISCTYPE:
-			switch(index)
-			{
-			case VPosIndex:				return "vPos";
-			case VFaceIndex:			return "vFace";
-			case InstanceIDIndex:		return "iID";
-			case VertexIDIndex:			return "vID";
-			default: ASSERT(false);
-			}
-		case PARAMETER_LABEL:			return "l";
-		case PARAMETER_PREDICATE:		return "p0";
-		case PARAMETER_FLOAT4LITERAL:	return "";
-		case PARAMETER_BOOL1LITERAL:	return "";
-		case PARAMETER_INT4LITERAL:		return "";
-	//	case PARAMETER_VOID:			return "";
-		default:
-			ASSERT(false);
-		}
-
-		return "";
-	}
-
-	bool Shader::Instruction::isBranch() const
-	{
-		return opcode == OPCODE_IF || opcode == OPCODE_IFC;
-	}
-
-	bool Shader::Instruction::isCall() const
-	{
-		return opcode == OPCODE_CALL || opcode == OPCODE_CALLNZ;
-	}
-
-	bool Shader::Instruction::isBreak() const
-	{
-		return opcode == OPCODE_BREAK || opcode == OPCODE_BREAKC || opcode == OPCODE_BREAKP;
-	}
-
-	bool Shader::Instruction::isLoop() const
-	{
-		return opcode == OPCODE_LOOP || opcode == OPCODE_REP || opcode == OPCODE_WHILE;
-	}
-
-	bool Shader::Instruction::isEndLoop() const
-	{
-		return opcode == OPCODE_ENDLOOP || opcode == OPCODE_ENDREP || opcode == OPCODE_ENDWHILE;
-	}
-
-	bool Shader::Instruction::isPredicated() const
-	{
-		return predicate ||
-		       analysisBranch ||
-		       analysisBreak ||
-		       analysisContinue ||
-		       analysisLeave;
-	}
-
-	Shader::Shader() : serialID(serialCounter++)
-	{
-		usedSamplers = 0;
-	}
-
-	Shader::~Shader()
-	{
-		for(auto &inst : instruction)
-		{
-			delete inst;
-			inst = 0;
-		}
-	}
-
-	void Shader::parse(const unsigned long *token)
-	{
-		minorVersion = (unsigned char)(token[0] & 0x000000FF);
-		majorVersion = (unsigned char)((token[0] & 0x0000FF00) >> 8);
-		shaderType = (ShaderType)((token[0] & 0xFFFF0000) >> 16);
-
-		int length = 0;
-
-		if(shaderType == SHADER_VERTEX)
-		{
-			length = VertexShader::validate(token);
-		}
-		else if(shaderType == SHADER_PIXEL)
-		{
-			length = PixelShader::validate(token);
-		}
-		else ASSERT(false);
-
-		ASSERT(length != 0);
-		instruction.resize(length);
-
-		for(int i = 0; i < length; i++)
-		{
-			while((*token & 0x0000FFFF) == 0x0000FFFE)   // Comment token
-			{
-				int length = (*token & 0x7FFF0000) >> 16;
-
-				token += length + 1;
-			}
-
-			int tokenCount = size(*token);
-
-			instruction[i] = new Instruction(token, tokenCount, majorVersion);
-
-			token += 1 + tokenCount;
-		}
-	}
-
-	int Shader::size(unsigned long opcode) const
-	{
-		return size(opcode, shaderModel);
-	}
-
-	int Shader::size(unsigned long opcode, unsigned short shaderModel)
-	{
-		if(shaderModel > 0x0300)
-		{
-			ASSERT(false);
-		}
-
-		static const signed char size[] =
-		{
-			0,   // NOP = 0
-			2,   // MOV
-			3,   // ADD
-			3,   // SUB
-			4,   // MAD
-			3,   // MUL
-			2,   // RCP
-			2,   // RSQ
-			3,   // DP3
-			3,   // DP4
-			3,   // MIN
-			3,   // MAX
-			3,   // SLT
-			3,   // SGE
-			2,   // EXP
-			2,   // LOG
-			2,   // LIT
-			3,   // DST
-			4,   // LRP
-			2,   // FRC
-			3,   // M4x4
-			3,   // M4x3
-			3,   // M3x4
-			3,   // M3x3
-			3,   // M3x2
-			1,   // CALL
-			2,   // CALLNZ
-			2,   // LOOP
-			0,   // RET
-			0,   // ENDLOOP
-			1,   // LABEL
-			2,   // DCL
-			3,   // POW
-			3,   // CRS
-			4,   // SGN
-			2,   // ABS
-			2,   // NRM
-			4,   // SINCOS
-			1,   // REP
-			0,   // ENDREP
-			1,   // IF
-			2,   // IFC
-			0,   // ELSE
-			0,   // ENDIF
-			0,   // BREAK
-			2,   // BREAKC
-			2,   // MOVA
-			2,   // DEFB
-			5,   // DEFI
-			-1,  // 49
-			-1,  // 50
-			-1,  // 51
-			-1,  // 52
-			-1,  // 53
-			-1,  // 54
-			-1,  // 55
-			-1,  // 56
-			-1,  // 57
-			-1,  // 58
-			-1,  // 59
-			-1,  // 60
-			-1,  // 61
-			-1,  // 62
-			-1,  // 63
-			1,   // TEXCOORD = 64
-			1,   // TEXKILL
-			1,   // TEX
-			2,   // TEXBEM
-			2,   // TEXBEML
-			2,   // TEXREG2AR
-			2,   // TEXREG2GB
-			2,   // TEXM3x2PAD
-			2,   // TEXM3x2TEX
-			2,   // TEXM3x3PAD
-			2,   // TEXM3x3TEX
-			-1,  // RESERVED0
-			3,   // TEXM3x3SPEC
-			2,   // TEXM3x3VSPEC
-			2,   // EXPP
-			2,   // LOGP
-			4,   // CND
-			5,   // DEF
-			2,   // TEXREG2RGB
-			2,   // TEXDP3TEX
-			2,   // TEXM3x2DEPTH
-			2,   // TEXDP3
-			2,   // TEXM3x3
-			1,   // TEXDEPTH
-			4,   // CMP
-			3,   // BEM
-			4,   // DP2ADD
-			2,   // DSX
-			2,   // DSY
-			5,   // TEXLDD
-			3,   // SETP
-			3,   // TEXLDL
-			2,   // BREAKP
-			-1,  // 97
-			-1,  // 98
-			-1,  // 99
-			-1,  // 100
-			-1,  // 101
-			-1,  // 102
-			-1,  // 103
-			-1,  // 104
-			-1,  // 105
-			-1,  // 106
-			-1,  // 107
-			-1,  // 108
-			-1,  // 109
-			-1,  // 110
-			-1,  // 111
-			-1,  // 112
-		};
-
-		int length = 0;
-
-		if((opcode & 0x0000FFFF) == OPCODE_COMMENT)
-		{
-			return (opcode & 0x7FFF0000) >> 16;
-		}
-
-		if(opcode != OPCODE_PS_1_0 &&
-		   opcode != OPCODE_PS_1_1 &&
-		   opcode != OPCODE_PS_1_2 &&
-		   opcode != OPCODE_PS_1_3 &&
-		   opcode != OPCODE_PS_1_4 &&
-		   opcode != OPCODE_PS_2_0 &&
-		   opcode != OPCODE_PS_2_x &&
-		   opcode != OPCODE_PS_3_0 &&
-		   opcode != OPCODE_VS_1_0 &&
-		   opcode != OPCODE_VS_1_1 &&
-		   opcode != OPCODE_VS_2_0 &&
-		   opcode != OPCODE_VS_2_x &&
-		   opcode != OPCODE_VS_2_sw &&
-		   opcode != OPCODE_VS_3_0 &&
-		   opcode != OPCODE_VS_3_sw &&
-		   opcode != OPCODE_PHASE &&
-		   opcode != OPCODE_END)
-		{
-			if(shaderModel >= 0x0200)
-			{
-				length = (opcode & 0x0F000000) >> 24;
-			}
-			else
-			{
-				length = size[opcode & 0x0000FFFF];
-			}
-		}
-
-		if(length < 0)
-		{
-			ASSERT(false);
-		}
-
-		if(shaderModel == 0x0104)
-		{
-			switch(opcode & 0x0000FFFF)
-			{
-			case OPCODE_TEX:
-				length += 1;
-				break;
-			case OPCODE_TEXCOORD:
-				length += 1;
-				break;
-			default:
-				break;
-			}
-		}
-
-		return length;
-	}
-
-	bool Shader::maskContainsComponent(int mask, int component)
-	{
-		return (mask & (1 << component)) != 0;
-	}
-
-	bool Shader::swizzleContainsComponent(int swizzle, int component)
-	{
-		if((swizzle & 0x03) >> 0 == component) return true;
-		if((swizzle & 0x0C) >> 2 == component) return true;
-		if((swizzle & 0x30) >> 4 == component) return true;
-		if((swizzle & 0xC0) >> 6 == component) return true;
-
-		return false;
-	}
-
-	bool Shader::swizzleContainsComponentMasked(int swizzle, int component, int mask)
-	{
-		if(mask & 0x1) if((swizzle & 0x03) >> 0 == component) return true;
-		if(mask & 0x2) if((swizzle & 0x0C) >> 2 == component) return true;
-		if(mask & 0x4) if((swizzle & 0x30) >> 4 == component) return true;
-		if(mask & 0x8) if((swizzle & 0xC0) >> 6 == component) return true;
-
-		return false;
-	}
-
-	bool Shader::containsDynamicBranching() const
-	{
-		return dynamicBranching;
-	}
-
-	bool Shader::containsBreakInstruction() const
-	{
-		return containsBreak;
-	}
-
-	bool Shader::containsContinueInstruction() const
-	{
-		return containsContinue;
-	}
-
-	bool Shader::containsLeaveInstruction() const
-	{
-		return containsLeave;
-	}
-
-	bool Shader::containsDefineInstruction() const
-	{
-		return containsDefine;
-	}
-
-	bool Shader::usesSampler(int index) const
-	{
-		return (usedSamplers & (1 << index)) != 0;
-	}
-
-	int Shader::getSerialID() const
-	{
-		return serialID;
-	}
-
-	size_t Shader::getLength() const
-	{
-		return instruction.size();
-	}
-
-	Shader::ShaderType Shader::getShaderType() const
-	{
-		return shaderType;
-	}
-
-	unsigned short Shader::getShaderModel() const
-	{
-		return shaderModel;
-	}
-
-	void Shader::print(const char *fileName, ...) const
-	{
-		char fullName[1024 + 1];
-
-		va_list vararg;
-		va_start(vararg, fileName);
-		vsnprintf(fullName, 1024, fileName, vararg);
-		va_end(vararg);
-
-		std::ofstream file(fullName, std::ofstream::out);
-
-		for(const auto &inst : instruction)
-		{
-			file << inst->string(shaderType, shaderModel) << std::endl;
-		}
-	}
-
-	void Shader::printInstruction(int index, const char *fileName) const
-	{
-		std::ofstream file(fileName, std::ofstream::out | std::ofstream::app);
-
-		file << instruction[index]->string(shaderType, shaderModel) << std::endl;
-	}
-
-	void Shader::append(Instruction *instruction)
-	{
-		this->instruction.push_back(instruction);
-	}
-
-	void Shader::declareSampler(int i)
-	{
-		if(i >= 0 && i < 16)
-		{
-			usedSamplers |= 1 << i;
-		}
-	}
-
-	const Shader::Instruction *Shader::getInstruction(size_t i) const
-	{
-		ASSERT(i < instruction.size());
-
-		return instruction[i];
-	}
-
-	void Shader::optimize()
-	{
-		optimizeLeave();
-		optimizeCall();
-		removeNull();
-	}
-
-	void Shader::optimizeLeave()
-	{
-		// A return (leave) right before the end of a function or the shader can be removed
-		for(unsigned int i = 0; i < instruction.size(); i++)
-		{
-			if(instruction[i]->opcode == OPCODE_LEAVE)
-			{
-				if(i == instruction.size() - 1 || instruction[i + 1]->opcode == OPCODE_RET)
-				{
-					instruction[i]->opcode = OPCODE_NULL;
-				}
-			}
-		}
-	}
-
-	void Shader::optimizeCall()
-	{
-		// Eliminate uncalled functions
-		std::set<int> calledFunctions;
-		bool rescan = true;
-
-		while(rescan)
-		{
-			calledFunctions.clear();
-			rescan = false;
-
-			for(const auto &inst : instruction)
-			{
-				if(inst->isCall())
-				{
-					calledFunctions.insert(inst->dst.label);
-				}
-			}
-
-			if(!calledFunctions.empty())
-			{
-				for(unsigned int i = 0; i < instruction.size(); i++)
-				{
-					if(instruction[i]->opcode == OPCODE_LABEL)
-					{
-						if(calledFunctions.find(instruction[i]->dst.label) == calledFunctions.end())
-						{
-							for( ; i < instruction.size(); i++)
-							{
-								Opcode oldOpcode = instruction[i]->opcode;
-								instruction[i]->opcode = OPCODE_NULL;
-
-								if(oldOpcode == OPCODE_RET)
-								{
-									rescan = true;
-									break;
-								}
-							}
-						}
-					}
-				}
-			}
-		}
-
-		// Optimize the entry call
-		if(instruction.size() >= 2 && instruction[0]->opcode == OPCODE_CALL && instruction[1]->opcode == OPCODE_RET)
-		{
-			if(calledFunctions.size() == 1)
-			{
-				instruction[0]->opcode = OPCODE_NULL;
-				instruction[1]->opcode = OPCODE_NULL;
-
-				for(size_t i = 2; i < instruction.size(); i++)
-				{
-					if(instruction[i]->opcode == OPCODE_LABEL || instruction[i]->opcode == OPCODE_RET)
-					{
-						instruction[i]->opcode = OPCODE_NULL;
-					}
-				}
-			}
-		}
-	}
-
-	void Shader::removeNull()
-	{
-		size_t size = 0;
-		for(size_t i = 0; i < instruction.size(); i++)
-		{
-			if(instruction[i]->opcode != OPCODE_NULL)
-			{
-				instruction[size] = instruction[i];
-				size++;
-			}
-			else
-			{
-				delete instruction[i];
-			}
-		}
-
-		instruction.resize(size);
-	}
-
-	void Shader::analyzeDirtyConstants()
-	{
-		dirtyConstantsF = 0;
-		dirtyConstantsI = 0;
-		dirtyConstantsB = 0;
-
-		for(const auto &inst : instruction)
-		{
-			switch(inst->opcode)
-			{
-			case OPCODE_DEF:
-				if(inst->dst.index + 1 > dirtyConstantsF)
-				{
-					dirtyConstantsF = inst->dst.index + 1;
-				}
-				break;
-			case OPCODE_DEFI:
-				if(inst->dst.index + 1 > dirtyConstantsI)
-				{
-					dirtyConstantsI = inst->dst.index + 1;
-				}
-				break;
-			case OPCODE_DEFB:
-				if(inst->dst.index + 1 > dirtyConstantsB)
-				{
-					dirtyConstantsB = inst->dst.index + 1;
-				}
-				break;
-			default:
-				break;
-			}
-		}
-	}
-
-	void Shader::analyzeDynamicBranching()
-	{
-		dynamicBranching = false;
-		containsLeave = false;
-		containsBreak = false;
-		containsContinue = false;
-		containsDefine = false;
-
-		// Determine global presence of branching instructions
-		for(const auto &inst : instruction)
-		{
-			switch(inst->opcode)
-			{
-			case OPCODE_CALLNZ:
-			case OPCODE_IF:
-			case OPCODE_IFC:
-			case OPCODE_BREAK:
-			case OPCODE_BREAKC:
-			case OPCODE_CMP:
-			case OPCODE_BREAKP:
-			case OPCODE_LEAVE:
-			case OPCODE_CONTINUE:
-				if(inst->src[0].type != PARAMETER_CONSTBOOL)
-				{
-					dynamicBranching = true;
-				}
-
-				if(inst->opcode == OPCODE_LEAVE)
-				{
-					containsLeave = true;
-				}
-
-				if(inst->isBreak())
-				{
-					containsBreak = true;
-				}
-
-				if(inst->opcode == OPCODE_CONTINUE)
-				{
-					containsContinue = true;
-				}
-			case OPCODE_DEF:
-			case OPCODE_DEFB:
-			case OPCODE_DEFI:
-				containsDefine = true;
-			default:
-				break;
-			}
-		}
-
-		// Conservatively determine which instructions are affected by dynamic branching
-		int branchDepth = 0;
-		int breakDepth = 0;
-		int continueDepth = 0;
-		bool leaveReturn = false;
-		unsigned int functionBegin = 0;
-
-		for(unsigned int i = 0; i < instruction.size(); i++)
-		{
-			// If statements and loops
-			if(instruction[i]->isBranch() || instruction[i]->isLoop())
-			{
-				branchDepth++;
-			}
-			else if(instruction[i]->opcode == OPCODE_ENDIF || instruction[i]->isEndLoop())
-			{
-				branchDepth--;
-			}
-
-			if(branchDepth > 0)
-			{
-				instruction[i]->analysisBranch = true;
-
-				if(instruction[i]->isCall())
-				{
-					markFunctionAnalysis(instruction[i]->dst.label, ANALYSIS_BRANCH);
-				}
-			}
-
-			// Break statemement
-			if(instruction[i]->isBreak())
-			{
-				breakDepth++;
-			}
-
-			if(breakDepth > 0)
-			{
-				if(instruction[i]->isLoop() || instruction[i]->opcode == OPCODE_SWITCH)   // Nested loop or switch, don't make the end of it disable the break execution mask
-				{
-					breakDepth++;
-				}
-				else if(instruction[i]->isEndLoop() || instruction[i]->opcode == OPCODE_ENDSWITCH)
-				{
-					breakDepth--;
-				}
-
-				instruction[i]->analysisBreak = true;
-
-				if(instruction[i]->isCall())
-				{
-					markFunctionAnalysis(instruction[i]->dst.label, ANALYSIS_BRANCH);
-				}
-			}
-
-			// Continue statement
-			if(instruction[i]->opcode == OPCODE_CONTINUE)
-			{
-				continueDepth++;
-			}
-
-			if(continueDepth > 0)
-			{
-				if(instruction[i]->isLoop() || instruction[i]->opcode == OPCODE_SWITCH)   // Nested loop or switch, don't make the end of it disable the break execution mask
-				{
-					continueDepth++;
-				}
-				else if(instruction[i]->isEndLoop() || instruction[i]->opcode == OPCODE_ENDSWITCH)
-				{
-					continueDepth--;
-				}
-
-				instruction[i]->analysisContinue = true;
-
-				if(instruction[i]->isCall())
-				{
-					markFunctionAnalysis(instruction[i]->dst.label, ANALYSIS_CONTINUE);
-				}
-			}
-
-			// Return (leave) statement
-			if(instruction[i]->opcode == OPCODE_LEAVE)
-			{
-				leaveReturn = true;
-
-				// Mark loop body instructions prior to the return statement
-				for(unsigned int l = functionBegin; l < i; l++)
-				{
-					if(instruction[l]->isLoop())
-					{
-						for(unsigned int r = l + 1; r < i; r++)
-						{
-							instruction[r]->analysisLeave = true;
-						}
-
-						break;
-					}
-				}
-			}
-			else if(instruction[i]->opcode == OPCODE_RET)   // End of the function
-			{
-				leaveReturn = false;
-			}
-			else if(instruction[i]->opcode == OPCODE_LABEL)
-			{
-				functionBegin = i;
-			}
-
-			if(leaveReturn)
-			{
-				instruction[i]->analysisLeave = true;
-
-				if(instruction[i]->isCall())
-				{
-					markFunctionAnalysis(instruction[i]->dst.label, ANALYSIS_LEAVE);
-				}
-			}
-		}
-	}
-
-	void Shader::markFunctionAnalysis(unsigned int functionLabel, Analysis flag)
-	{
-		bool marker = false;
-		for(auto &inst : instruction)
-		{
-			if(!marker)
-			{
-				if(inst->opcode == OPCODE_LABEL && inst->dst.label == functionLabel)
-				{
-					marker = true;
-				}
-			}
-			else
-			{
-				if(inst->opcode == OPCODE_RET)
-				{
-					break;
-				}
-				else if(inst->isCall())
-				{
-					markFunctionAnalysis(inst->dst.label, flag);
-				}
-
-				inst->analysis |= flag;
-			}
-		}
-	}
-
-	void Shader::analyzeSamplers()
-	{
-		for(const auto &inst : instruction)
-		{
-			switch(inst->opcode)
-			{
-			case OPCODE_TEX:
-			case OPCODE_TEXBEM:
-			case OPCODE_TEXBEML:
-			case OPCODE_TEXREG2AR:
-			case OPCODE_TEXREG2GB:
-			case OPCODE_TEXM3X2TEX:
-			case OPCODE_TEXM3X3TEX:
-			case OPCODE_TEXM3X3SPEC:
-			case OPCODE_TEXM3X3VSPEC:
-			case OPCODE_TEXREG2RGB:
-			case OPCODE_TEXDP3TEX:
-			case OPCODE_TEXM3X2DEPTH:
-			case OPCODE_TEXLDD:
-			case OPCODE_TEXLDL:
-			case OPCODE_TEXLOD:
-			case OPCODE_TEXOFFSET:
-			case OPCODE_TEXOFFSETBIAS:
-			case OPCODE_TEXLODOFFSET:
-			case OPCODE_TEXELFETCH:
-			case OPCODE_TEXELFETCHOFFSET:
-			case OPCODE_TEXGRAD:
-			case OPCODE_TEXGRADOFFSET:
-				{
-					Parameter &dst = inst->dst;
-					Parameter &src1 = inst->src[1];
-
-					if(majorVersion >= 2)
-					{
-						if(src1.type == PARAMETER_SAMPLER)
-						{
-							usedSamplers |= 1 << src1.index;
-						}
-					}
-					else
-					{
-						usedSamplers |= 1 << dst.index;
-					}
-				}
-				break;
-			default:
-				break;
-			}
-		}
-	}
-
-	// Assigns a unique index to each call instruction, on a per label basis.
-	// This is used to know what basic block to return to.
-	void Shader::analyzeCallSites()
-	{
-		int callSiteIndex[2048] = {0};
-
-		for(auto &inst : instruction)
-		{
-			if(inst->opcode == OPCODE_CALL || inst->opcode == OPCODE_CALLNZ)
-			{
-				int label = inst->dst.label;
-
-				inst->dst.callSite = callSiteIndex[label]++;
-			}
-		}
-	}
-
-	void Shader::analyzeIndirectAddressing()
-	{
-		indirectAddressableTemporaries = false;
-		indirectAddressableInput = false;
-		indirectAddressableOutput = false;
-
-		for(const auto &inst : instruction)
-		{
-			if(inst->dst.rel.type != PARAMETER_VOID)
-			{
-				switch(inst->dst.type)
-				{
-				case PARAMETER_TEMP:   indirectAddressableTemporaries = true; break;
-				case PARAMETER_INPUT:  indirectAddressableInput = true;       break;
-				case PARAMETER_OUTPUT: indirectAddressableOutput = true;      break;
-				default: break;
-				}
-			}
-
-			for(int j = 0; j < 3; j++)
-			{
-				if(inst->src[j].rel.type != PARAMETER_VOID)
-				{
-					switch(inst->src[j].type)
-					{
-					case PARAMETER_TEMP:   indirectAddressableTemporaries = true; break;
-					case PARAMETER_INPUT:  indirectAddressableInput = true;       break;
-					case PARAMETER_OUTPUT: indirectAddressableOutput = true;      break;
-					default: break;
-					}
-				}
-			}
-		}
-	}
-}
diff --git a/src/Pipeline/Shader.hpp b/src/Pipeline/Shader.hpp
deleted file mode 100644
index dc39494..0000000
--- a/src/Pipeline/Shader.hpp
+++ /dev/null
@@ -1,662 +0,0 @@
-// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//    http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef sw_Shader_hpp
-#define sw_Shader_hpp
-
-#include "System/Types.hpp"
-
-#include <string>
-#include <vector>
-
-namespace sw
-{
-	class Shader
-	{
-	public:
-		enum ShaderType
-		{
-			SHADER_PIXEL = 0xFFFF,
-			SHADER_VERTEX = 0xFFFE,
-			SHADER_GEOMETRY = 0xFFFD
-		};
-
-		enum Opcode
-		{
-			// Matches order in d3d9types.h
-			OPCODE_NOP = 0,
-			OPCODE_MOV,
-			OPCODE_ADD,
-			OPCODE_SUB,
-			OPCODE_MAD,
-			OPCODE_MUL,
-			OPCODE_RCPX,
-			OPCODE_RSQX,
-			OPCODE_DP3,
-			OPCODE_DP4,
-			OPCODE_MIN,
-			OPCODE_MAX,
-			OPCODE_SLT,
-			OPCODE_SGE,
-			OPCODE_EXP2X,   // D3DSIO_EXP
-			OPCODE_LOG2X,   // D3DSIO_LOG
-			OPCODE_LIT,
-			OPCODE_ATT,   // D3DSIO_DST
-			OPCODE_LRP,
-			OPCODE_FRC,
-			OPCODE_M4X4,
-			OPCODE_M4X3,
-			OPCODE_M3X4,
-			OPCODE_M3X3,
-			OPCODE_M3X2,
-			OPCODE_CALL,
-			OPCODE_CALLNZ,
-			OPCODE_LOOP,
-			OPCODE_RET,
-			OPCODE_ENDLOOP,
-			OPCODE_LABEL,
-			OPCODE_DCL,
-			OPCODE_POWX,
-			OPCODE_CRS,
-			OPCODE_SGN,
-			OPCODE_ABS,
-			OPCODE_NRM3,   // D3DSIO_NRM
-			OPCODE_SINCOS,
-			OPCODE_REP,
-			OPCODE_ENDREP,
-			OPCODE_IF,
-			OPCODE_IFC,
-			OPCODE_ELSE,
-			OPCODE_ENDIF,
-			OPCODE_BREAK,
-			OPCODE_BREAKC,
-			OPCODE_MOVA,
-			OPCODE_DEFB,
-			OPCODE_DEFI,
-
-			OPCODE_TEXCOORD = 64,
-			OPCODE_TEXKILL,
-			OPCODE_TEX,
-			OPCODE_TEXBEM,
-			OPCODE_TEXBEML,
-			OPCODE_TEXREG2AR,
-			OPCODE_TEXREG2GB,
-			OPCODE_TEXM3X2PAD,
-			OPCODE_TEXM3X2TEX,
-			OPCODE_TEXM3X3PAD,
-			OPCODE_TEXM3X3TEX,
-			OPCODE_RESERVED0,
-			OPCODE_TEXM3X3SPEC,
-			OPCODE_TEXM3X3VSPEC,
-			OPCODE_EXPP,
-			OPCODE_LOGP,
-			OPCODE_CND,
-			OPCODE_DEF,
-			OPCODE_TEXREG2RGB,
-			OPCODE_TEXDP3TEX,
-			OPCODE_TEXM3X2DEPTH,
-			OPCODE_TEXDP3,
-			OPCODE_TEXM3X3,
-			OPCODE_TEXDEPTH,
-			OPCODE_CMP0,   // D3DSIO_CMP
-			OPCODE_BEM,
-			OPCODE_DP2ADD,
-			OPCODE_DFDX,   // D3DSIO_DSX
-			OPCODE_DFDY,   // D3DSIO_DSY
-			OPCODE_TEXLDD,
-			OPCODE_CMP,   // D3DSIO_SETP
-			OPCODE_TEXLDL,
-			OPCODE_BREAKP,
-
-			OPCODE_PHASE = 0xFFFD,
-			OPCODE_COMMENT = 0xFFFE,
-			OPCODE_END = 0xFFFF,
-
-			OPCODE_PS_1_0 = 0xFFFF0100,
-			OPCODE_PS_1_1 = 0xFFFF0101,
-			OPCODE_PS_1_2 = 0xFFFF0102,
-			OPCODE_PS_1_3 = 0xFFFF0103,
-			OPCODE_PS_1_4 = 0xFFFF0104,
-			OPCODE_PS_2_0 = 0xFFFF0200,
-			OPCODE_PS_2_x = 0xFFFF0201,
-			OPCODE_PS_3_0 = 0xFFFF0300,
-
-			OPCODE_VS_1_0 = 0xFFFE0100,
-			OPCODE_VS_1_1 = 0xFFFE0101,
-			OPCODE_VS_2_0 = 0xFFFE0200,
-			OPCODE_VS_2_x = 0xFFFE0201,
-			OPCODE_VS_2_sw = 0xFFFE02FF,
-			OPCODE_VS_3_0 = 0xFFFE0300,
-			OPCODE_VS_3_sw = 0xFFFE03FF,
-
-			OPCODE_NULL = 0x10000000,   // Dead instruction, to be eliminated
-			OPCODE_WHILE,
-			OPCODE_ENDWHILE,
-			OPCODE_COS,
-			OPCODE_SIN,
-			OPCODE_TAN,
-			OPCODE_ACOS,
-			OPCODE_ASIN,
-			OPCODE_ATAN,
-			OPCODE_ATAN2,
-			OPCODE_COSH,
-			OPCODE_SINH,
-			OPCODE_TANH,
-			OPCODE_ACOSH,
-			OPCODE_ASINH,
-			OPCODE_ATANH,
-			OPCODE_DP1,
-			OPCODE_DP2,
-			OPCODE_TRUNC,
-			OPCODE_FLOOR,
-			OPCODE_ROUND,
-			OPCODE_ROUNDEVEN,
-			OPCODE_CEIL,
-			OPCODE_SQRT,
-			OPCODE_RSQ,
-			OPCODE_LEN2,
-			OPCODE_LEN3,
-			OPCODE_LEN4,
-			OPCODE_DIST1,
-			OPCODE_DIST2,
-			OPCODE_DIST3,
-			OPCODE_DIST4,
-			OPCODE_NRM2,
-			OPCODE_NRM4,
-			OPCODE_DIV,
-			OPCODE_MOD,
-			OPCODE_EXP2,
-			OPCODE_LOG2,
-			OPCODE_EXP,
-			OPCODE_LOG,
-			OPCODE_POW,
-			OPCODE_F2B,   // Float to bool
-			OPCODE_B2F,   // Bool to float
-			OPCODE_F2I,   // Float to int
-			OPCODE_I2F,   // Int to float
-			OPCODE_F2U,   // Float to uint
-			OPCODE_U2F,   // Uint to float
-			OPCODE_I2B,   // Int to bool
-			OPCODE_B2I,   // Bool to int
-			OPCODE_DET2,
-			OPCODE_DET3,
-			OPCODE_DET4,
-			OPCODE_ALL,
-			OPCODE_ANY,
-			OPCODE_NEG,
-			OPCODE_NOT,
-			OPCODE_OR,
-			OPCODE_XOR,
-			OPCODE_AND,
-			OPCODE_EQ,
-			OPCODE_NE,
-			OPCODE_STEP,
-			OPCODE_SMOOTH,
-			OPCODE_ISNAN,
-			OPCODE_ISINF,
-			OPCODE_TEXOFFSET,
-			OPCODE_TEXLODOFFSET,
-			OPCODE_TEXELFETCH,
-			OPCODE_TEXELFETCHOFFSET,
-			OPCODE_TEXGRAD,
-			OPCODE_TEXGRADOFFSET,
-			OPCODE_TEXBIAS,
-			OPCODE_TEXLOD,
-			OPCODE_TEXOFFSETBIAS,
-			OPCODE_TEXSIZE,
-			OPCODE_FLOATBITSTOINT,
-			OPCODE_FLOATBITSTOUINT,
-			OPCODE_INTBITSTOFLOAT,
-			OPCODE_UINTBITSTOFLOAT,
-			OPCODE_PACKSNORM2x16,
-			OPCODE_PACKUNORM2x16,
-			OPCODE_PACKHALF2x16,
-			OPCODE_UNPACKSNORM2x16,
-			OPCODE_UNPACKUNORM2x16,
-			OPCODE_UNPACKHALF2x16,
-			OPCODE_FORWARD1,
-			OPCODE_FORWARD2,
-			OPCODE_FORWARD3,
-			OPCODE_FORWARD4,
-			OPCODE_REFLECT1,
-			OPCODE_REFLECT2,
-			OPCODE_REFLECT3,
-			OPCODE_REFLECT4,
-			OPCODE_REFRACT1,
-			OPCODE_REFRACT2,
-			OPCODE_REFRACT3,
-			OPCODE_REFRACT4,
-			OPCODE_ICMP,
-			OPCODE_UCMP,
-			OPCODE_SELECT,
-			OPCODE_EXTRACT,
-			OPCODE_INSERT,
-			OPCODE_DISCARD,
-			OPCODE_FWIDTH,
-			OPCODE_LEAVE,   // Return before the end of the function
-			OPCODE_CONTINUE,
-			OPCODE_TEST,   // Marks the end of the code that can be skipped by 'continue'
-			OPCODE_SWITCH,
-			OPCODE_ENDSWITCH,
-
-			// Integer opcodes
-			OPCODE_INEG,
-			OPCODE_IABS,
-			OPCODE_ISGN,
-			OPCODE_IADD,
-			OPCODE_ISUB,
-			OPCODE_IMUL,
-			OPCODE_IDIV,
-			OPCODE_IMAD,
-			OPCODE_IMOD,
-			OPCODE_SHL,
-			OPCODE_ISHR,
-			OPCODE_IMIN,
-			OPCODE_IMAX,
-
-			// Unsigned integer opcodes
-			OPCODE_UDIV,
-			OPCODE_UMOD,
-			OPCODE_USHR,
-			OPCODE_UMIN,
-			OPCODE_UMAX,
-		};
-
-		static Opcode OPCODE_DP(int);
-		static Opcode OPCODE_LEN(int);
-		static Opcode OPCODE_DIST(int);
-		static Opcode OPCODE_NRM(int);
-		static Opcode OPCODE_FORWARD(int);
-		static Opcode OPCODE_REFLECT(int);
-		static Opcode OPCODE_REFRACT(int);
-
-		enum Control
-		{
-			CONTROL_RESERVED0,
-			CONTROL_GT,
-			CONTROL_EQ,
-			CONTROL_GE,
-			CONTROL_LT,
-			CONTROL_NE,
-			CONTROL_LE,
-			CONTROL_RESERVED1
-		};
-
-		enum SamplerType
-		{
-			SAMPLER_UNKNOWN,
-			SAMPLER_1D,
-			SAMPLER_2D,
-			SAMPLER_CUBE,
-			SAMPLER_VOLUME
-		};
-
-		enum Usage   // For vertex input/output declarations
-		{
-			USAGE_POSITION = 0,
-			USAGE_BLENDWEIGHT = 1,
-			USAGE_BLENDINDICES = 2,
-			USAGE_NORMAL = 3,
-			USAGE_PSIZE = 4,
-			USAGE_TEXCOORD = 5,
-			USAGE_TANGENT = 6,
-			USAGE_BINORMAL = 7,
-			USAGE_TESSFACTOR = 8,
-			USAGE_POSITIONT = 9,
-			USAGE_COLOR = 10,
-			USAGE_FOG = 11,
-			USAGE_DEPTH = 12,
-			USAGE_SAMPLE = 13
-		};
-
-		enum ParameterType
-		{
-			PARAMETER_TEMP = 0,
-			PARAMETER_INPUT = 1,
-			PARAMETER_CONST = 2,
-			PARAMETER_TEXTURE = 3,
-			PARAMETER_ADDR = 3,
-			PARAMETER_RASTOUT = 4,
-			PARAMETER_ATTROUT = 5,
-			PARAMETER_TEXCRDOUT = 6,
-			PARAMETER_OUTPUT = 6,
-			PARAMETER_CONSTINT = 7,
-			PARAMETER_COLOROUT = 8,
-			PARAMETER_DEPTHOUT = 9,
-			PARAMETER_SAMPLER = 10,
-			PARAMETER_CONST2 = 11,
-			PARAMETER_CONST3 = 12,
-			PARAMETER_CONST4 = 13,
-			PARAMETER_CONSTBOOL = 14,
-			PARAMETER_LOOP = 15,
-			PARAMETER_TEMPFLOAT16 = 16,
-			PARAMETER_MISCTYPE = 17,
-			PARAMETER_LABEL = 18,
-			PARAMETER_PREDICATE = 19,
-
-		//	PARAMETER_FLOAT1LITERAL,
-		//	PARAMETER_FLOAT2LITERAL,
-		//	PARAMETER_FLOAT3LITERAL,
-			PARAMETER_FLOAT4LITERAL,
-			PARAMETER_BOOL1LITERAL,
-		//	PARAMETER_BOOL2LITERAL,
-		//	PARAMETER_BOOL3LITERAL,
-		//	PARAMETER_BOOL4LITERAL,
-		//	PARAMETER_INT1LITERAL,
-		//	PARAMETER_INT2LITERAL,
-		//	PARAMETER_INT3LITERAL,
-			PARAMETER_INT4LITERAL,
-
-			PARAMETER_VOID
-		};
-
-		enum MiscParameterIndex
-		{
-			VPosIndex = 0,
-			VFaceIndex = 1,
-			InstanceIDIndex = 2,
-			VertexIDIndex = 3,
-		};
-
-		enum Modifier
-		{
-			MODIFIER_NONE,
-			MODIFIER_NEGATE,
-			MODIFIER_BIAS,
-			MODIFIER_BIAS_NEGATE,
-			MODIFIER_SIGN,
-			MODIFIER_SIGN_NEGATE,
-			MODIFIER_COMPLEMENT,
-			MODIFIER_X2,
-			MODIFIER_X2_NEGATE,
-			MODIFIER_DZ,
-			MODIFIER_DW,
-			MODIFIER_ABS,
-			MODIFIER_ABS_NEGATE,
-			MODIFIER_NOT
-		};
-
-		enum Analysis
-		{
-			// Flags indicating whether an instruction is affected by an execution enable mask
-			ANALYSIS_BRANCH   = 0x00000001,
-			ANALYSIS_BREAK    = 0x00000002,
-			ANALYSIS_CONTINUE = 0x00000004,
-			ANALYSIS_LEAVE    = 0x00000008,
-		};
-
-		struct Relative
-		{
-			ParameterType type : 8;
-			unsigned int index;
-			unsigned int swizzle : 8;
-			unsigned int scale;
-			bool dynamic;   // Varies between concurrent shader instances
-		};
-
-		struct Parameter
-		{
-			union
-			{
-				struct
-				{
-					unsigned int index;   // For registers types
-
-					Relative rel;
-				};
-
-				float value[4];       // For float constants
-				int integer[4];       // For integer constants
-				int boolean[4];       // For boolean constants
-
-				struct
-				{
-					unsigned int label;      // Label index
-					unsigned int callSite;   // Call index (per label)
-				};
-			};
-
-			Parameter() : index(0), type(PARAMETER_VOID)
-			{
-				rel.type = PARAMETER_VOID;
-				rel.index = 0;
-				rel.swizzle = 0;
-				rel.scale = 1;
-				rel.dynamic = true;
-			}
-
-			std::string string(ShaderType shaderType, unsigned short version) const;
-			std::string typeString(ShaderType shaderType, unsigned short version) const;
-			std::string relativeString() const;
-
-			ParameterType type : 8;
-		};
-
-		struct DestinationParameter : Parameter
-		{
-			union
-			{
-				unsigned char mask;
-
-				struct
-				{
-					bool x : 1;
-					bool y : 1;
-					bool z : 1;
-					bool w : 1;
-				};
-			};
-
-			DestinationParameter() : mask(0xF), saturate(false), partialPrecision(false), centroid(false), shift(0)
-			{
-			}
-
-			std::string modifierString() const;
-			std::string shiftString() const;
-			std::string maskString() const;
-
-			bool saturate         : 1;
-			bool partialPrecision : 1;
-			bool centroid         : 1;
-			signed char shift     : 4;
-		};
-
-		struct SourceParameter : Parameter
-		{
-			SourceParameter() : swizzle(0xE4), modifier(MODIFIER_NONE), bufferIndex(-1)
-			{
-			}
-
-			std::string string(ShaderType shaderType, unsigned short version) const;
-			std::string swizzleString() const;
-			std::string preModifierString() const;
-			std::string postModifierString() const;
-
-			unsigned int swizzle : 8;
-			Modifier modifier : 8;
-			int bufferIndex : 8;
-		};
-
-		struct Instruction
-		{
-			explicit Instruction(Opcode opcode);
-			Instruction(const unsigned long *token, int size, unsigned char majorVersion);
-
-			virtual ~Instruction();
-
-			void parseOperationToken(unsigned long token, unsigned char majorVersion);
-			void parseDeclarationToken(unsigned long token);
-			void parseDestinationToken(const unsigned long *token, unsigned char majorVersion);
-			void parseSourceToken(int i, const unsigned long *token, unsigned char majorVersion);
-
-			std::string string(ShaderType shaderType, unsigned short version) const;
-			static std::string swizzleString(ParameterType type, unsigned char swizzle);
-			std::string operationString(unsigned short version) const;
-			std::string controlString() const;
-
-			bool isBranch() const;
-			bool isCall() const;
-			bool isBreak() const;
-			bool isLoop() const;
-			bool isEndLoop() const;
-
-			bool isPredicated() const;
-
-			Opcode opcode;
-
-			union
-			{
-				Control control;
-
-				struct
-				{
-					unsigned char project : 1;   // D3DSI_TEXLD_PROJECT
-					unsigned char bias : 1;      // D3DSI_TEXLD_BIAS
-				};
-			};
-
-			bool predicate;
-			bool predicateNot;   // Negative predicate
-			unsigned char predicateSwizzle;
-
-			bool coissue;
-			SamplerType samplerType;
-			Usage usage;
-			unsigned char usageIndex;
-
-			DestinationParameter dst;
-			SourceParameter src[5];
-
-			union
-			{
-				unsigned int analysis;
-
-				struct
-				{
-					// Keep in sync with Shader::Analysis flags
-					unsigned int analysisBranch : 1;
-					unsigned int analysisBreak : 1;
-					unsigned int analysisContinue : 1;
-					unsigned int analysisLeave : 1;
-				};
-			};
-		};
-
-		Shader();
-
-		virtual ~Shader();
-
-		int getSerialID() const;
-		size_t getLength() const;
-		ShaderType getShaderType() const;
-		unsigned short getShaderModel() const;
-
-		void append(Instruction *instruction);
-		void declareSampler(int i);
-
-		const Instruction *getInstruction(size_t i) const;
-		int size(unsigned long opcode) const;
-		static int size(unsigned long opcode, unsigned short shaderModel);
-
-		void print(const char *fileName, ...) const;
-		void printInstruction(int index, const char *fileName) const;
-
-		static bool maskContainsComponent(int mask, int component);
-		static bool swizzleContainsComponent(int swizzle, int component);
-		static bool swizzleContainsComponentMasked(int swizzle, int component, int mask);
-
-		bool containsDynamicBranching() const;
-		bool containsBreakInstruction() const;
-		bool containsContinueInstruction() const;
-		bool containsLeaveInstruction() const;
-		bool containsDefineInstruction() const;
-		bool usesSampler(int i) const;
-
-		struct Semantic
-		{
-			Semantic(unsigned char usage = 0xFF, unsigned char index = 0xFF, bool flat = false) : usage(usage), index(index), centroid(false), flat(flat)
-			{
-			}
-
-			bool operator==(const Semantic &semantic) const
-			{
-				return usage == semantic.usage && index == semantic.index;
-			}
-
-			bool active() const
-			{
-				return usage != 0xFF;
-			}
-
-			unsigned char usage;
-			unsigned char index;
-			bool centroid;
-			bool flat;
-		};
-
-		void optimize();
-
-		// FIXME: Private
-		unsigned int dirtyConstantsF;
-		unsigned int dirtyConstantsI;
-		unsigned int dirtyConstantsB;
-
-		bool indirectAddressableTemporaries;
-		bool indirectAddressableInput;
-		bool indirectAddressableOutput;
-
-	protected:
-		void parse(const unsigned long *token);
-
-		void optimizeLeave();
-		void optimizeCall();
-		void removeNull();
-
-		void analyzeDirtyConstants();
-		void analyzeDynamicBranching();
-		void analyzeSamplers();
-		void analyzeCallSites();
-		void analyzeIndirectAddressing();
-		void markFunctionAnalysis(unsigned int functionLabel, Analysis flag);
-
-		ShaderType shaderType;
-
-		union
-		{
-			unsigned short shaderModel;
-
-			struct
-			{
-				unsigned char minorVersion;
-				unsigned char majorVersion;
-			};
-		};
-
-		std::vector<Instruction*> instruction;
-
-		unsigned short usedSamplers;   // Bit flags
-
-	private:
-		const int serialID;
-		static volatile int serialCounter;
-
-		bool dynamicBranching;
-		bool containsBreak;
-		bool containsContinue;
-		bool containsLeave;
-		bool containsDefine;
-	};
-}
-
-#endif   // sw_Shader_hpp
diff --git a/src/Pipeline/ShaderCore.cpp b/src/Pipeline/ShaderCore.cpp
index fe002b2..1b28013 100644
--- a/src/Pipeline/ShaderCore.cpp
+++ b/src/Pipeline/ShaderCore.cpp
@@ -1809,37 +1809,37 @@
 	{
 		switch(control)
 		{
-		case Shader::CONTROL_GT:
+		case CONTROL_GT:
 			dst.x = As<Float4>(CmpNLE(src0.x, src1.x));
 			dst.y = As<Float4>(CmpNLE(src0.y, src1.y));
 			dst.z = As<Float4>(CmpNLE(src0.z, src1.z));
 			dst.w = As<Float4>(CmpNLE(src0.w, src1.w));
 			break;
-		case Shader::CONTROL_EQ:
+		case CONTROL_EQ:
 			dst.x = As<Float4>(CmpEQ(src0.x, src1.x));
 			dst.y = As<Float4>(CmpEQ(src0.y, src1.y));
 			dst.z = As<Float4>(CmpEQ(src0.z, src1.z));
 			dst.w = As<Float4>(CmpEQ(src0.w, src1.w));
 			break;
-		case Shader::CONTROL_GE:
+		case CONTROL_GE:
 			dst.x = As<Float4>(CmpNLT(src0.x, src1.x));
 			dst.y = As<Float4>(CmpNLT(src0.y, src1.y));
 			dst.z = As<Float4>(CmpNLT(src0.z, src1.z));
 			dst.w = As<Float4>(CmpNLT(src0.w, src1.w));
 			break;
-		case Shader::CONTROL_LT:
+		case CONTROL_LT:
 			dst.x = As<Float4>(CmpLT(src0.x, src1.x));
 			dst.y = As<Float4>(CmpLT(src0.y, src1.y));
 			dst.z = As<Float4>(CmpLT(src0.z, src1.z));
 			dst.w = As<Float4>(CmpLT(src0.w, src1.w));
 			break;
-		case Shader::CONTROL_NE:
+		case CONTROL_NE:
 			dst.x = As<Float4>(CmpNEQ(src0.x, src1.x));
 			dst.y = As<Float4>(CmpNEQ(src0.y, src1.y));
 			dst.z = As<Float4>(CmpNEQ(src0.z, src1.z));
 			dst.w = As<Float4>(CmpNEQ(src0.w, src1.w));
 			break;
-		case Shader::CONTROL_LE:
+		case CONTROL_LE:
 			dst.x = As<Float4>(CmpLE(src0.x, src1.x));
 			dst.y = As<Float4>(CmpLE(src0.y, src1.y));
 			dst.z = As<Float4>(CmpLE(src0.z, src1.z));
@@ -1854,37 +1854,37 @@
 	{
 		switch(control)
 		{
-		case Shader::CONTROL_GT:
+		case CONTROL_GT:
 			dst.x = As<Float4>(CmpNLE(As<Int4>(src0.x), As<Int4>(src1.x)));
 			dst.y = As<Float4>(CmpNLE(As<Int4>(src0.y), As<Int4>(src1.y)));
 			dst.z = As<Float4>(CmpNLE(As<Int4>(src0.z), As<Int4>(src1.z)));
 			dst.w = As<Float4>(CmpNLE(As<Int4>(src0.w), As<Int4>(src1.w)));
 			break;
-		case Shader::CONTROL_EQ:
+		case CONTROL_EQ:
 			dst.x = As<Float4>(CmpEQ(As<Int4>(src0.x), As<Int4>(src1.x)));
 			dst.y = As<Float4>(CmpEQ(As<Int4>(src0.y), As<Int4>(src1.y)));
 			dst.z = As<Float4>(CmpEQ(As<Int4>(src0.z), As<Int4>(src1.z)));
 			dst.w = As<Float4>(CmpEQ(As<Int4>(src0.w), As<Int4>(src1.w)));
 			break;
-		case Shader::CONTROL_GE:
+		case CONTROL_GE:
 			dst.x = As<Float4>(CmpNLT(As<Int4>(src0.x), As<Int4>(src1.x)));
 			dst.y = As<Float4>(CmpNLT(As<Int4>(src0.y), As<Int4>(src1.y)));
 			dst.z = As<Float4>(CmpNLT(As<Int4>(src0.z), As<Int4>(src1.z)));
 			dst.w = As<Float4>(CmpNLT(As<Int4>(src0.w), As<Int4>(src1.w)));
 			break;
-		case Shader::CONTROL_LT:
+		case CONTROL_LT:
 			dst.x = As<Float4>(CmpLT(As<Int4>(src0.x), As<Int4>(src1.x)));
 			dst.y = As<Float4>(CmpLT(As<Int4>(src0.y), As<Int4>(src1.y)));
 			dst.z = As<Float4>(CmpLT(As<Int4>(src0.z), As<Int4>(src1.z)));
 			dst.w = As<Float4>(CmpLT(As<Int4>(src0.w), As<Int4>(src1.w)));
 			break;
-		case Shader::CONTROL_NE:
+		case CONTROL_NE:
 			dst.x = As<Float4>(CmpNEQ(As<Int4>(src0.x), As<Int4>(src1.x)));
 			dst.y = As<Float4>(CmpNEQ(As<Int4>(src0.y), As<Int4>(src1.y)));
 			dst.z = As<Float4>(CmpNEQ(As<Int4>(src0.z), As<Int4>(src1.z)));
 			dst.w = As<Float4>(CmpNEQ(As<Int4>(src0.w), As<Int4>(src1.w)));
 			break;
-		case Shader::CONTROL_LE:
+		case CONTROL_LE:
 			dst.x = As<Float4>(CmpLE(As<Int4>(src0.x), As<Int4>(src1.x)));
 			dst.y = As<Float4>(CmpLE(As<Int4>(src0.y), As<Int4>(src1.y)));
 			dst.z = As<Float4>(CmpLE(As<Int4>(src0.z), As<Int4>(src1.z)));
@@ -1899,37 +1899,37 @@
 	{
 		switch(control)
 		{
-		case Shader::CONTROL_GT:
+		case CONTROL_GT:
 			dst.x = As<Float4>(CmpNLE(As<UInt4>(src0.x), As<UInt4>(src1.x)));
 			dst.y = As<Float4>(CmpNLE(As<UInt4>(src0.y), As<UInt4>(src1.y)));
 			dst.z = As<Float4>(CmpNLE(As<UInt4>(src0.z), As<UInt4>(src1.z)));
 			dst.w = As<Float4>(CmpNLE(As<UInt4>(src0.w), As<UInt4>(src1.w)));
 			break;
-		case Shader::CONTROL_EQ:
+		case CONTROL_EQ:
 			dst.x = As<Float4>(CmpEQ(As<UInt4>(src0.x), As<UInt4>(src1.x)));
 			dst.y = As<Float4>(CmpEQ(As<UInt4>(src0.y), As<UInt4>(src1.y)));
 			dst.z = As<Float4>(CmpEQ(As<UInt4>(src0.z), As<UInt4>(src1.z)));
 			dst.w = As<Float4>(CmpEQ(As<UInt4>(src0.w), As<UInt4>(src1.w)));
 			break;
-		case Shader::CONTROL_GE:
+		case CONTROL_GE:
 			dst.x = As<Float4>(CmpNLT(As<UInt4>(src0.x), As<UInt4>(src1.x)));
 			dst.y = As<Float4>(CmpNLT(As<UInt4>(src0.y), As<UInt4>(src1.y)));
 			dst.z = As<Float4>(CmpNLT(As<UInt4>(src0.z), As<UInt4>(src1.z)));
 			dst.w = As<Float4>(CmpNLT(As<UInt4>(src0.w), As<UInt4>(src1.w)));
 			break;
-		case Shader::CONTROL_LT:
+		case CONTROL_LT:
 			dst.x = As<Float4>(CmpLT(As<UInt4>(src0.x), As<UInt4>(src1.x)));
 			dst.y = As<Float4>(CmpLT(As<UInt4>(src0.y), As<UInt4>(src1.y)));
 			dst.z = As<Float4>(CmpLT(As<UInt4>(src0.z), As<UInt4>(src1.z)));
 			dst.w = As<Float4>(CmpLT(As<UInt4>(src0.w), As<UInt4>(src1.w)));
 			break;
-		case Shader::CONTROL_NE:
+		case CONTROL_NE:
 			dst.x = As<Float4>(CmpNEQ(As<UInt4>(src0.x), As<UInt4>(src1.x)));
 			dst.y = As<Float4>(CmpNEQ(As<UInt4>(src0.y), As<UInt4>(src1.y)));
 			dst.z = As<Float4>(CmpNEQ(As<UInt4>(src0.z), As<UInt4>(src1.z)));
 			dst.w = As<Float4>(CmpNEQ(As<UInt4>(src0.w), As<UInt4>(src1.w)));
 			break;
-		case Shader::CONTROL_LE:
+		case CONTROL_LE:
 			dst.x = As<Float4>(CmpLE(As<UInt4>(src0.x), As<UInt4>(src1.x)));
 			dst.y = As<Float4>(CmpLE(As<UInt4>(src0.y), As<UInt4>(src1.y)));
 			dst.z = As<Float4>(CmpLE(As<UInt4>(src0.z), As<UInt4>(src1.z)));
diff --git a/src/Pipeline/ShaderCore.hpp b/src/Pipeline/ShaderCore.hpp
index 018b856..d0558b2 100644
--- a/src/Pipeline/ShaderCore.hpp
+++ b/src/Pipeline/ShaderCore.hpp
@@ -15,7 +15,6 @@
 #ifndef sw_ShaderCore_hpp
 #define sw_ShaderCore_hpp
 
-#include "Shader.hpp"
 #include "Reactor/Reactor.hpp"
 #include "Vulkan/VkDebug.hpp"
 
@@ -234,7 +233,18 @@
 
 	class ShaderCore
 	{
-		typedef Shader::Control Control;
+		enum Control
+		{
+			CONTROL_RESERVED0,
+			CONTROL_GT,
+			CONTROL_EQ,
+			CONTROL_GE,
+			CONTROL_LT,
+			CONTROL_NE,
+			CONTROL_LE,
+			CONTROL_RESERVED1
+		};
+
 
 	public:
 		void mov(Vector4f &dst, const Vector4f &src, bool integerDestination = false);
diff --git a/src/Pipeline/VertexProgram.cpp b/src/Pipeline/VertexProgram.cpp
index 171dca5..fc75f13 100644
--- a/src/Pipeline/VertexProgram.cpp
+++ b/src/Pipeline/VertexProgram.cpp
@@ -14,7 +14,6 @@
 
 #include "VertexProgram.hpp"
 
-#include "VertexShader.hpp"
 #include "SamplerCore.hpp"
 #include "Device/Renderer.hpp"
 #include "Device/Vertex.hpp"
@@ -23,36 +22,21 @@
 
 namespace sw
 {
-	VertexProgram::VertexProgram(const VertexProcessor::State &state, const VertexShader *shader)
-		: VertexRoutine(state, shader), shader(shader), r(shader->indirectAddressableTemporaries)
+	VertexProgram::VertexProgram(const VertexProcessor::State &state, SpirvShader const *spirvShader)
+		: VertexRoutine(state, spirvShader)
 	{
 		ifDepth = 0;
 		loopRepDepth = 0;
 		currentLabel = -1;
 		whileTest = false;
 
-		for(int i = 0; i < 2048; i++)
-		{
-			labelBlock[i] = 0;
-		}
-
-		loopDepth = -1;
 		enableStack[0] = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
 
-		if(shader->containsBreakInstruction())
-		{
-			enableBreak = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
-		}
-
-		if(shader->containsContinueInstruction())
-		{
-			enableContinue = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
-		}
-
-		if(shader->isInstanceIdDeclared())
-		{
-			instanceID = *Pointer<Int>(data + OFFSET(DrawData,instanceID));
-		}
+		// TODO: wire up builtins
+		//if(shader->isInstanceIdDeclared())
+		//{
+		//	instanceID = *Pointer<Int>(data + OFFSET(DrawData,instanceID));
+		//}
 	}
 
 	VertexProgram::~VertexProgram()
@@ -63,537 +47,24 @@
 	{
 		//	shader->print("VertexShader-%0.8X.txt", state.shaderID);
 
-		unsigned short shaderModel = shader->getShaderModel();
-
 		enableIndex = 0;
-		stackIndex = 0;
 
-		if(shader->containsLeaveInstruction())
-		{
-			enableLeave = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
-		}
+		//if(shader->isVertexIdDeclared())
+		//{
+		//	if(state.textureSampling)
+		//	{
+		//		vertexID = Int4(index);
+		//	}
+		//	else
+		//	{
+		//		vertexID = Insert(vertexID, As<Int>(index), 0);
+		//		vertexID = Insert(vertexID, As<Int>(index + 1), 1);
+		//		vertexID = Insert(vertexID, As<Int>(index + 2), 2);
+		//		vertexID = Insert(vertexID, As<Int>(index + 3), 3);
+		//	}
+		//}
 
-		if(shader->isVertexIdDeclared())
-		{
-			if(state.textureSampling)
-			{
-				vertexID = Int4(index);
-			}
-			else
-			{
-				vertexID = Insert(vertexID, As<Int>(index), 0);
-				vertexID = Insert(vertexID, As<Int>(index + 1), 1);
-				vertexID = Insert(vertexID, As<Int>(index + 2), 2);
-				vertexID = Insert(vertexID, As<Int>(index + 3), 3);
-			}
-		}
-
-		// Create all call site return blocks up front
-		for(size_t i = 0; i < shader->getLength(); i++)
-		{
-			const Shader::Instruction *instruction = shader->getInstruction(i);
-			Shader::Opcode opcode = instruction->opcode;
-
-			if(opcode == Shader::OPCODE_CALL || opcode == Shader::OPCODE_CALLNZ)
-			{
-				const Dst &dst = instruction->dst;
-
-				ASSERT(callRetBlock[dst.label].size() == dst.callSite);
-				callRetBlock[dst.label].push_back(Nucleus::createBasicBlock());
-			}
-		}
-
-		for(size_t i = 0; i < shader->getLength(); i++)
-		{
-			const Shader::Instruction *instruction = shader->getInstruction(i);
-			Shader::Opcode opcode = instruction->opcode;
-
-			if(opcode == Shader::OPCODE_DCL || opcode == Shader::OPCODE_DEF || opcode == Shader::OPCODE_DEFI || opcode == Shader::OPCODE_DEFB)
-			{
-				continue;
-			}
-
-			Dst dst = instruction->dst;
-			Src src0 = instruction->src[0];
-			Src src1 = instruction->src[1];
-			Src src2 = instruction->src[2];
-			Src src3 = instruction->src[3];
-			Src src4 = instruction->src[4];
-
-			bool predicate = instruction->predicate;
-			Control control = instruction->control;
-			bool integer = dst.type == Shader::PARAMETER_ADDR;
-			bool pp = dst.partialPrecision;
-
-			Vector4f d;
-			Vector4f s0;
-			Vector4f s1;
-			Vector4f s2;
-			Vector4f s3;
-			Vector4f s4;
-
-			if(src0.type != Shader::PARAMETER_VOID) s0 = fetchRegister(src0);
-			if(src1.type != Shader::PARAMETER_VOID) s1 = fetchRegister(src1);
-			if(src2.type != Shader::PARAMETER_VOID) s2 = fetchRegister(src2);
-			if(src3.type != Shader::PARAMETER_VOID) s3 = fetchRegister(src3);
-			if(src4.type != Shader::PARAMETER_VOID) s4 = fetchRegister(src4);
-
-			switch(opcode)
-			{
-			case Shader::OPCODE_VS_1_0:                                     break;
-			case Shader::OPCODE_VS_1_1:                                     break;
-			case Shader::OPCODE_VS_2_0:                                     break;
-			case Shader::OPCODE_VS_2_x:                                     break;
-			case Shader::OPCODE_VS_2_sw:                                    break;
-			case Shader::OPCODE_VS_3_0:                                     break;
-			case Shader::OPCODE_VS_3_sw:                                    break;
-			case Shader::OPCODE_DCL:                                        break;
-			case Shader::OPCODE_DEF:                                        break;
-			case Shader::OPCODE_DEFI:                                       break;
-			case Shader::OPCODE_DEFB:                                       break;
-			case Shader::OPCODE_NOP:                                        break;
-			case Shader::OPCODE_ABS:        abs(d, s0);                     break;
-			case Shader::OPCODE_IABS:       iabs(d, s0);                    break;
-			case Shader::OPCODE_ADD:        add(d, s0, s1);                 break;
-			case Shader::OPCODE_IADD:       iadd(d, s0, s1);                break;
-			case Shader::OPCODE_CRS:        crs(d, s0, s1);                 break;
-			case Shader::OPCODE_FORWARD1:   forward1(d, s0, s1, s2);        break;
-			case Shader::OPCODE_FORWARD2:   forward2(d, s0, s1, s2);        break;
-			case Shader::OPCODE_FORWARD3:   forward3(d, s0, s1, s2);        break;
-			case Shader::OPCODE_FORWARD4:   forward4(d, s0, s1, s2);        break;
-			case Shader::OPCODE_REFLECT1:   reflect1(d, s0, s1);            break;
-			case Shader::OPCODE_REFLECT2:   reflect2(d, s0, s1);            break;
-			case Shader::OPCODE_REFLECT3:   reflect3(d, s0, s1);            break;
-			case Shader::OPCODE_REFLECT4:   reflect4(d, s0, s1);            break;
-			case Shader::OPCODE_REFRACT1:   refract1(d, s0, s1, s2.x);      break;
-			case Shader::OPCODE_REFRACT2:   refract2(d, s0, s1, s2.x);      break;
-			case Shader::OPCODE_REFRACT3:   refract3(d, s0, s1, s2.x);      break;
-			case Shader::OPCODE_REFRACT4:   refract4(d, s0, s1, s2.x);      break;
-			case Shader::OPCODE_DP1:        dp1(d, s0, s1);                 break;
-			case Shader::OPCODE_DP2:        dp2(d, s0, s1);                 break;
-			case Shader::OPCODE_DP3:        dp3(d, s0, s1);                 break;
-			case Shader::OPCODE_DP4:        dp4(d, s0, s1);                 break;
-			case Shader::OPCODE_DET2:       det2(d, s0, s1);                break;
-			case Shader::OPCODE_DET3:       det3(d, s0, s1, s2);            break;
-			case Shader::OPCODE_DET4:       det4(d, s0, s1, s2, s3);        break;
-			case Shader::OPCODE_ATT:        att(d, s0, s1);                 break;
-			case Shader::OPCODE_EXP2X:      exp2x(d, s0, pp);               break;
-			case Shader::OPCODE_EXP2:       exp2(d, s0, pp);                break;
-			case Shader::OPCODE_EXPP:       expp(d, s0, shaderModel);       break;
-			case Shader::OPCODE_EXP:        exp(d, s0, pp);                 break;
-			case Shader::OPCODE_FRC:        frc(d, s0);                     break;
-			case Shader::OPCODE_TRUNC:      trunc(d, s0);                   break;
-			case Shader::OPCODE_FLOOR:      floor(d, s0);                   break;
-			case Shader::OPCODE_ROUND:      round(d, s0);                   break;
-			case Shader::OPCODE_ROUNDEVEN:  roundEven(d, s0);               break;
-			case Shader::OPCODE_CEIL:       ceil(d, s0);                    break;
-			case Shader::OPCODE_LIT:        lit(d, s0);                     break;
-			case Shader::OPCODE_LOG2X:      log2x(d, s0, pp);               break;
-			case Shader::OPCODE_LOG2:       log2(d, s0, pp);                break;
-			case Shader::OPCODE_LOGP:       logp(d, s0, shaderModel);       break;
-			case Shader::OPCODE_LOG:        log(d, s0, pp);                 break;
-			case Shader::OPCODE_LRP:        lrp(d, s0, s1, s2);             break;
-			case Shader::OPCODE_STEP:       step(d, s0, s1);                break;
-			case Shader::OPCODE_SMOOTH:     smooth(d, s0, s1, s2);          break;
-			case Shader::OPCODE_ISINF:      isinf(d, s0);                   break;
-			case Shader::OPCODE_ISNAN:      isnan(d, s0);                   break;
-			case Shader::OPCODE_FLOATBITSTOINT:
-			case Shader::OPCODE_FLOATBITSTOUINT:
-			case Shader::OPCODE_INTBITSTOFLOAT:
-			case Shader::OPCODE_UINTBITSTOFLOAT: d = s0;                    break;
-			case Shader::OPCODE_PACKSNORM2x16:   packSnorm2x16(d, s0);      break;
-			case Shader::OPCODE_PACKUNORM2x16:   packUnorm2x16(d, s0);      break;
-			case Shader::OPCODE_PACKHALF2x16:    packHalf2x16(d, s0);       break;
-			case Shader::OPCODE_UNPACKSNORM2x16: unpackSnorm2x16(d, s0);    break;
-			case Shader::OPCODE_UNPACKUNORM2x16: unpackUnorm2x16(d, s0);    break;
-			case Shader::OPCODE_UNPACKHALF2x16:  unpackHalf2x16(d, s0);     break;
-			case Shader::OPCODE_M3X2:       M3X2(d, s0, src1);              break;
-			case Shader::OPCODE_M3X3:       M3X3(d, s0, src1);              break;
-			case Shader::OPCODE_M3X4:       M3X4(d, s0, src1);              break;
-			case Shader::OPCODE_M4X3:       M4X3(d, s0, src1);              break;
-			case Shader::OPCODE_M4X4:       M4X4(d, s0, src1);              break;
-			case Shader::OPCODE_MAD:        mad(d, s0, s1, s2);             break;
-			case Shader::OPCODE_IMAD:       imad(d, s0, s1, s2);            break;
-			case Shader::OPCODE_MAX:        max(d, s0, s1);                 break;
-			case Shader::OPCODE_IMAX:       imax(d, s0, s1);                break;
-			case Shader::OPCODE_UMAX:       umax(d, s0, s1);                break;
-			case Shader::OPCODE_MIN:        min(d, s0, s1);                 break;
-			case Shader::OPCODE_IMIN:       imin(d, s0, s1);                break;
-			case Shader::OPCODE_UMIN:       umin(d, s0, s1);                break;
-			case Shader::OPCODE_MOV:        mov(d, s0, integer);            break;
-			case Shader::OPCODE_MOVA:       mov(d, s0, true);               break;
-			case Shader::OPCODE_NEG:        neg(d, s0);                     break;
-			case Shader::OPCODE_INEG:       ineg(d, s0);                    break;
-			case Shader::OPCODE_F2B:        f2b(d, s0);                     break;
-			case Shader::OPCODE_B2F:        b2f(d, s0);                     break;
-			case Shader::OPCODE_F2I:        f2i(d, s0);                     break;
-			case Shader::OPCODE_I2F:        i2f(d, s0);                     break;
-			case Shader::OPCODE_F2U:        f2u(d, s0);                     break;
-			case Shader::OPCODE_U2F:        u2f(d, s0);                     break;
-			case Shader::OPCODE_I2B:        i2b(d, s0);                     break;
-			case Shader::OPCODE_B2I:        b2i(d, s0);                     break;
-			case Shader::OPCODE_MUL:        mul(d, s0, s1);                 break;
-			case Shader::OPCODE_IMUL:       imul(d, s0, s1);                break;
-			case Shader::OPCODE_NRM2:       nrm2(d, s0, pp);                break;
-			case Shader::OPCODE_NRM3:       nrm3(d, s0, pp);                break;
-			case Shader::OPCODE_NRM4:       nrm4(d, s0, pp);                break;
-			case Shader::OPCODE_POWX:       powx(d, s0, s1, pp);            break;
-			case Shader::OPCODE_POW:        pow(d, s0, s1, pp);             break;
-			case Shader::OPCODE_RCPX:       rcpx(d, s0, pp);                break;
-			case Shader::OPCODE_DIV:        div(d, s0, s1);                 break;
-			case Shader::OPCODE_IDIV:       idiv(d, s0, s1);                break;
-			case Shader::OPCODE_UDIV:       udiv(d, s0, s1);                break;
-			case Shader::OPCODE_MOD:        mod(d, s0, s1);                 break;
-			case Shader::OPCODE_IMOD:       imod(d, s0, s1);                break;
-			case Shader::OPCODE_UMOD:       umod(d, s0, s1);                break;
-			case Shader::OPCODE_SHL:        shl(d, s0, s1);                 break;
-			case Shader::OPCODE_ISHR:       ishr(d, s0, s1);                break;
-			case Shader::OPCODE_USHR:       ushr(d, s0, s1);                break;
-			case Shader::OPCODE_RSQX:       rsqx(d, s0, pp);                break;
-			case Shader::OPCODE_SQRT:       sqrt(d, s0, pp);                break;
-			case Shader::OPCODE_RSQ:        rsq(d, s0, pp);                 break;
-			case Shader::OPCODE_LEN2:       len2(d.x, s0, pp);              break;
-			case Shader::OPCODE_LEN3:       len3(d.x, s0, pp);              break;
-			case Shader::OPCODE_LEN4:       len4(d.x, s0, pp);              break;
-			case Shader::OPCODE_DIST1:      dist1(d.x, s0, s1, pp);         break;
-			case Shader::OPCODE_DIST2:      dist2(d.x, s0, s1, pp);         break;
-			case Shader::OPCODE_DIST3:      dist3(d.x, s0, s1, pp);         break;
-			case Shader::OPCODE_DIST4:      dist4(d.x, s0, s1, pp);         break;
-			case Shader::OPCODE_SGE:        step(d, s1, s0);                break;
-			case Shader::OPCODE_SGN:        sgn(d, s0);                     break;
-			case Shader::OPCODE_ISGN:       isgn(d, s0);                    break;
-			case Shader::OPCODE_SINCOS:     sincos(d, s0, pp);              break;
-			case Shader::OPCODE_COS:        cos(d, s0, pp);                 break;
-			case Shader::OPCODE_SIN:        sin(d, s0, pp);                 break;
-			case Shader::OPCODE_TAN:        tan(d, s0);                     break;
-			case Shader::OPCODE_ACOS:       acos(d, s0);                    break;
-			case Shader::OPCODE_ASIN:       asin(d, s0);                    break;
-			case Shader::OPCODE_ATAN:       atan(d, s0);                    break;
-			case Shader::OPCODE_ATAN2:      atan2(d, s0, s1);               break;
-			case Shader::OPCODE_COSH:       cosh(d, s0, pp);                break;
-			case Shader::OPCODE_SINH:       sinh(d, s0, pp);                break;
-			case Shader::OPCODE_TANH:       tanh(d, s0, pp);                break;
-			case Shader::OPCODE_ACOSH:      acosh(d, s0, pp);               break;
-			case Shader::OPCODE_ASINH:      asinh(d, s0, pp);               break;
-			case Shader::OPCODE_ATANH:      atanh(d, s0, pp);               break;
-			case Shader::OPCODE_SLT:        slt(d, s0, s1);                 break;
-			case Shader::OPCODE_SUB:        sub(d, s0, s1);                 break;
-			case Shader::OPCODE_ISUB:       isub(d, s0, s1);                break;
-			case Shader::OPCODE_BREAK:      BREAK();                        break;
-			case Shader::OPCODE_BREAKC:     BREAKC(s0, s1, control);        break;
-			case Shader::OPCODE_BREAKP:     BREAKP(src0);                   break;
-			case Shader::OPCODE_CONTINUE:   CONTINUE();                     break;
-			case Shader::OPCODE_TEST:       TEST();                         break;
-			case Shader::OPCODE_CALL:       CALL(dst.label, dst.callSite);  break;
-			case Shader::OPCODE_CALLNZ:     CALLNZ(dst.label, dst.callSite, src0); break;
-			case Shader::OPCODE_ELSE:       ELSE();                         break;
-			case Shader::OPCODE_ENDIF:      ENDIF();                        break;
-			case Shader::OPCODE_ENDLOOP:    ENDLOOP();                      break;
-			case Shader::OPCODE_ENDREP:     ENDREP();                       break;
-			case Shader::OPCODE_ENDWHILE:   ENDWHILE();                     break;
-			case Shader::OPCODE_ENDSWITCH:  ENDSWITCH();                    break;
-			case Shader::OPCODE_IF:         IF(src0);                       break;
-			case Shader::OPCODE_IFC:        IFC(s0, s1, control);           break;
-			case Shader::OPCODE_LABEL:      LABEL(dst.index);               break;
-			case Shader::OPCODE_LOOP:       LOOP(src1);                     break;
-			case Shader::OPCODE_REP:        REP(src0);                      break;
-			case Shader::OPCODE_WHILE:      WHILE(src0);                    break;
-			case Shader::OPCODE_SWITCH:     SWITCH();                       break;
-			case Shader::OPCODE_RET:        RET();                          break;
-			case Shader::OPCODE_LEAVE:      LEAVE();                        break;
-			case Shader::OPCODE_CMP:        cmp(d, s0, s1, control);        break;
-			case Shader::OPCODE_ICMP:       icmp(d, s0, s1, control);       break;
-			case Shader::OPCODE_UCMP:       ucmp(d, s0, s1, control);       break;
-			case Shader::OPCODE_SELECT:     select(d, s0, s1, s2);          break;
-			case Shader::OPCODE_EXTRACT:    extract(d.x, s0, s1.x);         break;
-			case Shader::OPCODE_INSERT:     insert(d, s0, s1.x, s2.x);      break;
-			case Shader::OPCODE_ALL:        all(d.x, s0);                   break;
-			case Shader::OPCODE_ANY:        any(d.x, s0);                   break;
-			case Shader::OPCODE_NOT:        bitwise_not(d, s0);             break;
-			case Shader::OPCODE_OR:         bitwise_or(d, s0, s1);          break;
-			case Shader::OPCODE_XOR:        bitwise_xor(d, s0, s1);         break;
-			case Shader::OPCODE_AND:        bitwise_and(d, s0, s1);         break;
-			case Shader::OPCODE_EQ:         equal(d, s0, s1);               break;
-			case Shader::OPCODE_NE:         notEqual(d, s0, s1);            break;
-			case Shader::OPCODE_TEXLDL:     TEXLOD(d, s0, src1, s0.w);      break;
-			case Shader::OPCODE_TEXLOD:     TEXLOD(d, s0, src1, s2.x);      break;
-			case Shader::OPCODE_TEX:        TEX(d, s0, src1);               break;
-			case Shader::OPCODE_TEXOFFSET:  TEXOFFSET(d, s0, src1, s2);     break;
-			case Shader::OPCODE_TEXLODOFFSET: TEXLODOFFSET(d, s0, src1, s2, s3.x); break;
-			case Shader::OPCODE_TEXELFETCH: TEXELFETCH(d, s0, src1, s2.x);  break;
-			case Shader::OPCODE_TEXELFETCHOFFSET: TEXELFETCHOFFSET(d, s0, src1, s2, s3.x); break;
-			case Shader::OPCODE_TEXGRAD:    TEXGRAD(d, s0, src1, s2, s3);   break;
-			case Shader::OPCODE_TEXGRADOFFSET: TEXGRADOFFSET(d, s0, src1, s2, s3, s4); break;
-			case Shader::OPCODE_TEXSIZE:    TEXSIZE(d, s0.x, src1);         break;
-			case Shader::OPCODE_END:                                        break;
-			default:
-				ASSERT(false);
-			}
-
-			if(dst.type != Shader::PARAMETER_VOID && dst.type != Shader::PARAMETER_LABEL && opcode != Shader::OPCODE_NOP)
-			{
-				if(dst.saturate)
-				{
-					if(dst.x) d.x = Max(d.x, Float4(0.0f));
-					if(dst.y) d.y = Max(d.y, Float4(0.0f));
-					if(dst.z) d.z = Max(d.z, Float4(0.0f));
-					if(dst.w) d.w = Max(d.w, Float4(0.0f));
-
-					if(dst.x) d.x = Min(d.x, Float4(1.0f));
-					if(dst.y) d.y = Min(d.y, Float4(1.0f));
-					if(dst.z) d.z = Min(d.z, Float4(1.0f));
-					if(dst.w) d.w = Min(d.w, Float4(1.0f));
-				}
-
-				if(instruction->isPredicated())
-				{
-					Vector4f pDst;   // FIXME: Rename
-
-					switch(dst.type)
-					{
-					case Shader::PARAMETER_VOID: break;
-					case Shader::PARAMETER_TEMP:
-						if(dst.rel.type == Shader::PARAMETER_VOID)
-						{
-							if(dst.x) pDst.x = r[dst.index].x;
-							if(dst.y) pDst.y = r[dst.index].y;
-							if(dst.z) pDst.z = r[dst.index].z;
-							if(dst.w) pDst.w = r[dst.index].w;
-						}
-						else if(!dst.rel.dynamic)
-						{
-							Int a = dst.index + relativeAddress(dst.rel);
-
-							if(dst.x) pDst.x = r[a].x;
-							if(dst.y) pDst.y = r[a].y;
-							if(dst.z) pDst.z = r[a].z;
-							if(dst.w) pDst.w = r[a].w;
-						}
-						else
-						{
-							Int4 a = dst.index + dynamicAddress(dst.rel);
-
-							if(dst.x) pDst.x = r[a].x;
-							if(dst.y) pDst.y = r[a].y;
-							if(dst.z) pDst.z = r[a].z;
-							if(dst.w) pDst.w = r[a].w;
-						}
-						break;
-					case Shader::PARAMETER_ADDR: pDst = a0; break;
-					case Shader::PARAMETER_RASTOUT:
-						switch(dst.index)
-						{
-						case 0:
-							if(dst.x) pDst.x = o[Pos].x;
-							if(dst.y) pDst.y = o[Pos].y;
-							if(dst.z) pDst.z = o[Pos].z;
-							if(dst.w) pDst.w = o[Pos].w;
-							break;
-						case 1:
-							pDst.x = o[Fog].x;
-							break;
-						case 2:
-							pDst.x = o[Pts].y;
-							break;
-						default:
-							ASSERT(false);
-						}
-						break;
-					case Shader::PARAMETER_ATTROUT:
-						if(dst.x) pDst.x = o[C0 + dst.index].x;
-						if(dst.y) pDst.y = o[C0 + dst.index].y;
-						if(dst.z) pDst.z = o[C0 + dst.index].z;
-						if(dst.w) pDst.w = o[C0 + dst.index].w;
-						break;
-					case Shader::PARAMETER_TEXCRDOUT:
-						//	case Shader::PARAMETER_OUTPUT:
-						if(shaderModel < 0x0300)
-						{
-							if(dst.x) pDst.x = o[T0 + dst.index].x;
-							if(dst.y) pDst.y = o[T0 + dst.index].y;
-							if(dst.z) pDst.z = o[T0 + dst.index].z;
-							if(dst.w) pDst.w = o[T0 + dst.index].w;
-						}
-						else if(dst.rel.type == Shader::PARAMETER_VOID)   // Not relative
-						{
-							if(dst.x) pDst.x = o[dst.index].x;
-							if(dst.y) pDst.y = o[dst.index].y;
-							if(dst.z) pDst.z = o[dst.index].z;
-							if(dst.w) pDst.w = o[dst.index].w;
-						}
-						else if(!dst.rel.dynamic)
-						{
-							Int a = dst.index + relativeAddress(dst.rel);
-
-							if(dst.x) pDst.x = o[a].x;
-							if(dst.y) pDst.y = o[a].y;
-							if(dst.z) pDst.z = o[a].z;
-							if(dst.w) pDst.w = o[a].w;
-						}
-						else
-						{
-							Int4 a = dst.index + dynamicAddress(dst.rel);
-
-							if(dst.x) pDst.x = o[a].x;
-							if(dst.y) pDst.y = o[a].y;
-							if(dst.z) pDst.z = o[a].z;
-							if(dst.w) pDst.w = o[a].w;
-						}
-						break;
-					case Shader::PARAMETER_LABEL:                break;
-					case Shader::PARAMETER_PREDICATE: pDst = p0; break;
-					case Shader::PARAMETER_INPUT:                break;
-					default:
-						ASSERT(false);
-					}
-
-					Int4 enable = enableMask(instruction);
-
-					Int4 xEnable = enable;
-					Int4 yEnable = enable;
-					Int4 zEnable = enable;
-					Int4 wEnable = enable;
-
-					if(predicate)
-					{
-						unsigned char pSwizzle = instruction->predicateSwizzle;
-
-						Float4 xPredicate = p0[(pSwizzle >> 0) & 0x03];
-						Float4 yPredicate = p0[(pSwizzle >> 2) & 0x03];
-						Float4 zPredicate = p0[(pSwizzle >> 4) & 0x03];
-						Float4 wPredicate = p0[(pSwizzle >> 6) & 0x03];
-
-						if(!instruction->predicateNot)
-						{
-							if(dst.x) xEnable = xEnable & As<Int4>(xPredicate);
-							if(dst.y) yEnable = yEnable & As<Int4>(yPredicate);
-							if(dst.z) zEnable = zEnable & As<Int4>(zPredicate);
-							if(dst.w) wEnable = wEnable & As<Int4>(wPredicate);
-						}
-						else
-						{
-							if(dst.x) xEnable = xEnable & ~As<Int4>(xPredicate);
-							if(dst.y) yEnable = yEnable & ~As<Int4>(yPredicate);
-							if(dst.z) zEnable = zEnable & ~As<Int4>(zPredicate);
-							if(dst.w) wEnable = wEnable & ~As<Int4>(wPredicate);
-						}
-					}
-
-					if(dst.x) d.x = As<Float4>(As<Int4>(d.x) & xEnable);
-					if(dst.y) d.y = As<Float4>(As<Int4>(d.y) & yEnable);
-					if(dst.z) d.z = As<Float4>(As<Int4>(d.z) & zEnable);
-					if(dst.w) d.w = As<Float4>(As<Int4>(d.w) & wEnable);
-
-					if(dst.x) d.x = As<Float4>(As<Int4>(d.x) | (As<Int4>(pDst.x) & ~xEnable));
-					if(dst.y) d.y = As<Float4>(As<Int4>(d.y) | (As<Int4>(pDst.y) & ~yEnable));
-					if(dst.z) d.z = As<Float4>(As<Int4>(d.z) | (As<Int4>(pDst.z) & ~zEnable));
-					if(dst.w) d.w = As<Float4>(As<Int4>(d.w) | (As<Int4>(pDst.w) & ~wEnable));
-				}
-
-				switch(dst.type)
-				{
-				case Shader::PARAMETER_VOID:
-					break;
-				case Shader::PARAMETER_TEMP:
-					if(dst.rel.type == Shader::PARAMETER_VOID)
-					{
-						if(dst.x) r[dst.index].x = d.x;
-						if(dst.y) r[dst.index].y = d.y;
-						if(dst.z) r[dst.index].z = d.z;
-						if(dst.w) r[dst.index].w = d.w;
-					}
-					else if(!dst.rel.dynamic)
-					{
-						Int a = dst.index + relativeAddress(dst.rel);
-
-						if(dst.x) r[a].x = d.x;
-						if(dst.y) r[a].y = d.y;
-						if(dst.z) r[a].z = d.z;
-						if(dst.w) r[a].w = d.w;
-					}
-					else
-					{
-						Int4 a = dst.index + dynamicAddress(dst.rel);
-
-						if(dst.x) r.scatter_x(a, d.x);
-						if(dst.y) r.scatter_y(a, d.y);
-						if(dst.z) r.scatter_z(a, d.z);
-						if(dst.w) r.scatter_w(a, d.w);
-					}
-					break;
-				case Shader::PARAMETER_ADDR:
-					if(dst.x) a0.x = d.x;
-					if(dst.y) a0.y = d.y;
-					if(dst.z) a0.z = d.z;
-					if(dst.w) a0.w = d.w;
-					break;
-				case Shader::PARAMETER_RASTOUT:
-					switch(dst.index)
-					{
-					case 0:
-						if(dst.x) o[Pos].x = d.x;
-						if(dst.y) o[Pos].y = d.y;
-						if(dst.z) o[Pos].z = d.z;
-						if(dst.w) o[Pos].w = d.w;
-						break;
-					case 1:
-						o[Fog].x = d.x;
-						break;
-					case 2:
-						o[Pts].y = d.x;
-						break;
-					default:	ASSERT(false);
-					}
-					break;
-				case Shader::PARAMETER_ATTROUT:
-					if(dst.x) o[C0 + dst.index].x = d.x;
-					if(dst.y) o[C0 + dst.index].y = d.y;
-					if(dst.z) o[C0 + dst.index].z = d.z;
-					if(dst.w) o[C0 + dst.index].w = d.w;
-					break;
-				case Shader::PARAMETER_TEXCRDOUT:
-					//	case Shader::PARAMETER_OUTPUT:
-					if(shaderModel < 0x0300)
-					{
-						if(dst.x) o[T0 + dst.index].x = d.x;
-						if(dst.y) o[T0 + dst.index].y = d.y;
-						if(dst.z) o[T0 + dst.index].z = d.z;
-						if(dst.w) o[T0 + dst.index].w = d.w;
-					}
-					else if(dst.rel.type == Shader::PARAMETER_VOID)   // Not relative
-					{
-						if(dst.x) o[dst.index].x = d.x;
-						if(dst.y) o[dst.index].y = d.y;
-						if(dst.z) o[dst.index].z = d.z;
-						if(dst.w) o[dst.index].w = d.w;
-					}
-					else if(!dst.rel.dynamic)
-					{
-						Int a = dst.index + relativeAddress(dst.rel);
-
-						if(dst.x) o[a].x = d.x;
-						if(dst.y) o[a].y = d.y;
-						if(dst.z) o[a].z = d.z;
-						if(dst.w) o[a].w = d.w;
-					}
-					else
-					{
-						Int4 a = dst.index + dynamicAddress(dst.rel);
-
-						if(dst.x) o.scatter_x(a, d.x);
-						if(dst.y) o.scatter_y(a, d.y);
-						if(dst.z) o.scatter_z(a, d.z);
-						if(dst.w) o.scatter_w(a, d.w);
-					}
-					break;
-				case Shader::PARAMETER_LABEL:             break;
-				case Shader::PARAMETER_PREDICATE: p0 = d; break;
-				case Shader::PARAMETER_INPUT:             break;
-				default:
-					ASSERT(false);
-				}
-			}
-		}
+		// Actually emit code here
 
 		if(currentLabel != -1)
 		{
@@ -601,141 +72,6 @@
 		}
 	}
 
-	Vector4f VertexProgram::fetchRegister(const Src &src, unsigned int offset)
-	{
-		Vector4f reg;
-		unsigned int i = src.index + offset;
-
-		switch(src.type)
-		{
-		case Shader::PARAMETER_TEMP:
-			if(src.rel.type == Shader::PARAMETER_VOID)
-			{
-				reg = r[i];
-			}
-			else if(!src.rel.dynamic)
-			{
-				reg = r[i + relativeAddress(src.rel, src.bufferIndex)];
-			}
-			else
-			{
-				reg = r[i + dynamicAddress(src.rel)];
-			}
-			break;
-		case Shader::PARAMETER_CONST:
-			reg = readConstant(src, offset);
-			break;
-		case Shader::PARAMETER_INPUT:
-			if(src.rel.type == Shader::PARAMETER_VOID)
-			{
-				reg = v[i];
-			}
-			else if(!src.rel.dynamic)
-			{
-				reg = v[i + relativeAddress(src.rel, src.bufferIndex)];
-			}
-			else
-			{
-				reg = v[i + dynamicAddress(src.rel)];
-			}
-			break;
-		case Shader::PARAMETER_VOID: return r[0];   // Dummy
-		case Shader::PARAMETER_FLOAT4LITERAL:
-			reg.x = Float4(src.value[0]);
-			reg.y = Float4(src.value[1]);
-			reg.z = Float4(src.value[2]);
-			reg.w = Float4(src.value[3]);
-			break;
-		case Shader::PARAMETER_ADDR:      reg = a0; break;
-		case Shader::PARAMETER_CONSTBOOL: return r[0];   // Dummy
-		case Shader::PARAMETER_CONSTINT:  return r[0];   // Dummy
-		case Shader::PARAMETER_LOOP:      return r[0];   // Dummy
-		case Shader::PARAMETER_PREDICATE: return r[0];   // Dummy
-		case Shader::PARAMETER_SAMPLER:
-			if(src.rel.type == Shader::PARAMETER_VOID)
-			{
-				reg.x = As<Float4>(Int4(i));
-			}
-			else if(src.rel.type == Shader::PARAMETER_TEMP)
-			{
-				reg.x = As<Float4>(Int4(i) + As<Int4>(r[src.rel.index].x));
-			}
-			return reg;
-		case Shader::PARAMETER_OUTPUT:
-			if(src.rel.type == Shader::PARAMETER_VOID)
-			{
-				reg = o[i];
-			}
-			else if(!src.rel.dynamic)
-			{
-				reg = o[i + relativeAddress(src.rel, src.bufferIndex)];
-			}
-			else
-			{
-				reg = o[i + dynamicAddress(src.rel)];
-			}
-			break;
-		case Shader::PARAMETER_MISCTYPE:
-			if(src.index == Shader::InstanceIDIndex)
-			{
-				reg.x = As<Float>(instanceID);
-			}
-			else if(src.index == Shader::VertexIDIndex)
-			{
-				reg.x = As<Float4>(vertexID);
-			}
-			else ASSERT(false);
-			return reg;
-		default:
-			ASSERT(false);
-		}
-
-		const Float4 &x = reg[(src.swizzle >> 0) & 0x3];
-		const Float4 &y = reg[(src.swizzle >> 2) & 0x3];
-		const Float4 &z = reg[(src.swizzle >> 4) & 0x3];
-		const Float4 &w = reg[(src.swizzle >> 6) & 0x3];
-
-		Vector4f mod;
-
-		switch(src.modifier)
-		{
-		case Shader::MODIFIER_NONE:
-			mod.x = x;
-			mod.y = y;
-			mod.z = z;
-			mod.w = w;
-			break;
-		case Shader::MODIFIER_NEGATE:
-			mod.x = -x;
-			mod.y = -y;
-			mod.z = -z;
-			mod.w = -w;
-			break;
-		case Shader::MODIFIER_ABS:
-			mod.x = Abs(x);
-			mod.y = Abs(y);
-			mod.z = Abs(z);
-			mod.w = Abs(w);
-			break;
-		case Shader::MODIFIER_ABS_NEGATE:
-			mod.x = -Abs(x);
-			mod.y = -Abs(y);
-			mod.z = -Abs(z);
-			mod.w = -Abs(w);
-			break;
-		case Shader::MODIFIER_NOT:
-			mod.x = As<Float4>(As<Int4>(x) ^ Int4(0xFFFFFFFF));
-			mod.y = As<Float4>(As<Int4>(y) ^ Int4(0xFFFFFFFF));
-			mod.z = As<Float4>(As<Int4>(z) ^ Int4(0xFFFFFFFF));
-			mod.w = As<Float4>(As<Int4>(w) ^ Int4(0xFFFFFFFF));
-			break;
-		default:
-			ASSERT(false);
-		}
-
-		return mod;
-	}
-
 	RValue<Pointer<Byte>> VertexProgram::uniformAddress(int bufferIndex, unsigned int index)
 	{
 		if(bufferIndex == -1)
@@ -753,821 +89,10 @@
 		return uniformAddress(bufferIndex, index) + offset * sizeof(float4);
 	}
 
-	Vector4f VertexProgram::readConstant(const Src &src, unsigned int offset)
+	Int4 VertexProgram::enableMask()
 	{
-		Vector4f c;
-		unsigned int i = src.index + offset;
-
-		if(src.rel.type == Shader::PARAMETER_VOID)   // Not relative
-		{
-			c.x = c.y = c.z = c.w = *Pointer<Float4>(uniformAddress(src.bufferIndex, i));
-
-			c.x = c.x.xxxx;
-			c.y = c.y.yyyy;
-			c.z = c.z.zzzz;
-			c.w = c.w.wwww;
-
-			if(shader->containsDefineInstruction())   // Constant may be known at compile time
-			{
-				for(size_t j = 0; j < shader->getLength(); j++)
-				{
-					const Shader::Instruction &instruction = *shader->getInstruction(j);
-
-					if(instruction.opcode == Shader::OPCODE_DEF)
-					{
-						if(instruction.dst.index == i)
-						{
-							c.x = Float4(instruction.src[0].value[0]);
-							c.y = Float4(instruction.src[0].value[1]);
-							c.z = Float4(instruction.src[0].value[2]);
-							c.w = Float4(instruction.src[0].value[3]);
-
-							break;
-						}
-					}
-				}
-			}
-		}
-		else if(!src.rel.dynamic || src.rel.type == Shader::PARAMETER_LOOP)
-		{
-			Int a = relativeAddress(src.rel, src.bufferIndex);
-
-			c.x = c.y = c.z = c.w = *Pointer<Float4>(uniformAddress(src.bufferIndex, i, a));
-
-			c.x = c.x.xxxx;
-			c.y = c.y.yyyy;
-			c.z = c.z.zzzz;
-			c.w = c.w.wwww;
-		}
-		else
-		{
-			int component = src.rel.swizzle & 0x03;
-			Float4 a;
-
-			switch(src.rel.type)
-			{
-			case Shader::PARAMETER_ADDR:     a = a0[component]; break;
-			case Shader::PARAMETER_TEMP:     a = r[src.rel.index][component]; break;
-			case Shader::PARAMETER_INPUT:    a = v[src.rel.index][component]; break;
-			case Shader::PARAMETER_OUTPUT:   a = o[src.rel.index][component]; break;
-			case Shader::PARAMETER_CONST:    a = *Pointer<Float>(uniformAddress(src.bufferIndex, src.rel.index) + component * sizeof(float)); break;
-			case Shader::PARAMETER_MISCTYPE:
-				switch(src.rel.index)
-				{
-				case Shader::InstanceIDIndex: a = As<Float4>(Int4(instanceID)); break;
-				case Shader::VertexIDIndex:   a = As<Float4>(vertexID);         break;
-				default: ASSERT(false);
-				}
-				break;
-			default: ASSERT(false);
-			}
-
-			Int4 index = Int4(i) + As<Int4>(a) * Int4(src.rel.scale);
-
-			index = Min(As<UInt4>(index), UInt4(VERTEX_UNIFORM_VECTORS));   // Clamp to constant register range, c[VERTEX_UNIFORM_VECTORS] = {0, 0, 0, 0}
-
-			Int index0 = Extract(index, 0);
-			Int index1 = Extract(index, 1);
-			Int index2 = Extract(index, 2);
-			Int index3 = Extract(index, 3);
-
-			c.x = *Pointer<Float4>(uniformAddress(src.bufferIndex, 0, index0), 16);
-			c.y = *Pointer<Float4>(uniformAddress(src.bufferIndex, 0, index1), 16);
-			c.z = *Pointer<Float4>(uniformAddress(src.bufferIndex, 0, index2), 16);
-			c.w = *Pointer<Float4>(uniformAddress(src.bufferIndex, 0, index3), 16);
-
-			transpose4x4(c.x, c.y, c.z, c.w);
-		}
-
-		return c;
-	}
-
-	Int VertexProgram::relativeAddress(const Shader::Relative &rel, int bufferIndex)
-	{
-		ASSERT(!rel.dynamic);
-
-		if(rel.type == Shader::PARAMETER_TEMP)
-		{
-			return As<Int>(Extract(r[rel.index].x, 0)) * rel.scale;
-		}
-		else if(rel.type == Shader::PARAMETER_INPUT)
-		{
-			return As<Int>(Extract(v[rel.index].x, 0)) * rel.scale;
-		}
-		else if(rel.type == Shader::PARAMETER_OUTPUT)
-		{
-			return As<Int>(Extract(o[rel.index].x, 0)) * rel.scale;
-		}
-		else if(rel.type == Shader::PARAMETER_CONST)
-		{
-			return *Pointer<Int>(uniformAddress(bufferIndex, rel.index)) * rel.scale;
-		}
-		else if(rel.type == Shader::PARAMETER_LOOP)
-		{
-			return aL[loopDepth];
-		}
-		else ASSERT(false);
-
-		return 0;
-	}
-
-	Int4 VertexProgram::dynamicAddress(const Shader::Relative &rel)
-	{
-		int component = rel.swizzle & 0x03;
-		Float4 a;
-
-		switch(rel.type)
-		{
-		case Shader::PARAMETER_ADDR:     a = a0[component]; break;
-		case Shader::PARAMETER_TEMP:     a = r[rel.index][component]; break;
-		case Shader::PARAMETER_INPUT:    a = v[rel.index][component]; break;
-		case Shader::PARAMETER_OUTPUT:   a = o[rel.index][component]; break;
-		case Shader::PARAMETER_MISCTYPE:
-			switch(rel.index)
-			{
-			case Shader::InstanceIDIndex: a = As<Float>(instanceID); break;
-			case Shader::VertexIDIndex:   a = As<Float4>(vertexID);  break;
-			default: ASSERT(false);
-			}
-			break;
-		default: ASSERT(false);
-		}
-
-		return As<Int4>(a) * Int4(rel.scale);
-	}
-
-	Int4 VertexProgram::enableMask(const Shader::Instruction *instruction)
-	{
-		Int4 enable = instruction->analysisBranch ? Int4(enableStack[enableIndex]) : Int4(0xFFFFFFFF);
-
-		if(!whileTest)
-		{
-			if(shader->containsBreakInstruction() && instruction->analysisBreak)
-			{
-				enable &= enableBreak;
-			}
-
-			if(shader->containsContinueInstruction() && instruction->analysisContinue)
-			{
-				enable &= enableContinue;
-			}
-
-			if(shader->containsLeaveInstruction() && instruction->analysisLeave)
-			{
-				enable &= enableLeave;
-			}
-		}
-
+		Int4 enable = true ? Int4(enableStack[enableIndex]) : Int4(0xFFFFFFFF);
 		return enable;
 	}
 
-	void VertexProgram::M3X2(Vector4f &dst, Vector4f &src0, Src &src1)
-	{
-		Vector4f row0 = fetchRegister(src1, 0);
-		Vector4f row1 = fetchRegister(src1, 1);
-
-		dst.x = dot3(src0, row0);
-		dst.y = dot3(src0, row1);
-	}
-
-	void VertexProgram::M3X3(Vector4f &dst, Vector4f &src0, Src &src1)
-	{
-		Vector4f row0 = fetchRegister(src1, 0);
-		Vector4f row1 = fetchRegister(src1, 1);
-		Vector4f row2 = fetchRegister(src1, 2);
-
-		dst.x = dot3(src0, row0);
-		dst.y = dot3(src0, row1);
-		dst.z = dot3(src0, row2);
-	}
-
-	void VertexProgram::M3X4(Vector4f &dst, Vector4f &src0, Src &src1)
-	{
-		Vector4f row0 = fetchRegister(src1, 0);
-		Vector4f row1 = fetchRegister(src1, 1);
-		Vector4f row2 = fetchRegister(src1, 2);
-		Vector4f row3 = fetchRegister(src1, 3);
-
-		dst.x = dot3(src0, row0);
-		dst.y = dot3(src0, row1);
-		dst.z = dot3(src0, row2);
-		dst.w = dot3(src0, row3);
-	}
-
-	void VertexProgram::M4X3(Vector4f &dst, Vector4f &src0, Src &src1)
-	{
-		Vector4f row0 = fetchRegister(src1, 0);
-		Vector4f row1 = fetchRegister(src1, 1);
-		Vector4f row2 = fetchRegister(src1, 2);
-
-		dst.x = dot4(src0, row0);
-		dst.y = dot4(src0, row1);
-		dst.z = dot4(src0, row2);
-	}
-
-	void VertexProgram::M4X4(Vector4f &dst, Vector4f &src0, Src &src1)
-	{
-		Vector4f row0 = fetchRegister(src1, 0);
-		Vector4f row1 = fetchRegister(src1, 1);
-		Vector4f row2 = fetchRegister(src1, 2);
-		Vector4f row3 = fetchRegister(src1, 3);
-
-		dst.x = dot4(src0, row0);
-		dst.y = dot4(src0, row1);
-		dst.z = dot4(src0, row2);
-		dst.w = dot4(src0, row3);
-	}
-
-	void VertexProgram::BREAK()
-	{
-		enableBreak = enableBreak & ~enableStack[enableIndex];
-	}
-
-	void VertexProgram::BREAKC(Vector4f &src0, Vector4f &src1, Control control)
-	{
-		Int4 condition;
-
-		switch(control)
-		{
-		case Shader::CONTROL_GT: condition = CmpNLE(src0.x, src1.x); break;
-		case Shader::CONTROL_EQ: condition = CmpEQ(src0.x, src1.x);  break;
-		case Shader::CONTROL_GE: condition = CmpNLT(src0.x, src1.x); break;
-		case Shader::CONTROL_LT: condition = CmpLT(src0.x, src1.x);  break;
-		case Shader::CONTROL_NE: condition = CmpNEQ(src0.x, src1.x); break;
-		case Shader::CONTROL_LE: condition = CmpLE(src0.x, src1.x);  break;
-		default:
-			ASSERT(false);
-		}
-
-		BREAK(condition);
-	}
-
-	void VertexProgram::BREAKP(const Src &predicateRegister)   // FIXME: Factor out parts common with BREAKC
-	{
-		Int4 condition = As<Int4>(p0[predicateRegister.swizzle & 0x3]);
-
-		if(predicateRegister.modifier == Shader::MODIFIER_NOT)
-		{
-			condition = ~condition;
-		}
-
-		BREAK(condition);
-	}
-
-	void VertexProgram::BREAK(Int4 &condition)
-	{
-		condition &= enableStack[enableIndex];
-
-		enableBreak = enableBreak & ~condition;
-	}
-
-	void VertexProgram::CONTINUE()
-	{
-		enableContinue = enableContinue & ~enableStack[enableIndex];
-	}
-
-	void VertexProgram::TEST()
-	{
-		whileTest = true;
-	}
-
-	void VertexProgram::CALL(int labelIndex, int callSiteIndex)
-	{
-		if(!labelBlock[labelIndex])
-		{
-			labelBlock[labelIndex] = Nucleus::createBasicBlock();
-		}
-
-		if(callRetBlock[labelIndex].size() > 1)
-		{
-			callStack[stackIndex++] = UInt(callSiteIndex);
-		}
-
-		Int4 restoreLeave = enableLeave;
-
-		Nucleus::createBr(labelBlock[labelIndex]);
-		Nucleus::setInsertBlock(callRetBlock[labelIndex][callSiteIndex]);
-
-		enableLeave = restoreLeave;
-	}
-
-	void VertexProgram::CALLNZ(int labelIndex, int callSiteIndex, const Src &src)
-	{
-		if(src.type == Shader::PARAMETER_CONSTBOOL)
-		{
-			CALLNZb(labelIndex, callSiteIndex, src);
-		}
-		else if(src.type == Shader::PARAMETER_PREDICATE)
-		{
-			CALLNZp(labelIndex, callSiteIndex, src);
-		}
-		else ASSERT(false);
-	}
-
-	void VertexProgram::CALLNZb(int labelIndex, int callSiteIndex, const Src &boolRegister)
-	{
-		Bool condition = (*Pointer<Byte>(data + OFFSET(DrawData,vs.b[boolRegister.index])) != Byte(0));   // FIXME
-
-		if(boolRegister.modifier == Shader::MODIFIER_NOT)
-		{
-			condition = !condition;
-		}
-
-		if(!labelBlock[labelIndex])
-		{
-			labelBlock[labelIndex] = Nucleus::createBasicBlock();
-		}
-
-		if(callRetBlock[labelIndex].size() > 1)
-		{
-			callStack[stackIndex++] = UInt(callSiteIndex);
-		}
-
-		Int4 restoreLeave = enableLeave;
-
-		branch(condition, labelBlock[labelIndex], callRetBlock[labelIndex][callSiteIndex]);
-		Nucleus::setInsertBlock(callRetBlock[labelIndex][callSiteIndex]);
-
-		enableLeave = restoreLeave;
-	}
-
-	void VertexProgram::CALLNZp(int labelIndex, int callSiteIndex, const Src &predicateRegister)
-	{
-		Int4 condition = As<Int4>(p0[predicateRegister.swizzle & 0x3]);
-
-		if(predicateRegister.modifier == Shader::MODIFIER_NOT)
-		{
-			condition = ~condition;
-		}
-
-		condition &= enableStack[enableIndex];
-
-		if(!labelBlock[labelIndex])
-		{
-			labelBlock[labelIndex] = Nucleus::createBasicBlock();
-		}
-
-		if(callRetBlock[labelIndex].size() > 1)
-		{
-			callStack[stackIndex++] = UInt(callSiteIndex);
-		}
-
-		enableIndex++;
-		enableStack[enableIndex] = condition;
-		Int4 restoreLeave = enableLeave;
-
-		Bool notAllFalse = SignMask(condition) != 0;
-		branch(notAllFalse, labelBlock[labelIndex], callRetBlock[labelIndex][callSiteIndex]);
-		Nucleus::setInsertBlock(callRetBlock[labelIndex][callSiteIndex]);
-
-		enableIndex--;
-		enableLeave = restoreLeave;
-	}
-
-	void VertexProgram::ELSE()
-	{
-		ifDepth--;
-
-		BasicBlock *falseBlock = ifFalseBlock[ifDepth];
-		BasicBlock *endBlock = Nucleus::createBasicBlock();
-
-		if(isConditionalIf[ifDepth])
-		{
-			Int4 condition = ~enableStack[enableIndex] & enableStack[enableIndex - 1];
-			Bool notAllFalse = SignMask(condition) != 0;
-
-			branch(notAllFalse, falseBlock, endBlock);
-
-			enableStack[enableIndex] = ~enableStack[enableIndex] & enableStack[enableIndex - 1];
-		}
-		else
-		{
-			Nucleus::createBr(endBlock);
-			Nucleus::setInsertBlock(falseBlock);
-		}
-
-		ifFalseBlock[ifDepth] = endBlock;
-
-		ifDepth++;
-	}
-
-	void VertexProgram::ENDIF()
-	{
-		ifDepth--;
-
-		BasicBlock *endBlock = ifFalseBlock[ifDepth];
-
-		Nucleus::createBr(endBlock);
-		Nucleus::setInsertBlock(endBlock);
-
-		if(isConditionalIf[ifDepth])
-		{
-			enableIndex--;
-		}
-	}
-
-	void VertexProgram::ENDLOOP()
-	{
-		loopRepDepth--;
-
-		aL[loopDepth] = aL[loopDepth] + increment[loopDepth];   // FIXME: +=
-
-		BasicBlock *testBlock = loopRepTestBlock[loopRepDepth];
-		BasicBlock *endBlock = loopRepEndBlock[loopRepDepth];
-
-		Nucleus::createBr(testBlock);
-		Nucleus::setInsertBlock(endBlock);
-
-		loopDepth--;
-		enableBreak = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
-	}
-
-	void VertexProgram::ENDREP()
-	{
-		loopRepDepth--;
-
-		BasicBlock *testBlock = loopRepTestBlock[loopRepDepth];
-		BasicBlock *endBlock = loopRepEndBlock[loopRepDepth];
-
-		Nucleus::createBr(testBlock);
-		Nucleus::setInsertBlock(endBlock);
-
-		loopDepth--;
-		enableBreak = Int4(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
-	}
-
-	void VertexProgram::ENDWHILE()
-	{
-		loopRepDepth--;
-
-		BasicBlock *testBlock = loopRepTestBlock[loopRepDepth];
-		BasicBlock *endBlock = loopRepEndBlock[loopRepDepth];
-
-		Nucleus::createBr(testBlock);
-		Nucleus::setInsertBlock(endBlock);
-
-		enableIndex--;
-		whileTest = false;
-	}
-
-	void VertexProgram::ENDSWITCH()
-	{
-		loopRepDepth--;
-
-		BasicBlock *endBlock = loopRepEndBlock[loopRepDepth];
-
-		Nucleus::createBr(endBlock);
-		Nucleus::setInsertBlock(endBlock);
-	}
-
-	void VertexProgram::IF(const Src &src)
-	{
-		if(src.type == Shader::PARAMETER_CONSTBOOL)
-		{
-			IFb(src);
-		}
-		else if(src.type == Shader::PARAMETER_PREDICATE)
-		{
-			IFp(src);
-		}
-		else
-		{
-			Int4 condition = As<Int4>(fetchRegister(src).x);
-			IF(condition);
-		}
-	}
-
-	void VertexProgram::IFb(const Src &boolRegister)
-	{
-		ASSERT(ifDepth < 24 + 4);
-
-		Bool condition = (*Pointer<Byte>(data + OFFSET(DrawData,vs.b[boolRegister.index])) != Byte(0));   // FIXME
-
-		if(boolRegister.modifier == Shader::MODIFIER_NOT)
-		{
-			condition = !condition;
-		}
-
-		BasicBlock *trueBlock = Nucleus::createBasicBlock();
-		BasicBlock *falseBlock = Nucleus::createBasicBlock();
-
-		branch(condition, trueBlock, falseBlock);
-
-		isConditionalIf[ifDepth] = false;
-		ifFalseBlock[ifDepth] = falseBlock;
-
-		ifDepth++;
-	}
-
-	void VertexProgram::IFp(const Src &predicateRegister)
-	{
-		Int4 condition = As<Int4>(p0[predicateRegister.swizzle & 0x3]);
-
-		if(predicateRegister.modifier == Shader::MODIFIER_NOT)
-		{
-			condition = ~condition;
-		}
-
-		IF(condition);
-	}
-
-	void VertexProgram::IFC(Vector4f &src0, Vector4f &src1, Control control)
-	{
-		Int4 condition;
-
-		switch(control)
-		{
-		case Shader::CONTROL_GT: condition = CmpNLE(src0.x, src1.x); break;
-		case Shader::CONTROL_EQ: condition = CmpEQ(src0.x, src1.x);  break;
-		case Shader::CONTROL_GE: condition = CmpNLT(src0.x, src1.x); break;
-		case Shader::CONTROL_LT: condition = CmpLT(src0.x, src1.x);  break;
-		case Shader::CONTROL_NE: condition = CmpNEQ(src0.x, src1.x); break;
-		case Shader::CONTROL_LE: condition = CmpLE(src0.x, src1.x);  break;
-		default:
-			ASSERT(false);
-		}
-
-		IF(condition);
-	}
-
-	void VertexProgram::IF(Int4 &condition)
-	{
-		condition &= enableStack[enableIndex];
-
-		enableIndex++;
-		enableStack[enableIndex] = condition;
-
-		BasicBlock *trueBlock = Nucleus::createBasicBlock();
-		BasicBlock *falseBlock = Nucleus::createBasicBlock();
-
-		Bool notAllFalse = SignMask(condition) != 0;
-
-		branch(notAllFalse, trueBlock, falseBlock);
-
-		isConditionalIf[ifDepth] = true;
-		ifFalseBlock[ifDepth] = falseBlock;
-
-		ifDepth++;
-	}
-
-	void VertexProgram::LABEL(int labelIndex)
-	{
-		if(!labelBlock[labelIndex])
-		{
-			labelBlock[labelIndex] = Nucleus::createBasicBlock();
-		}
-
-		Nucleus::setInsertBlock(labelBlock[labelIndex]);
-		currentLabel = labelIndex;
-	}
-
-	void VertexProgram::LOOP(const Src &integerRegister)
-	{
-		loopDepth++;
-
-		iteration[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData,vs.i[integerRegister.index][0]));
-		aL[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData,vs.i[integerRegister.index][1]));
-		increment[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData,vs.i[integerRegister.index][2]));
-
-		// FIXME: Compiles to two instructions?
-		If(increment[loopDepth] == 0)
-		{
-			increment[loopDepth] = 1;
-		}
-
-		BasicBlock *loopBlock = Nucleus::createBasicBlock();
-		BasicBlock *testBlock = Nucleus::createBasicBlock();
-		BasicBlock *endBlock = Nucleus::createBasicBlock();
-
-		loopRepTestBlock[loopRepDepth] = testBlock;
-		loopRepEndBlock[loopRepDepth] = endBlock;
-
-		// FIXME: jump(testBlock)
-		Nucleus::createBr(testBlock);
-		Nucleus::setInsertBlock(testBlock);
-
-		branch(iteration[loopDepth] > 0, loopBlock, endBlock);
-		Nucleus::setInsertBlock(loopBlock);
-
-		iteration[loopDepth] = iteration[loopDepth] - 1;   // FIXME: --
-
-		loopRepDepth++;
-	}
-
-	void VertexProgram::REP(const Src &integerRegister)
-	{
-		loopDepth++;
-
-		iteration[loopDepth] = *Pointer<Int>(data + OFFSET(DrawData,vs.i[integerRegister.index][0]));
-		aL[loopDepth] = aL[loopDepth - 1];
-
-		BasicBlock *loopBlock = Nucleus::createBasicBlock();
-		BasicBlock *testBlock = Nucleus::createBasicBlock();
-		BasicBlock *endBlock = Nucleus::createBasicBlock();
-
-		loopRepTestBlock[loopRepDepth] = testBlock;
-		loopRepEndBlock[loopRepDepth] = endBlock;
-
-		// FIXME: jump(testBlock)
-		Nucleus::createBr(testBlock);
-		Nucleus::setInsertBlock(testBlock);
-
-		branch(iteration[loopDepth] > 0, loopBlock, endBlock);
-		Nucleus::setInsertBlock(loopBlock);
-
-		iteration[loopDepth] = iteration[loopDepth] - 1;   // FIXME: --
-
-		loopRepDepth++;
-	}
-
-	void VertexProgram::WHILE(const Src &temporaryRegister)
-	{
-		enableIndex++;
-
-		BasicBlock *loopBlock = Nucleus::createBasicBlock();
-		BasicBlock *testBlock = Nucleus::createBasicBlock();
-		BasicBlock *endBlock = Nucleus::createBasicBlock();
-
-		loopRepTestBlock[loopRepDepth] = testBlock;
-		loopRepEndBlock[loopRepDepth] = endBlock;
-
-		Int4 restoreBreak = enableBreak;
-		Int4 restoreContinue = enableContinue;
-
-		// TODO: jump(testBlock)
-		Nucleus::createBr(testBlock);
-		Nucleus::setInsertBlock(testBlock);
-		enableContinue = restoreContinue;
-
-		const Vector4f &src = fetchRegister(temporaryRegister);
-		Int4 condition = As<Int4>(src.x);
-		condition &= enableStack[enableIndex - 1];
-		if(shader->containsLeaveInstruction()) condition &= enableLeave;
-		if(shader->containsBreakInstruction()) condition &= enableBreak;
-		enableStack[enableIndex] = condition;
-
-		Bool notAllFalse = SignMask(condition) != 0;
-		branch(notAllFalse, loopBlock, endBlock);
-
-		Nucleus::setInsertBlock(endBlock);
-		enableBreak = restoreBreak;
-
-		Nucleus::setInsertBlock(loopBlock);
-
-		loopRepDepth++;
-	}
-
-	void VertexProgram::SWITCH()
-	{
-		BasicBlock *endBlock = Nucleus::createBasicBlock();
-
-		loopRepTestBlock[loopRepDepth] = nullptr;
-		loopRepEndBlock[loopRepDepth] = endBlock;
-
-		Int4 restoreBreak = enableBreak;
-
-		BasicBlock *currentBlock = Nucleus::getInsertBlock();
-
-		Nucleus::setInsertBlock(endBlock);
-		enableBreak = restoreBreak;
-
-		Nucleus::setInsertBlock(currentBlock);
-
-		loopRepDepth++;
-	}
-
-	void VertexProgram::RET()
-	{
-		if(currentLabel == -1)
-		{
-			returnBlock = Nucleus::createBasicBlock();
-			Nucleus::createBr(returnBlock);
-		}
-		else
-		{
-			BasicBlock *unreachableBlock = Nucleus::createBasicBlock();
-
-			if(callRetBlock[currentLabel].size() > 1)   // Pop the return destination from the call stack
-			{
-				// FIXME: Encapsulate
-				UInt index = callStack[--stackIndex];
-
-				Value *value = index.loadValue();
-				SwitchCases *switchCases = Nucleus::createSwitch(value, unreachableBlock, (int)callRetBlock[currentLabel].size());
-
-				for(unsigned int i = 0; i < callRetBlock[currentLabel].size(); i++)
-				{
-					Nucleus::addSwitchCase(switchCases, i, callRetBlock[currentLabel][i]);
-				}
-			}
-			else if(callRetBlock[currentLabel].size() == 1)   // Jump directly to the unique return destination
-			{
-				Nucleus::createBr(callRetBlock[currentLabel][0]);
-			}
-			else   // Function isn't called
-			{
-				Nucleus::createBr(unreachableBlock);
-			}
-
-			Nucleus::setInsertBlock(unreachableBlock);
-			Nucleus::createUnreachable();
-		}
-	}
-
-	void VertexProgram::LEAVE()
-	{
-		enableLeave = enableLeave & ~enableStack[enableIndex];
-
-		// FIXME: Return from function if all instances left
-		// FIXME: Use enableLeave in other control-flow constructs
-	}
-
-	void VertexProgram::TEX(Vector4f &dst, Vector4f &src0, const Src &src1)
-	{
-		dst = sampleTexture(src1, src0, (src0.x), (src0), (src0), (src0), Base);
-	}
-
-	void VertexProgram::TEXOFFSET(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &offset)
-	{
-		dst = sampleTexture(src1, src0, (src0.x), (src0), (src0), offset, {Base, Offset});
-	}
-
-	void VertexProgram::TEXLOD(Vector4f &dst, Vector4f &src0, const Src& src1, Float4 &lod)
-	{
-		dst = sampleTexture(src1, src0, lod, (src0), (src0), (src0), Lod);
-	}
-
-	void VertexProgram::TEXLODOFFSET(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &offset, Float4 &lod)
-	{
-		dst = sampleTexture(src1, src0, lod, (src0), (src0), offset, {Lod, Offset});
-	}
-
-	void VertexProgram::TEXELFETCH(Vector4f &dst, Vector4f &src0, const Src& src1, Float4 &lod)
-	{
-		dst = sampleTexture(src1, src0, lod, (src0), (src0), (src0), Fetch);
-	}
-
-	void VertexProgram::TEXELFETCHOFFSET(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &offset, Float4 &lod)
-	{
-		dst = sampleTexture(src1, src0, lod, (src0), (src0), offset, {Fetch, Offset});
-	}
-
-	void VertexProgram::TEXGRAD(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &dsx, Vector4f &dsy)
-	{
-		dst = sampleTexture(src1, src0, (src0.x), dsx, dsy, src0, Grad);
-	}
-
-	void VertexProgram::TEXGRADOFFSET(Vector4f &dst, Vector4f &src0, const Src& src1, Vector4f &dsx, Vector4f &dsy, Vector4f &offset)
-	{
-		dst = sampleTexture(src1, src0, (src0.x), dsx, dsy, offset, {Grad, Offset});
-	}
-
-	void VertexProgram::TEXSIZE(Vector4f &dst, Float4 &lod, const Src &src1)
-	{
-		bool uniformSampler = (src1.type == Shader::PARAMETER_SAMPLER && src1.rel.type == Shader::PARAMETER_VOID);
-		Int offset = uniformSampler ? src1.index * sizeof(Texture) : As<Int>(Float(fetchRegister(src1).x.x)) * sizeof(Texture);
-		Pointer<Byte> texture = data + OFFSET(DrawData, mipmap[TEXTURE_IMAGE_UNITS]) + offset;
-
-		dst = SamplerCore::textureSize(texture, lod);
-	}
-
-	Vector4f VertexProgram::sampleTexture(const Src &s, Vector4f &uvwq, Float4 &lod, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function)
-	{
-		Vector4f tmp;
-
-		if(s.type == Shader::PARAMETER_SAMPLER && s.rel.type == Shader::PARAMETER_VOID)
-		{
-			tmp = sampleTexture(s.index, uvwq, lod, dsx, dsy, offset, function);
-		}
-		else
-		{
-			Int index = As<Int>(Float(fetchRegister(s).x.x));
-
-			for(int i = 0; i < VERTEX_TEXTURE_IMAGE_UNITS; i++)
-			{
-				if(shader->usesSampler(i))
-				{
-					If(index == i)
-					{
-						tmp = sampleTexture(i, uvwq, lod, dsx, dsy, offset, function);
-						// FIXME: When the sampler states are the same, we could use one sampler and just index the texture
-					}
-				}
-			}
-		}
-
-		Vector4f c;
-		c.x = tmp[(s.swizzle >> 0) & 0x3];
-		c.y = tmp[(s.swizzle >> 2) & 0x3];
-		c.z = tmp[(s.swizzle >> 4) & 0x3];
-		c.w = tmp[(s.swizzle >> 6) & 0x3];
-
-		return c;
-	}
-
-	Vector4f VertexProgram::sampleTexture(int sampler, Vector4f &uvwq, Float4 &lod, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function)
-	{
-		Pointer<Byte> texture = data + OFFSET(DrawData, mipmap[TEXTURE_IMAGE_UNITS]) + sampler * sizeof(Texture);
-		return SamplerCore(constants, state.sampler[sampler]).sampleTexture(texture, uvwq.x, uvwq.y, uvwq.z, uvwq.w, lod, dsx, dsy, offset, function);
-	}
 }
diff --git a/src/Pipeline/VertexProgram.hpp b/src/Pipeline/VertexProgram.hpp
index 9d46b6a..773118f 100644
--- a/src/Pipeline/VertexProgram.hpp
+++ b/src/Pipeline/VertexProgram.hpp
@@ -25,99 +25,25 @@
 namespace sw
 {
 	struct Stream;
-	class VertexShader;
 
 	class VertexProgram : public VertexRoutine, public ShaderCore
 	{
 	public:
-		VertexProgram(const VertexProcessor::State &state, const VertexShader *vertexShader);
+		VertexProgram(const VertexProcessor::State &state, SpirvShader const *spirvShader);
 
 		virtual ~VertexProgram();
 
 	private:
-		const VertexShader *const shader;
-
-		RegisterArray<NUM_TEMPORARY_REGISTERS> r;   // Temporary registers
-		Vector4f a0;
-		Array<Int, 4> aL;
-		Vector4f p0;
-
-		Array<Int, 4> increment;
-		Array<Int, 4> iteration;
-
-		Int loopDepth;
-		Int stackIndex;   // FIXME: Inc/decrement callStack
-		Array<UInt, 16> callStack;
-
 		Int enableIndex;
 		Array<Int4, 1 + 24> enableStack;
-		Int4 enableBreak;
-		Int4 enableContinue;
-		Int4 enableLeave;
 
 		Int instanceID;
 		Int4 vertexID;
 
-		typedef Shader::DestinationParameter Dst;
-		typedef Shader::SourceParameter Src;
-		typedef Shader::Control Control;
-		typedef Shader::Usage Usage;
-
 		void program(UInt &index) override;
-
-		Vector4f fetchRegister(const Src &src, unsigned int offset = 0);
-		Vector4f readConstant(const Src &src, unsigned int offset = 0);
 		RValue<Pointer<Byte>> uniformAddress(int bufferIndex, unsigned int index);
 		RValue<Pointer<Byte>> uniformAddress(int bufferIndex, unsigned int index, Int &offset);
-		Int relativeAddress(const Shader::Relative &rel, int bufferIndex = -1);
-		Int4 dynamicAddress(const Shader::Relative &rel);
-		Int4 enableMask(const Shader::Instruction *instruction);
-
-		void M3X2(Vector4f &dst, Vector4f &src0, Src &src1);
-		void M3X3(Vector4f &dst, Vector4f &src0, Src &src1);
-		void M3X4(Vector4f &dst, Vector4f &src0, Src &src1);
-		void M4X3(Vector4f &dst, Vector4f &src0, Src &src1);
-		void M4X4(Vector4f &dst, Vector4f &src0, Src &src1);
-		void BREAK();
-		void BREAKC(Vector4f &src0, Vector4f &src1, Control);
-		void BREAKP(const Src &predicateRegister);
-		void BREAK(Int4 &condition);
-		void CONTINUE();
-		void TEST();
-		void CALL(int labelIndex, int callSiteIndex);
-		void CALLNZ(int labelIndex, int callSiteIndex, const Src &src);
-		void CALLNZb(int labelIndex, int callSiteIndex, const Src &boolRegister);
-		void CALLNZp(int labelIndex, int callSiteIndex, const Src &predicateRegister);
-		void ELSE();
-		void ENDIF();
-		void ENDLOOP();
-		void ENDREP();
-		void ENDWHILE();
-		void ENDSWITCH();
-		void IF(const Src &src);
-		void IFb(const Src &boolRegister);
-		void IFp(const Src &predicateRegister);
-		void IFC(Vector4f &src0, Vector4f &src1, Control);
-		void IF(Int4 &condition);
-		void LABEL(int labelIndex);
-		void LOOP(const Src &integerRegister);
-		void REP(const Src &integerRegister);
-		void WHILE(const Src &temporaryRegister);
-		void SWITCH();
-		void RET();
-		void LEAVE();
-		void TEX(Vector4f &dst, Vector4f &src, const Src&);
-		void TEXOFFSET(Vector4f &dst, Vector4f &src, const Src&, Vector4f &offset);
-		void TEXLOD(Vector4f &dst, Vector4f &src, const Src&, Float4 &lod);
-		void TEXLODOFFSET(Vector4f &dst, Vector4f &src, const Src&, Vector4f &offset, Float4 &lod);
-		void TEXELFETCH(Vector4f &dst, Vector4f &src, const Src&, Float4 &lod);
-		void TEXELFETCHOFFSET(Vector4f &dst, Vector4f &src, const Src&, Vector4f &offset, Float4 &lod);
-		void TEXGRAD(Vector4f &dst, Vector4f &src, const Src&, Vector4f &dsx, Vector4f &dsy);
-		void TEXGRADOFFSET(Vector4f &dst, Vector4f &src, const Src&, Vector4f &dsx, Vector4f &dsy, Vector4f &offset);
-		void TEXSIZE(Vector4f &dst, Float4 &lod, const Src&);
-
-		Vector4f sampleTexture(const Src &s, Vector4f &uvwq, Float4 &lod, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function);
-		Vector4f sampleTexture(int sampler, Vector4f &uvwq, Float4 &lod, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function);
+		Int4 enableMask();
 
 		int ifDepth;
 		int loopRepDepth;
diff --git a/src/Pipeline/VertexRoutine.cpp b/src/Pipeline/VertexRoutine.cpp
index f0bfc2a..7d76dbe 100644
--- a/src/Pipeline/VertexRoutine.cpp
+++ b/src/Pipeline/VertexRoutine.cpp
@@ -14,7 +14,6 @@
 
 #include "VertexRoutine.hpp"
 
-#include "VertexShader.hpp"
 #include "Constants.hpp"
 #include "Device/Vertex.hpp"
 #include "Device/Renderer.hpp"
@@ -23,13 +22,11 @@
 
 namespace sw
 {
-	extern bool halfIntegerCoordinates;     // Pixel centers are not at integer coordinates
-	extern bool symmetricNormalizedDepth;   // [-1, 1] instead of [0, 1]
-
-	VertexRoutine::VertexRoutine(const VertexProcessor::State &state, const VertexShader *shader)
-		: v(shader && shader->indirectAddressableInput),
-		  o(shader && shader->indirectAddressableOutput),
-		  state(state)
+	VertexRoutine::VertexRoutine(const VertexProcessor::State &state, SpirvShader const *spirvShader)
+		: v(true),		/* TODO: indirect addressable */
+		  o(true),
+		  state(state),
+		  spirvShader(spirvShader)
 	{
 	}
 
@@ -63,7 +60,6 @@
 
 				readInput(indexQ);
 				program(indexQ);
-				postTransform();
 				computeClipFlags();
 
 				Pointer<Byte> cacheLine0 = vertexCache + tagIndex * UInt((int)sizeof(Vertex));
@@ -74,18 +70,6 @@
 			Pointer<Byte> cacheLine = vertexCache + cacheIndex * UInt((int)sizeof(Vertex));
 			writeVertex(vertex, cacheLine);
 
-			if(state.transformFeedbackEnabled != 0)
-			{
-				transformFeedback(vertex, primitiveNumber, indexInPrimitive);
-
-				indexInPrimitive++;
-				If(indexInPrimitive == 3)
-				{
-					primitiveNumber++;
-					indexInPrimitive = 0;
-				}
-			}
-
 			vertex += sizeof(Vertex);
 			batch += sizeof(unsigned int);
 			vertexCount--;
@@ -603,17 +587,6 @@
 		return v;
 	}
 
-	void VertexRoutine::postTransform()
-	{
-		int pos = state.positionRegister;
-
-		if(!halfIntegerCoordinates)
-		{
-			o[pos].x = o[pos].x + *Pointer<Float4>(data + OFFSET(DrawData,halfPixelX)) * o[pos].w;
-			o[pos].y = o[pos].y + *Pointer<Float4>(data + OFFSET(DrawData,halfPixelY)) * o[pos].w;
-		}
-	}
-
 	void VertexRoutine::writeCache(Pointer<Byte> &cacheLine)
 	{
 		Vector4f v;
@@ -719,38 +692,4 @@
 		*Pointer<Int4>(vertex + OFFSET(Vertex,X)) = *Pointer<Int4>(cache + OFFSET(Vertex,X));
 		*Pointer<Int>(vertex + OFFSET(Vertex,clipFlags)) = *Pointer<Int>(cache + OFFSET(Vertex,clipFlags));
 	}
-
-	void VertexRoutine::transformFeedback(const Pointer<Byte> &vertex, const UInt &primitiveNumber, const UInt &indexInPrimitive)
-	{
-		If(indexInPrimitive < state.verticesPerPrimitive)
-		{
-			UInt tOffset = primitiveNumber * state.verticesPerPrimitive + indexInPrimitive;
-
-			for(int i = 0; i < MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS; i++)
-			{
-				if(state.transformFeedbackEnabled & (1ULL << i))
-				{
-					UInt reg = *Pointer<UInt>(data + OFFSET(DrawData, vs.reg[i]));
-					UInt row = *Pointer<UInt>(data + OFFSET(DrawData, vs.row[i]));
-					UInt col = *Pointer<UInt>(data + OFFSET(DrawData, vs.col[i]));
-					UInt str = *Pointer<UInt>(data + OFFSET(DrawData, vs.str[i]));
-
-					Pointer<Byte> t = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData, vs.t[i])) + (tOffset * str * sizeof(float));
-					Pointer<Byte> v = vertex + OFFSET(Vertex, v) + reg * sizeof(float);
-
-					For(UInt r = 0, r < row, r++)
-					{
-						UInt rOffsetX = r * col * sizeof(float);
-						UInt rOffset4 = r * sizeof(float4);
-
-						For(UInt c = 0, c < col, c++)
-						{
-							UInt cOffset = c * sizeof(float);
-							*Pointer<Float>(t + rOffsetX + cOffset) = *Pointer<Float>(v + rOffset4 + cOffset);
-						}
-					}
-				}
-			}
-		}
-	}
 }
diff --git a/src/Pipeline/VertexRoutine.hpp b/src/Pipeline/VertexRoutine.hpp
index f1f180d..cb2b0fd 100644
--- a/src/Pipeline/VertexRoutine.hpp
+++ b/src/Pipeline/VertexRoutine.hpp
@@ -18,7 +18,7 @@
 #include "Device/Color.hpp"
 #include "Device/VertexProcessor.hpp"
 #include "ShaderCore.hpp"
-#include "VertexShader.hpp"
+#include "SpirvShader.hpp"
 
 namespace sw
 {
@@ -38,7 +38,7 @@
 	class VertexRoutine : public VertexRoutinePrototype
 	{
 	public:
-		VertexRoutine(const VertexProcessor::State &state, const VertexShader *shader);
+		VertexRoutine(const VertexProcessor::State &state, SpirvShader const *spirvShader);
 		virtual ~VertexRoutine();
 
 		void generate();
@@ -52,6 +52,7 @@
 		RegisterArray<MAX_VERTEX_OUTPUTS> o;   // Output registers
 
 		const VertexProcessor::State &state;
+		SpirvShader const * const spirvShader;
 
 	private:
 		virtual void program(UInt &index) = 0;
@@ -61,10 +62,8 @@
 		Vector4f readStream(Pointer<Byte> &buffer, UInt &stride, const Stream &stream, const UInt &index);
 		void readInput(UInt &index);
 		void computeClipFlags();
-		void postTransform();
 		void writeCache(Pointer<Byte> &cacheLine);
 		void writeVertex(const Pointer<Byte> &vertex, Pointer<Byte> &cacheLine);
-		void transformFeedback(const Pointer<Byte> &vertex, const UInt &primitiveNumber, const UInt &indexInPrimitive);
 	};
 }
 
diff --git a/src/Pipeline/VertexShader.cpp b/src/Pipeline/VertexShader.cpp
deleted file mode 100644
index a251a14..0000000
--- a/src/Pipeline/VertexShader.cpp
+++ /dev/null
@@ -1,330 +0,0 @@
-// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//    http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "VertexShader.hpp"
-
-#include "Device/Vertex.hpp"
-#include "Vulkan/VkDebug.hpp"
-
-#include <string.h>
-
-namespace sw
-{
-	VertexShader::VertexShader(const VertexShader *vs) : Shader()
-	{
-		shaderModel = 0x0300;
-		positionRegister = Pos;
-		pointSizeRegister = Unused;
-		instanceIdDeclared = false;
-		vertexIdDeclared = false;
-		textureSampling = false;
-
-		for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
-		{
-			input[i] = Semantic();
-			attribType[i] = SpirvShader::ATTRIBTYPE_FLOAT;
-		}
-
-		if(vs)   // Make a copy
-		{
-			for(size_t i = 0; i < vs->getLength(); i++)
-			{
-				append(new sw::Shader::Instruction(*vs->getInstruction(i)));
-			}
-
-			memcpy(output, vs->output, sizeof(output));
-			memcpy(input, vs->input, sizeof(input));
-			memcpy(attribType, vs->attribType, sizeof(attribType));
-			positionRegister = vs->positionRegister;
-			pointSizeRegister = vs->pointSizeRegister;
-			instanceIdDeclared = vs->instanceIdDeclared;
-			vertexIdDeclared = vs->vertexIdDeclared;
-			usedSamplers = vs->usedSamplers;
-
-			optimize();
-			analyze();
-		}
-	}
-
-	VertexShader::VertexShader(const unsigned long *token) : Shader()
-	{
-		parse(token);
-
-		positionRegister = Pos;
-		pointSizeRegister = Unused;
-		instanceIdDeclared = false;
-		vertexIdDeclared = false;
-		textureSampling = false;
-
-		for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
-		{
-			input[i] = Semantic();
-			attribType[i] = SpirvShader::ATTRIBTYPE_FLOAT;
-		}
-
-		optimize();
-		analyze();
-	}
-
-	VertexShader::~VertexShader()
-	{
-	}
-
-	int VertexShader::validate(const unsigned long *const token)
-	{
-		if(!token)
-		{
-			return 0;
-		}
-
-		unsigned short version = (unsigned short)(token[0] & 0x0000FFFF);
-		unsigned char majorVersion = (unsigned char)((token[0] & 0x0000FF00) >> 8);
-		ShaderType shaderType = (ShaderType)((token[0] & 0xFFFF0000) >> 16);
-
-		if(shaderType != SHADER_VERTEX || majorVersion > 3)
-		{
-			return 0;
-		}
-
-		int instructionCount = 1;
-
-		for(int i = 0; token[i] != 0x0000FFFF; i++)
-		{
-			if((token[i] & 0x0000FFFF) == 0x0000FFFE)   // Comment token
-			{
-				int length = (token[i] & 0x7FFF0000) >> 16;
-
-				i += length;
-			}
-			else
-			{
-				Shader::Opcode opcode = (Shader::Opcode)(token[i] & 0x0000FFFF);
-
-				switch(opcode)
-				{
-				case Shader::OPCODE_TEXCOORD:
-				case Shader::OPCODE_TEXKILL:
-				case Shader::OPCODE_TEX:
-				case Shader::OPCODE_TEXBEM:
-				case Shader::OPCODE_TEXBEML:
-				case Shader::OPCODE_TEXREG2AR:
-				case Shader::OPCODE_TEXREG2GB:
-				case Shader::OPCODE_TEXM3X2PAD:
-				case Shader::OPCODE_TEXM3X2TEX:
-				case Shader::OPCODE_TEXM3X3PAD:
-				case Shader::OPCODE_TEXM3X3TEX:
-				case Shader::OPCODE_RESERVED0:
-				case Shader::OPCODE_TEXM3X3SPEC:
-				case Shader::OPCODE_TEXM3X3VSPEC:
-				case Shader::OPCODE_TEXREG2RGB:
-				case Shader::OPCODE_TEXDP3TEX:
-				case Shader::OPCODE_TEXM3X2DEPTH:
-				case Shader::OPCODE_TEXDP3:
-				case Shader::OPCODE_TEXM3X3:
-				case Shader::OPCODE_TEXDEPTH:
-				case Shader::OPCODE_CMP0:
-				case Shader::OPCODE_BEM:
-				case Shader::OPCODE_DP2ADD:
-				case Shader::OPCODE_DFDX:
-				case Shader::OPCODE_DFDY:
-				case Shader::OPCODE_TEXLDD:
-					return 0;   // Unsupported operation
-				default:
-					instructionCount++;
-					break;
-				}
-
-				i += size(token[i], version);
-			}
-		}
-
-		return instructionCount;
-	}
-
-	bool VertexShader::containsTextureSampling() const
-	{
-		return textureSampling;
-	}
-
-	void VertexShader::setInput(int inputIdx, const sw::Shader::Semantic& semantic, SpirvShader::AttribType aType)
-	{
-		input[inputIdx] = semantic;
-		attribType[inputIdx] = aType;
-	}
-
-	void VertexShader::setOutput(int outputIdx, int nbComponents, const sw::Shader::Semantic& semantic)
-	{
-		for(int i = 0; i < nbComponents; ++i)
-		{
-			output[outputIdx][i] = semantic;
-		}
-	}
-
-	void VertexShader::setPositionRegister(int posReg)
-	{
-		setOutput(posReg, 4, sw::Shader::Semantic(sw::Shader::USAGE_POSITION, 0));
-		positionRegister = posReg;
-	}
-
-	void VertexShader::setPointSizeRegister(int ptSizeReg)
-	{
-		setOutput(ptSizeReg, 4, sw::Shader::Semantic(sw::Shader::USAGE_PSIZE, 0));
-		pointSizeRegister = ptSizeReg;
-	}
-
-	const sw::Shader::Semantic& VertexShader::getInput(int inputIdx) const
-	{
-		return input[inputIdx];
-	}
-
-	SpirvShader::AttribType VertexShader::getAttribType(int inputIdx) const
-	{
-		return attribType[inputIdx];
-	}
-
-	const sw::Shader::Semantic& VertexShader::getOutput(int outputIdx, int component) const
-	{
-		return output[outputIdx][component];
-	}
-
-	void VertexShader::analyze()
-	{
-		analyzeInput();
-		analyzeOutput();
-		analyzeDirtyConstants();
-		analyzeTextureSampling();
-		analyzeDynamicBranching();
-		analyzeSamplers();
-		analyzeCallSites();
-		analyzeIndirectAddressing();
-	}
-
-	void VertexShader::analyzeInput()
-	{
-		for(unsigned int i = 0; i < instruction.size(); i++)
-		{
-			if(instruction[i]->opcode == Shader::OPCODE_DCL &&
-			   instruction[i]->dst.type == Shader::PARAMETER_INPUT)
-			{
-				int index = instruction[i]->dst.index;
-
-				input[index] = Semantic(instruction[i]->usage, instruction[i]->usageIndex);
-			}
-		}
-	}
-
-	void VertexShader::analyzeOutput()
-	{
-		if(shaderModel < 0x0300)
-		{
-			output[Pos][0] = Semantic(Shader::USAGE_POSITION, 0);
-			output[Pos][1] = Semantic(Shader::USAGE_POSITION, 0);
-			output[Pos][2] = Semantic(Shader::USAGE_POSITION, 0);
-			output[Pos][3] = Semantic(Shader::USAGE_POSITION, 0);
-
-			for(const auto &inst : instruction)
-			{
-				const DestinationParameter &dst = inst->dst;
-
-				switch(dst.type)
-				{
-				case Shader::PARAMETER_RASTOUT:
-					switch(dst.index)
-					{
-					case 0:
-						// Position already assumed written
-						break;
-					case 1:
-						output[Fog][0] = Semantic(Shader::USAGE_FOG, 0);
-						break;
-					case 2:
-						output[Pts][1] = Semantic(Shader::USAGE_PSIZE, 0);
-						pointSizeRegister = Pts;
-						break;
-					default: ASSERT(false);
-					}
-					break;
-				case Shader::PARAMETER_ATTROUT:
-					if(dst.index == 0)
-					{
-						if(dst.x) output[C0][0] = Semantic(Shader::USAGE_COLOR, 0);
-						if(dst.y) output[C0][1] = Semantic(Shader::USAGE_COLOR, 0);
-						if(dst.z) output[C0][2] = Semantic(Shader::USAGE_COLOR, 0);
-						if(dst.w) output[C0][3] = Semantic(Shader::USAGE_COLOR, 0);
-					}
-					else if(dst.index == 1)
-					{
-						if(dst.x) output[C1][0] = Semantic(Shader::USAGE_COLOR, 1);
-						if(dst.y) output[C1][1] = Semantic(Shader::USAGE_COLOR, 1);
-						if(dst.z) output[C1][2] = Semantic(Shader::USAGE_COLOR, 1);
-						if(dst.w) output[C1][3] = Semantic(Shader::USAGE_COLOR, 1);
-					}
-					else ASSERT(false);
-					break;
-				case Shader::PARAMETER_TEXCRDOUT:
-					if(dst.x) output[T0 + dst.index][0] = Semantic(Shader::USAGE_TEXCOORD, dst.index);
-					if(dst.y) output[T0 + dst.index][1] = Semantic(Shader::USAGE_TEXCOORD, dst.index);
-					if(dst.z) output[T0 + dst.index][2] = Semantic(Shader::USAGE_TEXCOORD, dst.index);
-					if(dst.w) output[T0 + dst.index][3] = Semantic(Shader::USAGE_TEXCOORD, dst.index);
-					break;
-				default:
-					break;
-				}
-			}
-		}
-		else   // Shader Model 3.0 input declaration
-		{
-			for(const auto &inst : instruction)
-			{
-				if(inst->opcode == Shader::OPCODE_DCL &&
-				   inst->dst.type == Shader::PARAMETER_OUTPUT)
-				{
-					unsigned char usage = inst->usage;
-					unsigned char usageIndex = inst->usageIndex;
-
-					const DestinationParameter &dst = inst->dst;
-
-					if(dst.x) output[dst.index][0] = Semantic(usage, usageIndex);
-					if(dst.y) output[dst.index][1] = Semantic(usage, usageIndex);
-					if(dst.z) output[dst.index][2] = Semantic(usage, usageIndex);
-					if(dst.w) output[dst.index][3] = Semantic(usage, usageIndex);
-
-					if(usage == Shader::USAGE_POSITION && usageIndex == 0)
-					{
-						positionRegister = dst.index;
-					}
-
-					if(usage == Shader::USAGE_PSIZE && usageIndex == 0)
-					{
-						pointSizeRegister = dst.index;
-					}
-				}
-			}
-		}
-	}
-
-	void VertexShader::analyzeTextureSampling()
-	{
-		textureSampling = false;
-
-		for(const auto &inst : instruction)
-		{
-			if(inst->src[1].type == PARAMETER_SAMPLER)
-			{
-				textureSampling = true;
-				break;
-			}
-		}
-	}
-}
diff --git a/src/Pipeline/VertexShader.hpp b/src/Pipeline/VertexShader.hpp
deleted file mode 100644
index c6ae335..0000000
--- a/src/Pipeline/VertexShader.hpp
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//    http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef sw_VertexShader_hpp
-#define sw_VertexShader_hpp
-
-#include "Shader.hpp"
-#include "SpirvShader.hpp"
-#include "Device/Config.hpp"
-
-namespace sw
-{
-	class VertexShader : public Shader
-	{
-	public:
-		explicit VertexShader(const VertexShader *vs = 0);
-		explicit VertexShader(const unsigned long *token);
-
-		virtual ~VertexShader();
-
-		static int validate(const unsigned long *const token);   // Returns number of instructions if valid
-		bool containsTextureSampling() const;
-
-		void setInput(int inputIdx, const Semantic& semantic, SpirvShader::AttribType attribType = SpirvShader::ATTRIBTYPE_FLOAT);
-		void setOutput(int outputIdx, int nbComponents, const Semantic& semantic);
-		void setPositionRegister(int posReg);
-		void setPointSizeRegister(int ptSizeReg);
-		void declareInstanceId() { instanceIdDeclared = true; }
-		void declareVertexId() { vertexIdDeclared = true; }
-
-		const Semantic& getInput(int inputIdx) const;
-		const Semantic& getOutput(int outputIdx, int component) const;
-		SpirvShader::AttribType getAttribType(int inputIndex) const;
-		int getPositionRegister() const { return positionRegister; }
-		int getPointSizeRegister() const { return pointSizeRegister; }
-		bool isInstanceIdDeclared() const { return instanceIdDeclared; }
-		bool isVertexIdDeclared() const { return vertexIdDeclared; }
-
-	private:
-		void analyze();
-		void analyzeInput();
-		void analyzeOutput();
-		void analyzeTextureSampling();
-
-		Semantic input[MAX_VERTEX_INPUTS];
-		Semantic output[MAX_VERTEX_OUTPUTS][4];
-
-		SpirvShader::AttribType attribType[MAX_VERTEX_INPUTS];
-
-		int positionRegister;
-		int pointSizeRegister;
-
-		bool instanceIdDeclared;
-		bool vertexIdDeclared;
-		bool textureSampling;
-	};
-}
-
-#endif   // sw_VertexShader_hpp
diff --git a/src/Vulkan/VkPipeline.cpp b/src/Vulkan/VkPipeline.cpp
index 917f5a9..103720c 100644
--- a/src/Vulkan/VkPipeline.cpp
+++ b/src/Vulkan/VkPipeline.cpp
@@ -395,11 +395,11 @@
 
 		switch (pStage->stage) {
 			case VK_SHADER_STAGE_VERTEX_BIT:
-				vertexShader = spirvShader;
+				context.vertexShader = vertexShader = spirvShader;
 				break;
 
 			case VK_SHADER_STAGE_FRAGMENT_BIT:
-				fragmentShader = spirvShader;
+				context.pixelShader = fragmentShader = spirvShader;
 				break;
 
 			default:
diff --git a/src/Vulkan/VkPipeline.hpp b/src/Vulkan/VkPipeline.hpp
index 0c7fef2..039b33e 100644
--- a/src/Vulkan/VkPipeline.hpp
+++ b/src/Vulkan/VkPipeline.hpp
@@ -70,9 +70,6 @@
 	sw::SpirvShader *vertexShader = nullptr;
 	sw::SpirvShader *fragmentShader = nullptr;
 
-	rr::Routine* vertexRoutine;
-	rr::Routine* fragmentRoutine;
-
 	sw::Context context;
 	sw::Rect scissor;
 	VkViewport viewport;
diff --git a/src/Vulkan/vulkan.vcxproj b/src/Vulkan/vulkan.vcxproj
index 275b383..80b8916 100644
--- a/src/Vulkan/vulkan.vcxproj
+++ b/src/Vulkan/vulkan.vcxproj
@@ -143,15 +143,12 @@
     <ClCompile Include="..\Pipeline\Constants.cpp" />

     <ClCompile Include="..\Pipeline\PixelProgram.cpp" />

     <ClCompile Include="..\Pipeline\PixelRoutine.cpp" />

-    <ClCompile Include="..\Pipeline\PixelShader.cpp" />

     <ClCompile Include="..\Pipeline\SamplerCore.cpp" />

     <ClCompile Include="..\Pipeline\SetupRoutine.cpp" />

-    <ClCompile Include="..\Pipeline\Shader.cpp" />

     <ClCompile Include="..\Pipeline\ShaderCore.cpp" />

     <ClCompile Include="..\Pipeline\SpirvShader.cpp" />

     <ClCompile Include="..\Pipeline\VertexProgram.cpp" />

     <ClCompile Include="..\Pipeline\VertexRoutine.cpp" />

-    <ClCompile Include="..\Pipeline\VertexShader.cpp" />

     <ClCompile Include="..\System\Configurator.cpp" />

     <ClCompile Include="..\System\CPUID.cpp" />

     <ClCompile Include="..\System\Debug.cpp" />

@@ -253,16 +250,13 @@
     <ClInclude Include="..\Pipeline\Constants.hpp" />

     <ClInclude Include="..\Pipeline\PixelProgram.hpp" />

     <ClInclude Include="..\Pipeline\PixelRoutine.hpp" />

-    <ClInclude Include="..\Pipeline\PixelShader.hpp" />

     <ClInclude Include="..\Pipeline\SamplerCore.hpp" />

     <ClInclude Include="..\Pipeline\SetupRoutine.hpp" />

-    <ClInclude Include="..\Pipeline\Shader.hpp" />

     <ClInclude Include="..\Pipeline\ShaderCore.hpp" />

     <ClInclude Include="..\Pipeline\SpirvShader.hpp" />

     <ClInclude Include="..\Pipeline\VertexPipeline.hpp" />

     <ClInclude Include="..\Pipeline\VertexProgram.hpp" />

     <ClInclude Include="..\Pipeline\VertexRoutine.hpp" />

-    <ClInclude Include="..\Pipeline\VertexShader.hpp" />

     <ClInclude Include="..\System\Configurator.hpp" />

     <ClInclude Include="..\System\CPUID.hpp" />

     <ClInclude Include="..\System\Debug.hpp" />