Eliminate legacy functionality.

Vulkan doesn't require any fixed-function vertex and pixel processing.

Bug b/117152542

Change-Id: I4c758c70ff97a785c263c38497e7fb435b81b05d
Reviewed-on: https://swiftshader-review.googlesource.com/c/22148
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/Device/Context.cpp b/src/Device/Context.cpp
index 33f3041..d9bad6b 100644
--- a/src/Device/Context.cpp
+++ b/src/Device/Context.cpp
@@ -63,42 +63,30 @@
 		deallocate(pointer);
 	}
 
-	bool Context::isDrawPoint(bool fillModeAware) const
+	bool Context::isDrawPoint() const
 	{
 		switch(drawType)
 		{
 		case DRAW_POINTLIST:
-		case DRAW_INDEXEDPOINTLIST8:
 		case DRAW_INDEXEDPOINTLIST16:
 		case DRAW_INDEXEDPOINTLIST32:
 			return true;
 		case DRAW_LINELIST:
 		case DRAW_LINESTRIP:
-		case DRAW_LINELOOP:
-		case DRAW_INDEXEDLINELIST8:
-		case DRAW_INDEXEDLINESTRIP8:
-		case DRAW_INDEXEDLINELOOP8:
 		case DRAW_INDEXEDLINELIST16:
 		case DRAW_INDEXEDLINESTRIP16:
-		case DRAW_INDEXEDLINELOOP16:
 		case DRAW_INDEXEDLINELIST32:
 		case DRAW_INDEXEDLINESTRIP32:
-		case DRAW_INDEXEDLINELOOP32:
 			return false;
 		case DRAW_TRIANGLELIST:
 		case DRAW_TRIANGLESTRIP:
 		case DRAW_TRIANGLEFAN:
-		case DRAW_INDEXEDTRIANGLELIST8:
-		case DRAW_INDEXEDTRIANGLESTRIP8:
-		case DRAW_INDEXEDTRIANGLEFAN8:
 		case DRAW_INDEXEDTRIANGLELIST16:
 		case DRAW_INDEXEDTRIANGLESTRIP16:
 		case DRAW_INDEXEDTRIANGLEFAN16:
 		case DRAW_INDEXEDTRIANGLELIST32:
 		case DRAW_INDEXEDTRIANGLESTRIP32:
 		case DRAW_INDEXEDTRIANGLEFAN32:
-			return fillModeAware ? fillMode == FILL_VERTEX : false;
-		case DRAW_QUADLIST:
 			return false;
 		default:
 			ASSERT(false);
@@ -107,42 +95,30 @@
 		return false;
 	}
 
-	bool Context::isDrawLine(bool fillModeAware) const
+	bool Context::isDrawLine() const
 	{
 		switch(drawType)
 		{
 		case DRAW_POINTLIST:
-		case DRAW_INDEXEDPOINTLIST8:
 		case DRAW_INDEXEDPOINTLIST16:
 		case DRAW_INDEXEDPOINTLIST32:
 			return false;
 		case DRAW_LINELIST:
 		case DRAW_LINESTRIP:
-		case DRAW_LINELOOP:
-		case DRAW_INDEXEDLINELIST8:
-		case DRAW_INDEXEDLINESTRIP8:
-		case DRAW_INDEXEDLINELOOP8:
 		case DRAW_INDEXEDLINELIST16:
 		case DRAW_INDEXEDLINESTRIP16:
-		case DRAW_INDEXEDLINELOOP16:
 		case DRAW_INDEXEDLINELIST32:
 		case DRAW_INDEXEDLINESTRIP32:
-		case DRAW_INDEXEDLINELOOP32:
 			return true;
 		case DRAW_TRIANGLELIST:
 		case DRAW_TRIANGLESTRIP:
 		case DRAW_TRIANGLEFAN:
-		case DRAW_INDEXEDTRIANGLELIST8:
-		case DRAW_INDEXEDTRIANGLESTRIP8:
-		case DRAW_INDEXEDTRIANGLEFAN8:
 		case DRAW_INDEXEDTRIANGLELIST16:
 		case DRAW_INDEXEDTRIANGLESTRIP16:
 		case DRAW_INDEXEDTRIANGLEFAN16:
 		case DRAW_INDEXEDTRIANGLELIST32:
 		case DRAW_INDEXEDTRIANGLESTRIP32:
 		case DRAW_INDEXEDTRIANGLEFAN32:
-			return fillModeAware ? fillMode == FILL_WIREFRAME : false;
-		case DRAW_QUADLIST:
 			return false;
 		default:
 			ASSERT(false);
@@ -151,44 +127,31 @@
 		return false;
 	}
 
-	bool Context::isDrawTriangle(bool fillModeAware) const
+	bool Context::isDrawTriangle() const
 	{
 		switch(drawType)
 		{
 		case DRAW_POINTLIST:
-		case DRAW_INDEXEDPOINTLIST8:
 		case DRAW_INDEXEDPOINTLIST16:
 		case DRAW_INDEXEDPOINTLIST32:
 			return false;
 		case DRAW_LINELIST:
 		case DRAW_LINESTRIP:
-		case DRAW_LINELOOP:
-		case DRAW_INDEXEDLINELIST8:
-		case DRAW_INDEXEDLINESTRIP8:
-		case DRAW_INDEXEDLINELOOP8:
 		case DRAW_INDEXEDLINELIST16:
 		case DRAW_INDEXEDLINESTRIP16:
-		case DRAW_INDEXEDLINELOOP16:
 		case DRAW_INDEXEDLINELIST32:
 		case DRAW_INDEXEDLINESTRIP32:
-		case DRAW_INDEXEDLINELOOP32:
 			return false;
 		case DRAW_TRIANGLELIST:
 		case DRAW_TRIANGLESTRIP:
 		case DRAW_TRIANGLEFAN:
-		case DRAW_INDEXEDTRIANGLELIST8:
-		case DRAW_INDEXEDTRIANGLESTRIP8:
-		case DRAW_INDEXEDTRIANGLEFAN8:
 		case DRAW_INDEXEDTRIANGLELIST16:
 		case DRAW_INDEXEDTRIANGLESTRIP16:
 		case DRAW_INDEXEDTRIANGLEFAN16:
 		case DRAW_INDEXEDTRIANGLELIST32:
 		case DRAW_INDEXEDTRIANGLESTRIP32:
 		case DRAW_INDEXEDTRIANGLEFAN32:
-			return fillModeAware ? fillMode == FILL_SOLID : true;
-		case DRAW_QUADLIST:
-			// Quads are broken up into triangles
-			return fillModeAware ? fillMode == FILL_SOLID : true;
+			return true;
 		default:
 			ASSERT(false);
 		}
@@ -198,28 +161,12 @@
 
 	void Context::init()
 	{
-		for(int i = 0; i < 8; i++)
-		{
-			textureStage[i].init(i, &sampler[i], (i >= 1) ? &textureStage[i - 1] : 0);
-		}
-
 		// Set vertex streams to null stream
 		for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
 		{
 			input[i].defaults();
 		}
 
-		fogStart = 0.0f;
-		fogEnd = 1.0f;
-
-		for(int i = 0; i < TEXTURE_IMAGE_UNITS; i++) textureWrap[i] = 0;
-		for(int i = 0; i < 8; i++) texGen[i] = TEXGEN_PASSTHRU;
-		for(int i = 0; i < 8; i++) textureTransformCount[i] = 0;
-		for(int i = 0; i < 8; i++) textureTransformProject[i] = false;
-		textureWrapActive = false;
-		localViewer = true;
-		normalizeNormals = false;
-
 		for(int i = 0; i < RENDERTARGETS; ++i)
 		{
 			renderTarget[i] = nullptr;
@@ -245,17 +192,8 @@
 		stencilZFailOperationCCW = OPERATION_KEEP;
 		stencilWriteMaskCCW = 0xFFFFFFFF;
 
-		setGlobalMipmapBias(0);
-
-		lightingEnable = true;
-		specularEnable = false;
-		for(int i = 0; i < 8; i++) lightEnable[i] = false;
-		for(int i = 0; i < 8; i++) worldLightPosition[i] = 0;
-
 		alphaCompareMode = ALPHA_ALWAYS;
 		alphaTestEnable = false;
-		fillMode = FILL_SOLID;
-		shadingMode = SHADING_GOURAUD;
 
 		rasterizerDiscard = false;
 
@@ -285,23 +223,8 @@
 			colorWriteMask[i] = 0x0000000F;
 		}
 
-		ambientMaterialSource = MATERIAL_MATERIAL;
-		diffuseMaterialSource = MATERIAL_COLOR1;
-		specularMaterialSource = MATERIAL_COLOR2;
-		emissiveMaterialSource = MATERIAL_MATERIAL;
-		colorVertexEnable = true;
-
-		fogEnable = false;
-		pixelFogMode = FOG_NONE;
-		vertexFogMode = FOG_NONE;
-		wBasedFog = false;
-		rangeFogEnable = false;
-
-		indexedVertexBlendEnable = false;
-		vertexBlendMatrixCount = 0;
-
-		pixelShader = 0;
-		vertexShader = 0;
+		pixelShader = nullptr;
+		vertexShader = nullptr;
 
 		instanceID = 0;
 
@@ -309,8 +232,6 @@
 		transformFeedbackQueryEnabled = false;
 		transformFeedbackEnabled = 0;
 
-		pointSpriteEnable = false;
-		pointScaleEnable = false;
 		lineWidth = 1.0f;
 
 		writeSRGB = false;
@@ -320,71 +241,6 @@
 		logicalOperation = LOGICALOP_COPY;
 	}
 
-	const float &Context::exp2Bias()
-	{
-		return bias;
-	}
-
-	const Point &Context::getLightPosition(int light)
-	{
-		return worldLightPosition[light];
-	}
-
-	void Context::setGlobalMipmapBias(float bias)
-	{
-		this->bias = exp2(bias + 0.5f);
-	}
-
-	void Context::setLightingEnable(bool lightingEnable)
-	{
-		this->lightingEnable = lightingEnable;
-	}
-
-	void Context::setSpecularEnable(bool specularEnable)
-	{
-		Context::specularEnable = specularEnable;
-	}
-
-	void Context::setLightEnable(int light, bool lightEnable)
-	{
-		Context::lightEnable[light] = lightEnable;
-	}
-
-	void Context::setLightPosition(int light, Point worldLightPosition)
-	{
-		Context::worldLightPosition[light] = worldLightPosition;
-	}
-
-	void Context::setAmbientMaterialSource(MaterialSource ambientMaterialSource)
-	{
-		Context::ambientMaterialSource = ambientMaterialSource;
-	}
-
-	void Context::setDiffuseMaterialSource(MaterialSource diffuseMaterialSource)
-	{
-		Context::diffuseMaterialSource = diffuseMaterialSource;
-	}
-
-	void Context::setSpecularMaterialSource(MaterialSource specularMaterialSource)
-	{
-		Context::specularMaterialSource = specularMaterialSource;
-	}
-
-	void Context::setEmissiveMaterialSource(MaterialSource emissiveMaterialSource)
-	{
-		Context::emissiveMaterialSource = emissiveMaterialSource;
-	}
-
-	void Context::setPointSpriteEnable(bool pointSpriteEnable)
-	{
-		Context::pointSpriteEnable = pointSpriteEnable;
-	}
-
-	void Context::setPointScaleEnable(bool pointScaleEnable)
-	{
-		Context::pointScaleEnable = pointScaleEnable;
-	}
-
 	bool Context::setDepthBufferEnable(bool depthBufferEnable)
 	{
 		bool modified = (Context::depthBufferEnable != depthBufferEnable);
@@ -476,40 +332,6 @@
 		return modified;
 	}
 
-	void Context::setColorVertexEnable(bool colorVertexEnable)
-	{
-		Context::colorVertexEnable = colorVertexEnable;
-	}
-
-	bool Context::fogActive()
-	{
-		if(!colorUsed()) return false;
-
-		if(pixelShaderModel() >= 0x0300) return false;
-
-		return fogEnable;
-	}
-
-	bool Context::pointSizeActive()
-	{
-		if(vertexShader)
-		{
-			return false;
-		}
-
-		return isDrawPoint(true) && (input[PointSize] || (!preTransformed && pointScaleActive()));
-	}
-
-	FogMode Context::pixelFogActive()
-	{
-		if(fogActive())
-		{
-			return pixelFogMode;
-		}
-
-		return FOG_NONE;
-	}
-
 	bool Context::depthWriteActive()
 	{
 		if(!depthBufferActive()) return false;
@@ -537,213 +359,6 @@
 		return stencilBuffer && stencilEnable;
 	}
 
-	bool Context::vertexLightingActive()
-	{
-		if(vertexShader)
-		{
-			return false;
-		}
-
-		return lightingEnable && !preTransformed;
-	}
-
-	bool Context::texCoordActive(int coordinate, int component)
-	{
-		bool hasTexture = pointSpriteActive();
-
-		if(vertexShader)
-		{
-			if(!preTransformed)
-			{
-				if(vertexShader->getOutput(T0 + coordinate, component).usage == Shader::USAGE_TEXCOORD)
-				{
-					hasTexture = true;
-				}
-			}
-			else
-			{
-				hasTexture = true;   // FIXME: Check vertex buffer streams
-			}
-		}
-		else
-		{
-			switch(texGen[coordinate])
-			{
-			case TEXGEN_NONE:
-				hasTexture = true;
-				break;
-			case TEXGEN_PASSTHRU:
-				hasTexture = hasTexture || (component < input[TexCoord0 + textureStage[coordinate].texCoordIndex].count);
-				break;
-			case TEXGEN_NORMAL:
-				hasTexture = hasTexture || (component <= 2);
-				break;
-			case TEXGEN_POSITION:
-				hasTexture = hasTexture || (component <= 2);
-				break;
-			case TEXGEN_REFLECTION:
-				hasTexture = hasTexture || (component <= 2);
-				break;
-			case TEXGEN_SPHEREMAP:
-				hasTexture = hasTexture || (component <= 1);
-				break;
-			default:
-				ASSERT(false);
-			}
-		}
-
-		bool project = isProjectionComponent(coordinate, component);
-		bool usesTexture = false;
-
-		if(pixelShader)
-		{
-			usesTexture = pixelShader->usesTexture(coordinate, component) || project;
-		}
-		else
-		{
-			usesTexture = textureStage[coordinate].usesTexture() || project;
-		}
-
-		return hasTexture && usesTexture;
-	}
-
-	bool Context::texCoordActive(int coordinate)
-	{
-		return texCoordActive(coordinate, 0) ||
-		       texCoordActive(coordinate, 1) ||
-		       texCoordActive(coordinate, 2) ||
-		       texCoordActive(coordinate, 3);
-	}
-
-	bool Context::isProjectionComponent(unsigned int coordinate, int component)
-	{
-		if(pixelShaderModel() <= 0x0103 && coordinate < 8 && textureTransformProject[coordinate])
-		{
-			if(textureTransformCount[coordinate] == 2)
-			{
-				if(component == 1) return true;
-			}
-			else if(textureTransformCount[coordinate] == 3)
-			{
-				if(component == 2) return true;
-			}
-			else if(textureTransformCount[coordinate] == 4 || textureTransformCount[coordinate] == 0)
-			{
-				if(component == 3) return true;
-			}
-		}
-
-		return false;
-	}
-
-	bool Context::vertexSpecularActive()
-	{
-		return vertexLightingActive() && specularEnable && vertexNormalActive();
-	}
-
-	bool Context::vertexNormalActive()
-	{
-		if(vertexShader)
-		{
-			return false;
-		}
-
-		return input[Normal];
-	}
-
-	bool Context::vertexLightActive(int i)
-	{
-		if(vertexShader)
-		{
-			return false;
-		}
-
-		return lightingEnable && lightEnable[i];
-	}
-
-	MaterialSource Context::vertexDiffuseMaterialSourceActive()
-	{
-		if(vertexShader)
-		{
-			return MATERIAL_MATERIAL;
-		}
-
-		if(diffuseMaterialSource == MATERIAL_MATERIAL || !colorVertexEnable ||
-		   (diffuseMaterialSource == MATERIAL_COLOR1 && !input[Color0]) ||
-		   (diffuseMaterialSource == MATERIAL_COLOR2 && !input[Color1]))
-		{
-			return MATERIAL_MATERIAL;
-		}
-
-		return diffuseMaterialSource;
-	}
-
-	MaterialSource Context::vertexSpecularMaterialSourceActive()
-	{
-		if(vertexShader)
-		{
-			return MATERIAL_MATERIAL;
-		}
-
-		if(!colorVertexEnable ||
-		   (specularMaterialSource == MATERIAL_COLOR1 && !input[Color0]) ||
-		   (specularMaterialSource == MATERIAL_COLOR2 && !input[Color1]))
-		{
-			return MATERIAL_MATERIAL;
-		}
-
-		return specularMaterialSource;
-	}
-
-	MaterialSource Context::vertexAmbientMaterialSourceActive()
-	{
-		if(vertexShader)
-		{
-			return MATERIAL_MATERIAL;
-		}
-
-		if(!colorVertexEnable ||
-		   (ambientMaterialSource == MATERIAL_COLOR1 && !input[Color0]) ||
-		   (ambientMaterialSource == MATERIAL_COLOR2 && !input[Color1]))
-		{
-			return MATERIAL_MATERIAL;
-		}
-
-		return ambientMaterialSource;
-	}
-
-	MaterialSource Context::vertexEmissiveMaterialSourceActive()
-	{
-		if(vertexShader)
-		{
-			return MATERIAL_MATERIAL;
-		}
-
-		if(!colorVertexEnable ||
-		   (emissiveMaterialSource == MATERIAL_COLOR1 && !input[Color0]) ||
-		   (emissiveMaterialSource == MATERIAL_COLOR2 && !input[Color1]))
-		{
-			return MATERIAL_MATERIAL;
-		}
-
-		return emissiveMaterialSource;
-	}
-
-	bool Context::pointSpriteActive()
-	{
-		return isDrawPoint(true) && pointSpriteEnable;
-	}
-
-	bool Context::pointScaleActive()
-	{
-		if(vertexShader)
-		{
-			return false;
-		}
-
-		return isDrawPoint(true) && pointScaleEnable;
-	}
-
 	bool Context::alphaBlendActive()
 	{
 		if(!alphaBlendEnable)
@@ -1090,96 +705,6 @@
 		}
 	}
 
-	bool Context::indexedVertexBlendActive()
-	{
-		if(vertexShader)
-		{
-			return false;
-		}
-
-		return indexedVertexBlendEnable;
-	}
-
-	int Context::vertexBlendMatrixCountActive()
-	{
-		if(vertexShader)
-		{
-			return 0;
-		}
-
-		return vertexBlendMatrixCount;
-	}
-
-	bool Context::localViewerActive()
-	{
-		if(vertexShader)
-		{
-			return false;
-		}
-
-		return localViewer;
-	}
-
-	bool Context::normalizeNormalsActive()
-	{
-		if(vertexShader)
-		{
-			return false;
-		}
-
-		return normalizeNormals;
-	}
-
-	FogMode Context::vertexFogModeActive()
-	{
-		if(vertexShader || !fogActive())
-		{
-			return FOG_NONE;
-		}
-
-		return vertexFogMode;
-	}
-
-	bool Context::rangeFogActive()
-	{
-		if(vertexShader || !fogActive())
-		{
-			return false;
-		}
-
-		return rangeFogEnable;
-	}
-
-	TexGen Context::texGenActive(int stage)
-	{
-		if(vertexShader || !texCoordActive(stage))
-		{
-			return TEXGEN_PASSTHRU;
-		}
-
-		return texGen[stage];
-	}
-
-	int Context::textureTransformCountActive(int stage)
-	{
-		if(vertexShader || !texCoordActive(stage))
-		{
-			return 0;
-		}
-
-		return textureTransformCount[stage];
-	}
-
-	int Context::texCoordIndexActive(int stage)
-	{
-		if(vertexShader || !texCoordActive(stage))
-		{
-			return stage;
-		}
-
-		return textureStage[stage].texCoordIndex;
-	}
-
 	bool Context::perspectiveActive()
 	{
 		if(!colorUsed())
@@ -1192,7 +717,7 @@
 			return false;
 		}
 
-		if(isDrawPoint(true))
+		if(isDrawPoint())
 		{
 			return false;
 		}
@@ -1200,242 +725,6 @@
 		return true;
 	}
 
-	bool Context::diffuseUsed()
-	{
-		return diffuseUsed(0) || diffuseUsed(1) || diffuseUsed(2) || diffuseUsed(3);
-	}
-
-	bool Context::diffuseUsed(int component)
-	{
-		if(!colorUsed())
-		{
-			return false;
-		}
-
-		if(pixelShader)
-		{
-			return pixelShader->usesDiffuse(component);
-		}
-
-		// Directly using the diffuse input color
-		for(int i = 0; i < 8; i++)
-		{
-			if(textureStage[i].isStageDisabled())
-			{
-				break;
-			}
-
-			if(textureStage[i].usesDiffuse())
-			{
-				return true;
-			}
-		}
-
-		// Using the current color (initialized to diffuse) before it's overwritten
-		for(int i = 0; i < 8; i++)
-		{
-			if(textureStage[i].usesCurrent() || textureStage[i].isStageDisabled())   // Current color contains diffuse before being overwritten
-			{
-				return true;
-			}
-
-			if(textureStage[i].writesCurrent())
-			{
-				return false;
-			}
-		}
-
-		return true;
-	}
-
-	bool Context::diffuseActive()
-	{
-		return diffuseActive(0) || diffuseActive(1) || diffuseActive(2) || diffuseActive(3);
-	}
-
-	bool Context::diffuseActive(int component)
-	{
-		if(!colorUsed())
-		{
-			return false;
-		}
-
-		// Vertex processor provides diffuse component
-		bool vertexDiffuse;
-
-		if(vertexShader)
-		{
-			vertexDiffuse = vertexShader->getOutput(C0, component).active();
-		}
-		else if(!preTransformed)
-		{
-			vertexDiffuse = input[Color0] || lightingEnable;
-		}
-		else
-		{
-			vertexDiffuse = input[Color0];
-		}
-
-		// Pixel processor requires diffuse component
-		bool pixelDiffuse = diffuseUsed(component);
-
-		return vertexDiffuse && pixelDiffuse;
-	}
-
-	bool Context::specularUsed()
-	{
-		return Context::specularUsed(0) || Context::specularUsed(1) || Context::specularUsed(2) || Context::specularUsed(3);
-	}
-
-	bool Context::specularUsed(int component)
-	{
-		if(!colorUsed())
-		{
-			return false;
-		}
-
-		if(pixelShader)
-		{
-			return pixelShader->usesSpecular(component);
-		}
-
-		bool pixelSpecular = specularEnable;
-
-		for(int i = 0; i < 8; i++)
-		{
-			if(textureStage[i].isStageDisabled()) break;
-
-			pixelSpecular = pixelSpecular || textureStage[i].usesSpecular();
-		}
-
-		return pixelSpecular;
-	}
-
-	bool Context::specularActive()
-	{
-		return specularActive(0) || specularActive(1) || specularActive(2) || specularActive(3);
-	}
-
-	bool Context::specularActive(int component)
-	{
-		if(!colorUsed())
-		{
-			return false;
-		}
-
-		// Vertex processor provides specular component
-		bool vertexSpecular;
-
-		if(!vertexShader)
-		{
-			vertexSpecular = input[Color1] || (lightingEnable && specularEnable);
-		}
-		else
-		{
-			vertexSpecular = vertexShader->getOutput(C1, component).active();
-		}
-
-		// Pixel processor requires specular component
-		bool pixelSpecular = specularUsed(component);
-
-		return vertexSpecular && pixelSpecular;
-	}
-
-	bool Context::colorActive(int color, int component)
-	{
-		if(color == 0)
-		{
-			return diffuseActive(component);
-		}
-		else
-		{
-			return specularActive(component);
-		}
-	}
-
-	bool Context::textureActive()
-	{
-		for(int i = 0; i < 8; i++)
-		{
-			if(textureActive(i))
-			{
-				return true;
-			}
-		}
-
-		return false;
-	}
-
-	bool Context::textureActive(int coordinate)
-	{
-		return textureActive(coordinate, 0) || textureActive(coordinate, 1) || textureActive(coordinate, 2) || textureActive(coordinate, 3);
-	}
-
-	bool Context::textureActive(int coordinate, int component)
-	{
-		if(!colorUsed())
-		{
-			return false;
-		}
-
-		if(!texCoordActive(coordinate, component))
-		{
-			return false;
-		}
-
-		if(textureTransformProject[coordinate] && pixelShaderModel() <= 0x0103)
-		{
-			if(textureTransformCount[coordinate] == 2)
-			{
-				if(component == 1) return true;
-			}
-			else if(textureTransformCount[coordinate] == 3)
-			{
-				if(component == 2) return true;
-			}
-			else if(textureTransformCount[coordinate] == 4 || textureTransformCount[coordinate] == 0)
-			{
-				if(component == 3) return true;
-			}
-		}
-
-		if(!pixelShader)
-		{
-			bool texture = textureStage[coordinate].usesTexture();
-			bool cube = sampler[coordinate].hasCubeTexture();
-			bool volume = sampler[coordinate].hasVolumeTexture();
-
-			if(texture)
-			{
-				for(int i = coordinate; i >= 0; i--)
-				{
-					if(textureStage[i].stageOperation == TextureStage::STAGE_DISABLE)
-					{
-						return false;
-					}
-				}
-			}
-
-			switch(component)
-			{
-			case 0:
-				return texture;
-			case 1:
-				return texture;
-			case 2:
-				return (texture && (cube || volume));
-			case 3:
-				return false;
-			}
-		}
-		else
-		{
-			return pixelShader->usesTexture(coordinate, component);
-		}
-
-		return false;
-	}
-
 	unsigned short Context::pixelShaderModel() const
 	{
 		return pixelShader ? pixelShader->getShaderModel() : 0x0000;
@@ -1451,11 +740,6 @@
 		return renderTarget[0] ? renderTarget[0]->getMultiSampleCount() : 1;
 	}
 
-	int Context::getSuperSampleCount() const
-	{
-		return renderTarget[0] ? renderTarget[0]->getSuperSampleCount() : 1;
-	}
-
 	Format Context::renderTargetInternalFormat(int index)
 	{
 		if(renderTarget[index])
diff --git a/src/Device/Context.hpp b/src/Device/Context.hpp
index 6ad2aef..64bd0d5 100644
--- a/src/Device/Context.hpp
+++ b/src/Device/Context.hpp
@@ -16,7 +16,6 @@
 #define sw_Context_hpp
 
 #include "Sampler.hpp"
-#include "TextureStage.hpp"
 #include "Stream.hpp"
 #include "Point.hpp"
 #include "Vertex.hpp"
@@ -60,29 +59,17 @@
 		DRAW_POINTLIST     = 0x00,
 		DRAW_LINELIST      = 0x01,
 		DRAW_LINESTRIP     = 0x02,
-		DRAW_LINELOOP      = 0x03,
-		DRAW_TRIANGLELIST  = 0x04,
-		DRAW_TRIANGLESTRIP = 0x05,
-		DRAW_TRIANGLEFAN   = 0x06,
-		DRAW_QUADLIST      = 0x07,
+		DRAW_TRIANGLELIST  = 0x03,
+		DRAW_TRIANGLESTRIP = 0x04,
+		DRAW_TRIANGLEFAN   = 0x05,
 
 		DRAW_NONINDEXED = 0x00,
-		DRAW_INDEXED8   = 0x10,
 		DRAW_INDEXED16  = 0x20,
 		DRAW_INDEXED32  = 0x30,
 
-		DRAW_INDEXEDPOINTLIST8 = DRAW_POINTLIST | DRAW_INDEXED8,
-		DRAW_INDEXEDLINELIST8  = DRAW_LINELIST  | DRAW_INDEXED8,
-		DRAW_INDEXEDLINESTRIP8 = DRAW_LINESTRIP | DRAW_INDEXED8,
-		DRAW_INDEXEDLINELOOP8  = DRAW_LINELOOP  | DRAW_INDEXED8,
-		DRAW_INDEXEDTRIANGLELIST8  = DRAW_TRIANGLELIST  | DRAW_INDEXED8,
-		DRAW_INDEXEDTRIANGLESTRIP8 = DRAW_TRIANGLESTRIP | DRAW_INDEXED8,
-		DRAW_INDEXEDTRIANGLEFAN8   = DRAW_TRIANGLEFAN   | DRAW_INDEXED8,
-
 		DRAW_INDEXEDPOINTLIST16 = DRAW_POINTLIST | DRAW_INDEXED16,
 		DRAW_INDEXEDLINELIST16  = DRAW_LINELIST  | DRAW_INDEXED16,
 		DRAW_INDEXEDLINESTRIP16 = DRAW_LINESTRIP | DRAW_INDEXED16,
-		DRAW_INDEXEDLINELOOP16  = DRAW_LINELOOP  | DRAW_INDEXED16,
 		DRAW_INDEXEDTRIANGLELIST16  = DRAW_TRIANGLELIST  | DRAW_INDEXED16,
 		DRAW_INDEXEDTRIANGLESTRIP16 = DRAW_TRIANGLESTRIP | DRAW_INDEXED16,
 		DRAW_INDEXEDTRIANGLEFAN16   = DRAW_TRIANGLEFAN   | DRAW_INDEXED16,
@@ -90,7 +77,6 @@
 		DRAW_INDEXEDPOINTLIST32 = DRAW_POINTLIST | DRAW_INDEXED32,
 		DRAW_INDEXEDLINELIST32  = DRAW_LINELIST  | DRAW_INDEXED32,
 		DRAW_INDEXEDLINESTRIP32 = DRAW_LINESTRIP | DRAW_INDEXED32,
-		DRAW_INDEXEDLINELOOP32  = DRAW_LINELOOP  | DRAW_INDEXED32,
 		DRAW_INDEXEDTRIANGLELIST32  = DRAW_TRIANGLELIST  | DRAW_INDEXED32,
 		DRAW_INDEXEDTRIANGLESTRIP32 = DRAW_TRIANGLESTRIP | DRAW_INDEXED32,
 		DRAW_INDEXEDTRIANGLEFAN32   = DRAW_TRIANGLEFAN   | DRAW_INDEXED32,
@@ -98,23 +84,6 @@
 		DRAW_LAST = DRAW_INDEXEDTRIANGLEFAN32
 	};
 
-	enum FillMode ENUM_UNDERLYING_TYPE_UNSIGNED_INT
-	{
-		FILL_SOLID,
-		FILL_WIREFRAME,
-		FILL_VERTEX,
-
-		FILL_LAST = FILL_VERTEX
-	};
-
-	enum ShadingMode ENUM_UNDERLYING_TYPE_UNSIGNED_INT
-	{
-		SHADING_FLAT,
-		SHADING_GOURAUD,
-
-		SHADING_LAST = SHADING_GOURAUD
-	};
-
 	enum DepthCompareMode ENUM_UNDERLYING_TYPE_UNSIGNED_INT
 	{
 		DEPTH_ALWAYS,
@@ -238,37 +207,6 @@
 		LOGICALOP_LAST = LOGICALOP_OR_INVERTED
 	};
 
-	enum MaterialSource ENUM_UNDERLYING_TYPE_UNSIGNED_INT
-	{
-		MATERIAL_MATERIAL,
-		MATERIAL_COLOR1,
-		MATERIAL_COLOR2,
-
-		MATERIAL_LAST = MATERIAL_COLOR2
-	};
-
-	enum FogMode ENUM_UNDERLYING_TYPE_UNSIGNED_INT
-	{
-		FOG_NONE,
-		FOG_LINEAR,
-		FOG_EXP,
-		FOG_EXP2,
-
-		FOG_LAST = FOG_EXP2
-	};
-
-	enum TexGen ENUM_UNDERLYING_TYPE_UNSIGNED_INT
-	{
-		TEXGEN_PASSTHRU,
-		TEXGEN_NORMAL,
-		TEXGEN_POSITION,
-		TEXGEN_REFLECTION,
-		TEXGEN_SPHEREMAP,
-		TEXGEN_NONE,
-
-		TEXGEN_LAST = TEXGEN_NONE
-	};
-
 	enum TransparencyAntialiasing ENUM_UNDERLYING_TYPE_UNSIGNED_INT
 	{
 		TRANSPARENCY_NONE,
@@ -287,34 +225,12 @@
 		void *operator new(size_t bytes);
 		void operator delete(void *pointer, size_t bytes);
 
-		bool isDrawPoint(bool fillModeAware = false) const;
-		bool isDrawLine(bool fillModeAware = false) const;
-		bool isDrawTriangle(bool fillModeAware = false) const;
-
 		void init();
 
-		const float &exp2Bias();   // NOTE: Needs address for JIT
+		bool isDrawPoint() const;
+		bool isDrawLine() const;
+		bool isDrawTriangle() const;
 
-		const Point &getLightPosition(int light);
-
-		void setGlobalMipmapBias(float bias);
-
-		// Set fixed-function vertex pipeline states
-		void setLightingEnable(bool lightingEnable);
-		void setSpecularEnable(bool specularEnable);
-		void setLightEnable(int light, bool lightEnable);
-		void setLightPosition(int light, Point worldLightPosition);
-
-		void setColorVertexEnable(bool colorVertexEnable);
-		void setAmbientMaterialSource(MaterialSource ambientMaterialSource);
-		void setDiffuseMaterialSource(MaterialSource diffuseMaterialSource);
-		void setSpecularMaterialSource(MaterialSource specularMaterialSource);
-		void setEmissiveMaterialSource(MaterialSource emissiveMaterialSource);
-
-		void setPointSpriteEnable(bool pointSpriteEnable);
-		void setPointScaleEnable(bool pointScaleEnable);
-
-		// Set fixed-function pixel pipeline states, return true when modified
 		bool setDepthBufferEnable(bool depthBufferEnable);
 
 		bool setAlphaBlendEnable(bool alphaBlendEnable);
@@ -333,10 +249,6 @@
 		bool setColorLogicOpEnabled(bool colorLogicOpEnabled);
 		bool setLogicalOperation(LogicalOperation logicalOperation);
 
-		// Active fixed-function pixel pipeline states
-		bool fogActive();
-		bool pointSizeActive();
-		FogMode pixelFogActive();
 		bool depthWriteActive();
 		bool alphaTestActive();
 		bool depthBufferActive();
@@ -344,24 +256,6 @@
 
 		bool perspectiveActive();
 
-		// Active fixed-function vertex pipeline states
-		bool vertexLightingActive();
-		bool texCoordActive(int coordinate, int component);
-		bool texCoordActive(int coordinate);
-		bool isProjectionComponent(unsigned int coordinate, int component);
-		bool vertexSpecularInputActive();
-		bool vertexSpecularActive();
-		bool vertexNormalActive();
-		bool vertexLightActive();
-		bool vertexLightActive(int i);
-		MaterialSource vertexDiffuseMaterialSourceActive();
-		MaterialSource vertexSpecularMaterialSourceActive();
-		MaterialSource vertexAmbientMaterialSourceActive();
-		MaterialSource vertexEmissiveMaterialSourceActive();
-
-		bool pointSpriteActive();
-		bool pointScaleActive();
-
 		bool alphaBlendActive();
 		BlendFactor sourceBlendFactor();
 		BlendFactor destBlendFactor();
@@ -372,38 +266,11 @@
 		BlendOperation blendOperationAlpha();
 
 		LogicalOperation colorLogicOp();
-		LogicalOperation indexLogicOp();
-
-		bool indexedVertexBlendActive();
-		int vertexBlendMatrixCountActive();
-		bool localViewerActive();
-		bool normalizeNormalsActive();
-		FogMode vertexFogModeActive();
-		bool rangeFogActive();
-
-		TexGen texGenActive(int stage);
-		int textureTransformCountActive(int stage);
-		int texCoordIndexActive(int stage);
-
-		// Active context states
-		bool diffuseUsed();     // Used by pixel processor but not provided by vertex processor
-		bool diffuseUsed(int component);     // Used by pixel processor but not provided by vertex processor
-		bool diffuseActive();
-		bool diffuseActive(int component);
-		bool specularUsed();
-		bool specularUsed(int component);
-		bool specularActive();
-		bool specularActive(int component);
-		bool colorActive(int color, int component);
-		bool textureActive();
-		bool textureActive(int coordinate);
-		bool textureActive(int coordinate, int component);
 
 		unsigned short pixelShaderModel() const;
 		unsigned short vertexShaderModel() const;
 
 		int getMultiSampleCount() const;
-		int getSuperSampleCount() const;
 
 		DrawType drawType;
 
@@ -428,8 +295,6 @@
 		// Pixel processor states
 		AlphaCompareMode alphaCompareMode;
 		bool alphaTestEnable;
-		FillMode fillMode;
-		ShadingMode shadingMode;
 
 		CullMode cullMode;
 		bool frontFacingCCW;
@@ -438,7 +303,6 @@
 		float depthBias;
 		float slopeDepthBias;
 
-		TextureStage textureStage[8];
 		Sampler sampler[TOTAL_IMAGE_UNITS];
 
 		Format renderTargetInternalFormat(int index);
@@ -450,21 +314,6 @@
 		Stream input[MAX_VERTEX_INPUTS];
 		Resource *indexBuffer;
 
-		bool preTransformed;   // FIXME: Private
-
-		float fogStart;
-		float fogEnd;
-
-		void computeIllumination();
-
-		bool textureWrapActive;
-		unsigned char textureWrap[TEXTURE_IMAGE_UNITS];
-		TexGen texGen[8];
-		bool localViewer;
-		bool normalizeNormals;
-		int textureTransformCount[8];
-		bool textureTransformProject[8];
-
 		Surface *renderTarget[RENDERTARGETS];
 		unsigned int renderTargetLayer[RENDERTARGETS];
 		Surface *depthBuffer;
@@ -472,39 +321,13 @@
 		Surface *stencilBuffer;
 		unsigned int stencilBufferLayer;
 
-		// Fog
-		bool fogEnable;
-		FogMode pixelFogMode;
-		FogMode vertexFogMode;
-		bool wBasedFog;
-		bool rangeFogEnable;
-
-		// Vertex blending
-		bool indexedVertexBlendEnable;
-		int vertexBlendMatrixCount;
-
 		// Shaders
 		const PixelShader *pixelShader;
 		const VertexShader *vertexShader;
 
-		// Global mipmap bias
-		float bias;
-
 		// Instancing
 		int instanceID;
 
-		// Fixed-function vertex pipeline state
-		bool lightingEnable;
-		bool specularEnable;
-		bool lightEnable[8];
-		Point worldLightPosition[8];
-
-		MaterialSource ambientMaterialSource;
-		MaterialSource diffuseMaterialSource;
-		MaterialSource specularMaterialSource;
-		MaterialSource emissiveMaterialSource;
-		bool colorVertexEnable;
-
 		bool occlusionEnabled;
 		bool transformFeedbackQueryEnabled;
 		uint64_t transformFeedbackEnabled;
@@ -525,8 +348,6 @@
 		BlendFactor destBlendFactorStateAlpha;
 		BlendOperation blendOperationStateAlpha;
 
-		bool pointSpriteEnable;
-		bool pointScaleEnable;
 		float lineWidth;
 
 		int colorWriteMask[RENDERTARGETS];   // RGBA
diff --git a/src/Device/PixelProcessor.cpp b/src/Device/PixelProcessor.cpp
index 4ee287d..79d3d63 100644
--- a/src/Device/PixelProcessor.cpp
+++ b/src/Device/PixelProcessor.cpp
@@ -16,7 +16,6 @@
 
 #include "Surface.hpp"
 #include "Primitive.hpp"
-#include "Pipeline/PixelPipeline.hpp"
 #include "Pipeline/PixelProgram.hpp"
 #include "Pipeline/PixelShader.hpp"
 #include "Pipeline/Constants.hpp"
@@ -68,18 +67,14 @@
 
 	PixelProcessor::PixelProcessor(Context *context) : context(context)
 	{
-		setGlobalMipmapBias(0.0f);   // Round to highest LOD [0.5, 1.0]: -0.5
-		                             // Round to nearest LOD [0.7, 1.4]:  0.0
-		                             // Round to lowest LOD  [1.0, 2.0]:  0.5
-
-		routineCache = 0;
+		routineCache = nullptr;
 		setRoutineCacheSize(1024);
 	}
 
 	PixelProcessor::~PixelProcessor()
 	{
 		delete routineCache;
-		routineCache = 0;
+		routineCache = nullptr;
 	}
 
 	void PixelProcessor::setFloatConstant(unsigned int index, const float value[4])
@@ -92,35 +87,6 @@
 			c[index][3] = value[3];
 		}
 		else ASSERT(false);
-
-		if(index < 8)   // ps_1_x constants
-		{
-			// FIXME: Compact into generic function
-			short x = iround(4095 * clamp(value[0], -1.0f, 1.0f));
-			short y = iround(4095 * clamp(value[1], -1.0f, 1.0f));
-			short z = iround(4095 * clamp(value[2], -1.0f, 1.0f));
-			short w = iround(4095 * clamp(value[3], -1.0f, 1.0f));
-
-			cW[index][0][0] = x;
-			cW[index][0][1] = x;
-			cW[index][0][2] = x;
-			cW[index][0][3] = x;
-
-			cW[index][1][0] = y;
-			cW[index][1][1] = y;
-			cW[index][1][2] = y;
-			cW[index][1][3] = y;
-
-			cW[index][2][0] = z;
-			cW[index][2][1] = z;
-			cW[index][2][2] = z;
-			cW[index][2][3] = z;
-
-			cW[index][3][0] = w;
-			cW[index][3][1] = w;
-			cW[index][3][2] = w;
-			cW[index][3][3] = w;
-		}
 	}
 
 	void PixelProcessor::setIntegerConstant(unsigned int index, const int value[4])
@@ -177,186 +143,6 @@
 		context->stencilBufferLayer = layer;
 	}
 
-	void PixelProcessor::setTexCoordIndex(unsigned int stage, int texCoordIndex)
-	{
-		if(stage < 8)
-		{
-			context->textureStage[stage].setTexCoordIndex(texCoordIndex);
-		}
-		else ASSERT(false);
-	}
-
-	void PixelProcessor::setStageOperation(unsigned int stage, TextureStage::StageOperation stageOperation)
-	{
-		if(stage < 8)
-		{
-			context->textureStage[stage].setStageOperation(stageOperation);
-		}
-		else ASSERT(false);
-	}
-
-	void PixelProcessor::setFirstArgument(unsigned int stage, TextureStage::SourceArgument firstArgument)
-	{
-		if(stage < 8)
-		{
-			context->textureStage[stage].setFirstArgument(firstArgument);
-		}
-		else ASSERT(false);
-	}
-
-	void PixelProcessor::setSecondArgument(unsigned int stage, TextureStage::SourceArgument secondArgument)
-	{
-		if(stage < 8)
-		{
-			context->textureStage[stage].setSecondArgument(secondArgument);
-		}
-		else ASSERT(false);
-	}
-
-	void PixelProcessor::setThirdArgument(unsigned int stage, TextureStage::SourceArgument thirdArgument)
-	{
-		if(stage < 8)
-		{
-			context->textureStage[stage].setThirdArgument(thirdArgument);
-		}
-		else ASSERT(false);
-	}
-
-	void PixelProcessor::setStageOperationAlpha(unsigned int stage, TextureStage::StageOperation stageOperationAlpha)
-	{
-		if(stage < 8)
-		{
-			context->textureStage[stage].setStageOperationAlpha(stageOperationAlpha);
-		}
-		else ASSERT(false);
-	}
-
-	void PixelProcessor::setFirstArgumentAlpha(unsigned int stage, TextureStage::SourceArgument firstArgumentAlpha)
-	{
-		if(stage < 8)
-		{
-			context->textureStage[stage].setFirstArgumentAlpha(firstArgumentAlpha);
-		}
-		else ASSERT(false);
-	}
-
-	void PixelProcessor::setSecondArgumentAlpha(unsigned int stage, TextureStage::SourceArgument secondArgumentAlpha)
-	{
-		if(stage < 8)
-		{
-			context->textureStage[stage].setSecondArgumentAlpha(secondArgumentAlpha);
-		}
-		else ASSERT(false);
-	}
-
-	void PixelProcessor::setThirdArgumentAlpha(unsigned int stage, TextureStage::SourceArgument thirdArgumentAlpha)
-	{
-		if(stage < 8)
-		{
-			context->textureStage[stage].setThirdArgumentAlpha(thirdArgumentAlpha);
-		}
-		else ASSERT(false);
-	}
-
-	void PixelProcessor::setFirstModifier(unsigned int stage, TextureStage::ArgumentModifier firstModifier)
-	{
-		if(stage < 8)
-		{
-			context->textureStage[stage].setFirstModifier(firstModifier);
-		}
-		else ASSERT(false);
-	}
-
-	void PixelProcessor::setSecondModifier(unsigned int stage, TextureStage::ArgumentModifier secondModifier)
-	{
-		if(stage < 8)
-		{
-			context->textureStage[stage].setSecondModifier(secondModifier);
-		}
-		else ASSERT(false);
-	}
-
-	void PixelProcessor::setThirdModifier(unsigned int stage, TextureStage::ArgumentModifier thirdModifier)
-	{
-		if(stage < 8)
-		{
-			context->textureStage[stage].setThirdModifier(thirdModifier);
-		}
-		else ASSERT(false);
-	}
-
-	void PixelProcessor::setFirstModifierAlpha(unsigned int stage, TextureStage::ArgumentModifier firstModifierAlpha)
-	{
-		if(stage < 8)
-		{
-			context->textureStage[stage].setFirstModifierAlpha(firstModifierAlpha);
-		}
-		else ASSERT(false);
-	}
-
-	void PixelProcessor::setSecondModifierAlpha(unsigned int stage, TextureStage::ArgumentModifier secondModifierAlpha)
-	{
-		if(stage < 8)
-		{
-			context->textureStage[stage].setSecondModifierAlpha(secondModifierAlpha);
-		}
-		else ASSERT(false);
-	}
-
-	void PixelProcessor::setThirdModifierAlpha(unsigned int stage, TextureStage::ArgumentModifier thirdModifierAlpha)
-	{
-		if(stage < 8)
-		{
-			context->textureStage[stage].setThirdModifierAlpha(thirdModifierAlpha);
-		}
-		else ASSERT(false);
-	}
-
-	void PixelProcessor::setDestinationArgument(unsigned int stage, TextureStage::DestinationArgument destinationArgument)
-	{
-		if(stage < 8)
-		{
-			context->textureStage[stage].setDestinationArgument(destinationArgument);
-		}
-		else ASSERT(false);
-	}
-
-	void PixelProcessor::setConstantColor(unsigned int stage, const Color<float> &constantColor)
-	{
-		if(stage < 8)
-		{
-			context->textureStage[stage].setConstantColor(constantColor);
-		}
-		else ASSERT(false);
-	}
-
-	void PixelProcessor::setBumpmapMatrix(unsigned int stage, int element, float value)
-	{
-		if(stage < 8)
-		{
-			context->textureStage[stage].setBumpmapMatrix(element, value);
-		}
-		else ASSERT(false);
-	}
-
-	void PixelProcessor::setLuminanceScale(unsigned int stage, float value)
-	{
-		if(stage < 8)
-		{
-			context->textureStage[stage].setLuminanceScale(value);
-		}
-		else ASSERT(false);
-	}
-
-	void PixelProcessor::setLuminanceOffset(unsigned int stage, float value)
-	{
-		if(stage < 8)
-		{
-			context->textureStage[stage].setLuminanceOffset(value);
-		}
-		else ASSERT(false);
-	}
-
 	void PixelProcessor::setTextureFilter(unsigned int sampler, FilterType textureFilter)
 	{
 		if(sampler < TEXTURE_IMAGE_UNITS)
@@ -537,15 +323,6 @@
 		else ASSERT(false);
 	}
 
-	void PixelProcessor::setSyncRequired(unsigned int sampler, bool isSincRequired)
-	{
-		if(sampler < TEXTURE_IMAGE_UNITS)
-		{
-			context->sampler[sampler].setSyncRequired(isSincRequired);
-		}
-		else ASSERT(false);
-	}
-
 	void PixelProcessor::setWriteSRGB(bool sRGB)
 	{
 		context->setWriteSRGB(sRGB);
@@ -683,35 +460,6 @@
 		context->stencilZFailOperationCCW = stencilZFailOperation;
 	}
 
-	void PixelProcessor::setTextureFactor(const Color<float> &textureFactor)
-	{
-		// FIXME: Compact into generic function   // FIXME: Clamp
-		short textureFactorR = iround(4095 * textureFactor.r);
-		short textureFactorG = iround(4095 * textureFactor.g);
-		short textureFactorB = iround(4095 * textureFactor.b);
-		short textureFactorA = iround(4095 * textureFactor.a);
-
-		factor.textureFactor4[0][0] = textureFactorR;
-		factor.textureFactor4[0][1] = textureFactorR;
-		factor.textureFactor4[0][2] = textureFactorR;
-		factor.textureFactor4[0][3] = textureFactorR;
-
-		factor.textureFactor4[1][0] = textureFactorG;
-		factor.textureFactor4[1][1] = textureFactorG;
-		factor.textureFactor4[1][2] = textureFactorG;
-		factor.textureFactor4[1][3] = textureFactorG;
-
-		factor.textureFactor4[2][0] = textureFactorB;
-		factor.textureFactor4[2][1] = textureFactorB;
-		factor.textureFactor4[2][2] = textureFactorB;
-		factor.textureFactor4[2][3] = textureFactorB;
-
-		factor.textureFactor4[3][0] = textureFactorA;
-		factor.textureFactor4[3][1] = textureFactorA;
-		factor.textureFactor4[3][2] = textureFactorA;
-		factor.textureFactor4[3][3] = textureFactorA;
-	}
-
 	void PixelProcessor::setBlendConstant(const Color<float> &blendConstant)
 	{
 		// FIXME: Compact into generic function   // FIXME: Clamp
@@ -807,16 +555,6 @@
 		factor.invBlendConstant4F[3][3] = 1 - blendConstant.a;
 	}
 
-	void PixelProcessor::setFillMode(FillMode fillMode)
-	{
-		context->fillMode = fillMode;
-	}
-
-	void PixelProcessor::setShadingMode(ShadingMode shadingMode)
-	{
-		context->shadingMode = shadingMode;
-	}
-
 	void PixelProcessor::setAlphaBlendEnable(bool alphaBlendEnable)
 	{
 		context->setAlphaBlendEnable(alphaBlendEnable);
@@ -867,59 +605,6 @@
 		factor.alphaReference4[3] = (word)iround(alphaReference * 0x1000 / 0xFF);
 	}
 
-	void PixelProcessor::setGlobalMipmapBias(float bias)
-	{
-		context->setGlobalMipmapBias(bias);
-	}
-
-	void PixelProcessor::setFogStart(float start)
-	{
-		setFogRanges(start, context->fogEnd);
-	}
-
-	void PixelProcessor::setFogEnd(float end)
-	{
-		setFogRanges(context->fogStart, end);
-	}
-
-	void PixelProcessor::setFogColor(Color<float> fogColor)
-	{
-		// TODO: Compact into generic function
-		word fogR = (unsigned short)(65535 * fogColor.r);
-		word fogG = (unsigned short)(65535 * fogColor.g);
-		word fogB = (unsigned short)(65535 * fogColor.b);
-
-		fog.color4[0][0] = fogR;
-		fog.color4[0][1] = fogR;
-		fog.color4[0][2] = fogR;
-		fog.color4[0][3] = fogR;
-
-		fog.color4[1][0] = fogG;
-		fog.color4[1][1] = fogG;
-		fog.color4[1][2] = fogG;
-		fog.color4[1][3] = fogG;
-
-		fog.color4[2][0] = fogB;
-		fog.color4[2][1] = fogB;
-		fog.color4[2][2] = fogB;
-		fog.color4[2][3] = fogB;
-
-		fog.colorF[0] = replicate(fogColor.r);
-		fog.colorF[1] = replicate(fogColor.g);
-		fog.colorF[2] = replicate(fogColor.b);
-	}
-
-	void PixelProcessor::setFogDensity(float fogDensity)
-	{
-		fog.densityE = replicate(-fogDensity * 1.442695f);   // 1/e^x = 2^(-x*1.44)
-		fog.density2E = replicate(-fogDensity * fogDensity * 1.442695f);
-	}
-
-	void PixelProcessor::setPixelFogMode(FogMode fogMode)
-	{
-		context->pixelFogMode = fogMode;
-	}
-
 	void PixelProcessor::setPerspectiveCorrection(bool perspectiveEnable)
 	{
 		perspectiveCorrection = perspectiveEnable;
@@ -936,23 +621,6 @@
 		routineCache = new RoutineCache<State>(clamp(cacheSize, 1, 65536), precachePixel ? "sw-pixel" : 0);
 	}
 
-	void PixelProcessor::setFogRanges(float start, float end)
-	{
-		context->fogStart = start;
-		context->fogEnd = end;
-
-		if(start == end)
-		{
-			end += 0.001f;   // Hack: ensure there is a small range
-		}
-
-		float fogScale = -1.0f / (end - start);
-		float fogOffset = end * -fogScale;
-
-		fog.scale = replicate(fogScale);
-		fog.offset = replicate(fogOffset);
-	}
-
 	const PixelProcessor::State PixelProcessor::update() const
 	{
 		State state;
@@ -1008,9 +676,6 @@
 
 		state.occlusionEnabled = context->occlusionEnabled;
 
-		state.fogActive = context->fogActive();
-		state.pixelFogMode = context->pixelFogActive();
-		state.wBasedFog = context->wBasedFog && context->pixelFogActive() != FOG_NONE;
 		state.perspective = context->perspectiveActive();
 		state.depthClamp = (context->depthBias != 0.0f) || (context->slopeDepthBias != 0.0f);
 
@@ -1044,15 +709,6 @@
 
 		state.frontFaceCCW = context->frontFacingCCW;
 
-		if(!context->pixelShader)
-		{
-			for(unsigned int i = 0; i < 8; i++)
-			{
-				state.textureStage[i] = context->textureStage[i].textureStageState();
-			}
-
-			state.specularAdd = context->specularActive() && context->specularEnable;
-		}
 
 		for(unsigned int i = 0; i < 16; i++)
 		{
@@ -1063,104 +719,31 @@
 					state.sampler[i] = context->sampler[i].samplerState();
 				}
 			}
-			else
-			{
-				if(i < 8 && state.textureStage[i].stageOperation != TextureStage::STAGE_DISABLE)
-				{
-					state.sampler[i] = context->sampler[i].samplerState();
-				}
-				else break;
-			}
 		}
 
-		const bool point = context->isDrawPoint(true);
-		const bool sprite = context->pointSpriteActive();
-		const bool flatShading = (context->shadingMode == SHADING_FLAT) || point;
+		const bool point = context->isDrawPoint();
 
-		if(context->pixelShaderModel() < 0x0300)
+		for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
 		{
-			for(int coordinate = 0; coordinate < 8; coordinate++)
+			for(int component = 0; component < 4; component++)
 			{
-				for(int component = 0; component < 4; component++)
+				const Shader::Semantic &semantic = context->pixelShader->getInput(interpolant, component);
+
+				if(semantic.active())
 				{
-					if(context->textureActive(coordinate, component))
-					{
-						state.texture[coordinate].component |= 1 << component;
+					bool flat = point;
 
-						if(point && !sprite)
-						{
-							state.texture[coordinate].flat |= 1 << component;
-						}
+					switch(semantic.usage)
+					{
+					case Shader::USAGE_TEXCOORD: flat = false;                  break;
+					case Shader::USAGE_COLOR:    flat = semantic.flat || point; break;
 					}
-				}
 
-				if(context->textureTransformProject[coordinate] && context->pixelShaderModel() <= 0x0103)
-				{
-					if(context->textureTransformCount[coordinate] == 2)
+					state.interpolant[interpolant].component |= 1 << component;
+
+					if(flat)
 					{
-						state.texture[coordinate].project = 1;
-					}
-					else if(context->textureTransformCount[coordinate] == 3)
-					{
-						state.texture[coordinate].project = 2;
-					}
-					else if(context->textureTransformCount[coordinate] == 4 || context->textureTransformCount[coordinate] == 0)
-					{
-						state.texture[coordinate].project = 3;
-					}
-				}
-			}
-
-			for(int color = 0; color < 2; color++)
-			{
-				for(int component = 0; component < 4; component++)
-				{
-					if(context->colorActive(color, component))
-					{
-						state.color[color].component |= 1 << component;
-
-						if(point || flatShading)
-						{
-							state.color[color].flat |= 1 << component;
-						}
-					}
-				}
-			}
-
-			if(context->fogActive())
-			{
-				state.fog.component = true;
-
-				if(point)
-				{
-					state.fog.flat = true;
-				}
-			}
-		}
-		else
-		{
-			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 = point && !sprite;             break;
-						case Shader::USAGE_COLOR:    flat = semantic.flat || flatShading; break;
-						}
-
-						state.interpolant[interpolant].component |= 1 << component;
-
-						if(flat)
-						{
-							state.interpolant[interpolant].flat |= 1 << component;
-						}
+						state.interpolant[interpolant].flat |= 1 << component;
 					}
 				}
 			}
@@ -1189,17 +772,7 @@
 		if(!routine)
 		{
 			const bool integerPipeline = (context->pixelShaderModel() <= 0x0104);
-			QuadRasterizer *generator = nullptr;
-
-			if(integerPipeline)
-			{
-				generator = new PixelPipeline(state, context->pixelShader);
-			}
-			else
-			{
-				generator = new PixelProgram(state, context->pixelShader);
-			}
-
+			QuadRasterizer *generator = new PixelProgram(state, context->pixelShader);
 			generator->generate();
 			routine = (*generator)(L"PixelRoutine_%0.8X", state.shaderID);
 			delete generator;
diff --git a/src/Device/PixelProcessor.hpp b/src/Device/PixelProcessor.hpp
index 98300de..d8645b8 100644
--- a/src/Device/PixelProcessor.hpp
+++ b/src/Device/PixelProcessor.hpp
@@ -60,11 +60,7 @@
 			bool stencilWriteMaskedCCW                : 1;
 
 			bool depthTestActive                      : 1;
-			bool fogActive                            : 1;
-			FogMode pixelFogMode                      : BITS(FOG_LAST);
-			bool specularAdd                          : 1;
 			bool occlusionEnabled                     : 1;
-			bool wBasedFog                            : 1;
 			bool perspective                          : 1;
 			bool depthClamp                           : 1;
 
@@ -88,7 +84,6 @@
 			LogicalOperation logicalOperation : BITS(LOGICALOP_LAST);
 
 			Sampler::State sampler[TEXTURE_IMAGE_UNITS];
-			TextureStage::State textureStage[8];
 
 			struct Interpolant
 			{
@@ -127,11 +122,6 @@
 				return (alphaCompareMode != ALPHA_ALWAYS) || (transparencyAntialiasing != TRANSPARENCY_NONE);
 			}
 
-			bool pixelFogActive() const
-			{
-				return pixelFogMode != FOG_NONE;
-			}
-
 			unsigned int hash;
 		};
 
@@ -162,20 +152,8 @@
 			}
 		};
 
-		struct Fog
-		{
-			float4 scale;
-			float4 offset;
-			word4 color4[3];
-			float4 colorF[3];
-			float4 densityE;
-			float4 density2E;
-		};
-
 		struct Factor
 		{
-			word4 textureFactor4[4];
-
 			word4 alphaReference4;
 
 			word4 blendConstant4W[4];
@@ -203,21 +181,6 @@
 		void setStencilBuffer(Surface *stencilBuffer, unsigned int layer = 0);
 
 		void setTexCoordIndex(unsigned int stage, int texCoordIndex);
-		void setStageOperation(unsigned int stage, TextureStage::StageOperation stageOperation);
-		void setFirstArgument(unsigned int stage, TextureStage::SourceArgument firstArgument);
-		void setSecondArgument(unsigned int stage, TextureStage::SourceArgument secondArgument);
-		void setThirdArgument(unsigned int stage, TextureStage::SourceArgument thirdArgument);
-		void setStageOperationAlpha(unsigned int stage, TextureStage::StageOperation stageOperationAlpha);
-		void setFirstArgumentAlpha(unsigned int stage, TextureStage::SourceArgument firstArgumentAlpha);
-		void setSecondArgumentAlpha(unsigned int stage, TextureStage::SourceArgument secondArgumentAlpha);
-		void setThirdArgumentAlpha(unsigned int stage, TextureStage::SourceArgument thirdArgumentAlpha);
-		void setFirstModifier(unsigned int stage, TextureStage::ArgumentModifier firstModifier);
-		void setSecondModifier(unsigned int stage, TextureStage::ArgumentModifier secondModifier);
-		void setThirdModifier(unsigned int stage, TextureStage::ArgumentModifier thirdModifier);
-		void setFirstModifierAlpha(unsigned int stage, TextureStage::ArgumentModifier firstModifierAlpha);
-		void setSecondModifierAlpha(unsigned int stage, TextureStage::ArgumentModifier secondModifierAlpha);
-		void setThirdModifierAlpha(unsigned int stage, TextureStage::ArgumentModifier thirdModifierAlpha);
-		void setDestinationArgument(unsigned int stage, TextureStage::DestinationArgument destinationArgument);
 		void setConstantColor(unsigned int stage, const Color<float> &constantColor);
 		void setBumpmapMatrix(unsigned int stage, int element, float value);
 		void setLuminanceScale(unsigned int stage, float value);
@@ -243,7 +206,6 @@
 		void setMaxLevel(unsigned int sampler, int maxLevel);
 		void setMinLod(unsigned int sampler, float minLod);
 		void setMaxLod(unsigned int sampler, float maxLod);
-		void setSyncRequired(unsigned int sampler, bool isSincRequired);
 
 		void setWriteSRGB(bool sRGB);
 		void setDepthBufferEnable(bool depthBufferEnable);
@@ -274,12 +236,8 @@
 		void setStencilZFailOperationCCW(StencilOperation stencilZFailOperation);
 		void setStencilWriteMaskCCW(int stencilWriteMask);
 
-		void setTextureFactor(const Color<float> &textureFactor);
 		void setBlendConstant(const Color<float> &blendConstant);
 
-		void setFillMode(FillMode fillMode);
-		void setShadingMode(ShadingMode shadingMode);
-
 		void setAlphaBlendEnable(bool alphaBlendEnable);
 		void setSourceBlendFactor(BlendFactor sourceBlendFactor);
 		void setDestBlendFactor(BlendFactor destBlendFactor);
@@ -292,14 +250,6 @@
 
 		void setAlphaReference(float alphaReference);
 
-		void setGlobalMipmapBias(float bias);
-
-		void setFogStart(float start);
-		void setFogEnd(float end);
-		void setFogColor(Color<float> fogColor);
-		void setFogDensity(float fogDensity);
-		void setPixelFogMode(FogMode fogMode);
-
 		void setPerspectiveCorrection(bool perspectiveCorrection);
 
 		void setOcclusionEnabled(bool enable);
@@ -310,7 +260,6 @@
 		void setRoutineCacheSize(int routineCacheSize);
 
 		// Shader constants
-		word4 cW[8][4];
 		float4 c[FRAGMENT_UNIFORM_VECTORS];
 		int4 i[16];
 		bool b[16];
@@ -318,7 +267,6 @@
 		// Other semi-constants
 		Stencil stencil;
 		Stencil stencilCCW;
-		Fog fog;
 		Factor factor;
 
 	private:
diff --git a/src/Device/Renderer.cpp b/src/Device/Renderer.cpp
index 71b22a5..6df648e 100644
--- a/src/Device/Renderer.cpp
+++ b/src/Device/Renderer.cpp
@@ -125,13 +125,10 @@
 	{
 		setGlobalRenderingSettings(conventions, exactColorRounding);
 
-		setRenderTarget(0, 0);
+		setRenderTarget(0, nullptr);
 		clipper = new Clipper(symmetricNormalizedDepth);
 		blitter = new Blitter;
 
-		updateViewMatrix = true;
-		updateBaseMatrix = true;
-		updateProjectionMatrix = true;
 		updateClipPlanes = true;
 
 		#if PERF_HUD
@@ -140,11 +137,11 @@
 
 		for(int i = 0; i < 16; i++)
 		{
-			vertexTask[i] = 0;
+			vertexTask[i] = nullptr;
 
-			worker[i] = 0;
-			resume[i] = 0;
-			suspend[i] = 0;
+			worker[i] = nullptr;
+			resume[i] = nullptr;
+			suspend[i] = nullptr;
 		}
 
 		threadsAwake = 0;
@@ -158,8 +155,8 @@
 
 		for(int i = 0; i < 16; i++)
 		{
-			triangleBatch[i] = 0;
-			primitiveBatch[i] = 0;
+			triangleBatch[i] = nullptr;
+			primitiveBatch[i] = nullptr;
 		}
 
 		for(int draw = 0; draw < DRAW_COUNT; draw++)
@@ -233,472 +230,371 @@
 		updateConfiguration();
 		updateClipper();
 
-		int ss = context->getSuperSampleCount();
 		int ms = context->getMultiSampleCount();
-		bool requiresSync = false;
+		unsigned int oldMultiSampleMask = context->multiSampleMask;
+		context->multiSampleMask = context->sampleMask & ((unsigned)0xFFFFFFFF >> (32 - ms));
 
-		for(int q = 0; q < ss; q++)
+		if(!context->multiSampleMask)
 		{
-			unsigned int oldMultiSampleMask = context->multiSampleMask;
-			context->multiSampleMask = (context->sampleMask >> (ms * q)) & ((unsigned)0xFFFFFFFF >> (32 - ms));
+			return;
+		}
 
-			if(!context->multiSampleMask)
+		sync->lock(sw::PRIVATE);
+
+		if(update || oldMultiSampleMask != context->multiSampleMask)
+		{
+			vertexState = VertexProcessor::update(drawType);
+			setupState = SetupProcessor::update();
+			pixelState = PixelProcessor::update();
+
+			vertexRoutine = VertexProcessor::routine(vertexState);
+			setupRoutine = SetupProcessor::routine(setupState);
+			pixelRoutine = PixelProcessor::routine(pixelState);
+		}
+
+		int batch = batchSize / ms;
+
+		int (Renderer::*setupPrimitives)(int batch, int count);
+
+		if(context->isDrawTriangle())
+		{
+			setupPrimitives = &Renderer::setupTriangles;
+		}
+		else if(context->isDrawLine())
+		{
+			setupPrimitives = &Renderer::setupLines;
+		}
+		else   // Point draw
+		{
+			setupPrimitives = &Renderer::setupPoints;
+		}
+
+		DrawCall *draw = nullptr;
+
+		do
+		{
+			for(int i = 0; i < DRAW_COUNT; i++)
 			{
-				continue;
-			}
-
-			sync->lock(sw::PRIVATE);
-
-			if(update || oldMultiSampleMask != context->multiSampleMask)
-			{
-				vertexState = VertexProcessor::update(drawType);
-				setupState = SetupProcessor::update();
-				pixelState = PixelProcessor::update();
-
-				vertexRoutine = VertexProcessor::routine(vertexState);
-				setupRoutine = SetupProcessor::routine(setupState);
-				pixelRoutine = PixelProcessor::routine(pixelState);
-			}
-
-			int batch = batchSize / ms;
-
-			int (Renderer::*setupPrimitives)(int batch, int count);
-
-			if(context->isDrawTriangle())
-			{
-				switch(context->fillMode)
+				if(drawCall[i]->references == -1)
 				{
-				case FILL_SOLID:
-					setupPrimitives = &Renderer::setupSolidTriangles;
+					draw = drawCall[i];
+					drawList[nextDraw & DRAW_COUNT_BITS] = draw;
+
 					break;
-				case FILL_WIREFRAME:
-					setupPrimitives = &Renderer::setupWireframeTriangle;
-					batch = 1;
-					break;
-				case FILL_VERTEX:
-					setupPrimitives = &Renderer::setupVertexTriangle;
-					batch = 1;
-					break;
-				default:
-					ASSERT(false);
-					return;
-				}
-			}
-			else if(context->isDrawLine())
-			{
-				setupPrimitives = &Renderer::setupLines;
-			}
-			else   // Point draw
-			{
-				setupPrimitives = &Renderer::setupPoints;
-			}
-
-			DrawCall *draw = nullptr;
-
-			do
-			{
-				for(int i = 0; i < DRAW_COUNT; i++)
-				{
-					if(drawCall[i]->references == -1)
-					{
-						draw = drawCall[i];
-						drawList[nextDraw & DRAW_COUNT_BITS] = draw;
-
-						break;
-					}
-				}
-
-				if(!draw)
-				{
-					resumeApp->wait();
-				}
-			}
-			while(!draw);
-
-			DrawData *data = draw->data;
-
-			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);
-					}
 				}
 			}
 
-			draw->drawType = drawType;
-			draw->batchSize = batch;
-
-			vertexRoutine->bind();
-			setupRoutine->bind();
-			pixelRoutine->bind();
-
-			draw->vertexRoutine = vertexRoutine;
-			draw->setupRoutine = setupRoutine;
-			draw->pixelRoutine = pixelRoutine;
-			draw->vertexPointer = (VertexProcessor::RoutinePointer)vertexRoutine->getEntry();
-			draw->setupPointer = (SetupProcessor::RoutinePointer)setupRoutine->getEntry();
-			draw->pixelPointer = (PixelProcessor::RoutinePointer)pixelRoutine->getEntry();
-			draw->setupPrimitives = setupPrimitives;
-			draw->setupState = setupState;
-
-			for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
+			if(!draw)
 			{
-				draw->vertexStream[i] = context->input[i].resource;
-				data->input[i] = context->input[i].buffer;
-				data->stride[i] = context->input[i].stride;
-
-				if(draw->vertexStream[i])
-				{
-					draw->vertexStream[i]->lock(PUBLIC, PRIVATE);
-				}
+				resumeApp->wait();
 			}
+		}
+		while(!draw);
 
-			if(context->indexBuffer)
+		DrawData *data = draw->data;
+
+		if(queries.size() != 0)
+		{
+			draw->queries = new std::list<Query*>();
+			bool includePrimitivesWrittenQueries = vertexState.transformFeedbackQueryEnabled && vertexState.transformFeedbackEnabled;
+			for(auto &query : queries)
 			{
-				data->indices = (unsigned char*)context->indexBuffer->lock(PUBLIC, PRIVATE) + indexOffset;
-			}
-
-			draw->indexBuffer = context->indexBuffer;
-
-			for(int sampler = 0; sampler < TOTAL_IMAGE_UNITS; sampler++)
-			{
-				draw->texture[sampler] = 0;
-			}
-
-			for(int sampler = 0; sampler < TEXTURE_IMAGE_UNITS; sampler++)
-			{
-				if(pixelState.sampler[sampler].textureType != TEXTURE_NULL)
+				if(includePrimitivesWrittenQueries || (query->type != Query::TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN))
 				{
-					draw->texture[sampler] = context->texture[sampler];
-					draw->texture[sampler]->lock(PUBLIC, isReadWriteTexture(sampler) ? MANAGED : PRIVATE);   // If the texure is both read and written, use the same read/write lock as render targets
-
-					data->mipmap[sampler] = context->sampler[sampler].getTextureData();
-
-					requiresSync |= context->sampler[sampler].requiresSync();
-				}
-			}
-
-			if(context->pixelShader)
-			{
-				if(draw->psDirtyConstF)
-				{
-					memcpy(&data->ps.cW, PixelProcessor::cW, sizeof(word4) * 4 * (draw->psDirtyConstF < 8 ? draw->psDirtyConstF : 8));
-					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
-			{
-				for(int i = 0; i < MAX_UNIFORM_BUFFER_BINDINGS; i++)
-				{
-					draw->pUniformBuffers[i] = nullptr;
-				}
-			}
-
-			if(context->pixelShaderModel() <= 0x0104)
-			{
-				for(int stage = 0; stage < 8; stage++)
-				{
-					if(pixelState.textureStage[stage].stageOperation != TextureStage::STAGE_DISABLE || context->pixelShader)
-					{
-						data->textureStage[stage] = context->textureStage[stage].uniforms;
-					}
-					else break;
-				}
-			}
-
-			if(context->vertexShader)
-			{
-				if(context->vertexShader->getShaderModel() >= 0x0300)
-				{
-					for(int sampler = 0; sampler < VERTEX_TEXTURE_IMAGE_UNITS; sampler++)
-					{
-						if(vertexState.sampler[sampler].textureType != TEXTURE_NULL)
-						{
-							draw->texture[TEXTURE_IMAGE_UNITS + sampler] = context->texture[TEXTURE_IMAGE_UNITS + sampler];
-							draw->texture[TEXTURE_IMAGE_UNITS + sampler]->lock(PUBLIC, PRIVATE);
-
-							data->mipmap[TEXTURE_IMAGE_UNITS + sampler] = context->sampler[TEXTURE_IMAGE_UNITS + sampler].getTextureData();
-
-							requiresSync |= context->sampler[TEXTURE_IMAGE_UNITS + sampler].requiresSync();
-						}
-					}
-				}
-
-				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())
-				{
-					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);
-			}
-			else
-			{
-				data->ff = ff;
-
-				draw->vsDirtyConstF = VERTEX_UNIFORM_VECTORS + 1;
-				draw->vsDirtyConstI = 16;
-				draw->vsDirtyConstB = 16;
-
-				for(int i = 0; i < MAX_UNIFORM_BUFFER_BINDINGS; i++)
-				{
-					draw->vUniformBuffers[i] = nullptr;
-				}
-
-				for(int i = 0; i < MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS; i++)
-				{
-					draw->transformFeedbackBuffers[i] = nullptr;
-				}
-			}
-
-			if(pixelState.stencilActive)
-			{
-				data->stencil[0] = stencil;
-				data->stencil[1] = stencilCCW;
-			}
-
-			if(pixelState.fogActive)
-			{
-				data->fog = fog;
-			}
-
-			if(setupState.isDrawPoint)
-			{
-				data->point = point;
-			}
-
-			data->lineWidth = context->lineWidth;
-
-			data->factor = factor;
-
-			if(pixelState.transparencyAntialiasing == TRANSPARENCY_ALPHA_TO_COVERAGE)
-			{
-				float ref = context->alphaReference * (1.0f / 255.0f);
-				float margin = sw::min(ref, 1.0f - ref);
-
-				if(ms == 4)
-				{
-					data->a2c0 = replicate(ref - margin * 0.6f);
-					data->a2c1 = replicate(ref - margin * 0.2f);
-					data->a2c2 = replicate(ref + margin * 0.2f);
-					data->a2c3 = replicate(ref + margin * 0.6f);
-				}
-				else if(ms == 2)
-				{
-					data->a2c0 = replicate(ref - margin * 0.3f);
-					data->a2c1 = replicate(ref + margin * 0.3f);
-				}
-				else ASSERT(false);
-			}
-
-			if(pixelState.occlusionEnabled)
-			{
-				for(int cluster = 0; cluster < clusterCount; cluster++)
-				{
-					data->occlusion[cluster] = 0;
-				}
-			}
-
-			#if PERF_PROFILE
-				for(int cluster = 0; cluster < clusterCount; cluster++)
-				{
-					for(int i = 0; i < PERF_TIMERS; i++)
-					{
-						data->cycles[i][cluster] = 0;
-					}
-				}
-			#endif
-
-			// Viewport
-			{
-				float W = 0.5f * viewport.width;
-				float H = 0.5f * viewport.height;
-				float X0 = viewport.x0 + W;
-				float Y0 = viewport.y0 + H;
-				float N = viewport.minZ;
-				float F = viewport.maxZ;
-				float Z = F - N;
-
-				if(context->isDrawTriangle(false))
-				{
-					N += context->depthBias;
-				}
-
-				if(complementaryDepthBuffer)
-				{
-					Z = -Z;
-					N = 1 - N;
-				}
-
-				static const float X[5][16] =   // Fragment offsets
-				{
-					{+0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f},   // 1 sample
-					{-0.2500f, +0.2500f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f},   // 2 samples
-					{-0.3000f, +0.1000f, +0.3000f, -0.1000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f},   // 4 samples
-					{+0.1875f, -0.3125f, +0.3125f, -0.4375f, -0.0625f, +0.4375f, +0.0625f, -0.1875f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f},   // 8 samples
-					{+0.2553f, -0.1155f, +0.1661f, -0.1828f, +0.2293f, -0.4132f, -0.1773f, -0.0577f, +0.3891f, -0.4656f, +0.4103f, +0.4248f, -0.2109f, +0.3966f, -0.2664f, -0.3872f}    // 16 samples
-				};
-
-				static const float Y[5][16] =   // Fragment offsets
-				{
-					{+0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f},   // 1 sample
-					{-0.2500f, +0.2500f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f},   // 2 samples
-					{-0.1000f, -0.3000f, +0.1000f, +0.3000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f},   // 4 samples
-					{-0.4375f, -0.3125f, -0.1875f, -0.0625f, +0.0625f, +0.1875f, +0.3125f, +0.4375f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f, +0.0000f},   // 8 samples
-					{-0.4503f, +0.1883f, +0.3684f, -0.4668f, -0.0690f, -0.1315f, +0.4999f, +0.0728f, +0.1070f, -0.3086f, +0.3725f, -0.1547f, -0.1102f, -0.3588f, +0.1789f, +0.0269f}    // 16 samples
-				};
-
-				int s = sw::log2(ss);
-
-				data->Wx16 = replicate(W * 16);
-				data->Hx16 = replicate(H * 16);
-				data->X0x16 = replicate(X0 * 16 - 8);
-				data->Y0x16 = replicate(Y0 * 16 - 8);
-				data->XXXX = replicate(X[s][q] / W);
-				data->YYYY = replicate(Y[s][q] / H);
-				data->halfPixelX = replicate(0.5f / W);
-				data->halfPixelY = replicate(0.5f / H);
-				data->viewportHeight = abs(viewport.height);
-				data->slopeDepthBias = context->slopeDepthBias;
-				data->depthRange = Z;
-				data->depthNear = N;
-				draw->clipFlags = clipFlags;
-
-				if(clipFlags)
-				{
-					if(clipFlags & Clipper::CLIP_PLANE0) data->clipPlane[0] = clipPlane[0];
-					if(clipFlags & Clipper::CLIP_PLANE1) data->clipPlane[1] = clipPlane[1];
-					if(clipFlags & Clipper::CLIP_PLANE2) data->clipPlane[2] = clipPlane[2];
-					if(clipFlags & Clipper::CLIP_PLANE3) data->clipPlane[3] = clipPlane[3];
-					if(clipFlags & Clipper::CLIP_PLANE4) data->clipPlane[4] = clipPlane[4];
-					if(clipFlags & Clipper::CLIP_PLANE5) data->clipPlane[5] = clipPlane[5];
-				}
-			}
-
-			// Target
-			{
-				for(int index = 0; index < RENDERTARGETS; index++)
-				{
-					draw->renderTarget[index] = context->renderTarget[index];
-
-					if(draw->renderTarget[index])
-					{
-						unsigned int layer = context->renderTargetLayer[index];
-						requiresSync |= context->renderTarget[index]->requiresSync();
-						data->colorBuffer[index] = (unsigned int*)context->renderTarget[index]->lockInternal(0, 0, layer, LOCK_READWRITE, MANAGED);
-						data->colorBuffer[index] += q * ms * context->renderTarget[index]->getSliceB(true);
-						data->colorPitchB[index] = context->renderTarget[index]->getInternalPitchB();
-						data->colorSliceB[index] = context->renderTarget[index]->getInternalSliceB();
-					}
-				}
-
-				draw->depthBuffer = context->depthBuffer;
-				draw->stencilBuffer = context->stencilBuffer;
-
-				if(draw->depthBuffer)
-				{
-					unsigned int layer = context->depthBufferLayer;
-					requiresSync |= context->depthBuffer->requiresSync();
-					data->depthBuffer = (float*)context->depthBuffer->lockInternal(0, 0, layer, LOCK_READWRITE, MANAGED);
-					data->depthBuffer += q * ms * context->depthBuffer->getSliceB(true);
-					data->depthPitchB = context->depthBuffer->getInternalPitchB();
-					data->depthSliceB = context->depthBuffer->getInternalSliceB();
-				}
-
-				if(draw->stencilBuffer)
-				{
-					unsigned int layer = context->stencilBufferLayer;
-					requiresSync |= context->stencilBuffer->requiresSync();
-					data->stencilBuffer = (unsigned char*)context->stencilBuffer->lockStencil(0, 0, layer, MANAGED);
-					data->stencilBuffer += q * ms * context->stencilBuffer->getSliceB(true);
-					data->stencilPitchB = context->stencilBuffer->getStencilPitchB();
-					data->stencilSliceB = context->stencilBuffer->getStencilSliceB();
-				}
-			}
-
-			// Scissor
-			{
-				data->scissorX0 = scissor.x0;
-				data->scissorX1 = scissor.x1;
-				data->scissorY0 = scissor.y0;
-				data->scissorY1 = scissor.y1;
-			}
-
-			draw->primitive = 0;
-			draw->count = count;
-
-			draw->references = (count + batch - 1) / batch;
-
-			schedulerMutex.lock();
-			++nextDraw; // Atomic
-			schedulerMutex.unlock();
-
-			#ifndef NDEBUG
-			if(threadCount == 1)   // Use main thread for draw execution
-			{
-				threadsAwake = 1;
-				task[0].type = Task::RESUME;
-
-				taskLoop(0);
-			}
-			else
-			#endif
-			{
-				if(!threadsAwake)
-				{
-					suspend[0]->wait();
-
-					threadsAwake = 1;
-					task[0].type = Task::RESUME;
-
-					resume[0]->signal();
+					++query->reference; // Atomic
+					draw->queries->push_back(query);
 				}
 			}
 		}
 
-		// TODO(sugoi): This is a temporary brute-force workaround to ensure IOSurface synchronization.
-		if(requiresSync)
+		draw->drawType = drawType;
+		draw->batchSize = batch;
+
+		vertexRoutine->bind();
+		setupRoutine->bind();
+		pixelRoutine->bind();
+
+		draw->vertexRoutine = vertexRoutine;
+		draw->setupRoutine = setupRoutine;
+		draw->pixelRoutine = pixelRoutine;
+		draw->vertexPointer = (VertexProcessor::RoutinePointer)vertexRoutine->getEntry();
+		draw->setupPointer = (SetupProcessor::RoutinePointer)setupRoutine->getEntry();
+		draw->pixelPointer = (PixelProcessor::RoutinePointer)pixelRoutine->getEntry();
+		draw->setupPrimitives = setupPrimitives;
+		draw->setupState = setupState;
+
+		for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
 		{
-			synchronize();
+			draw->vertexStream[i] = context->input[i].resource;
+			data->input[i] = context->input[i].buffer;
+			data->stride[i] = context->input[i].stride;
+
+			if(draw->vertexStream[i])
+			{
+				draw->vertexStream[i]->lock(PUBLIC, PRIVATE);
+			}
+		}
+
+		if(context->indexBuffer)
+		{
+			data->indices = (unsigned char*)context->indexBuffer->lock(PUBLIC, PRIVATE) + indexOffset;
+		}
+
+		draw->indexBuffer = context->indexBuffer;
+
+		for(int sampler = 0; sampler < TOTAL_IMAGE_UNITS; sampler++)
+		{
+			draw->texture[sampler] = 0;
+		}
+
+		for(int sampler = 0; sampler < TEXTURE_IMAGE_UNITS; sampler++)
+		{
+			if(pixelState.sampler[sampler].textureType != TEXTURE_NULL)
+			{
+				draw->texture[sampler] = context->texture[sampler];
+				draw->texture[sampler]->lock(PUBLIC, isReadWriteTexture(sampler) ? MANAGED : PRIVATE);   // If the texure is both read and written, use the same read/write lock as render targets
+
+				data->mipmap[sampler] = context->sampler[sampler].getTextureData();
+			}
+		}
+
+		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
+		{
+			for(int i = 0; i < MAX_UNIFORM_BUFFER_BINDINGS; i++)
+			{
+				draw->pUniformBuffers[i] = nullptr;
+			}
+		}
+
+		for(int sampler = 0; sampler < VERTEX_TEXTURE_IMAGE_UNITS; sampler++)
+		{
+			if(vertexState.sampler[sampler].textureType != TEXTURE_NULL)
+			{
+				draw->texture[TEXTURE_IMAGE_UNITS + sampler] = context->texture[TEXTURE_IMAGE_UNITS + sampler];
+				draw->texture[TEXTURE_IMAGE_UNITS + sampler]->lock(PUBLIC, PRIVATE);
+
+				data->mipmap[TEXTURE_IMAGE_UNITS + sampler] = context->sampler[TEXTURE_IMAGE_UNITS + sampler].getTextureData();
+			}
+		}
+
+		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())
+		{
+			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)
+		{
+			data->stencil[0] = stencil;
+			data->stencil[1] = stencilCCW;
+		}
+
+		if(setupState.isDrawPoint)
+		{
+			data->pointSizeMin = pointSizeMin;
+			data->pointSizeMax = pointSizeMax;
+		}
+
+		data->lineWidth = context->lineWidth;
+
+		data->factor = factor;
+
+		if(pixelState.transparencyAntialiasing == TRANSPARENCY_ALPHA_TO_COVERAGE)
+		{
+			float ref = context->alphaReference * (1.0f / 255.0f);
+			float margin = sw::min(ref, 1.0f - ref);
+
+			if(ms == 4)
+			{
+				data->a2c0 = replicate(ref - margin * 0.6f);
+				data->a2c1 = replicate(ref - margin * 0.2f);
+				data->a2c2 = replicate(ref + margin * 0.2f);
+				data->a2c3 = replicate(ref + margin * 0.6f);
+			}
+			else if(ms == 2)
+			{
+				data->a2c0 = replicate(ref - margin * 0.3f);
+				data->a2c1 = replicate(ref + margin * 0.3f);
+			}
+			else ASSERT(false);
+		}
+
+		if(pixelState.occlusionEnabled)
+		{
+			for(int cluster = 0; cluster < clusterCount; cluster++)
+			{
+				data->occlusion[cluster] = 0;
+			}
+		}
+
+		#if PERF_PROFILE
+			for(int cluster = 0; cluster < clusterCount; cluster++)
+			{
+				for(int i = 0; i < PERF_TIMERS; i++)
+				{
+					data->cycles[i][cluster] = 0;
+				}
+			}
+		#endif
+
+		// Viewport
+		{
+			float W = 0.5f * viewport.width;
+			float H = 0.5f * viewport.height;
+			float X0 = viewport.x0 + W;
+			float Y0 = viewport.y0 + H;
+			float N = viewport.minZ;
+			float F = viewport.maxZ;
+			float Z = F - N;
+
+			if(context->isDrawTriangle())
+			{
+				N += context->depthBias;
+			}
+
+			if(complementaryDepthBuffer)
+			{
+				Z = -Z;
+				N = 1 - N;
+			}
+
+			data->Wx16 = replicate(W * 16);
+			data->Hx16 = replicate(H * 16);
+			data->X0x16 = replicate(X0 * 16 - 8);
+			data->Y0x16 = replicate(Y0 * 16 - 8);
+			data->halfPixelX = replicate(0.5f / W);
+			data->halfPixelY = replicate(0.5f / H);
+			data->viewportHeight = abs(viewport.height);
+			data->slopeDepthBias = context->slopeDepthBias;
+			data->depthRange = Z;
+			data->depthNear = N;
+			draw->clipFlags = clipFlags;
+
+			if(clipFlags)
+			{
+				if(clipFlags & Clipper::CLIP_PLANE0) data->clipPlane[0] = clipPlane[0];
+				if(clipFlags & Clipper::CLIP_PLANE1) data->clipPlane[1] = clipPlane[1];
+				if(clipFlags & Clipper::CLIP_PLANE2) data->clipPlane[2] = clipPlane[2];
+				if(clipFlags & Clipper::CLIP_PLANE3) data->clipPlane[3] = clipPlane[3];
+				if(clipFlags & Clipper::CLIP_PLANE4) data->clipPlane[4] = clipPlane[4];
+				if(clipFlags & Clipper::CLIP_PLANE5) data->clipPlane[5] = clipPlane[5];
+			}
+		}
+
+		// Target
+		{
+			for(int index = 0; index < RENDERTARGETS; index++)
+			{
+				draw->renderTarget[index] = context->renderTarget[index];
+
+				if(draw->renderTarget[index])
+				{
+					unsigned int layer = context->renderTargetLayer[index];
+					data->colorBuffer[index] = (unsigned int*)context->renderTarget[index]->lockInternal(0, 0, layer, LOCK_READWRITE, MANAGED);
+					data->colorPitchB[index] = context->renderTarget[index]->getInternalPitchB();
+					data->colorSliceB[index] = context->renderTarget[index]->getInternalSliceB();
+				}
+			}
+
+			draw->depthBuffer = context->depthBuffer;
+			draw->stencilBuffer = context->stencilBuffer;
+
+			if(draw->depthBuffer)
+			{
+				unsigned int layer = context->depthBufferLayer;
+				data->depthBuffer = (float*)context->depthBuffer->lockInternal(0, 0, layer, LOCK_READWRITE, MANAGED);
+				data->depthPitchB = context->depthBuffer->getInternalPitchB();
+				data->depthSliceB = context->depthBuffer->getInternalSliceB();
+			}
+
+			if(draw->stencilBuffer)
+			{
+				unsigned int layer = context->stencilBufferLayer;
+				data->stencilBuffer = (unsigned char*)context->stencilBuffer->lockStencil(0, 0, layer, MANAGED);
+				data->stencilPitchB = context->stencilBuffer->getStencilPitchB();
+				data->stencilSliceB = context->stencilBuffer->getStencilSliceB();
+			}
+		}
+
+		// Scissor
+		{
+			data->scissorX0 = scissor.x0;
+			data->scissorX1 = scissor.x1;
+			data->scissorY0 = scissor.y0;
+			data->scissorY1 = scissor.y1;
+		}
+
+		draw->primitive = 0;
+		draw->count = count;
+
+		draw->references = (count + batch - 1) / batch;
+
+		schedulerMutex.lock();
+		++nextDraw; // Atomic
+		schedulerMutex.unlock();
+
+		#ifndef NDEBUG
+		if(threadCount == 1)   // Use main thread for draw execution
+		{
+			threadsAwake = 1;
+			task[0].type = Task::RESUME;
+
+			taskLoop(0);
+		}
+		else
+		#endif
+		{
+			if(!threadsAwake)
+			{
+				suspend[0]->wait();
+
+				threadsAwake = 1;
+				task[0].type = Task::RESUME;
+
+				resume[0]->signal();
+			}
 		}
 	}
 
@@ -1156,20 +1052,6 @@
 				}
 			}
 			break;
-		case DRAW_LINELOOP:
-			{
-				unsigned int index = start;
-
-				for(unsigned int i = 0; i < triangleCount; i++)
-				{
-					batch[i][0] = (index + 0) % loop;
-					batch[i][1] = (index + 1) % loop;
-					batch[i][2] = (index + 1) % loop;
-
-					index += 1;
-				}
-			}
-			break;
 		case DRAW_TRIANGLELIST:
 			{
 				unsigned int index = 3 * start;
@@ -1230,20 +1112,6 @@
 				}
 			}
 			break;
-		case DRAW_INDEXEDPOINTLIST8:
-			{
-				const unsigned char *index = (const unsigned char*)indices + start;
-
-				for(unsigned int i = 0; i < triangleCount; i++)
-				{
-					batch[i][0] = *index;
-					batch[i][1] = *index;
-					batch[i][2] = *index;
-
-					index += 1;
-				}
-			}
-			break;
 		case DRAW_INDEXEDPOINTLIST16:
 			{
 				const unsigned short *index = (const unsigned short*)indices + start;
@@ -1272,20 +1140,6 @@
 				}
 			}
 			break;
-		case DRAW_INDEXEDLINELIST8:
-			{
-				const unsigned char *index = (const unsigned char*)indices + 2 * start;
-
-				for(unsigned int i = 0; i < triangleCount; i++)
-				{
-					batch[i][0] = index[0];
-					batch[i][1] = index[1];
-					batch[i][2] = index[1];
-
-					index += 2;
-				}
-			}
-			break;
 		case DRAW_INDEXEDLINELIST16:
 			{
 				const unsigned short *index = (const unsigned short*)indices + 2 * start;
@@ -1314,20 +1168,6 @@
 				}
 			}
 			break;
-		case DRAW_INDEXEDLINESTRIP8:
-			{
-				const unsigned char *index = (const unsigned char*)indices + start;
-
-				for(unsigned int i = 0; i < triangleCount; i++)
-				{
-					batch[i][0] = index[0];
-					batch[i][1] = index[1];
-					batch[i][2] = index[1];
-
-					index += 1;
-				}
-			}
-			break;
 		case DRAW_INDEXEDLINESTRIP16:
 			{
 				const unsigned short *index = (const unsigned short*)indices + start;
@@ -1356,56 +1196,6 @@
 				}
 			}
 			break;
-		case DRAW_INDEXEDLINELOOP8:
-			{
-				const unsigned char *index = (const unsigned char*)indices;
-
-				for(unsigned int i = 0; i < triangleCount; i++)
-				{
-					batch[i][0] = index[(start + i + 0) % loop];
-					batch[i][1] = index[(start + i + 1) % loop];
-					batch[i][2] = index[(start + i + 1) % loop];
-				}
-			}
-			break;
-		case DRAW_INDEXEDLINELOOP16:
-			{
-				const unsigned short *index = (const unsigned short*)indices;
-
-				for(unsigned int i = 0; i < triangleCount; i++)
-				{
-					batch[i][0] = index[(start + i + 0) % loop];
-					batch[i][1] = index[(start + i + 1) % loop];
-					batch[i][2] = index[(start + i + 1) % loop];
-				}
-			}
-			break;
-		case DRAW_INDEXEDLINELOOP32:
-			{
-				const unsigned int *index = (const unsigned int*)indices;
-
-				for(unsigned int i = 0; i < triangleCount; i++)
-				{
-					batch[i][0] = index[(start + i + 0) % loop];
-					batch[i][1] = index[(start + i + 1) % loop];
-					batch[i][2] = index[(start + i + 1) % loop];
-				}
-			}
-			break;
-		case DRAW_INDEXEDTRIANGLELIST8:
-			{
-				const unsigned char *index = (const unsigned char*)indices + 3 * start;
-
-				for(unsigned int i = 0; i < triangleCount; i++)
-				{
-					batch[i][0] = index[0];
-					batch[i][1] = index[1];
-					batch[i][2] = index[2];
-
-					index += 3;
-				}
-			}
-			break;
 		case DRAW_INDEXEDTRIANGLELIST16:
 			{
 				const unsigned short *index = (const unsigned short*)indices + 3 * start;
@@ -1434,20 +1224,6 @@
 				}
 			}
 			break;
-		case DRAW_INDEXEDTRIANGLESTRIP8:
-			{
-				const unsigned char *index = (const unsigned char*)indices + start;
-
-				for(unsigned int i = 0; i < triangleCount; i++)
-				{
-					batch[i][0] = index[0];
-					batch[i][1] = index[((start + i) & 1) + 1];
-					batch[i][2] = index[(~(start + i) & 1) + 1];
-
-					index += 1;
-				}
-			}
-			break;
 		case DRAW_INDEXEDTRIANGLESTRIP16:
 			{
 				const unsigned short *index = (const unsigned short*)indices + start;
@@ -1476,18 +1252,6 @@
 				}
 			}
 			break;
-		case DRAW_INDEXEDTRIANGLEFAN8:
-			{
-				const unsigned char *index = (const unsigned char*)indices;
-
-				for(unsigned int i = 0; i < triangleCount; i++)
-				{
-					batch[i][0] = index[start + i + 1];
-					batch[i][1] = index[start + i + 2];
-					batch[i][2] = index[0];
-				}
-			}
-			break;
 		case DRAW_INDEXEDTRIANGLEFAN16:
 			{
 				const unsigned short *index = (const unsigned short*)indices;
@@ -1512,24 +1276,6 @@
 				}
 			}
 			break;
-		case DRAW_QUADLIST:
-			{
-				unsigned int index = 4 * start / 2;
-
-				for(unsigned int i = 0; i < triangleCount; i += 2)
-				{
-					batch[i+0][0] = index + 0;
-					batch[i+0][1] = index + 1;
-					batch[i+0][2] = index + 2;
-
-					batch[i+1][0] = index + 0;
-					batch[i+1][1] = index + 2;
-					batch[i+1][2] = index + 3;
-
-					index += 4;
-				}
-			}
-			break;
 		default:
 			ASSERT(false);
 			return;
@@ -1540,7 +1286,7 @@
 		vertexRoutine(&triangle->v0, (unsigned int*)&batch, task, data);
 	}
 
-	int Renderer::setupSolidTriangles(int unit, int count)
+	int Renderer::setupTriangles(int unit, int count)
 	{
 		Triangle *triangle = triangleBatch[unit];
 		Primitive *primitive = primitiveBatch[unit];
@@ -1585,107 +1331,6 @@
 		return visible;
 	}
 
-	int Renderer::setupWireframeTriangle(int unit, int count)
-	{
-		Triangle *triangle = triangleBatch[unit];
-		Primitive *primitive = primitiveBatch[unit];
-		int visible = 0;
-
-		DrawCall &draw = *drawList[primitiveProgress[unit].drawCall & DRAW_COUNT_BITS];
-		SetupProcessor::State &state = draw.setupState;
-
-		const Vertex &v0 = triangle[0].v0;
-		const Vertex &v1 = triangle[0].v1;
-		const Vertex &v2 = triangle[0].v2;
-
-		float d = (v0.y * v1.x - v0.x * v1.y) * v2.w + (v0.x * v2.y - v0.y * v2.x) * v1.w + (v2.x * v1.y - v1.x * v2.y) * v0.w;
-
-		if(state.cullMode == CULL_CLOCKWISE)
-		{
-			if(d >= 0) return 0;
-		}
-		else if(state.cullMode == CULL_COUNTERCLOCKWISE)
-		{
-			if(d <= 0) return 0;
-		}
-
-		// Copy attributes
-		triangle[1].v0 = v1;
-		triangle[1].v1 = v2;
-		triangle[2].v0 = v2;
-		triangle[2].v1 = v0;
-
-		if(state.color[0][0].flat)   // FIXME
-		{
-			for(int i = 0; i < 2; i++)
-			{
-				triangle[1].v0.C[i] = triangle[0].v0.C[i];
-				triangle[1].v1.C[i] = triangle[0].v0.C[i];
-				triangle[2].v0.C[i] = triangle[0].v0.C[i];
-				triangle[2].v1.C[i] = triangle[0].v0.C[i];
-			}
-		}
-
-		for(int i = 0; i < 3; i++)
-		{
-			if(setupLine(*primitive, *triangle, draw))
-			{
-				primitive->area = 0.5f * d;
-
-				primitive++;
-				visible++;
-			}
-
-			triangle++;
-		}
-
-		return visible;
-	}
-
-	int Renderer::setupVertexTriangle(int unit, int count)
-	{
-		Triangle *triangle = triangleBatch[unit];
-		Primitive *primitive = primitiveBatch[unit];
-		int visible = 0;
-
-		DrawCall &draw = *drawList[primitiveProgress[unit].drawCall & DRAW_COUNT_BITS];
-		SetupProcessor::State &state = draw.setupState;
-
-		const Vertex &v0 = triangle[0].v0;
-		const Vertex &v1 = triangle[0].v1;
-		const Vertex &v2 = triangle[0].v2;
-
-		float d = (v0.y * v1.x - v0.x * v1.y) * v2.w + (v0.x * v2.y - v0.y * v2.x) * v1.w + (v2.x * v1.y - v1.x * v2.y) * v0.w;
-
-		if(state.cullMode == CULL_CLOCKWISE)
-		{
-			if(d >= 0) return 0;
-		}
-		else if(state.cullMode == CULL_COUNTERCLOCKWISE)
-		{
-			if(d <= 0) return 0;
-		}
-
-		// Copy attributes
-		triangle[1].v0 = v1;
-		triangle[2].v0 = v2;
-
-		for(int i = 0; i < 3; i++)
-		{
-			if(setupPoint(*primitive, *triangle, draw))
-			{
-				primitive->area = 0.5f * d;
-
-				primitive++;
-				visible++;
-			}
-
-			triangle++;
-		}
-
-		return visible;
-	}
-
 	int Renderer::setupLines(int unit, int count)
 	{
 		Triangle *triangle = triangleBatch[unit];
@@ -1950,10 +1595,10 @@
 		}
 		else
 		{
-			pSize = data.point.pointSize[0];
+			pSize = 1.0f;
 		}
 
-		pSize = clamp(pSize, data.point.pointSizeMin, data.point.pointSizeMax);
+		pSize = clamp(pSize, data.pointSizeMin, data.pointSizeMax);
 
 		float4 P[4];
 		int C[4];
@@ -2082,8 +1727,6 @@
 
 	void Renderer::loadConstants(const VertexShader *vertexShader)
 	{
-		if(!vertexShader) return;
-
 		size_t count = vertexShader->getLength();
 
 		for(size_t i = 0; i < count; i++)
@@ -2205,26 +1848,12 @@
 	{
 		if(updateClipPlanes)
 		{
-			if(VertexProcessor::isFixedFunction())   // User plane in world space
-			{
-				const Matrix &scissorWorld = getViewTransform();
-
-				if(clipFlags & Clipper::CLIP_PLANE0) clipPlane[0] = scissorWorld * userPlane[0];
-				if(clipFlags & Clipper::CLIP_PLANE1) clipPlane[1] = scissorWorld * userPlane[1];
-				if(clipFlags & Clipper::CLIP_PLANE2) clipPlane[2] = scissorWorld * userPlane[2];
-				if(clipFlags & Clipper::CLIP_PLANE3) clipPlane[3] = scissorWorld * userPlane[3];
-				if(clipFlags & Clipper::CLIP_PLANE4) clipPlane[4] = scissorWorld * userPlane[4];
-				if(clipFlags & Clipper::CLIP_PLANE5) clipPlane[5] = scissorWorld * userPlane[5];
-			}
-			else   // User plane in clip space
-			{
-				if(clipFlags & Clipper::CLIP_PLANE0) clipPlane[0] = userPlane[0];
-				if(clipFlags & Clipper::CLIP_PLANE1) clipPlane[1] = userPlane[1];
-				if(clipFlags & Clipper::CLIP_PLANE2) clipPlane[2] = userPlane[2];
-				if(clipFlags & Clipper::CLIP_PLANE3) clipPlane[3] = userPlane[3];
-				if(clipFlags & Clipper::CLIP_PLANE4) clipPlane[4] = userPlane[4];
-				if(clipFlags & Clipper::CLIP_PLANE5) clipPlane[5] = userPlane[5];
-			}
+			if(clipFlags & Clipper::CLIP_PLANE0) clipPlane[0] = userPlane[0];
+			if(clipFlags & Clipper::CLIP_PLANE1) clipPlane[1] = userPlane[1];
+			if(clipFlags & Clipper::CLIP_PLANE2) clipPlane[2] = userPlane[2];
+			if(clipFlags & Clipper::CLIP_PLANE3) clipPlane[3] = userPlane[3];
+			if(clipFlags & Clipper::CLIP_PLANE4) clipPlane[4] = userPlane[4];
+			if(clipFlags & Clipper::CLIP_PLANE5) clipPlane[5] = userPlane[5];
 
 			updateClipPlanes = false;
 		}
@@ -2484,28 +2113,6 @@
 		}
 	}
 
-	void Renderer::setSyncRequired(SamplerType type, int sampler, bool syncRequired)
-	{
-		if(type == SAMPLER_PIXEL)
-		{
-			PixelProcessor::setSyncRequired(sampler, syncRequired);
-		}
-		else
-		{
-			VertexProcessor::setSyncRequired(sampler, syncRequired);
-		}
-	}
-
-	void Renderer::setPointSpriteEnable(bool pointSpriteEnable)
-	{
-		context->setPointSpriteEnable(pointSpriteEnable);
-	}
-
-	void Renderer::setPointScaleEnable(bool pointScaleEnable)
-	{
-		context->setPointScaleEnable(pointScaleEnable);
-	}
-
 	void Renderer::setLineWidth(float width)
 	{
 		context->lineWidth = width;
@@ -2642,29 +2249,6 @@
 		}
 	}
 
-	void Renderer::setModelMatrix(const Matrix &M, int i)
-	{
-		VertexProcessor::setModelMatrix(M, i);
-	}
-
-	void Renderer::setViewMatrix(const Matrix &V)
-	{
-		VertexProcessor::setViewMatrix(V);
-		updateClipPlanes = true;
-	}
-
-	void Renderer::setBaseMatrix(const Matrix &B)
-	{
-		VertexProcessor::setBaseMatrix(B);
-		updateClipPlanes = true;
-	}
-
-	void Renderer::setProjectionMatrix(const Matrix &P)
-	{
-		VertexProcessor::setProjectionMatrix(P);
-		updateClipPlanes = true;
-	}
-
 	void Renderer::addQuery(Query *query)
 	{
 		queries.push_back(query);
diff --git a/src/Device/Renderer.hpp b/src/Device/Renderer.hpp
index 2f5e23f..539a48d 100644
--- a/src/Device/Renderer.hpp
+++ b/src/Device/Renderer.hpp
@@ -135,29 +135,23 @@
 
 		struct PS
 		{
-			word4 cW[8][4];
 			float4 c[FRAGMENT_UNIFORM_VECTORS];
 			byte* u[MAX_UNIFORM_BUFFER_BINDINGS];
 			int4 i[16];
 			bool b[16];
 		};
 
-		union
-		{
-			VS vs;
-			VertexProcessor::FixedFunction ff;
-		};
-
+		VS vs;
 		PS ps;
 
 		int instanceID;
 
-		VertexProcessor::PointSprite point;
+		float pointSizeMin;
+		float pointSizeMax;
 		float lineWidth;
 
 		PixelProcessor::Stencil stencil[2];   // clockwise, counterclockwise
 		PixelProcessor::Stencil stencilCCW;
-		PixelProcessor::Fog fog;
 		PixelProcessor::Factor factor;
 		unsigned int occlusion[16];   // Number of pixels passing depth test
 
@@ -165,14 +159,10 @@
 			int64_t cycles[PERF_TIMERS][16];
 		#endif
 
-		TextureStage::Uniforms textureStage[8];
-
 		float4 Wx16;
 		float4 Hx16;
 		float4 X0x16;
 		float4 Y0x16;
-		float4 XXXX;
-		float4 YYYY;
 		float4 halfPixelX;
 		float4 halfPixelY;
 		float viewportHeight;
@@ -304,10 +294,7 @@
 		void setMaxLevel(SamplerType type, int sampler, int maxLevel);
 		void setMinLod(SamplerType type, int sampler, float minLod);
 		void setMaxLod(SamplerType type, int sampler, float maxLod);
-		void setSyncRequired(SamplerType type, int sampler, bool syncRequired);
 
-		void setPointSpriteEnable(bool pointSpriteEnable);
-		void setPointScaleEnable(bool pointScaleEnable);
 		void setLineWidth(float width);
 
 		void setDepthBias(float bias);
@@ -366,9 +353,7 @@
 
 		void processPrimitiveVertices(int unit, unsigned int start, unsigned int count, unsigned int loop, int thread);
 
-		int setupSolidTriangles(int batch, int count);
-		int setupWireframeTriangle(int batch, int count);
-		int setupVertexTriangle(int batch, int count);
+		int setupTriangles(int batch, int count);
 		int setupLines(int batch, int count);
 		int setupPoints(int batch, int count);
 
diff --git a/src/Device/Sampler.cpp b/src/Device/Sampler.cpp
index f0bd1a8..2f33684 100644
--- a/src/Device/Sampler.cpp
+++ b/src/Device/Sampler.cpp
@@ -401,16 +401,6 @@
 		return textureType == TEXTURE_3D || textureType == TEXTURE_2D_ARRAY;
 	}
 
-	void Sampler::setSyncRequired(bool isSyncRequired)
-	{
-		syncRequired = isSyncRequired;
-	}
-
-	bool Sampler::requiresSync() const
-	{
-		return syncRequired;
-	}
-
 	const Texture &Sampler::getTextureData()
 	{
 		return texture;
diff --git a/src/Device/Sampler.hpp b/src/Device/Sampler.hpp
index c6fc90c..81b308d 100644
--- a/src/Device/Sampler.hpp
+++ b/src/Device/Sampler.hpp
@@ -193,7 +193,6 @@
 		void setMaxLevel(int maxLevel);
 		void setMinLod(float minLod);
 		void setMaxLod(float maxLod);
-		void setSyncRequired(bool isSincRequired);
 
 		static void setFilterQuality(FilterType maximumFilterQuality);
 		static void setMipmapQuality(MipmapType maximumFilterQuality);
@@ -203,7 +202,6 @@
 		bool hasUnsignedTexture() const;
 		bool hasCubeTexture() const;
 		bool hasVolumeTexture() const;
-		bool requiresSync() const;
 
 		const Texture &getTextureData();
 
@@ -228,7 +226,6 @@
 		bool sRGB;
 		bool gather;
 		bool highPrecisionFiltering;
-		bool syncRequired;
 		int border;
 
 		SwizzleType swizzleR;
diff --git a/src/Device/SetupProcessor.cpp b/src/Device/SetupProcessor.cpp
index dffff48..029fb1a 100644
--- a/src/Device/SetupProcessor.cpp
+++ b/src/Device/SetupProcessor.cpp
@@ -59,14 +59,14 @@
 
 	SetupProcessor::SetupProcessor(Context *context) : context(context)
 	{
-		routineCache = 0;
+		routineCache = nullptr;
 		setRoutineCacheSize(1024);
 	}
 
 	SetupProcessor::~SetupProcessor()
 	{
 		delete routineCache;
-		routineCache = 0;
+		routineCache = nullptr;
 	}
 
 	SetupProcessor::State SetupProcessor::update() const
@@ -75,14 +75,12 @@
 
 		bool vPosZW = (context->pixelShader && context->pixelShader->isVPosDeclared() && fullPixelPositionRegister);
 
-		state.isDrawPoint = context->isDrawPoint(true);
-		state.isDrawLine = context->isDrawLine(true);
-		state.isDrawTriangle = context->isDrawTriangle(false);
-		state.isDrawSolidTriangle = context->isDrawTriangle(true);
-		state.interpolateZ = context->depthBufferActive() || context->pixelFogActive() != FOG_NONE || vPosZW;
+		state.isDrawPoint = context->isDrawPoint();
+		state.isDrawLine = context->isDrawLine();
+		state.isDrawTriangle = context->isDrawTriangle();
+		state.interpolateZ = context->depthBufferActive() || vPosZW;
 		state.interpolateW = context->perspectiveActive() || vPosZW;
 		state.perspective = context->perspectiveActive();
-		state.pointSprite = context->pointSpriteActive();
 		state.cullMode = context->cullMode;
 		state.twoSidedStencil = context->stencilActive() && context->twoSidedStencil;
 		state.slopeDepthBias = context->slopeDepthBias != 0.0f;
@@ -94,15 +92,8 @@
 		state.multiSample = context->getMultiSampleCount();
 		state.rasterizerDiscard = context->rasterizerDiscard;
 
-		if(context->vertexShader)
-		{
-			state.positionRegister = context->vertexShader->getPositionRegister();
-			state.pointSizeRegister = context->vertexShader->getPointSizeRegister();
-		}
-		else if(context->pointSizeActive())
-		{
-			state.pointSizeRegister = Pts;
-		}
+		state.positionRegister = context->vertexShader->getPositionRegister();
+		state.pointSizeRegister = context->vertexShader->getPointSizeRegister();
 
 		for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
 		{
@@ -114,109 +105,39 @@
 			}
 		}
 
-		state.fog.attribute = Unused;
-		state.fog.flat = false;
-		state.fog.wrap = false;
+		const bool point = context->isDrawPoint();
 
-		const bool point = context->isDrawPoint(true);
-		const bool sprite = context->pointSpriteActive();
-		const bool flatShading = (context->shadingMode == SHADING_FLAT) || point;
-
-		if(context->vertexShader && context->pixelShader)
+		for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
 		{
-			for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
+			for(int component = 0; component < 4; component++)
 			{
-				for(int component = 0; component < 4; component++)
-				{
-					int project = context->isProjectionComponent(interpolant - 2, component) ? 1 : 0;
-					const Shader::Semantic& semantic = context->pixelShader->getInput(interpolant, component - project);
+				const Shader::Semantic& semantic = context->pixelShader->getInput(interpolant, component);
 
-					if(semantic.active())
+				if(semantic.active())
+				{
+					int input = interpolant;
+					for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++)
 					{
-						int input = interpolant;
-						for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++)
+						if(semantic == context->vertexShader->getOutput(i, component))
 						{
-							if(semantic == context->vertexShader->getOutput(i, component - project))
-							{
-								input = i;
-								break;
-							}
+							input = i;
+							break;
 						}
-
-						bool flat = point;
-
-						switch(semantic.usage)
-						{
-						case Shader::USAGE_TEXCOORD: flat = point && !sprite;             break;
-						case Shader::USAGE_COLOR:    flat = semantic.flat || flatShading; break;
-						}
-
-						state.gradient[interpolant][component].attribute = input;
-						state.gradient[interpolant][component].flat = flat;
 					}
-				}
-			}
-		}
-		else if(context->preTransformed && context->pixelShader)
-		{
-			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);
+
+					bool flat = point;
 
 					switch(semantic.usage)
 					{
-					case 0xFF:
-						break;
-					case Shader::USAGE_TEXCOORD:
-						state.gradient[interpolant][component].attribute = T0 + semantic.index;
-						state.gradient[interpolant][component].flat = semantic.flat || (point && !sprite);
-						break;
-					case Shader::USAGE_COLOR:
-						state.gradient[interpolant][component].attribute = C0 + semantic.index;
-						state.gradient[interpolant][component].flat = semantic.flat || flatShading;
-						break;
-					default:
-						ASSERT(false);
+					case Shader::USAGE_TEXCOORD: flat = false;                  break;
+					case Shader::USAGE_COLOR:    flat = semantic.flat || point; break;
 					}
-				}
-			}
-		}
-		else if(context->pixelShaderModel() < 0x0300)
-		{
-			for(int coordinate = 0; coordinate < 8; coordinate++)
-			{
-				for(int component = 0; component < 4; component++)
-				{
-					if(context->textureActive(coordinate, component))
-					{
-						state.texture[coordinate][component].attribute = T0 + coordinate;
-						state.texture[coordinate][component].flat = point && !sprite;
-						state.texture[coordinate][component].wrap = (context->textureWrap[coordinate] & (1 << component)) != 0;
-					}
-				}
-			}
 
-			for(int color = 0; color < 2; color++)
-			{
-				for(int component = 0; component < 4; component++)
-				{
-					if(context->colorActive(color, component))
-					{
-						state.color[color][component].attribute = C0 + color;
-						state.color[color][component].flat = flatShading;
-					}
+					state.gradient[interpolant][component].attribute = input;
+					state.gradient[interpolant][component].flat = flat;
 				}
 			}
 		}
-		else ASSERT(false);
-
-		if(context->fogActive())
-		{
-			state.fog.attribute = Fog;
-			state.fog.flat = point;
-		}
 
 		state.hash = state.computeHash();
 
diff --git a/src/Device/SetupProcessor.hpp b/src/Device/SetupProcessor.hpp
index 4e080dd..622a053 100644
--- a/src/Device/SetupProcessor.hpp
+++ b/src/Device/SetupProcessor.hpp
@@ -40,11 +40,9 @@
 			bool isDrawPoint               : 1;
 			bool isDrawLine                : 1;
 			bool isDrawTriangle            : 1;
-			bool isDrawSolidTriangle       : 1;
 			bool interpolateZ              : 1;
 			bool interpolateW              : 1;
 			bool perspective               : 1;
-			bool pointSprite               : 1;
 			unsigned int positionRegister  : BITS(VERTEX_OUTPUT_LAST);
 			unsigned int pointSizeRegister : BITS(VERTEX_OUTPUT_LAST);
 			CullMode cullMode              : BITS(CULL_LAST);
@@ -61,17 +59,7 @@
 				bool wrap               : 1;
 			};
 
-			union
-			{
-				struct
-				{
-					Gradient color[2][4];
-					Gradient texture[8][4];
-					Gradient fog;
-				};
-
-				Gradient gradient[MAX_FRAGMENT_INPUTS][4];
-			};
+			Gradient gradient[MAX_FRAGMENT_INPUTS][4];
 		};
 
 		struct State : States
diff --git a/src/Device/TextureStage.cpp b/src/Device/TextureStage.cpp
deleted file mode 100644
index 0327478..0000000
--- a/src/Device/TextureStage.cpp
+++ /dev/null
@@ -1,412 +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 "TextureStage.hpp"
-
-#include "Sampler.hpp"
-#include "Common/Debug.hpp"
-
-#include <string.h>
-
-namespace sw
-{
-	TextureStage::State::State()
-	{
-		memset(this, 0, sizeof(State));
-	}
-
-	TextureStage::TextureStage() : sampler(0), previousStage(0)
-	{
-	}
-
-	TextureStage::~TextureStage()
-	{
-	}
-
-	void TextureStage::init(int stage, const Sampler *sampler, const TextureStage *previousStage)
-	{
-		this->stage = stage;
-
-		stageOperation = (stage == 0 ? STAGE_MODULATE : STAGE_DISABLE);
-		firstArgument = SOURCE_TEXTURE;
-		secondArgument = SOURCE_CURRENT;
-		thirdArgument = SOURCE_CURRENT;
-		stageOperationAlpha = (stage == 0 ? STAGE_SELECTARG1 : STAGE_DISABLE);
-		firstArgumentAlpha = SOURCE_DIFFUSE;
-		secondArgumentAlpha = SOURCE_CURRENT;
-		thirdArgumentAlpha = SOURCE_CURRENT;
-		firstModifier = MODIFIER_COLOR;
-		secondModifier = MODIFIER_COLOR;
-		thirdModifier = MODIFIER_COLOR;
-	    firstModifierAlpha = MODIFIER_COLOR;
-		secondModifierAlpha = MODIFIER_COLOR;
-		thirdModifierAlpha = MODIFIER_COLOR;
-		destinationArgument = DESTINATION_CURRENT;
-
-		texCoordIndex = stage;
-		this->sampler = sampler;
-		this->previousStage = previousStage;
-	}
-
-	TextureStage::State TextureStage::textureStageState() const
-	{
-		State state;
-
-		if(!isStageDisabled())
-		{
-			state.stageOperation = stageOperation;
-			state.firstArgument = firstArgument;
-			state.secondArgument = secondArgument;
-			state.thirdArgument = thirdArgument;
-			state.stageOperationAlpha = stageOperationAlpha;
-			state.firstArgumentAlpha = firstArgumentAlpha;
-			state.secondArgumentAlpha = secondArgumentAlpha;
-			state.thirdArgumentAlpha = thirdArgumentAlpha;
-			state.firstModifier = firstModifier;
-			state.secondModifier = secondModifier;
-			state.thirdModifier = thirdModifier;
-			state.firstModifierAlpha = firstModifierAlpha;
-			state.secondModifierAlpha = secondModifierAlpha;
-			state.thirdModifierAlpha = thirdModifierAlpha;
-			state.destinationArgument = destinationArgument;
-			state.texCoordIndex = texCoordIndex;
-
-			state.cantUnderflow = sampler->hasUnsignedTexture() || !usesTexture();
-			state.usesTexture = usesTexture();
-		}
-
-		return state;
-	}
-
-	void TextureStage::setConstantColor(const Color<float> &constantColor)
-	{
-		// FIXME: Compact into generic function   // FIXME: Clamp
-		short r = iround(4095 * constantColor.r);
-		short g = iround(4095 * constantColor.g);
-		short b = iround(4095 * constantColor.b);
-		short a = iround(4095 * constantColor.a);
-
-		uniforms.constantColor4[0][0] = uniforms.constantColor4[0][1] = uniforms.constantColor4[0][2] = uniforms.constantColor4[0][3] = r;
-		uniforms.constantColor4[1][0] = uniforms.constantColor4[1][1] = uniforms.constantColor4[1][2] = uniforms.constantColor4[1][3] = g;
-		uniforms.constantColor4[2][0] = uniforms.constantColor4[2][1] = uniforms.constantColor4[2][2] = uniforms.constantColor4[2][3] = b;
-		uniforms.constantColor4[3][0] = uniforms.constantColor4[3][1] = uniforms.constantColor4[3][2] = uniforms.constantColor4[3][3] = a;
-	}
-
-	void TextureStage::setBumpmapMatrix(int element, float value)
-	{
-		uniforms.bumpmapMatrix4F[element / 2][element % 2][0] = value;
-		uniforms.bumpmapMatrix4F[element / 2][element % 2][1] = value;
-		uniforms.bumpmapMatrix4F[element / 2][element % 2][2] = value;
-		uniforms.bumpmapMatrix4F[element / 2][element % 2][3] = value;
-
-		uniforms.bumpmapMatrix4W[element / 2][element % 2][0] = iround(4095 * value);
-		uniforms.bumpmapMatrix4W[element / 2][element % 2][1] = iround(4095 * value);
-		uniforms.bumpmapMatrix4W[element / 2][element % 2][2] = iround(4095 * value);
-		uniforms.bumpmapMatrix4W[element / 2][element % 2][3] = iround(4095 * value);
-	}
-
-	void TextureStage::setLuminanceScale(float value)
-	{
-		short scale = iround(4095 * value);
-
-		uniforms.luminanceScale4[0] = uniforms.luminanceScale4[1] = uniforms.luminanceScale4[2] = uniforms.luminanceScale4[3] = scale;
-	}
-
-	void TextureStage::setLuminanceOffset(float value)
-	{
-		short offset = iround(4095 * value);
-
-		uniforms.luminanceOffset4[0] = uniforms.luminanceOffset4[1] = uniforms.luminanceOffset4[2] = uniforms.luminanceOffset4[3] = offset;
-	}
-
-	void TextureStage::setTexCoordIndex(unsigned int texCoordIndex)
-	{
-		ASSERT(texCoordIndex < 8);
-
-		this->texCoordIndex = texCoordIndex;
-	}
-
-	void TextureStage::setStageOperation(StageOperation stageOperation)
-	{
-		this->stageOperation = stageOperation;
-	}
-
-	void TextureStage::setFirstArgument(SourceArgument firstArgument)
-	{
-		this->firstArgument = firstArgument;
-	}
-
-	void TextureStage::setSecondArgument(SourceArgument secondArgument)
-	{
-		this->secondArgument = secondArgument;
-	}
-
-	void TextureStage::setThirdArgument(SourceArgument thirdArgument)
-	{
-		this->thirdArgument = thirdArgument;
-	}
-
-	void TextureStage::setStageOperationAlpha(StageOperation stageOperationAlpha)
-	{
-		this->stageOperationAlpha = stageOperationAlpha;
-	}
-
-	void TextureStage::setFirstArgumentAlpha(SourceArgument firstArgumentAlpha)
-	{
-		this->firstArgumentAlpha = firstArgumentAlpha;
-	}
-
-	void TextureStage::setSecondArgumentAlpha(SourceArgument secondArgumentAlpha)
-	{
-		this->secondArgumentAlpha = secondArgumentAlpha;
-	}
-
-	void TextureStage::setThirdArgumentAlpha(SourceArgument thirdArgumentAlpha)
-	{
-		this->thirdArgumentAlpha= thirdArgumentAlpha;
-	}
-
-	void TextureStage::setFirstModifier(ArgumentModifier firstModifier)
-	{
-		this->firstModifier = firstModifier;
-	}
-
-	void TextureStage::setSecondModifier(ArgumentModifier secondModifier)
-	{
-		this->secondModifier = secondModifier;
-	}
-
-	void TextureStage::setThirdModifier(ArgumentModifier thirdModifier)
-	{
-		this->thirdModifier = thirdModifier;
-	}
-
-	void TextureStage::setFirstModifierAlpha(ArgumentModifier firstModifierAlpha)
-	{
-		this->firstModifierAlpha = firstModifierAlpha;
-	}
-
-	void TextureStage::setSecondModifierAlpha(ArgumentModifier secondModifierAlpha)
-	{
-		this->secondModifierAlpha = secondModifierAlpha;
-	}
-
-	void TextureStage::setThirdModifierAlpha(ArgumentModifier thirdModifierAlpha)
-	{
-		this->thirdModifierAlpha = thirdModifierAlpha;
-	}
-
-	void TextureStage::setDestinationArgument(DestinationArgument destinationArgument)
-	{
-		this->destinationArgument = destinationArgument;
-	}
-
-	bool TextureStage::usesColor(SourceArgument source) const
-	{
-		// One argument
-		if(stageOperation == STAGE_SELECTARG1 || stageOperation == STAGE_PREMODULATE)
-		{
-			return firstArgument == source;
-		}
-		else if(stageOperation == STAGE_SELECTARG2)
-		{
-			return secondArgument == source;
-		}
-		else if(stageOperation == STAGE_SELECTARG3)
-		{
-			return thirdArgument == source;
-		}
-		else
-		{
-			// Two arguments or more
-			if(firstArgument == source || secondArgument == source)
-			{
-				return true;
-			}
-
-			// Three arguments
-			if(stageOperation == STAGE_MULTIPLYADD || stageOperation == STAGE_LERP)
-			{
-				return thirdArgument == source;
-			}
-		}
-	
-		return false;
-	}
-
-	bool TextureStage::usesAlpha(SourceArgument source) const
-	{
-		if(stageOperationAlpha == STAGE_DISABLE)
-		{
-			return false;
-		}
-
-		if(source == SOURCE_TEXTURE)
-		{
-			if(stageOperation == STAGE_BLENDTEXTUREALPHA ||	stageOperation == STAGE_BLENDTEXTUREALPHAPM)
-			{
-				return true;
-			}
-		}
-		else if(source == SOURCE_CURRENT)
-		{
-			if(stageOperation == STAGE_BLENDCURRENTALPHA)
-			{
-				return true;
-			}
-		}
-		else if(source == SOURCE_DIFFUSE)
-		{
-			if(stageOperation == STAGE_BLENDDIFFUSEALPHA)
-			{
-				return true;
-			}
-		}
-		else if(source == SOURCE_TFACTOR)
-		{
-			if(stageOperation == STAGE_BLENDFACTORALPHA)
-			{
-				return true;
-			}
-		}
-
-		// One argument
-		if(stageOperation == STAGE_SELECTARG1 || stageOperation == STAGE_PREMODULATE)
-		{
-			if(firstArgument == source && (firstModifier == MODIFIER_ALPHA || firstModifier == MODIFIER_INVALPHA))
-			{
-				return true;
-			}
-		}
-		else if(stageOperation == STAGE_SELECTARG2)
-		{
-			if(secondArgument == source && (secondModifier == MODIFIER_ALPHA || secondModifier == MODIFIER_INVALPHA))
-			{
-				return true;
-			}
-		}
-		else if(stageOperation == STAGE_SELECTARG3)
-		{
-			if(thirdArgument == source && (thirdModifier == MODIFIER_ALPHA || thirdModifier == MODIFIER_INVALPHA))
-			{
-				return true;
-			}
-		}
-		else
-		{
-			// Two arguments or more
-			if(firstArgument == source || secondArgument == source)
-			{
-				if(firstArgument == source && (firstModifier == MODIFIER_ALPHA || firstModifier == MODIFIER_INVALPHA))
-				{
-					return true;
-				}
-
-				if(secondArgument == source && (secondModifier == MODIFIER_ALPHA || secondModifier == MODIFIER_INVALPHA))
-				{
-					return true;
-				}
-			}
-
-			// Three arguments
-			if(stageOperation == STAGE_MULTIPLYADD || stageOperation == STAGE_LERP)
-			{
-				if(thirdArgument == source && (thirdModifier == MODIFIER_ALPHA || thirdModifier == MODIFIER_INVALPHA))
-				{
-					return true;
-				}
-			}
-		}
-
-		// One argument
-		if(stageOperationAlpha == STAGE_SELECTARG1 || stageOperationAlpha == STAGE_PREMODULATE)
-		{
-			return firstArgumentAlpha == source;
-		}
-		else if(stageOperationAlpha == STAGE_SELECTARG2)
-		{
-			return secondArgumentAlpha == source;
-		}
-		else if(stageOperationAlpha == STAGE_SELECTARG3)
-		{
-			return thirdArgumentAlpha == source;
-		}
-		else
-		{
-			// Two arguments or more
-			if(firstArgumentAlpha == source || secondArgumentAlpha == source)
-			{
-				return true;
-			}
-
-			// Three arguments
-			if(stageOperationAlpha == STAGE_MULTIPLYADD || stageOperationAlpha == STAGE_LERP)
-			{
-				return thirdArgumentAlpha == source;
-			}
-		}
-		
-		return false;
-	}
-
-	bool TextureStage::uses(SourceArgument source) const
-	{
-		return usesColor(source) || usesAlpha(source);
-	}
-
-	bool TextureStage::usesCurrent() const
-	{
-		return uses(SOURCE_CURRENT) || (stageOperation == STAGE_BLENDCURRENTALPHA || stageOperationAlpha == STAGE_BLENDCURRENTALPHA);
-	}
-
-	bool TextureStage::usesDiffuse() const
-	{
-		return uses(SOURCE_DIFFUSE) || (stageOperation == STAGE_BLENDDIFFUSEALPHA || stageOperationAlpha == STAGE_BLENDDIFFUSEALPHA);
-	}
-
-	bool TextureStage::usesSpecular() const
-	{
-		return uses(SOURCE_SPECULAR);
-	}
-
-	bool TextureStage::usesTexture() const
-	{
-		return uses(SOURCE_TEXTURE) ||
-		       stageOperation == STAGE_BLENDTEXTUREALPHA ||
-		       stageOperationAlpha == STAGE_BLENDTEXTUREALPHA ||
-		       stageOperation == STAGE_BLENDTEXTUREALPHAPM ||
-		       stageOperationAlpha == STAGE_BLENDTEXTUREALPHAPM ||
-		       (previousStage && previousStage->stageOperation == STAGE_PREMODULATE) ||
-		       (previousStage && previousStage->stageOperationAlpha == STAGE_PREMODULATE);
-	}
-
-	bool TextureStage::isStageDisabled() const
-	{
-		bool disabled = (stageOperation == STAGE_DISABLE) || (!sampler->hasTexture() && usesTexture());
-
-		if(!previousStage || disabled)
-		{
-			return disabled;
-		}
-		else
-		{
-			return previousStage->isStageDisabled();
-		}
-	}
-
-	bool TextureStage::writesCurrent() const
-	{
-		return !isStageDisabled() && destinationArgument == DESTINATION_CURRENT && stageOperation != STAGE_BUMPENVMAP && stageOperation != STAGE_BUMPENVMAPLUMINANCE;
-	}
-}
diff --git a/src/Device/TextureStage.hpp b/src/Device/TextureStage.hpp
deleted file mode 100644
index 8e71b25..0000000
--- a/src/Device/TextureStage.hpp
+++ /dev/null
@@ -1,198 +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_TextureStage_hpp
-#define sw_TextureStage_hpp
-
-#include "System/Types.hpp"
-#include "System/Math.hpp"
-#include "Device/Color.hpp"
-
-namespace sw
-{
-	class Sampler;
-	class PixelRoutine;
-	class Context;
-
-	class TextureStage
-	{
-		friend class Context;   // FIXME
-
-	public:
-		enum StageOperation
-		{
-			STAGE_DISABLE,
-			STAGE_SELECTARG1,
-			STAGE_SELECTARG2,
-			STAGE_SELECTARG3,
-			STAGE_MODULATE,
-			STAGE_MODULATE2X,
-			STAGE_MODULATE4X,
-			STAGE_ADD,
-			STAGE_ADDSIGNED,
-			STAGE_ADDSIGNED2X,
-			STAGE_SUBTRACT,
-			STAGE_ADDSMOOTH,
-			STAGE_MULTIPLYADD,
-			STAGE_LERP,
-			STAGE_DOT3,
-			STAGE_BLENDCURRENTALPHA,
-			STAGE_BLENDDIFFUSEALPHA,
-			STAGE_BLENDFACTORALPHA,
-			STAGE_BLENDTEXTUREALPHA,
-			STAGE_BLENDTEXTUREALPHAPM,
-			STAGE_PREMODULATE,
-			STAGE_MODULATEALPHA_ADDCOLOR,
-			STAGE_MODULATECOLOR_ADDALPHA,
-			STAGE_MODULATEINVALPHA_ADDCOLOR,
-			STAGE_MODULATEINVCOLOR_ADDALPHA,
-			STAGE_BUMPENVMAP,
-			STAGE_BUMPENVMAPLUMINANCE,
-
-			STAGE_LAST = STAGE_BUMPENVMAPLUMINANCE
-		};
-
-		enum SourceArgument
-		{
-			SOURCE_TEXTURE,
-			SOURCE_CONSTANT,
-			SOURCE_CURRENT,
-			SOURCE_DIFFUSE,
-			SOURCE_SPECULAR,
-			SOURCE_TEMP,
-			SOURCE_TFACTOR,
-
-			SOURCE_LAST = SOURCE_TFACTOR
-		};
-
-		enum DestinationArgument
-		{
-			DESTINATION_CURRENT,
-			DESTINATION_TEMP,
-
-			DESTINATION_LAST = DESTINATION_TEMP
-		};
-
-		enum ArgumentModifier
-		{
-			MODIFIER_COLOR,
-			MODIFIER_INVCOLOR,
-			MODIFIER_ALPHA,
-			MODIFIER_INVALPHA,
-
-			MODIFIER_LAST = MODIFIER_INVALPHA
-		};
-
-		struct State
-		{
-			State();
-
-			unsigned int stageOperation			: BITS(STAGE_LAST);
-			unsigned int firstArgument			: BITS(SOURCE_LAST);
-			unsigned int secondArgument			: BITS(SOURCE_LAST);
-			unsigned int thirdArgument			: BITS(SOURCE_LAST);
-			unsigned int stageOperationAlpha	: BITS(STAGE_LAST);
-			unsigned int firstArgumentAlpha		: BITS(SOURCE_LAST);
-			unsigned int secondArgumentAlpha	: BITS(SOURCE_LAST);
-			unsigned int thirdArgumentAlpha		: BITS(SOURCE_LAST);
-			unsigned int firstModifier			: BITS(MODIFIER_LAST);
-			unsigned int secondModifier			: BITS(MODIFIER_LAST);
-			unsigned int thirdModifier			: BITS(MODIFIER_LAST);
-			unsigned int firstModifierAlpha		: BITS(MODIFIER_LAST);
-			unsigned int secondModifierAlpha	: BITS(MODIFIER_LAST);
-			unsigned int thirdModifierAlpha		: BITS(MODIFIER_LAST);
-			unsigned int destinationArgument	: BITS(DESTINATION_LAST);
-			unsigned int texCoordIndex			: BITS(7);
-
-			unsigned int cantUnderflow			: 1;
-			unsigned int usesTexture			: 1;
-		};
-
-		struct Uniforms
-		{
-			word4 constantColor4[4];
-			float4 bumpmapMatrix4F[2][2];
-			word4 bumpmapMatrix4W[2][2];
-			word4 luminanceScale4;
-			word4 luminanceOffset4;
-		};
-
-		TextureStage();
-
-		~TextureStage();
-
-		void init(int stage, const Sampler *sampler, const TextureStage *previousStage);
-
-		State textureStageState() const;
-
-		void setConstantColor(const Color<float> &constantColor);
-		void setBumpmapMatrix(int element, float value);
-		void setLuminanceScale(float value);
-		void setLuminanceOffset(float value);
-
-		void setTexCoordIndex(unsigned int texCoordIndex);
-		void setStageOperation(StageOperation stageOperation);
-		void setFirstArgument(SourceArgument firstArgument);
-		void setSecondArgument(SourceArgument secondArgument);
-		void setThirdArgument(SourceArgument thirdArgument);
-		void setStageOperationAlpha(StageOperation stageOperationAlpha);
-		void setFirstArgumentAlpha(SourceArgument firstArgumentAlpha);
-		void setSecondArgumentAlpha(SourceArgument secondArgumentAlpha);
-		void setThirdArgumentAlpha(SourceArgument thirdArgumentAlpha);
-		void setFirstModifier(ArgumentModifier firstModifier);
-		void setSecondModifier(ArgumentModifier secondModifier);
-		void setThirdModifier(ArgumentModifier thirdModifier);
-		void setFirstModifierAlpha(ArgumentModifier firstModifierAlpha);
-		void setSecondModifierAlpha(ArgumentModifier secondModifierAlpha);
-		void setThirdModifierAlpha(ArgumentModifier thirdModifierAlpha);
-		void setDestinationArgument(DestinationArgument destinationArgument);
-
-		Uniforms uniforms;   // FIXME: Private
-
-	private:
-		bool usesColor(SourceArgument source) const;
-		bool usesAlpha(SourceArgument source) const;
-		bool uses(SourceArgument source) const;
-		bool usesCurrent() const;
-		bool usesDiffuse() const;
-		bool usesSpecular() const;
-		bool usesTexture() const;
-		bool isStageDisabled() const;
-		bool writesCurrent() const;
-
-		int stage;
-
-		StageOperation stageOperation;
-		SourceArgument firstArgument;
-		SourceArgument secondArgument;
-		SourceArgument thirdArgument;
-		StageOperation stageOperationAlpha;
-		SourceArgument firstArgumentAlpha;
-		SourceArgument secondArgumentAlpha;
-		SourceArgument thirdArgumentAlpha;
-		ArgumentModifier firstModifier;
-		ArgumentModifier secondModifier;
-		ArgumentModifier thirdModifier;
-		ArgumentModifier firstModifierAlpha;
-		ArgumentModifier secondModifierAlpha;
-		ArgumentModifier thirdModifierAlpha;
-		DestinationArgument destinationArgument;
-
-		int texCoordIndex;
-		const Sampler *sampler;
-		const TextureStage *previousStage;
-	};
-}
-
-#endif  // sw_TextureStage_hpp
diff --git a/src/Device/VertexProcessor.cpp b/src/Device/VertexProcessor.cpp
index 5c5e1fd..9fc7308 100644
--- a/src/Device/VertexProcessor.cpp
+++ b/src/Device/VertexProcessor.cpp
@@ -14,7 +14,6 @@
 
 #include "VertexProcessor.hpp"
 
-#include "Pipeline/VertexPipeline.hpp"
 #include "Pipeline/VertexProgram.hpp"
 #include "Pipeline/VertexShader.hpp"
 #include "Pipeline/PixelShader.hpp"
@@ -82,50 +81,14 @@
 
 	VertexProcessor::VertexProcessor(Context *context) : context(context)
 	{
-		for(int i = 0; i < 12; i++)
-		{
-			M[i] = 1;
-		}
-
-		V = 1;
-		B = 1;
-		P = 0;
-		PB = 0;
-		PBV = 0;
-
-		for(int i = 0; i < 12; i++)
-		{
-			PBVM[i] = 0;
-		}
-
-		setLightingEnable(true);
-		setSpecularEnable(false);
-
-		for(int i = 0; i < 8; i++)
-		{
-			setLightEnable(i, false);
-			setLightPosition(i, 0);
-		}
-
-		updateMatrix = true;
-		updateViewMatrix = true;
-		updateBaseMatrix = true;
-		updateProjectionMatrix = true;
-		updateLighting = true;
-
-		for(int i = 0; i < 12; i++)
-		{
-			updateModelMatrix[i] = true;
-		}
-
-		routineCache = 0;
+		routineCache = nullptr;
 		setRoutineCacheSize(1024);
 	}
 
 	VertexProcessor::~VertexProcessor()
 	{
 		delete routineCache;
-		routineCache = 0;
+		routineCache = nullptr;
 	}
 
 	void VertexProcessor::setInputStream(int index, const Stream &stream)
@@ -133,14 +96,12 @@
 		context->input[index] = stream;
 	}
 
-	void VertexProcessor::resetInputStreams(bool preTransformed)
+	void VertexProcessor::resetInputStreams()
 	{
 		for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
 		{
 			context->input[i].defaults();
 		}
-
-		context->preTransformed = preTransformed;
 	}
 
 	void VertexProcessor::setFloatConstant(unsigned int index, const float value[4])
@@ -214,304 +175,11 @@
 		}
 	}
 
-	void VertexProcessor::setModelMatrix(const Matrix &M, int i)
-	{
-		if(i < 12)
-		{
-			this->M[i] = M;
-
-			updateMatrix = true;
-			updateModelMatrix[i] = true;
-			updateLighting = true;
-		}
-		else ASSERT(false);
-	}
-
-	void VertexProcessor::setViewMatrix(const Matrix &V)
-	{
-		this->V = V;
-
-		updateMatrix = true;
-		updateViewMatrix = true;
-	}
-
-	void VertexProcessor::setBaseMatrix(const Matrix &B)
-	{
-		this->B = B;
-
-		updateMatrix = true;
-		updateBaseMatrix = true;
-	}
-
-	void VertexProcessor::setProjectionMatrix(const Matrix &P)
-	{
-		this->P = P;
-		context->wBasedFog = (P[3][0] != 0.0f) || (P[3][1] != 0.0f) || (P[3][2] != 0.0f) || (P[3][3] != 1.0f);
-
-		updateMatrix = true;
-		updateProjectionMatrix = true;
-	}
-
-	void VertexProcessor::setLightingEnable(bool lightingEnable)
-	{
-		context->setLightingEnable(lightingEnable);
-
-		updateLighting = true;
-	}
-
-	void VertexProcessor::setLightEnable(unsigned int light, bool lightEnable)
-	{
-		if(light < 8)
-		{
-			context->setLightEnable(light, lightEnable);
-		}
-		else ASSERT(false);
-
-		updateLighting = true;
-	}
-
-	void VertexProcessor::setSpecularEnable(bool specularEnable)
-	{
-		context->setSpecularEnable(specularEnable);
-
-		updateLighting = true;
-	}
-
-	void VertexProcessor::setLightPosition(unsigned int light, const Point &lightPosition)
-	{
-		if(light < 8)
-		{
-			context->setLightPosition(light, lightPosition);
-		}
-		else ASSERT(false);
-
-		updateLighting = true;
-	}
-
-	void VertexProcessor::setLightDiffuse(unsigned int light, const Color<float> &lightDiffuse)
-	{
-		if(light < 8)
-		{
-			ff.lightDiffuse[light][0] = lightDiffuse.r;
-			ff.lightDiffuse[light][1] = lightDiffuse.g;
-			ff.lightDiffuse[light][2] = lightDiffuse.b;
-			ff.lightDiffuse[light][3] = lightDiffuse.a;
-		}
-		else ASSERT(false);
-	}
-
-	void VertexProcessor::setLightSpecular(unsigned int light, const Color<float> &lightSpecular)
-	{
-		if(light < 8)
-		{
-			ff.lightSpecular[light][0] = lightSpecular.r;
-			ff.lightSpecular[light][1] = lightSpecular.g;
-			ff.lightSpecular[light][2] = lightSpecular.b;
-			ff.lightSpecular[light][3] = lightSpecular.a;
-		}
-		else ASSERT(false);
-	}
-
-	void VertexProcessor::setLightAmbient(unsigned int light, const Color<float> &lightAmbient)
-	{
-		if(light < 8)
-		{
-			ff.lightAmbient[light][0] = lightAmbient.r;
-			ff.lightAmbient[light][1] = lightAmbient.g;
-			ff.lightAmbient[light][2] = lightAmbient.b;
-			ff.lightAmbient[light][3] = lightAmbient.a;
-		}
-		else ASSERT(false);
-	}
-
-	void VertexProcessor::setLightAttenuation(unsigned int light, float constant, float linear, float quadratic)
-	{
-		if(light < 8)
-		{
-			ff.attenuationConstant[light] = replicate(constant);
-			ff.attenuationLinear[light] = replicate(linear);
-			ff.attenuationQuadratic[light] = replicate(quadratic);
-		}
-		else ASSERT(false);
-	}
-
-	void VertexProcessor::setLightRange(unsigned int light, float lightRange)
-	{
-		if(light < 8)
-		{
-			ff.lightRange[light] = lightRange;
-		}
-		else ASSERT(false);
-	}
-
-	void VertexProcessor::setFogEnable(bool fogEnable)
-	{
-		context->fogEnable = fogEnable;
-	}
-
-	void VertexProcessor::setVertexFogMode(FogMode fogMode)
-	{
-		context->vertexFogMode = fogMode;
-	}
-
 	void VertexProcessor::setInstanceID(int instanceID)
 	{
 		context->instanceID = instanceID;
 	}
 
-	void VertexProcessor::setColorVertexEnable(bool colorVertexEnable)
-	{
-		context->setColorVertexEnable(colorVertexEnable);
-	}
-
-	void VertexProcessor::setDiffuseMaterialSource(MaterialSource diffuseMaterialSource)
-	{
-		context->setDiffuseMaterialSource(diffuseMaterialSource);
-	}
-
-	void VertexProcessor::setSpecularMaterialSource(MaterialSource specularMaterialSource)
-	{
-		context->setSpecularMaterialSource(specularMaterialSource);
-	}
-
-	void VertexProcessor::setAmbientMaterialSource(MaterialSource ambientMaterialSource)
-	{
-		context->setAmbientMaterialSource(ambientMaterialSource);
-	}
-
-	void VertexProcessor::setEmissiveMaterialSource(MaterialSource emissiveMaterialSource)
-	{
-		context->setEmissiveMaterialSource(emissiveMaterialSource);
-	}
-
-	void VertexProcessor::setGlobalAmbient(const Color<float> &globalAmbient)
-	{
-		ff.globalAmbient[0] = globalAmbient.r;
-		ff.globalAmbient[1] = globalAmbient.g;
-		ff.globalAmbient[2] = globalAmbient.b;
-		ff.globalAmbient[3] = globalAmbient.a;
-	}
-
-	void VertexProcessor::setMaterialEmission(const Color<float> &emission)
-	{
-		ff.materialEmission[0] = emission.r;
-		ff.materialEmission[1] = emission.g;
-		ff.materialEmission[2] = emission.b;
-		ff.materialEmission[3] = emission.a;
-	}
-
-	void VertexProcessor::setMaterialAmbient(const Color<float> &materialAmbient)
-	{
-		ff.materialAmbient[0] = materialAmbient.r;
-		ff.materialAmbient[1] = materialAmbient.g;
-		ff.materialAmbient[2] = materialAmbient.b;
-		ff.materialAmbient[3] = materialAmbient.a;
-	}
-
-	void VertexProcessor::setMaterialDiffuse(const Color<float> &diffuseColor)
-	{
-		ff.materialDiffuse[0] = diffuseColor.r;
-		ff.materialDiffuse[1] = diffuseColor.g;
-		ff.materialDiffuse[2] = diffuseColor.b;
-		ff.materialDiffuse[3] = diffuseColor.a;
-	}
-
-	void VertexProcessor::setMaterialSpecular(const Color<float> &specularColor)
-	{
-		ff.materialSpecular[0] = specularColor.r;
-		ff.materialSpecular[1] = specularColor.g;
-		ff.materialSpecular[2] = specularColor.b;
-		ff.materialSpecular[3] = specularColor.a;
-	}
-
-	void VertexProcessor::setMaterialShininess(float specularPower)
-	{
-		ff.materialShininess = specularPower;
-	}
-
-	void VertexProcessor::setLightViewPosition(unsigned int light, const Point &P)
-	{
-		if(light < 8)
-		{
-			ff.lightPosition[light][0] = P.x;
-			ff.lightPosition[light][1] = P.y;
-			ff.lightPosition[light][2] = P.z;
-			ff.lightPosition[light][3] = 1;
-		}
-		else ASSERT(false);
-	}
-
-	void VertexProcessor::setRangeFogEnable(bool enable)
-	{
-		context->rangeFogEnable = enable;
-	}
-
-	void VertexProcessor::setIndexedVertexBlendEnable(bool indexedVertexBlendEnable)
-	{
-		context->indexedVertexBlendEnable = indexedVertexBlendEnable;
-	}
-
-	void VertexProcessor::setVertexBlendMatrixCount(unsigned int vertexBlendMatrixCount)
-	{
-		if(vertexBlendMatrixCount <= 4)
-		{
-			context->vertexBlendMatrixCount = vertexBlendMatrixCount;
-		}
-		else ASSERT(false);
-	}
-
-	void VertexProcessor::setTextureWrap(unsigned int stage, int mask)
-	{
-		if(stage < TEXTURE_IMAGE_UNITS)
-		{
-			context->textureWrap[stage] = mask;
-		}
-		else ASSERT(false);
-
-		context->textureWrapActive = false;
-
-		for(int i = 0; i < TEXTURE_IMAGE_UNITS; i++)
-		{
-			context->textureWrapActive |= (context->textureWrap[i] != 0x00);
-		}
-	}
-
-	void VertexProcessor::setTexGen(unsigned int stage, TexGen texGen)
-	{
-		if(stage < 8)
-		{
-			context->texGen[stage] = texGen;
-		}
-		else ASSERT(false);
-	}
-
-	void VertexProcessor::setLocalViewer(bool localViewer)
-	{
-		context->localViewer = localViewer;
-	}
-
-	void VertexProcessor::setNormalizeNormals(bool normalizeNormals)
-	{
-		context->normalizeNormals = normalizeNormals;
-	}
-
-	void VertexProcessor::setTextureMatrix(int stage, const Matrix &T)
-	{
-		for(int i = 0; i < 4; i++)
-		{
-			for(int j = 0; j < 4; j++)
-			{
-				ff.textureTransform[stage][i][j] = T[i][j];
-			}
-		}
-	}
-
-	void VertexProcessor::setTextureTransform(int stage, int count, bool project)
-	{
-		context->textureTransformCount[stage] = count;
-		context->textureTransformProject[stage] = project;
-	}
-
 	void VertexProcessor::setTextureFilter(unsigned int sampler, FilterType textureFilter)
 	{
 		if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
@@ -692,43 +360,14 @@
 		else ASSERT(false);
 	}
 
-	void VertexProcessor::setSyncRequired(unsigned int sampler, bool isSincRequired)
-	{
-		if(sampler < TEXTURE_IMAGE_UNITS)
-		{
-			context->sampler[sampler].setSyncRequired(isSincRequired);
-		}
-		else ASSERT(false);
-	}
-
-	void VertexProcessor::setPointSize(float pointSize)
-	{
-		point.pointSize = replicate(pointSize);
-	}
-
 	void VertexProcessor::setPointSizeMin(float pointSizeMin)
 	{
-		point.pointSizeMin = pointSizeMin;
+		this->pointSizeMin = pointSizeMin;
 	}
 
 	void VertexProcessor::setPointSizeMax(float pointSizeMax)
 	{
-		point.pointSizeMax = pointSizeMax;
-	}
-
-	void VertexProcessor::setPointScaleA(float pointScaleA)
-	{
-		point.pointScaleA = pointScaleA;
-	}
-
-	void VertexProcessor::setPointScaleB(float pointScaleB)
-	{
-		point.pointScaleB = pointScaleB;
-	}
-
-	void VertexProcessor::setPointScaleC(float pointScaleC)
-	{
-		point.pointScaleC = pointScaleC;
+		this->pointSizeMax = pointSizeMax;
 	}
 
 	void VertexProcessor::setTransformFeedbackQueryEnabled(bool enable)
@@ -741,161 +380,6 @@
 		context->transformFeedbackEnabled = enable;
 	}
 
-	const Matrix &VertexProcessor::getModelTransform(int i)
-	{
-		updateTransform();
-		return PBVM[i];
-	}
-
-	const Matrix &VertexProcessor::getViewTransform()
-	{
-		updateTransform();
-		return PBV;
-	}
-
-	bool VertexProcessor::isFixedFunction()
-	{
-		return !context->vertexShader;
-	}
-
-	void VertexProcessor::setTransform(const Matrix &M, int i)
-	{
-		ff.transformT[i][0][0] = M[0][0];
-		ff.transformT[i][0][1] = M[1][0];
-		ff.transformT[i][0][2] = M[2][0];
-		ff.transformT[i][0][3] = M[3][0];
-
-		ff.transformT[i][1][0] = M[0][1];
-		ff.transformT[i][1][1] = M[1][1];
-		ff.transformT[i][1][2] = M[2][1];
-		ff.transformT[i][1][3] = M[3][1];
-
-		ff.transformT[i][2][0] = M[0][2];
-		ff.transformT[i][2][1] = M[1][2];
-		ff.transformT[i][2][2] = M[2][2];
-		ff.transformT[i][2][3] = M[3][2];
-
-		ff.transformT[i][3][0] = M[0][3];
-		ff.transformT[i][3][1] = M[1][3];
-		ff.transformT[i][3][2] = M[2][3];
-		ff.transformT[i][3][3] = M[3][3];
-	}
-
-	void VertexProcessor::setCameraTransform(const Matrix &M, int i)
-	{
-		ff.cameraTransformT[i][0][0] = M[0][0];
-		ff.cameraTransformT[i][0][1] = M[1][0];
-		ff.cameraTransformT[i][0][2] = M[2][0];
-		ff.cameraTransformT[i][0][3] = M[3][0];
-
-		ff.cameraTransformT[i][1][0] = M[0][1];
-		ff.cameraTransformT[i][1][1] = M[1][1];
-		ff.cameraTransformT[i][1][2] = M[2][1];
-		ff.cameraTransformT[i][1][3] = M[3][1];
-
-		ff.cameraTransformT[i][2][0] = M[0][2];
-		ff.cameraTransformT[i][2][1] = M[1][2];
-		ff.cameraTransformT[i][2][2] = M[2][2];
-		ff.cameraTransformT[i][2][3] = M[3][2];
-
-		ff.cameraTransformT[i][3][0] = M[0][3];
-		ff.cameraTransformT[i][3][1] = M[1][3];
-		ff.cameraTransformT[i][3][2] = M[2][3];
-		ff.cameraTransformT[i][3][3] = M[3][3];
-	}
-
-	void VertexProcessor::setNormalTransform(const Matrix &M, int i)
-	{
-		ff.normalTransformT[i][0][0] = M[0][0];
-		ff.normalTransformT[i][0][1] = M[1][0];
-		ff.normalTransformT[i][0][2] = M[2][0];
-		ff.normalTransformT[i][0][3] = M[3][0];
-
-		ff.normalTransformT[i][1][0] = M[0][1];
-		ff.normalTransformT[i][1][1] = M[1][1];
-		ff.normalTransformT[i][1][2] = M[2][1];
-		ff.normalTransformT[i][1][3] = M[3][1];
-
-		ff.normalTransformT[i][2][0] = M[0][2];
-		ff.normalTransformT[i][2][1] = M[1][2];
-		ff.normalTransformT[i][2][2] = M[2][2];
-		ff.normalTransformT[i][2][3] = M[3][2];
-
-		ff.normalTransformT[i][3][0] = M[0][3];
-		ff.normalTransformT[i][3][1] = M[1][3];
-		ff.normalTransformT[i][3][2] = M[2][3];
-		ff.normalTransformT[i][3][3] = M[3][3];
-	}
-
-	void VertexProcessor::updateTransform()
-	{
-		if(!updateMatrix) return;
-
-		int activeMatrices = context->indexedVertexBlendEnable ? 12 : max(context->vertexBlendMatrixCount, 1);
-
-		if(updateProjectionMatrix)
-		{
-			PB = P * B;
-			PBV = PB * V;
-
-			for(int i = 0; i < activeMatrices; i++)
-			{
-				PBVM[i] = PBV * M[i];
-				updateModelMatrix[i] = false;
-			}
-
-			updateProjectionMatrix = false;
-			updateBaseMatrix = false;
-			updateViewMatrix = false;
-		}
-
-		if(updateBaseMatrix)
-		{
-			PB = P * B;
-			PBV = PB * V;
-
-			for(int i = 0; i < activeMatrices; i++)
-			{
-				PBVM[i] = PBV * M[i];
-				updateModelMatrix[i] = false;
-			}
-
-			updateBaseMatrix = false;
-			updateViewMatrix = false;
-		}
-
-		if(updateViewMatrix)
-		{
-			PBV = PB * V;
-
-			for(int i = 0; i < activeMatrices; i++)
-			{
-				PBVM[i] = PBV * M[i];
-				updateModelMatrix[i] = false;
-			}
-
-			updateViewMatrix = false;
-		}
-
-		for(int i = 0; i < activeMatrices; i++)
-		{
-			if(updateModelMatrix[i])
-			{
-				PBVM[i] = PBV * M[i];
-				updateModelMatrix[i] = false;
-			}
-		}
-
-		for(int i = 0; i < activeMatrices; i++)
-		{
-			setTransform(PBVM[i], i);
-			setCameraTransform(B * V * M[i], i);
-			setNormalTransform(~!(B * V * M[i]), i);
-		}
-
-		updateMatrix = false;
-	}
-
 	void VertexProcessor::setRoutineCacheSize(int cacheSize)
 	{
 		delete routineCache;
@@ -904,72 +388,15 @@
 
 	const VertexProcessor::State VertexProcessor::update(DrawType drawType)
 	{
-		if(isFixedFunction())
-		{
-			updateTransform();
-
-			if(updateLighting)
-			{
-				for(int i = 0; i < 8; i++)
-				{
-					if(context->vertexLightActive(i))
-					{
-						// Light position in camera coordinates
-						setLightViewPosition(i, B * V * context->getLightPosition(i));
-					}
-				}
-
-				updateLighting = false;
-			}
-		}
-
 		State state;
 
-		if(context->vertexShader)
-		{
-			state.shaderID = context->vertexShader->getSerialID();
-		}
-		else
-		{
-			state.shaderID = 0;
-		}
+		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.vertexBlendMatrixCount = context->vertexBlendMatrixCountActive();
-		state.indexedVertexBlendEnable = context->indexedVertexBlendActive();
-		state.vertexNormalActive = context->vertexNormalActive();
-		state.normalizeNormals = context->normalizeNormalsActive();
-		state.vertexLightingActive = context->vertexLightingActive();
-		state.diffuseActive = context->diffuseActive();
-		state.specularActive = context->specularActive();
-		state.vertexSpecularActive = context->vertexSpecularActive();
-
-		state.vertexLightActive = context->vertexLightActive(0) << 0 |
-		                          context->vertexLightActive(1) << 1 |
-		                          context->vertexLightActive(2) << 2 |
-		                          context->vertexLightActive(3) << 3 |
-		                          context->vertexLightActive(4) << 4 |
-		                          context->vertexLightActive(5) << 5 |
-		                          context->vertexLightActive(6) << 6 |
-		                          context->vertexLightActive(7) << 7;
-
-		state.vertexDiffuseMaterialSourceActive = context->vertexDiffuseMaterialSourceActive();
-		state.vertexSpecularMaterialSourceActive = context->vertexSpecularMaterialSourceActive();
-		state.vertexAmbientMaterialSourceActive = context->vertexAmbientMaterialSourceActive();
-		state.vertexEmissiveMaterialSourceActive = context->vertexEmissiveMaterialSourceActive();
-		state.fogActive = context->fogActive();
-		state.vertexFogMode = context->vertexFogModeActive();
-		state.rangeFogActive = context->rangeFogActive();
-		state.localViewerActive = context->localViewerActive();
-		state.pointSizeActive = context->pointSizeActive();
-		state.pointScaleActive = context->pointScaleActive();
-
-		state.preTransformed = context->preTransformed;
-		state.superSampling = context->getSuperSampleCount() > 1;
 		state.multiSampling = context->getMultiSampleCount() > 1;
 
 		state.transformFeedbackQueryEnabled = context->transformFeedbackQueryEnabled;
@@ -988,24 +415,11 @@
 			state.input[i].attribType = context->vertexShader ? context->vertexShader->getAttribType(i) : VertexShader::ATTRIBTYPE_FLOAT;
 		}
 
-		if(!context->vertexShader)
+		for(unsigned int i = 0; i < VERTEX_TEXTURE_IMAGE_UNITS; i++)
 		{
-			for(int i = 0; i < 8; i++)
+			if(context->vertexShader->usesSampler(i))
 			{
-			//	state.textureState[i].vertexTextureActive = context->vertexTextureActive(i, 0);
-				state.textureState[i].texGenActive = context->texGenActive(i);
-				state.textureState[i].textureTransformCountActive = context->textureTransformCountActive(i);
-				state.textureState[i].texCoordIndexActive = context->texCoordIndexActive(i);
-			}
-		}
-		else
-		{
-			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();
-				}
+				state.sampler[i] = context->sampler[TEXTURE_IMAGE_UNITS + i].samplerState();
 			}
 		}
 
@@ -1019,70 +433,6 @@
 				state.output[i].wWrite = context->vertexShader->getOutput(i, 3).active();
 			}
 		}
-		else if(!context->preTransformed || context->pixelShaderModel() < 0x0300)
-		{
-			state.output[Pos].write = 0xF;
-
-			if(context->diffuseActive() && (context->lightingEnable || context->input[Color0]))
-			{
-				state.output[C0].write = 0xF;
-			}
-
-			if(context->specularActive())
-			{
-				state.output[C1].write = 0xF;
-			}
-
-			for(int stage = 0; stage < 8; stage++)
-			{
-				if(context->texCoordActive(stage, 0)) state.output[T0 + stage].write |= 0x01;
-				if(context->texCoordActive(stage, 1)) state.output[T0 + stage].write |= 0x02;
-				if(context->texCoordActive(stage, 2)) state.output[T0 + stage].write |= 0x04;
-				if(context->texCoordActive(stage, 3)) state.output[T0 + stage].write |= 0x08;
-			}
-
-			if(context->fogActive())
-			{
-				state.output[Fog].xWrite = true;
-			}
-
-			if(context->pointSizeActive())
-			{
-				state.output[Pts].yWrite = true;
-			}
-		}
-		else
-		{
-			state.output[Pos].write = 0xF;
-
-			for(int i = 0; i < 2; i++)
-			{
-				if(context->input[Color0 + i])
-				{
-					state.output[C0 + i].write = 0xF;
-				}
-			}
-
-			for(int i = 0; i < 8; i++)
-			{
-				if(context->input[TexCoord0 + i])
-				{
-					state.output[T0 + i].write = 0xF;
-				}
-			}
-
-			if(context->input[PointSize])
-			{
-				state.output[Pts].yWrite = true;
-			}
-		}
-
-		if(context->vertexShaderModel() < 0x0300)
-		{
-			state.output[C0].clamp = 0xF;
-			state.output[C1].clamp = 0xF;
-			state.output[Fog].xClamp = true;
-		}
 
 		state.hash = state.computeHash();
 
@@ -1095,17 +445,7 @@
 
 		if(!routine)   // Create one
 		{
-			VertexRoutine *generator = nullptr;
-
-			if(state.fixedFunction)
-			{
-				generator = new VertexPipeline(state);
-			}
-			else
-			{
-				generator = new VertexProgram(state, context->vertexShader);
-			}
-
+			VertexRoutine *generator = new VertexProgram(state, context->vertexShader);
 			generator->generate();
 			routine = (*generator)(L"VertexRoutine_%0.8X", state.shaderID);
 			delete generator;
diff --git a/src/Device/VertexProcessor.hpp b/src/Device/VertexProcessor.hpp
index cfb90b8..83383e3 100644
--- a/src/Device/VertexProcessor.hpp
+++ b/src/Device/VertexProcessor.hpp
@@ -55,42 +55,12 @@
 			unsigned int positionRegister  : BITS(MAX_VERTEX_OUTPUTS);   // TODO: Eliminate by querying shader.
 			unsigned int pointSizeRegister : BITS(MAX_VERTEX_OUTPUTS);   // TODO: Eliminate by querying shader.
 
-			unsigned int vertexBlendMatrixCount               : 3;
-			bool indexedVertexBlendEnable                     : 1;
-			bool vertexNormalActive                           : 1;
-			bool normalizeNormals                             : 1;
-			bool vertexLightingActive                         : 1;
-			bool diffuseActive                                : 1;
-			bool specularActive                               : 1;
-			bool vertexSpecularActive                         : 1;
-			unsigned int vertexLightActive                    : 8;
-			MaterialSource vertexDiffuseMaterialSourceActive  : BITS(MATERIAL_LAST);
-			MaterialSource vertexSpecularMaterialSourceActive : BITS(MATERIAL_LAST);
-			MaterialSource vertexAmbientMaterialSourceActive  : BITS(MATERIAL_LAST);
-			MaterialSource vertexEmissiveMaterialSourceActive : BITS(MATERIAL_LAST);
-			bool fogActive                                    : 1;
-			FogMode vertexFogMode                             : BITS(FOG_LAST);
-			bool rangeFogActive                               : 1;
-			bool localViewerActive                            : 1;
-			bool pointSizeActive                              : 1;
-			bool pointScaleActive                             : 1;
 			bool transformFeedbackQueryEnabled                : 1;
 			uint64_t transformFeedbackEnabled                 : 64;
 			unsigned char verticesPerPrimitive                : 2; // 1 (points), 2 (lines) or 3 (triangles)
 
-			bool preTransformed : 1;
-			bool superSampling  : 1;
 			bool multiSampling  : 1;
 
-			struct TextureState
-			{
-				TexGen texGenActive                       : BITS(TEXGEN_LAST);
-				unsigned char textureTransformCountActive : 3;
-				unsigned char texCoordIndexActive         : 3;
-			};
-
-			TextureState textureState[8];
-
 			Sampler::State sampler[VERTEX_TEXTURE_IMAGE_UNITS];
 
 			struct Input
@@ -148,39 +118,6 @@
 			unsigned int hash;
 		};
 
-		struct FixedFunction
-		{
-			float4 transformT[12][4];
-			float4 cameraTransformT[12][4];
-			float4 normalTransformT[12][4];
-			float4 textureTransform[8][4];
-
-			float4 lightPosition[8];
-			float4 lightAmbient[8];
-			float4 lightSpecular[8];
-			float4 lightDiffuse[8];
-			float4 attenuationConstant[8];
-			float4 attenuationLinear[8];
-			float4 attenuationQuadratic[8];
-			float lightRange[8];
-			float4 materialDiffuse;
-			float4 materialSpecular;
-			float materialShininess;
-			float4 globalAmbient;
-			float4 materialEmission;
-			float4 materialAmbient;
-		};
-
-		struct PointSprite
-		{
-			float4 pointSize;
-			float pointSizeMin;
-			float pointSizeMax;
-			float pointScaleA;
-			float pointScaleB;
-			float pointScaleC;
-		};
-
 		typedef void (*RoutinePointer)(Vertex *output, unsigned int *batch, VertexTask *vertexTask, DrawData *draw);
 
 		VertexProcessor(Context *context);
@@ -188,7 +125,7 @@
 		virtual ~VertexProcessor();
 
 		void setInputStream(int index, const Stream &stream);
-		void resetInputStreams(bool preTransformed);
+		void resetInputStreams();
 
 		void setFloatConstant(unsigned int index, const float value[4]);
 		void setIntegerConstant(unsigned int index, const int integer[4]);
@@ -200,54 +137,8 @@
 		void setTransformFeedbackBuffer(int index, sw::Resource* transformFeedbackBuffer, int offset, unsigned int reg, unsigned int row, unsigned int col, unsigned int stride);
 		void lockTransformFeedbackBuffers(byte** t, unsigned int* v, unsigned int* r, unsigned int* c, unsigned int* s, sw::Resource* transformFeedbackBuffers[]);
 
-		// Transformations
-		void setModelMatrix(const Matrix &M, int i = 0);
-		void setViewMatrix(const Matrix &V);
-		void setBaseMatrix(const Matrix &B);
-		void setProjectionMatrix(const Matrix &P);
-
-		// Lighting
-		void setLightingEnable(bool lightingEnable);
-		void setLightEnable(unsigned int light, bool lightEnable);
-		void setSpecularEnable(bool specularEnable);
-
-		void setGlobalAmbient(const Color<float> &globalAmbient);
-		void setLightPosition(unsigned int light, const Point &lightPosition);
-		void setLightViewPosition(unsigned int light, const Point &lightPosition);
-		void setLightDiffuse(unsigned int light, const Color<float> &lightDiffuse);
-		void setLightSpecular(unsigned int light, const Color<float> &lightSpecular);
-		void setLightAmbient(unsigned int light, const Color<float> &lightAmbient);
-		void setLightAttenuation(unsigned int light, float constant, float linear, float quadratic);
-		void setLightRange(unsigned int light, float lightRange);
-
 		void setInstanceID(int instanceID);
 
-		void setFogEnable(bool fogEnable);
-		void setVertexFogMode(FogMode fogMode);
-		void setRangeFogEnable(bool enable);
-
-		void setColorVertexEnable(bool colorVertexEnable);
-		void setDiffuseMaterialSource(MaterialSource diffuseMaterialSource);
-		void setSpecularMaterialSource(MaterialSource specularMaterialSource);
-		void setAmbientMaterialSource(MaterialSource ambientMaterialSource);
-		void setEmissiveMaterialSource(MaterialSource emissiveMaterialSource);
-
-		void setMaterialEmission(const Color<float> &emission);
-		void setMaterialAmbient(const Color<float> &materialAmbient);
-		void setMaterialDiffuse(const Color<float> &diffuseColor);
-		void setMaterialSpecular(const Color<float> &specularColor);
-		void setMaterialShininess(float specularPower);
-
-		void setIndexedVertexBlendEnable(bool indexedVertexBlendEnable);
-		void setVertexBlendMatrixCount(unsigned int vertexBlendMatrixCount);
-
-		void setTextureWrap(unsigned int stage, int mask);
-		void setTexGen(unsigned int stage, TexGen texGen);
-		void setLocalViewer(bool localViewer);
-		void setNormalizeNormals(bool normalizeNormals);
-		void setTextureMatrix(int stage, const Matrix &T);
-		void setTextureTransform(int stage, int count, bool project);
-
 		void setTextureFilter(unsigned int sampler, FilterType textureFilter);
 		void setMipmapFilter(unsigned int sampler, MipmapType mipmapFilter);
 		void setGatherEnable(unsigned int sampler, bool enable);
@@ -268,26 +159,17 @@
 		void setMaxLevel(unsigned int sampler, int maxLevel);
 		void setMinLod(unsigned int sampler, float minLod);
 		void setMaxLod(unsigned int sampler, float maxLod);
-		void setSyncRequired(unsigned int sampler, bool isSincRequired);
 
-		void setPointSize(float pointSize);
 		void setPointSizeMin(float pointSizeMin);
 		void setPointSizeMax(float pointSizeMax);
-		void setPointScaleA(float pointScaleA);
-		void setPointScaleB(float pointScaleB);
-		void setPointScaleC(float pointScaleC);
 
 		void setTransformFeedbackQueryEnabled(bool enable);
 		void enableTransformFeedback(uint64_t enable);
 
 	protected:
-		const Matrix &getModelTransform(int i);
-		const Matrix &getViewTransform();
-
 		const State update(DrawType drawType);
 		Routine *routine(const State &state);
 
-		bool isFixedFunction();
 		void setRoutineCacheSize(int cacheSize);
 
 		// Shader constants
@@ -295,8 +177,8 @@
 		int4 i[16];
 		bool b[16];
 
-		PointSprite point;
-		FixedFunction ff;
+		float pointSizeMin;
+		float pointSizeMax;
 
 	private:
 		struct UniformBufferInfo
@@ -321,31 +203,9 @@
 		};
 		TransformFeedbackInfo transformFeedbackInfo[MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS];
 
-		void updateTransform();
-		void setTransform(const Matrix &M, int i);
-		void setCameraTransform(const Matrix &M, int i);
-		void setNormalTransform(const Matrix &M, int i);
-
 		Context *const context;
 
 		RoutineCache<State> *routineCache;
-
-	protected:
-		Matrix M[12];      // Model/Geometry/World matrix
-		Matrix V;          // View/Camera/Eye matrix
-		Matrix B;          // Base matrix
-		Matrix P;          // Projection matrix
-		Matrix PB;         // P * B
-		Matrix PBV;        // P * B * V
-		Matrix PBVM[12];   // P * B * V * M
-
-		// Update hierarchy
-		bool updateMatrix;
-		bool updateModelMatrix[12];
-		bool updateViewMatrix;
-		bool updateBaseMatrix;
-		bool updateProjectionMatrix;
-		bool updateLighting;
 	};
 }
 
diff --git a/src/Pipeline/PixelPipeline.cpp b/src/Pipeline/PixelPipeline.cpp
deleted file mode 100644
index d4faebd..0000000
--- a/src/Pipeline/PixelPipeline.cpp
+++ /dev/null
@@ -1,1959 +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 "PixelPipeline.hpp"
-#include "SamplerCore.hpp"
-#include "Renderer/Renderer.hpp"
-
-namespace sw
-{
-	extern bool postBlendSRGB;
-
-	void PixelPipeline::setBuiltins(Int &x, Int &y, Float4(&z)[4], Float4 &w)
-	{
-		if(state.color[0].component & 0x1) diffuse.x = convertFixed12(v[0].x); else diffuse.x = Short4(0x1000);
-		if(state.color[0].component & 0x2) diffuse.y = convertFixed12(v[0].y); else diffuse.y = Short4(0x1000);
-		if(state.color[0].component & 0x4) diffuse.z = convertFixed12(v[0].z); else diffuse.z = Short4(0x1000);
-		if(state.color[0].component & 0x8) diffuse.w = convertFixed12(v[0].w); else diffuse.w = Short4(0x1000);
-
-		if(state.color[1].component & 0x1) specular.x = convertFixed12(v[1].x); else specular.x = Short4(0x0000);
-		if(state.color[1].component & 0x2) specular.y = convertFixed12(v[1].y); else specular.y = Short4(0x0000);
-		if(state.color[1].component & 0x4) specular.z = convertFixed12(v[1].z); else specular.z = Short4(0x0000);
-		if(state.color[1].component & 0x8) specular.w = convertFixed12(v[1].w); else specular.w = Short4(0x0000);
-	}
-
-	void PixelPipeline::fixedFunction()
-	{
-		current = diffuse;
-		Vector4s temp(0x0000, 0x0000, 0x0000, 0x0000);
-
-		for(int stage = 0; stage < 8; stage++)
-		{
-			if(state.textureStage[stage].stageOperation == TextureStage::STAGE_DISABLE)
-			{
-				break;
-			}
-
-			Vector4s texture;
-
-			if(state.textureStage[stage].usesTexture)
-			{
-				texture = sampleTexture(stage, stage);
-			}
-
-			blendTexture(temp, texture, stage);
-		}
-
-		specularPixel(current, specular);
-	}
-
-	void PixelPipeline::applyShader(Int cMask[4])
-	{
-		if(!shader)
-		{
-			fixedFunction();
-			return;
-		}
-
-		int pad = 0;        // Count number of texm3x3pad instructions
-		Vector4s dPairing;   // Destination for first pairing instruction
-
-		for(size_t i = 0; i < shader->getLength(); i++)
-		{
-			const Shader::Instruction *instruction = shader->getInstruction(i);
-			Shader::Opcode opcode = instruction->opcode;
-
-			//	#ifndef NDEBUG   // FIXME: Centralize debug output control
-			//		shader->printInstruction(i, "debug.txt");
-			//	#endif
-
-			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];
-
-			unsigned short shaderModel = shader->getShaderModel();
-			bool pairing = i + 1 < shader->getLength() && shader->getInstruction(i + 1)->coissue;   // First instruction of pair
-			bool coissue = instruction->coissue;                                                              // Second instruction of pair
-
-			Vector4s d;
-			Vector4s s0;
-			Vector4s s1;
-			Vector4s s2;
-
-			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);
-
-			Float4 x = shaderModel < 0x0104 ? v[2 + dst.index].x : v[2 + src0.index].x;
-			Float4 y = shaderModel < 0x0104 ? v[2 + dst.index].y : v[2 + src0.index].y;
-			Float4 z = shaderModel < 0x0104 ? v[2 + dst.index].z : v[2 + src0.index].z;
-			Float4 w = shaderModel < 0x0104 ? v[2 + dst.index].w : v[2 + src0.index].w;
-
-			switch(opcode)
-			{
-			case Shader::OPCODE_PS_1_0: break;
-			case Shader::OPCODE_PS_1_1: break;
-			case Shader::OPCODE_PS_1_2: break;
-			case Shader::OPCODE_PS_1_3: break;
-			case Shader::OPCODE_PS_1_4: break;
-
-			case Shader::OPCODE_DEF:    break;
-
-			case Shader::OPCODE_NOP:    break;
-			case Shader::OPCODE_MOV: MOV(d, s0);         break;
-			case Shader::OPCODE_ADD: ADD(d, s0, s1);     break;
-			case Shader::OPCODE_SUB: SUB(d, s0, s1);     break;
-			case Shader::OPCODE_MAD: MAD(d, s0, s1, s2); break;
-			case Shader::OPCODE_MUL: MUL(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_LRP: LRP(d, s0, s1, s2); break;
-			case Shader::OPCODE_TEXCOORD:
-				if(shaderModel < 0x0104)
-				{
-					TEXCOORD(d, x, y, z, dst.index);
-			}
-				else
-				{
-					if((src0.swizzle & 0x30) == 0x20)   // .xyz
-					{
-						TEXCRD(d, x, y, z, src0.index, src0.modifier == Shader::MODIFIER_DZ || src0.modifier == Shader::MODIFIER_DW);
-					}
-					else   // .xwy
-					{
-						TEXCRD(d, x, y, w, src0.index, src0.modifier == Shader::MODIFIER_DZ || src0.modifier == Shader::MODIFIER_DW);
-					}
-				}
-				break;
-			case Shader::OPCODE_TEXKILL:
-				if(shaderModel < 0x0104)
-				{
-					TEXKILL(cMask, x, y, z);
-				}
-				else if(shaderModel == 0x0104)
-				{
-					if(dst.type == Shader::PARAMETER_TEXTURE)
-					{
-						TEXKILL(cMask, x, y, z);
-					}
-					else
-					{
-						TEXKILL(cMask, rs[dst.index]);
-					}
-				}
-				else ASSERT(false);
-				break;
-			case Shader::OPCODE_TEX:
-				if(shaderModel < 0x0104)
-				{
-					TEX(d, x, y, z, dst.index, false);
-				}
-				else if(shaderModel == 0x0104)
-				{
-					if(src0.type == Shader::PARAMETER_TEXTURE)
-					{
-						if((src0.swizzle & 0x30) == 0x20)   // .xyz
-						{
-							TEX(d, x, y, z, dst.index, src0.modifier == Shader::MODIFIER_DZ || src0.modifier == Shader::MODIFIER_DW);
-						}
-						else   // .xyw
-						{
-							TEX(d, x, y, w, dst.index, src0.modifier == Shader::MODIFIER_DZ || src0.modifier == Shader::MODIFIER_DW);
-						}
-					}
-					else
-					{
-						TEXLD(d, s0, dst.index, src0.modifier == Shader::MODIFIER_DZ || src0.modifier == Shader::MODIFIER_DW);
-					}
-				}
-				else ASSERT(false);
-				break;
-			case Shader::OPCODE_TEXBEM:       TEXBEM(d, s0, x, y, z, dst.index);                                             break;
-			case Shader::OPCODE_TEXBEML:      TEXBEML(d, s0, x, y, z, dst.index);                                            break;
-			case Shader::OPCODE_TEXREG2AR:    TEXREG2AR(d, s0, dst.index);                                                   break;
-			case Shader::OPCODE_TEXREG2GB:    TEXREG2GB(d, s0, dst.index);                                                   break;
-			case Shader::OPCODE_TEXM3X2PAD:   TEXM3X2PAD(x, y, z, s0, 0, src0.modifier == Shader::MODIFIER_SIGN);            break;
-			case Shader::OPCODE_TEXM3X2TEX:   TEXM3X2TEX(d, x, y, z, dst.index, s0, src0.modifier == Shader::MODIFIER_SIGN); break;
-			case Shader::OPCODE_TEXM3X3PAD:   TEXM3X3PAD(x, y, z, s0, pad++ % 2, src0.modifier == Shader::MODIFIER_SIGN);    break;
-			case Shader::OPCODE_TEXM3X3TEX:   TEXM3X3TEX(d, x, y, z, dst.index, s0, src0.modifier == Shader::MODIFIER_SIGN); break;
-			case Shader::OPCODE_TEXM3X3SPEC:  TEXM3X3SPEC(d, x, y, z, dst.index, s0, s1);                                    break;
-			case Shader::OPCODE_TEXM3X3VSPEC: TEXM3X3VSPEC(d, x, y, z, dst.index, s0);                                       break;
-			case Shader::OPCODE_CND:          CND(d, s0, s1, s2);                                                            break;
-			case Shader::OPCODE_TEXREG2RGB:   TEXREG2RGB(d, s0, dst.index);                                                  break;
-			case Shader::OPCODE_TEXDP3TEX:    TEXDP3TEX(d, x, y, z, dst.index, s0);                                          break;
-			case Shader::OPCODE_TEXM3X2DEPTH: TEXM3X2DEPTH(d, x, y, z, s0, src0.modifier == Shader::MODIFIER_SIGN);          break;
-			case Shader::OPCODE_TEXDP3:       TEXDP3(d, x, y, z, s0);                                                        break;
-			case Shader::OPCODE_TEXM3X3:      TEXM3X3(d, x, y, z, s0, src0.modifier == Shader::MODIFIER_SIGN);               break;
-			case Shader::OPCODE_TEXDEPTH:     TEXDEPTH();                                                                    break;
-			case Shader::OPCODE_CMP0:         CMP(d, s0, s1, s2);                                                            break;
-			case Shader::OPCODE_BEM:          BEM(d, s0, s1, dst.index);                                                     break;
-			case Shader::OPCODE_PHASE:                                                                                       break;
-			case Shader::OPCODE_END:                                                                                         break;
-			default:
-				ASSERT(false);
-			}
-
-			if(dst.type != Shader::PARAMETER_VOID && opcode != Shader::OPCODE_TEXKILL)
-			{
-				if(dst.shift > 0)
-				{
-					if(dst.mask & 0x1) { d.x = AddSat(d.x, d.x); if(dst.shift > 1) d.x = AddSat(d.x, d.x); if(dst.shift > 2) d.x = AddSat(d.x, d.x); }
-					if(dst.mask & 0x2) { d.y = AddSat(d.y, d.y); if(dst.shift > 1) d.y = AddSat(d.y, d.y); if(dst.shift > 2) d.y = AddSat(d.y, d.y); }
-					if(dst.mask & 0x4) { d.z = AddSat(d.z, d.z); if(dst.shift > 1) d.z = AddSat(d.z, d.z); if(dst.shift > 2) d.z = AddSat(d.z, d.z); }
-					if(dst.mask & 0x8) { d.w = AddSat(d.w, d.w); if(dst.shift > 1) d.w = AddSat(d.w, d.w); if(dst.shift > 2) d.w = AddSat(d.w, d.w); }
-				}
-				else if(dst.shift < 0)
-				{
-					if(dst.mask & 0x1) d.x = d.x >> -dst.shift;
-					if(dst.mask & 0x2) d.y = d.y >> -dst.shift;
-					if(dst.mask & 0x4) d.z = d.z >> -dst.shift;
-					if(dst.mask & 0x8) d.w = d.w >> -dst.shift;
-				}
-
-				if(dst.saturate)
-				{
-					if(dst.mask & 0x1) { d.x = Min(d.x, Short4(0x1000)); d.x = Max(d.x, Short4(0x0000)); }
-					if(dst.mask & 0x2) { d.y = Min(d.y, Short4(0x1000)); d.y = Max(d.y, Short4(0x0000)); }
-					if(dst.mask & 0x4) { d.z = Min(d.z, Short4(0x1000)); d.z = Max(d.z, Short4(0x0000)); }
-					if(dst.mask & 0x8) { d.w = Min(d.w, Short4(0x1000)); d.w = Max(d.w, Short4(0x0000)); }
-				}
-
-				if(pairing)
-				{
-					if(dst.mask & 0x1) dPairing.x = d.x;
-					if(dst.mask & 0x2) dPairing.y = d.y;
-					if(dst.mask & 0x4) dPairing.z = d.z;
-					if(dst.mask & 0x8) dPairing.w = d.w;
-				}
-
-				if(coissue)
-				{
-					const Dst &dst = shader->getInstruction(i - 1)->dst;
-
-					writeDestination(dPairing, dst);
-				}
-
-				if(!pairing)
-				{
-					writeDestination(d, dst);
-				}
-			}
-		}
-
-		current.x = Min(current.x, Short4(0x0FFF)); current.x = Max(current.x, Short4(0x0000));
-		current.y = Min(current.y, Short4(0x0FFF)); current.y = Max(current.y, Short4(0x0000));
-		current.z = Min(current.z, Short4(0x0FFF)); current.z = Max(current.z, Short4(0x0000));
-		current.w = Min(current.w, Short4(0x0FFF)); current.w = Max(current.w, Short4(0x0000));
-	}
-
-	Bool PixelPipeline::alphaTest(Int cMask[4])
-	{
-		if(!state.alphaTestActive())
-		{
-			return true;
-		}
-
-		Int aMask;
-
-		if(state.transparencyAntialiasing == TRANSPARENCY_NONE)
-		{
-			PixelRoutine::alphaTest(aMask, current.w);
-
-			for(unsigned int q = 0; q < state.multiSample; q++)
-			{
-				cMask[q] &= aMask;
-			}
-		}
-		else if(state.transparencyAntialiasing == TRANSPARENCY_ALPHA_TO_COVERAGE)
-		{
-			Float4 alpha = Float4(current.w) * Float4(1.0f / 0x1000);
-
-			alphaToCoverage(cMask, alpha);
-		}
-		else ASSERT(false);
-
-		Int pass = cMask[0];
-
-		for(unsigned int q = 1; q < state.multiSample; q++)
-		{
-			pass = pass | cMask[q];
-		}
-
-		return pass != 0x0;
-	}
-
-	void PixelPipeline::rasterOperation(Float4 &fog, Pointer<Byte> cBuffer[4], Int &x, Int sMask[4], Int zMask[4], Int cMask[4])
-	{
-		if(!state.colorWriteActive(0))
-		{
-			return;
-		}
-
-		Vector4f oC;
-
-		switch(state.targetFormat[0])
-		{
-		case FORMAT_R5G6B5:
-		case FORMAT_X8R8G8B8:
-		case FORMAT_X8B8G8R8:
-		case FORMAT_A8R8G8B8:
-		case FORMAT_A8B8G8R8:
-		case FORMAT_A8:
-		case FORMAT_G16R16:
-		case FORMAT_A16B16G16R16:
-			if(!postBlendSRGB && state.writeSRGB)
-			{
-				linearToSRGB12_16(current);
-			}
-			else
-			{
-				current.x <<= 4;
-				current.y <<= 4;
-				current.z <<= 4;
-				current.w <<= 4;
-			}
-
-			if(state.targetFormat[0] == FORMAT_R5G6B5)
-			{
-				current.x &= Short4(0xF800u);
-				current.y &= Short4(0xFC00u);
-				current.z &= Short4(0xF800u);
-			}
-
-			fogBlend(current, fog);
-
-			for(unsigned int q = 0; q < state.multiSample; q++)
-			{
-				Pointer<Byte> buffer = cBuffer[0] + q * *Pointer<Int>(data + OFFSET(DrawData, colorSliceB[0]));
-				Vector4s color = current;
-
-				if(state.multiSampleMask & (1 << q))
-				{
-					alphaBlend(0, buffer, color, x);
-					logicOperation(0, buffer, color, x);
-					writeColor(0, buffer, x, color, sMask[q], zMask[q], cMask[q]);
-				}
-			}
-			break;
-		case FORMAT_R32F:
-		case FORMAT_G32R32F:
-		case FORMAT_X32B32G32R32F:
-		case FORMAT_A32B32G32R32F:
-	//	case FORMAT_X32B32G32R32F_UNSIGNED:   // Not renderable in any fixed-function API.
-			convertSigned12(oC, current);
-			PixelRoutine::fogBlend(oC, fog);
-
-			for(unsigned int q = 0; q < state.multiSample; q++)
-			{
-				Pointer<Byte> buffer = cBuffer[0] + q * *Pointer<Int>(data + OFFSET(DrawData, colorSliceB[0]));
-				Vector4f color = oC;
-
-				if(state.multiSampleMask & (1 << q))
-				{
-					alphaBlend(0, buffer, color, x);
-					writeColor(0, buffer, x, color, sMask[q], zMask[q], cMask[q]);
-				}
-			}
-			break;
-		default:
-			ASSERT(false);
-		}
-	}
-
-	void PixelPipeline::blendTexture(Vector4s &temp, Vector4s &texture, int stage)
-	{
-		Vector4s *arg1 = nullptr;
-		Vector4s *arg2 = nullptr;
-		Vector4s *arg3 = nullptr;
-		Vector4s res;
-
-		Vector4s constant;
-		Vector4s tfactor;
-
-		const TextureStage::State &textureStage = state.textureStage[stage];
-
-		if(textureStage.firstArgument == TextureStage::SOURCE_CONSTANT ||
-		   textureStage.firstArgumentAlpha == TextureStage::SOURCE_CONSTANT ||
-		   textureStage.secondArgument == TextureStage::SOURCE_CONSTANT ||
-		   textureStage.secondArgumentAlpha == TextureStage::SOURCE_CONSTANT ||
-		   textureStage.thirdArgument == TextureStage::SOURCE_CONSTANT ||
-		   textureStage.thirdArgumentAlpha == TextureStage::SOURCE_CONSTANT)
-		{
-			constant.x = *Pointer<Short4>(data + OFFSET(DrawData, textureStage[stage].constantColor4[0]));
-			constant.y = *Pointer<Short4>(data + OFFSET(DrawData, textureStage[stage].constantColor4[1]));
-			constant.z = *Pointer<Short4>(data + OFFSET(DrawData, textureStage[stage].constantColor4[2]));
-			constant.w = *Pointer<Short4>(data + OFFSET(DrawData, textureStage[stage].constantColor4[3]));
-		}
-
-		if(textureStage.firstArgument == TextureStage::SOURCE_TFACTOR ||
-		   textureStage.firstArgumentAlpha == TextureStage::SOURCE_TFACTOR ||
-		   textureStage.secondArgument == TextureStage::SOURCE_TFACTOR ||
-		   textureStage.secondArgumentAlpha == TextureStage::SOURCE_TFACTOR ||
-		   textureStage.thirdArgument == TextureStage::SOURCE_TFACTOR ||
-		   textureStage.thirdArgumentAlpha == TextureStage::SOURCE_TFACTOR)
-		{
-			tfactor.x = *Pointer<Short4>(data + OFFSET(DrawData, factor.textureFactor4[0]));
-			tfactor.y = *Pointer<Short4>(data + OFFSET(DrawData, factor.textureFactor4[1]));
-			tfactor.z = *Pointer<Short4>(data + OFFSET(DrawData, factor.textureFactor4[2]));
-			tfactor.w = *Pointer<Short4>(data + OFFSET(DrawData, factor.textureFactor4[3]));
-		}
-
-		// Premodulate
-		if(stage > 0 && textureStage.usesTexture)
-		{
-			if(state.textureStage[stage - 1].stageOperation == TextureStage::STAGE_PREMODULATE)
-			{
-				current.x = MulHigh(current.x, texture.x) << 4;
-				current.y = MulHigh(current.y, texture.y) << 4;
-				current.z = MulHigh(current.z, texture.z) << 4;
-			}
-
-			if(state.textureStage[stage - 1].stageOperationAlpha == TextureStage::STAGE_PREMODULATE)
-			{
-				current.w = MulHigh(current.w, texture.w) << 4;
-			}
-		}
-
-		if(luminance)
-		{
-			texture.x = MulHigh(texture.x, L) << 4;
-			texture.y = MulHigh(texture.y, L) << 4;
-			texture.z = MulHigh(texture.z, L) << 4;
-
-			luminance = false;
-		}
-
-		switch(textureStage.firstArgument)
-		{
-		case TextureStage::SOURCE_TEXTURE:	arg1 = &texture;    break;
-		case TextureStage::SOURCE_CONSTANT:	arg1 = &constant;   break;
-		case TextureStage::SOURCE_CURRENT:	arg1 = &current;  break;
-		case TextureStage::SOURCE_DIFFUSE:	arg1 = &diffuse;  break;
-		case TextureStage::SOURCE_SPECULAR:	arg1 = &specular; break;
-		case TextureStage::SOURCE_TEMP:		arg1 = &temp;       break;
-		case TextureStage::SOURCE_TFACTOR:	arg1 = &tfactor;    break;
-		default:
-			ASSERT(false);
-		}
-
-		switch(textureStage.secondArgument)
-		{
-		case TextureStage::SOURCE_TEXTURE:	arg2 = &texture;    break;
-		case TextureStage::SOURCE_CONSTANT:	arg2 = &constant;   break;
-		case TextureStage::SOURCE_CURRENT:	arg2 = &current;  break;
-		case TextureStage::SOURCE_DIFFUSE:	arg2 = &diffuse;  break;
-		case TextureStage::SOURCE_SPECULAR:	arg2 = &specular; break;
-		case TextureStage::SOURCE_TEMP:		arg2 = &temp;       break;
-		case TextureStage::SOURCE_TFACTOR:	arg2 = &tfactor;    break;
-		default:
-			ASSERT(false);
-		}
-
-		switch(textureStage.thirdArgument)
-		{
-		case TextureStage::SOURCE_TEXTURE:	arg3 = &texture;    break;
-		case TextureStage::SOURCE_CONSTANT:	arg3 = &constant;   break;
-		case TextureStage::SOURCE_CURRENT:	arg3 = &current;  break;
-		case TextureStage::SOURCE_DIFFUSE:	arg3 = &diffuse;  break;
-		case TextureStage::SOURCE_SPECULAR:	arg3 = &specular; break;
-		case TextureStage::SOURCE_TEMP:		arg3 = &temp;       break;
-		case TextureStage::SOURCE_TFACTOR:	arg3 = &tfactor;    break;
-		default:
-			ASSERT(false);
-		}
-
-		Vector4s mod1;
-		Vector4s mod2;
-		Vector4s mod3;
-
-		switch(textureStage.firstModifier)
-		{
-		case TextureStage::MODIFIER_COLOR:
-			break;
-		case TextureStage::MODIFIER_INVCOLOR:
-			mod1.x = SubSat(Short4(0x1000), arg1->x);
-			mod1.y = SubSat(Short4(0x1000), arg1->y);
-			mod1.z = SubSat(Short4(0x1000), arg1->z);
-			mod1.w = SubSat(Short4(0x1000), arg1->w);
-
-			arg1 = &mod1;
-			break;
-		case TextureStage::MODIFIER_ALPHA:
-			mod1.x = arg1->w;
-			mod1.y = arg1->w;
-			mod1.z = arg1->w;
-			mod1.w = arg1->w;
-
-			arg1 = &mod1;
-			break;
-		case TextureStage::MODIFIER_INVALPHA:
-			mod1.x = SubSat(Short4(0x1000), arg1->w);
-			mod1.y = SubSat(Short4(0x1000), arg1->w);
-			mod1.z = SubSat(Short4(0x1000), arg1->w);
-			mod1.w = SubSat(Short4(0x1000), arg1->w);
-
-			arg1 = &mod1;
-			break;
-		default:
-			ASSERT(false);
-		}
-
-		switch(textureStage.secondModifier)
-		{
-		case TextureStage::MODIFIER_COLOR:
-			break;
-		case TextureStage::MODIFIER_INVCOLOR:
-			mod2.x = SubSat(Short4(0x1000), arg2->x);
-			mod2.y = SubSat(Short4(0x1000), arg2->y);
-			mod2.z = SubSat(Short4(0x1000), arg2->z);
-			mod2.w = SubSat(Short4(0x1000), arg2->w);
-
-			arg2 = &mod2;
-			break;
-		case TextureStage::MODIFIER_ALPHA:
-			mod2.x = arg2->w;
-			mod2.y = arg2->w;
-			mod2.z = arg2->w;
-			mod2.w = arg2->w;
-
-			arg2 = &mod2;
-			break;
-		case TextureStage::MODIFIER_INVALPHA:
-			mod2.x = SubSat(Short4(0x1000), arg2->w);
-			mod2.y = SubSat(Short4(0x1000), arg2->w);
-			mod2.z = SubSat(Short4(0x1000), arg2->w);
-			mod2.w = SubSat(Short4(0x1000), arg2->w);
-
-			arg2 = &mod2;
-			break;
-		default:
-			ASSERT(false);
-		}
-
-		switch(textureStage.thirdModifier)
-		{
-		case TextureStage::MODIFIER_COLOR:
-			break;
-		case TextureStage::MODIFIER_INVCOLOR:
-			mod3.x = SubSat(Short4(0x1000), arg3->x);
-			mod3.y = SubSat(Short4(0x1000), arg3->y);
-			mod3.z = SubSat(Short4(0x1000), arg3->z);
-			mod3.w = SubSat(Short4(0x1000), arg3->w);
-
-			arg3 = &mod3;
-			break;
-		case TextureStage::MODIFIER_ALPHA:
-			mod3.x = arg3->w;
-			mod3.y = arg3->w;
-			mod3.z = arg3->w;
-			mod3.w = arg3->w;
-
-			arg3 = &mod3;
-			break;
-		case TextureStage::MODIFIER_INVALPHA:
-			mod3.x = SubSat(Short4(0x1000), arg3->w);
-			mod3.y = SubSat(Short4(0x1000), arg3->w);
-			mod3.z = SubSat(Short4(0x1000), arg3->w);
-			mod3.w = SubSat(Short4(0x1000), arg3->w);
-
-			arg3 = &mod3;
-			break;
-		default:
-			ASSERT(false);
-		}
-
-		switch(textureStage.stageOperation)
-		{
-		case TextureStage::STAGE_DISABLE:
-			break;
-		case TextureStage::STAGE_SELECTARG1: // Arg1
-			res.x = arg1->x;
-			res.y = arg1->y;
-			res.z = arg1->z;
-			break;
-		case TextureStage::STAGE_SELECTARG2: // Arg2
-			res.x = arg2->x;
-			res.y = arg2->y;
-			res.z = arg2->z;
-			break;
-		case TextureStage::STAGE_SELECTARG3: // Arg3
-			res.x = arg3->x;
-			res.y = arg3->y;
-			res.z = arg3->z;
-			break;
-		case TextureStage::STAGE_MODULATE: // Arg1 * Arg2
-			res.x = MulHigh(arg1->x, arg2->x) << 4;
-			res.y = MulHigh(arg1->y, arg2->y) << 4;
-			res.z = MulHigh(arg1->z, arg2->z) << 4;
-			break;
-		case TextureStage::STAGE_MODULATE2X: // Arg1 * Arg2 * 2
-			res.x = MulHigh(arg1->x, arg2->x) << 5;
-			res.y = MulHigh(arg1->y, arg2->y) << 5;
-			res.z = MulHigh(arg1->z, arg2->z) << 5;
-			break;
-		case TextureStage::STAGE_MODULATE4X: // Arg1 * Arg2 * 4
-			res.x = MulHigh(arg1->x, arg2->x) << 6;
-			res.y = MulHigh(arg1->y, arg2->y) << 6;
-			res.z = MulHigh(arg1->z, arg2->z) << 6;
-			break;
-		case TextureStage::STAGE_ADD: // Arg1 + Arg2
-			res.x = AddSat(arg1->x, arg2->x);
-			res.y = AddSat(arg1->y, arg2->y);
-			res.z = AddSat(arg1->z, arg2->z);
-			break;
-		case TextureStage::STAGE_ADDSIGNED: // Arg1 + Arg2 - 0.5
-			res.x = AddSat(arg1->x, arg2->x);
-			res.y = AddSat(arg1->y, arg2->y);
-			res.z = AddSat(arg1->z, arg2->z);
-
-			res.x = SubSat(res.x, Short4(0x0800));
-			res.y = SubSat(res.y, Short4(0x0800));
-			res.z = SubSat(res.z, Short4(0x0800));
-			break;
-		case TextureStage::STAGE_ADDSIGNED2X: // (Arg1 + Arg2 - 0.5) << 1
-			res.x = AddSat(arg1->x, arg2->x);
-			res.y = AddSat(arg1->y, arg2->y);
-			res.z = AddSat(arg1->z, arg2->z);
-
-			res.x = SubSat(res.x, Short4(0x0800));
-			res.y = SubSat(res.y, Short4(0x0800));
-			res.z = SubSat(res.z, Short4(0x0800));
-
-			res.x = AddSat(res.x, res.x);
-			res.y = AddSat(res.y, res.y);
-			res.z = AddSat(res.z, res.z);
-			break;
-		case TextureStage::STAGE_SUBTRACT: // Arg1 - Arg2
-			res.x = SubSat(arg1->x, arg2->x);
-			res.y = SubSat(arg1->y, arg2->y);
-			res.z = SubSat(arg1->z, arg2->z);
-			break;
-		case TextureStage::STAGE_ADDSMOOTH: // Arg1 + Arg2 - Arg1 * Arg2
-			{
-				Short4 tmp;
-
-				tmp = MulHigh(arg1->x, arg2->x) << 4; res.x = AddSat(arg1->x, arg2->x); res.x = SubSat(res.x, tmp);
-				tmp = MulHigh(arg1->y, arg2->y) << 4; res.y = AddSat(arg1->y, arg2->y); res.y = SubSat(res.y, tmp);
-				tmp = MulHigh(arg1->z, arg2->z) << 4; res.z = AddSat(arg1->z, arg2->z); res.z = SubSat(res.z, tmp);
-			}
-			break;
-		case TextureStage::STAGE_MULTIPLYADD: // Arg3 + Arg1 * Arg2
-			res.x = MulHigh(arg1->x, arg2->x) << 4; res.x = AddSat(res.x, arg3->x);
-			res.y = MulHigh(arg1->y, arg2->y) << 4; res.y = AddSat(res.y, arg3->y);
-			res.z = MulHigh(arg1->z, arg2->z) << 4; res.z = AddSat(res.z, arg3->z);
-			break;
-		case TextureStage::STAGE_LERP: // Arg3 * (Arg1 - Arg2) + Arg2
-			res.x = SubSat(arg1->x, arg2->x); res.x = MulHigh(res.x, arg3->x) << 4; res.x = AddSat(res.x, arg2->x);
-			res.y = SubSat(arg1->y, arg2->y); res.y = MulHigh(res.y, arg3->y) << 4; res.y = AddSat(res.y, arg2->y);
-			res.z = SubSat(arg1->z, arg2->z); res.z = MulHigh(res.z, arg3->z) << 4; res.z = AddSat(res.z, arg2->z);
-			break;
-		case TextureStage::STAGE_DOT3: // 2 * (Arg1.x - 0.5) * 2 * (Arg2.x - 0.5) + 2 * (Arg1.y - 0.5) * 2 * (Arg2.y - 0.5) + 2 * (Arg1.z - 0.5) * 2 * (Arg2.z - 0.5)
-			{
-				Short4 tmp;
-
-				res.x = SubSat(arg1->x, Short4(0x0800)); tmp = SubSat(arg2->x, Short4(0x0800)); res.x = MulHigh(res.x, tmp);
-				res.y = SubSat(arg1->y, Short4(0x0800)); tmp = SubSat(arg2->y, Short4(0x0800)); res.y = MulHigh(res.y, tmp);
-				res.z = SubSat(arg1->z, Short4(0x0800)); tmp = SubSat(arg2->z, Short4(0x0800)); res.z = MulHigh(res.z, tmp);
-
-				res.x = res.x << 6;
-				res.y = res.y << 6;
-				res.z = res.z << 6;
-
-				res.x = AddSat(res.x, res.y);
-				res.x = AddSat(res.x, res.z);
-
-				// Clamp to [0, 1]
-				res.x = Max(res.x, Short4(0x0000));
-				res.x = Min(res.x, Short4(0x1000));
-
-				res.y = res.x;
-				res.z = res.x;
-				res.w = res.x;
-			}
-			break;
-		case TextureStage::STAGE_BLENDCURRENTALPHA: // Alpha * (Arg1 - Arg2) + Arg2
-			res.x = SubSat(arg1->x, arg2->x); res.x = MulHigh(res.x, current.w) << 4; res.x = AddSat(res.x, arg2->x);
-			res.y = SubSat(arg1->y, arg2->y); res.y = MulHigh(res.y, current.w) << 4; res.y = AddSat(res.y, arg2->y);
-			res.z = SubSat(arg1->z, arg2->z); res.z = MulHigh(res.z, current.w) << 4; res.z = AddSat(res.z, arg2->z);
-			break;
-		case TextureStage::STAGE_BLENDDIFFUSEALPHA: // Alpha * (Arg1 - Arg2) + Arg2
-			res.x = SubSat(arg1->x, arg2->x); res.x = MulHigh(res.x, diffuse.w) << 4; res.x = AddSat(res.x, arg2->x);
-			res.y = SubSat(arg1->y, arg2->y); res.y = MulHigh(res.y, diffuse.w) << 4; res.y = AddSat(res.y, arg2->y);
-			res.z = SubSat(arg1->z, arg2->z); res.z = MulHigh(res.z, diffuse.w) << 4; res.z = AddSat(res.z, arg2->z);
-			break;
-		case TextureStage::STAGE_BLENDFACTORALPHA: // Alpha * (Arg1 - Arg2) + Arg2
-			res.x = SubSat(arg1->x, arg2->x); res.x = MulHigh(res.x, *Pointer<Short4>(data + OFFSET(DrawData, factor.textureFactor4[3]))) << 4; res.x = AddSat(res.x, arg2->x);
-			res.y = SubSat(arg1->y, arg2->y); res.y = MulHigh(res.y, *Pointer<Short4>(data + OFFSET(DrawData, factor.textureFactor4[3]))) << 4; res.y = AddSat(res.y, arg2->y);
-			res.z = SubSat(arg1->z, arg2->z); res.z = MulHigh(res.z, *Pointer<Short4>(data + OFFSET(DrawData, factor.textureFactor4[3]))) << 4; res.z = AddSat(res.z, arg2->z);
-			break;
-		case TextureStage::STAGE_BLENDTEXTUREALPHA: // Alpha * (Arg1 - Arg2) + Arg2
-			res.x = SubSat(arg1->x, arg2->x); res.x = MulHigh(res.x, texture.w) << 4; res.x = AddSat(res.x, arg2->x);
-			res.y = SubSat(arg1->y, arg2->y); res.y = MulHigh(res.y, texture.w) << 4; res.y = AddSat(res.y, arg2->y);
-			res.z = SubSat(arg1->z, arg2->z); res.z = MulHigh(res.z, texture.w) << 4; res.z = AddSat(res.z, arg2->z);
-			break;
-		case TextureStage::STAGE_BLENDTEXTUREALPHAPM: // Arg1 + Arg2 * (1 - Alpha)
-			res.x = SubSat(Short4(0x1000), texture.w); res.x = MulHigh(res.x, arg2->x) << 4; res.x = AddSat(res.x, arg1->x);
-			res.y = SubSat(Short4(0x1000), texture.w); res.y = MulHigh(res.y, arg2->y) << 4; res.y = AddSat(res.y, arg1->y);
-			res.z = SubSat(Short4(0x1000), texture.w); res.z = MulHigh(res.z, arg2->z) << 4; res.z = AddSat(res.z, arg1->z);
-			break;
-		case TextureStage::STAGE_PREMODULATE:
-			res.x = arg1->x;
-			res.y = arg1->y;
-			res.z = arg1->z;
-			break;
-		case TextureStage::STAGE_MODULATEALPHA_ADDCOLOR: // Arg1 + Arg1.w * Arg2
-			res.x = MulHigh(arg1->w, arg2->x) << 4; res.x = AddSat(res.x, arg1->x);
-			res.y = MulHigh(arg1->w, arg2->y) << 4; res.y = AddSat(res.y, arg1->y);
-			res.z = MulHigh(arg1->w, arg2->z) << 4; res.z = AddSat(res.z, arg1->z);
-			break;
-		case TextureStage::STAGE_MODULATECOLOR_ADDALPHA: // Arg1 * Arg2 + Arg1.w
-			res.x = MulHigh(arg1->x, arg2->x) << 4; res.x = AddSat(res.x, arg1->w);
-			res.y = MulHigh(arg1->y, arg2->y) << 4; res.y = AddSat(res.y, arg1->w);
-			res.z = MulHigh(arg1->z, arg2->z) << 4; res.z = AddSat(res.z, arg1->w);
-			break;
-		case TextureStage::STAGE_MODULATEINVALPHA_ADDCOLOR: // (1 - Arg1.w) * Arg2 + Arg1
-			{
-				Short4 tmp;
-
-				res.x = AddSat(arg1->x, arg2->x); tmp = MulHigh(arg1->w, arg2->x) << 4; res.x = SubSat(res.x, tmp);
-				res.y = AddSat(arg1->y, arg2->y); tmp = MulHigh(arg1->w, arg2->y) << 4; res.y = SubSat(res.y, tmp);
-				res.z = AddSat(arg1->z, arg2->z); tmp = MulHigh(arg1->w, arg2->z) << 4; res.z = SubSat(res.z, tmp);
-			}
-			break;
-		case TextureStage::STAGE_MODULATEINVCOLOR_ADDALPHA: // (1 - Arg1) * Arg2 + Arg1.w
-			{
-				Short4 tmp;
-
-				res.x = AddSat(arg1->w, arg2->x); tmp = MulHigh(arg1->x, arg2->x) << 4; res.x = SubSat(res.x, tmp);
-				res.y = AddSat(arg1->w, arg2->y); tmp = MulHigh(arg1->y, arg2->y) << 4; res.y = SubSat(res.y, tmp);
-				res.z = AddSat(arg1->w, arg2->z); tmp = MulHigh(arg1->z, arg2->z) << 4; res.z = SubSat(res.z, tmp);
-			}
-			break;
-		case TextureStage::STAGE_BUMPENVMAP:
-			{
-				du = Float4(texture.x) * Float4(1.0f / 0x0FE0);
-				dv = Float4(texture.y) * Float4(1.0f / 0x0FE0);
-
-				Float4 du2;
-				Float4 dv2;
-
-				du2 = du;
-				dv2 = dv;
-				du *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[0][0]));
-				dv2 *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[1][0]));
-				du += dv2;
-				dv *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[1][1]));
-				du2 *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[0][1]));
-				dv += du2;
-
-				perturbate = true;
-
-				res.x = current.x;
-				res.y = current.y;
-				res.z = current.z;
-				res.w = current.w;
-			}
-			break;
-		case TextureStage::STAGE_BUMPENVMAPLUMINANCE:
-			{
-				du = Float4(texture.x) * Float4(1.0f / 0x0FE0);
-				dv = Float4(texture.y) * Float4(1.0f / 0x0FE0);
-
-				Float4 du2;
-				Float4 dv2;
-
-				du2 = du;
-				dv2 = dv;
-
-				du *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[0][0]));
-				dv2 *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[1][0]));
-				du += dv2;
-				dv *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[1][1]));
-				du2 *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[0][1]));
-				dv += du2;
-
-				perturbate = true;
-
-				L = texture.z;
-				L = MulHigh(L, *Pointer<Short4>(data + OFFSET(DrawData, textureStage[stage].luminanceScale4)));
-				L = L << 4;
-				L = AddSat(L, *Pointer<Short4>(data + OFFSET(DrawData, textureStage[stage].luminanceOffset4)));
-				L = Max(L, Short4(0x0000));
-				L = Min(L, Short4(0x1000));
-
-				luminance = true;
-
-				res.x = current.x;
-				res.y = current.y;
-				res.z = current.z;
-				res.w = current.w;
-			}
-			break;
-		default:
-			ASSERT(false);
-		}
-
-		if(textureStage.stageOperation != TextureStage::STAGE_DOT3)
-		{
-			switch(textureStage.firstArgumentAlpha)
-			{
-			case TextureStage::SOURCE_TEXTURE:	arg1 = &texture;		break;
-			case TextureStage::SOURCE_CONSTANT:	arg1 = &constant;		break;
-			case TextureStage::SOURCE_CURRENT:	arg1 = &current;		break;
-			case TextureStage::SOURCE_DIFFUSE:	arg1 = &diffuse;		break;
-			case TextureStage::SOURCE_SPECULAR:	arg1 = &specular;		break;
-			case TextureStage::SOURCE_TEMP:		arg1 = &temp;			break;
-			case TextureStage::SOURCE_TFACTOR:	arg1 = &tfactor;		break;
-			default:
-				ASSERT(false);
-			}
-
-			switch(textureStage.secondArgumentAlpha)
-			{
-			case TextureStage::SOURCE_TEXTURE:	arg2 = &texture;		break;
-			case TextureStage::SOURCE_CONSTANT:	arg2 = &constant;		break;
-			case TextureStage::SOURCE_CURRENT:	arg2 = &current;		break;
-			case TextureStage::SOURCE_DIFFUSE:	arg2 = &diffuse;		break;
-			case TextureStage::SOURCE_SPECULAR:	arg2 = &specular;		break;
-			case TextureStage::SOURCE_TEMP:		arg2 = &temp;			break;
-			case TextureStage::SOURCE_TFACTOR:	arg2 = &tfactor;		break;
-			default:
-				ASSERT(false);
-			}
-
-			switch(textureStage.thirdArgumentAlpha)
-			{
-			case TextureStage::SOURCE_TEXTURE:	arg3 = &texture;		break;
-			case TextureStage::SOURCE_CONSTANT:	arg3 = &constant;		break;
-			case TextureStage::SOURCE_CURRENT:	arg3 = &current;		break;
-			case TextureStage::SOURCE_DIFFUSE:	arg3 = &diffuse;		break;
-			case TextureStage::SOURCE_SPECULAR:	arg3 = &specular;		break;
-			case TextureStage::SOURCE_TEMP:		arg3 = &temp;			break;
-			case TextureStage::SOURCE_TFACTOR:	arg3 = &tfactor;		break;
-			default:
-				ASSERT(false);
-			}
-
-			switch(textureStage.firstModifierAlpha)   // FIXME: Check if actually used
-			{
-			case TextureStage::MODIFIER_COLOR:
-				break;
-			case TextureStage::MODIFIER_INVCOLOR:
-				mod1.w = SubSat(Short4(0x1000), arg1->w);
-
-				arg1 = &mod1;
-				break;
-			case TextureStage::MODIFIER_ALPHA:
-				// Redudant
-				break;
-			case TextureStage::MODIFIER_INVALPHA:
-				mod1.w = SubSat(Short4(0x1000), arg1->w);
-
-				arg1 = &mod1;
-				break;
-			default:
-				ASSERT(false);
-			}
-
-			switch(textureStage.secondModifierAlpha)   // FIXME: Check if actually used
-			{
-			case TextureStage::MODIFIER_COLOR:
-				break;
-			case TextureStage::MODIFIER_INVCOLOR:
-				mod2.w = SubSat(Short4(0x1000), arg2->w);
-
-				arg2 = &mod2;
-				break;
-			case TextureStage::MODIFIER_ALPHA:
-				// Redudant
-				break;
-			case TextureStage::MODIFIER_INVALPHA:
-				mod2.w = SubSat(Short4(0x1000), arg2->w);
-
-				arg2 = &mod2;
-				break;
-			default:
-				ASSERT(false);
-			}
-
-			switch(textureStage.thirdModifierAlpha)   // FIXME: Check if actually used
-			{
-			case TextureStage::MODIFIER_COLOR:
-				break;
-			case TextureStage::MODIFIER_INVCOLOR:
-				mod3.w = SubSat(Short4(0x1000), arg3->w);
-
-				arg3 = &mod3;
-				break;
-			case TextureStage::MODIFIER_ALPHA:
-				// Redudant
-				break;
-			case TextureStage::MODIFIER_INVALPHA:
-				mod3.w = SubSat(Short4(0x1000), arg3->w);
-
-				arg3 = &mod3;
-				break;
-			default:
-				ASSERT(false);
-			}
-
-			switch(textureStage.stageOperationAlpha)
-			{
-			case TextureStage::STAGE_DISABLE:
-				break;
-			case TextureStage::STAGE_SELECTARG1: // Arg1
-				res.w = arg1->w;
-				break;
-			case TextureStage::STAGE_SELECTARG2: // Arg2
-				res.w = arg2->w;
-				break;
-			case TextureStage::STAGE_SELECTARG3: // Arg3
-				res.w = arg3->w;
-				break;
-			case TextureStage::STAGE_MODULATE: // Arg1 * Arg2
-				res.w = MulHigh(arg1->w, arg2->w) << 4;
-				break;
-			case TextureStage::STAGE_MODULATE2X: // Arg1 * Arg2 * 2
-				res.w = MulHigh(arg1->w, arg2->w) << 5;
-				break;
-			case TextureStage::STAGE_MODULATE4X: // Arg1 * Arg2 * 4
-				res.w = MulHigh(arg1->w, arg2->w) << 6;
-				break;
-			case TextureStage::STAGE_ADD: // Arg1 + Arg2
-				res.w = AddSat(arg1->w, arg2->w);
-				break;
-			case TextureStage::STAGE_ADDSIGNED: // Arg1 + Arg2 - 0.5
-				res.w = AddSat(arg1->w, arg2->w);
-				res.w = SubSat(res.w, Short4(0x0800));
-				break;
-			case TextureStage::STAGE_ADDSIGNED2X: // (Arg1 + Arg2 - 0.5) << 1
-				res.w = AddSat(arg1->w, arg2->w);
-				res.w = SubSat(res.w, Short4(0x0800));
-				res.w = AddSat(res.w, res.w);
-				break;
-			case TextureStage::STAGE_SUBTRACT: // Arg1 - Arg2
-				res.w = SubSat(arg1->w, arg2->w);
-				break;
-			case TextureStage::STAGE_ADDSMOOTH: // Arg1 + Arg2 - Arg1 * Arg2
-				{
-					Short4 tmp;
-
-					tmp = MulHigh(arg1->w, arg2->w) << 4; res.w = AddSat(arg1->w, arg2->w); res.w = SubSat(res.w, tmp);
-				}
-				break;
-			case TextureStage::STAGE_MULTIPLYADD: // Arg3 + Arg1 * Arg2
-				res.w = MulHigh(arg1->w, arg2->w) << 4; res.w = AddSat(res.w, arg3->w);
-				break;
-			case TextureStage::STAGE_LERP: // Arg3 * (Arg1 - Arg2) + Arg2
-				res.w = SubSat(arg1->w, arg2->w); res.w = MulHigh(res.w, arg3->w) << 4; res.w = AddSat(res.w, arg2->w);
-				break;
-			case TextureStage::STAGE_DOT3:
-				break;   // Already computed in color channel
-			case TextureStage::STAGE_BLENDCURRENTALPHA: // Alpha * (Arg1 - Arg2) + Arg2
-				res.w = SubSat(arg1->w, arg2->w); res.w = MulHigh(res.w, current.w) << 4; res.w = AddSat(res.w, arg2->w);
-				break;
-			case TextureStage::STAGE_BLENDDIFFUSEALPHA: // Arg1 * (Alpha) + Arg2 * (1 - Alpha)
-				res.w = SubSat(arg1->w, arg2->w); res.w = MulHigh(res.w, diffuse.w) << 4; res.w = AddSat(res.w, arg2->w);
-				break;
-			case TextureStage::STAGE_BLENDFACTORALPHA:
-				res.w = SubSat(arg1->w, arg2->w); res.w = MulHigh(res.w, *Pointer<Short4>(data + OFFSET(DrawData, factor.textureFactor4[3]))) << 4; res.w = AddSat(res.w, arg2->w);
-				break;
-			case TextureStage::STAGE_BLENDTEXTUREALPHA: // Arg1 * (Alpha) + Arg2 * (1 - Alpha)
-				res.w = SubSat(arg1->w, arg2->w); res.w = MulHigh(res.w, texture.w) << 4; res.w = AddSat(res.w, arg2->w);
-				break;
-			case TextureStage::STAGE_BLENDTEXTUREALPHAPM: // Arg1 + Arg2 * (1 - Alpha)
-				res.w = SubSat(Short4(0x1000), texture.w); res.w = MulHigh(res.w, arg2->w) << 4; res.w = AddSat(res.w, arg1->w);
-				break;
-			case TextureStage::STAGE_PREMODULATE:
-				res.w = arg1->w;
-				break;
-			case TextureStage::STAGE_MODULATEALPHA_ADDCOLOR:
-			case TextureStage::STAGE_MODULATECOLOR_ADDALPHA:
-			case TextureStage::STAGE_MODULATEINVALPHA_ADDCOLOR:
-			case TextureStage::STAGE_MODULATEINVCOLOR_ADDALPHA:
-			case TextureStage::STAGE_BUMPENVMAP:
-			case TextureStage::STAGE_BUMPENVMAPLUMINANCE:
-				break;   // Invalid alpha operations
-			default:
-				ASSERT(false);
-			}
-		}
-
-		// Clamp result to [0, 1]
-
-		switch(textureStage.stageOperation)
-		{
-		case TextureStage::STAGE_DISABLE:
-		case TextureStage::STAGE_SELECTARG1:
-		case TextureStage::STAGE_SELECTARG2:
-		case TextureStage::STAGE_SELECTARG3:
-		case TextureStage::STAGE_MODULATE:
-		case TextureStage::STAGE_MODULATE2X:
-		case TextureStage::STAGE_MODULATE4X:
-		case TextureStage::STAGE_ADD:
-		case TextureStage::STAGE_MULTIPLYADD:
-		case TextureStage::STAGE_LERP:
-		case TextureStage::STAGE_BLENDCURRENTALPHA:
-		case TextureStage::STAGE_BLENDDIFFUSEALPHA:
-		case TextureStage::STAGE_BLENDFACTORALPHA:
-		case TextureStage::STAGE_BLENDTEXTUREALPHA:
-		case TextureStage::STAGE_BLENDTEXTUREALPHAPM:
-		case TextureStage::STAGE_DOT3:   // Already clamped
-		case TextureStage::STAGE_PREMODULATE:
-		case TextureStage::STAGE_MODULATEALPHA_ADDCOLOR:
-		case TextureStage::STAGE_MODULATECOLOR_ADDALPHA:
-		case TextureStage::STAGE_MODULATEINVALPHA_ADDCOLOR:
-		case TextureStage::STAGE_MODULATEINVCOLOR_ADDALPHA:
-		case TextureStage::STAGE_BUMPENVMAP:
-		case TextureStage::STAGE_BUMPENVMAPLUMINANCE:
-			if(state.textureStage[stage].cantUnderflow)
-			{
-				break;   // Can't go below zero
-			}
-		case TextureStage::STAGE_ADDSIGNED:
-		case TextureStage::STAGE_ADDSIGNED2X:
-		case TextureStage::STAGE_SUBTRACT:
-		case TextureStage::STAGE_ADDSMOOTH:
-			res.x = Max(res.x, Short4(0x0000));
-			res.y = Max(res.y, Short4(0x0000));
-			res.z = Max(res.z, Short4(0x0000));
-			break;
-		default:
-			ASSERT(false);
-		}
-
-		switch(textureStage.stageOperationAlpha)
-		{
-		case TextureStage::STAGE_DISABLE:
-		case TextureStage::STAGE_SELECTARG1:
-		case TextureStage::STAGE_SELECTARG2:
-		case TextureStage::STAGE_SELECTARG3:
-		case TextureStage::STAGE_MODULATE:
-		case TextureStage::STAGE_MODULATE2X:
-		case TextureStage::STAGE_MODULATE4X:
-		case TextureStage::STAGE_ADD:
-		case TextureStage::STAGE_MULTIPLYADD:
-		case TextureStage::STAGE_LERP:
-		case TextureStage::STAGE_BLENDCURRENTALPHA:
-		case TextureStage::STAGE_BLENDDIFFUSEALPHA:
-		case TextureStage::STAGE_BLENDFACTORALPHA:
-		case TextureStage::STAGE_BLENDTEXTUREALPHA:
-		case TextureStage::STAGE_BLENDTEXTUREALPHAPM:
-		case TextureStage::STAGE_DOT3:   // Already clamped
-		case TextureStage::STAGE_PREMODULATE:
-		case TextureStage::STAGE_MODULATEALPHA_ADDCOLOR:
-		case TextureStage::STAGE_MODULATECOLOR_ADDALPHA:
-		case TextureStage::STAGE_MODULATEINVALPHA_ADDCOLOR:
-		case TextureStage::STAGE_MODULATEINVCOLOR_ADDALPHA:
-		case TextureStage::STAGE_BUMPENVMAP:
-		case TextureStage::STAGE_BUMPENVMAPLUMINANCE:
-			if(state.textureStage[stage].cantUnderflow)
-			{
-				break;   // Can't go below zero
-			}
-		case TextureStage::STAGE_ADDSIGNED:
-		case TextureStage::STAGE_ADDSIGNED2X:
-		case TextureStage::STAGE_SUBTRACT:
-		case TextureStage::STAGE_ADDSMOOTH:
-			res.w = Max(res.w, Short4(0x0000));
-			break;
-		default:
-			ASSERT(false);
-		}
-
-		switch(textureStage.stageOperation)
-		{
-		case TextureStage::STAGE_DISABLE:
-		case TextureStage::STAGE_SELECTARG1:
-		case TextureStage::STAGE_SELECTARG2:
-		case TextureStage::STAGE_SELECTARG3:
-		case TextureStage::STAGE_MODULATE:
-		case TextureStage::STAGE_SUBTRACT:
-		case TextureStage::STAGE_ADDSMOOTH:
-		case TextureStage::STAGE_LERP:
-		case TextureStage::STAGE_BLENDCURRENTALPHA:
-		case TextureStage::STAGE_BLENDDIFFUSEALPHA:
-		case TextureStage::STAGE_BLENDFACTORALPHA:
-		case TextureStage::STAGE_BLENDTEXTUREALPHA:
-		case TextureStage::STAGE_DOT3:   // Already clamped
-		case TextureStage::STAGE_PREMODULATE:
-		case TextureStage::STAGE_MODULATEINVALPHA_ADDCOLOR:
-		case TextureStage::STAGE_MODULATEINVCOLOR_ADDALPHA:
-		case TextureStage::STAGE_BUMPENVMAP:
-		case TextureStage::STAGE_BUMPENVMAPLUMINANCE:
-			break;   // Can't go above one
-		case TextureStage::STAGE_MODULATE2X:
-		case TextureStage::STAGE_MODULATE4X:
-		case TextureStage::STAGE_ADD:
-		case TextureStage::STAGE_ADDSIGNED:
-		case TextureStage::STAGE_ADDSIGNED2X:
-		case TextureStage::STAGE_MULTIPLYADD:
-		case TextureStage::STAGE_BLENDTEXTUREALPHAPM:
-		case TextureStage::STAGE_MODULATEALPHA_ADDCOLOR:
-		case TextureStage::STAGE_MODULATECOLOR_ADDALPHA:
-			res.x = Min(res.x, Short4(0x1000));
-			res.y = Min(res.y, Short4(0x1000));
-			res.z = Min(res.z, Short4(0x1000));
-			break;
-		default:
-			ASSERT(false);
-		}
-
-		switch(textureStage.stageOperationAlpha)
-		{
-		case TextureStage::STAGE_DISABLE:
-		case TextureStage::STAGE_SELECTARG1:
-		case TextureStage::STAGE_SELECTARG2:
-		case TextureStage::STAGE_SELECTARG3:
-		case TextureStage::STAGE_MODULATE:
-		case TextureStage::STAGE_SUBTRACT:
-		case TextureStage::STAGE_ADDSMOOTH:
-		case TextureStage::STAGE_LERP:
-		case TextureStage::STAGE_BLENDCURRENTALPHA:
-		case TextureStage::STAGE_BLENDDIFFUSEALPHA:
-		case TextureStage::STAGE_BLENDFACTORALPHA:
-		case TextureStage::STAGE_BLENDTEXTUREALPHA:
-		case TextureStage::STAGE_DOT3:   // Already clamped
-		case TextureStage::STAGE_PREMODULATE:
-		case TextureStage::STAGE_MODULATEINVALPHA_ADDCOLOR:
-		case TextureStage::STAGE_MODULATEINVCOLOR_ADDALPHA:
-		case TextureStage::STAGE_BUMPENVMAP:
-		case TextureStage::STAGE_BUMPENVMAPLUMINANCE:
-			break;   // Can't go above one
-		case TextureStage::STAGE_MODULATE2X:
-		case TextureStage::STAGE_MODULATE4X:
-		case TextureStage::STAGE_ADD:
-		case TextureStage::STAGE_ADDSIGNED:
-		case TextureStage::STAGE_ADDSIGNED2X:
-		case TextureStage::STAGE_MULTIPLYADD:
-		case TextureStage::STAGE_BLENDTEXTUREALPHAPM:
-		case TextureStage::STAGE_MODULATEALPHA_ADDCOLOR:
-		case TextureStage::STAGE_MODULATECOLOR_ADDALPHA:
-			res.w = Min(res.w, Short4(0x1000));
-			break;
-		default:
-			ASSERT(false);
-		}
-
-		switch(textureStage.destinationArgument)
-		{
-		case TextureStage::DESTINATION_CURRENT:
-			current.x = res.x;
-			current.y = res.y;
-			current.z = res.z;
-			current.w = res.w;
-			break;
-		case TextureStage::DESTINATION_TEMP:
-			temp.x = res.x;
-			temp.y = res.y;
-			temp.z = res.z;
-			temp.w = res.w;
-			break;
-		default:
-			ASSERT(false);
-		}
-	}
-
-	void PixelPipeline::fogBlend(Vector4s &current, Float4 &f)
-	{
-		if(!state.fogActive)
-		{
-			return;
-		}
-
-		if(state.pixelFogMode != FOG_NONE)
-		{
-			pixelFog(f);
-		}
-
-		UShort4 fog = convertFixed16(f, true);
-
-		current.x = As<Short4>(MulHigh(As<UShort4>(current.x), fog));
-		current.y = As<Short4>(MulHigh(As<UShort4>(current.y), fog));
-		current.z = As<Short4>(MulHigh(As<UShort4>(current.z), fog));
-
-		UShort4 invFog = UShort4(0xFFFFu) - fog;
-
-		current.x += As<Short4>(MulHigh(invFog, *Pointer<UShort4>(data + OFFSET(DrawData, fog.color4[0]))));
-		current.y += As<Short4>(MulHigh(invFog, *Pointer<UShort4>(data + OFFSET(DrawData, fog.color4[1]))));
-		current.z += As<Short4>(MulHigh(invFog, *Pointer<UShort4>(data + OFFSET(DrawData, fog.color4[2]))));
-	}
-
-	void PixelPipeline::specularPixel(Vector4s &current, Vector4s &specular)
-	{
-		if(!state.specularAdd)
-		{
-			return;
-		}
-
-		current.x = AddSat(current.x, specular.x);
-		current.y = AddSat(current.y, specular.y);
-		current.z = AddSat(current.z, specular.z);
-	}
-
-	Vector4s PixelPipeline::sampleTexture(int coordinates, int stage, bool project)
-	{
-		Float4 x = v[2 + coordinates].x;
-		Float4 y = v[2 + coordinates].y;
-		Float4 z = v[2 + coordinates].z;
-		Float4 w = v[2 + coordinates].w;
-
-		if(perturbate)
-		{
-			x += du;
-			y += dv;
-
-			perturbate = false;
-		}
-
-		return sampleTexture(stage, x, y, z, w, project);
-	}
-
-	Vector4s PixelPipeline::sampleTexture(int stage, Float4 &u, Float4 &v, Float4 &w, Float4 &q, bool project)
-	{
-		Vector4s c;
-
-		#if PERF_PROFILE
-			Long texTime = Ticks();
-		#endif
-
-		Vector4f dsx;
-		Vector4f dsy;
-
-		Pointer<Byte> texture = data + OFFSET(DrawData, mipmap) + stage * sizeof(Texture);
-
-		if(!project)
-		{
-			c = SamplerCore(constants, state.sampler[stage]).sampleTexture(texture, u, v, w, q, q, dsx, dsy);
-		}
-		else
-		{
-			Float4 rq = reciprocal(q);
-
-			Float4 u_q = u * rq;
-			Float4 v_q = v * rq;
-			Float4 w_q = w * rq;
-
-			c = SamplerCore(constants, state.sampler[stage]).sampleTexture(texture, u_q, v_q, w_q, q, q, dsx, dsy);
-		}
-
-		#if PERF_PROFILE
-			cycles[PERF_TEX] += Ticks() - texTime;
-		#endif
-
-		return c;
-	}
-
-	Short4 PixelPipeline::convertFixed12(RValue<Float4> cf)
-	{
-		return RoundShort4(cf * Float4(0x1000));
-	}
-
-	void PixelPipeline::convertFixed12(Vector4s &cs, Vector4f &cf)
-	{
-		cs.x = convertFixed12(cf.x);
-		cs.y = convertFixed12(cf.y);
-		cs.z = convertFixed12(cf.z);
-		cs.w = convertFixed12(cf.w);
-	}
-
-	Float4 PixelPipeline::convertSigned12(Short4 &cs)
-	{
-		return Float4(cs) * Float4(1.0f / 0x0FFE);
-	}
-
-	void PixelPipeline::convertSigned12(Vector4f &cf, Vector4s &cs)
-	{
-		cf.x = convertSigned12(cs.x);
-		cf.y = convertSigned12(cs.y);
-		cf.z = convertSigned12(cs.z);
-		cf.w = convertSigned12(cs.w);
-	}
-
-	void PixelPipeline::writeDestination(Vector4s &d, const Dst &dst)
-	{
-		switch(dst.type)
-		{
-		case Shader::PARAMETER_TEMP:
-			if(dst.mask & 0x1) rs[dst.index].x = d.x;
-			if(dst.mask & 0x2) rs[dst.index].y = d.y;
-			if(dst.mask & 0x4) rs[dst.index].z = d.z;
-			if(dst.mask & 0x8) rs[dst.index].w = d.w;
-			break;
-		case Shader::PARAMETER_INPUT:
-			if(dst.mask & 0x1) vs[dst.index].x = d.x;
-			if(dst.mask & 0x2) vs[dst.index].y = d.y;
-			if(dst.mask & 0x4) vs[dst.index].z = d.z;
-			if(dst.mask & 0x8) vs[dst.index].w = d.w;
-			break;
-		case Shader::PARAMETER_CONST: ASSERT(false); break;
-		case Shader::PARAMETER_TEXTURE:
-			if(dst.mask & 0x1) ts[dst.index].x = d.x;
-			if(dst.mask & 0x2) ts[dst.index].y = d.y;
-			if(dst.mask & 0x4) ts[dst.index].z = d.z;
-			if(dst.mask & 0x8) ts[dst.index].w = d.w;
-			break;
-		case Shader::PARAMETER_COLOROUT:
-			if(dst.mask & 0x1) vs[dst.index].x = d.x;
-			if(dst.mask & 0x2) vs[dst.index].y = d.y;
-			if(dst.mask & 0x4) vs[dst.index].z = d.z;
-			if(dst.mask & 0x8) vs[dst.index].w = d.w;
-			break;
-		default:
-			ASSERT(false);
-		}
-	}
-
-	Vector4s PixelPipeline::fetchRegister(const Src &src)
-	{
-		Vector4s *reg;
-		int i = src.index;
-
-		Vector4s c;
-
-		if(src.type == Shader::PARAMETER_CONST)
-		{
-			c.x = *Pointer<Short4>(data + OFFSET(DrawData, ps.cW[i][0]));
-			c.y = *Pointer<Short4>(data + OFFSET(DrawData, ps.cW[i][1]));
-			c.z = *Pointer<Short4>(data + OFFSET(DrawData, ps.cW[i][2]));
-			c.w = *Pointer<Short4>(data + OFFSET(DrawData, ps.cW[i][3]));
-		}
-
-		switch(src.type)
-		{
-		case Shader::PARAMETER_TEMP:          reg = &rs[i]; break;
-		case Shader::PARAMETER_INPUT:         reg = &vs[i]; break;
-		case Shader::PARAMETER_CONST:         reg = &c;       break;
-		case Shader::PARAMETER_TEXTURE:       reg = &ts[i]; break;
-		case Shader::PARAMETER_VOID:          return rs[0]; // Dummy
-		case Shader::PARAMETER_FLOAT4LITERAL: return rs[0]; // Dummy
-		default: ASSERT(false); return rs[0];
-		}
-
-		const Short4 &x = (*reg)[(src.swizzle >> 0) & 0x3];
-		const Short4 &y = (*reg)[(src.swizzle >> 2) & 0x3];
-		const Short4 &z = (*reg)[(src.swizzle >> 4) & 0x3];
-		const Short4 &w = (*reg)[(src.swizzle >> 6) & 0x3];
-
-		Vector4s mod;
-
-		switch(src.modifier)
-		{
-		case Shader::MODIFIER_NONE:
-			mod.x = x;
-			mod.y = y;
-			mod.z = z;
-			mod.w = w;
-			break;
-		case Shader::MODIFIER_BIAS:
-			mod.x = SubSat(x, Short4(0x0800));
-			mod.y = SubSat(y, Short4(0x0800));
-			mod.z = SubSat(z, Short4(0x0800));
-			mod.w = SubSat(w, Short4(0x0800));
-			break;
-		case Shader::MODIFIER_BIAS_NEGATE:
-			mod.x = SubSat(Short4(0x0800), x);
-			mod.y = SubSat(Short4(0x0800), y);
-			mod.z = SubSat(Short4(0x0800), z);
-			mod.w = SubSat(Short4(0x0800), w);
-			break;
-		case Shader::MODIFIER_COMPLEMENT:
-			mod.x = SubSat(Short4(0x1000), x);
-			mod.y = SubSat(Short4(0x1000), y);
-			mod.z = SubSat(Short4(0x1000), z);
-			mod.w = SubSat(Short4(0x1000), w);
-			break;
-		case Shader::MODIFIER_NEGATE:
-			mod.x = -x;
-			mod.y = -y;
-			mod.z = -z;
-			mod.w = -w;
-			break;
-		case Shader::MODIFIER_X2:
-			mod.x = AddSat(x, x);
-			mod.y = AddSat(y, y);
-			mod.z = AddSat(z, z);
-			mod.w = AddSat(w, w);
-			break;
-		case Shader::MODIFIER_X2_NEGATE:
-			mod.x = -AddSat(x, x);
-			mod.y = -AddSat(y, y);
-			mod.z = -AddSat(z, z);
-			mod.w = -AddSat(w, w);
-			break;
-		case Shader::MODIFIER_SIGN:
-			mod.x = SubSat(x, Short4(0x0800));
-			mod.y = SubSat(y, Short4(0x0800));
-			mod.z = SubSat(z, Short4(0x0800));
-			mod.w = SubSat(w, Short4(0x0800));
-			mod.x = AddSat(mod.x, mod.x);
-			mod.y = AddSat(mod.y, mod.y);
-			mod.z = AddSat(mod.z, mod.z);
-			mod.w = AddSat(mod.w, mod.w);
-			break;
-		case Shader::MODIFIER_SIGN_NEGATE:
-			mod.x = SubSat(Short4(0x0800), x);
-			mod.y = SubSat(Short4(0x0800), y);
-			mod.z = SubSat(Short4(0x0800), z);
-			mod.w = SubSat(Short4(0x0800), w);
-			mod.x = AddSat(mod.x, mod.x);
-			mod.y = AddSat(mod.y, mod.y);
-			mod.z = AddSat(mod.z, mod.z);
-			mod.w = AddSat(mod.w, mod.w);
-			break;
-		case Shader::MODIFIER_DZ:
-			mod.x = x;
-			mod.y = y;
-			mod.z = z;
-			mod.w = w;
-			// Projection performed by texture sampler
-			break;
-		case Shader::MODIFIER_DW:
-			mod.x = x;
-			mod.y = y;
-			mod.z = z;
-			mod.w = w;
-			// Projection performed by texture sampler
-			break;
-		default:
-			ASSERT(false);
-		}
-
-		if(src.type == Shader::PARAMETER_CONST && (src.modifier == Shader::MODIFIER_X2 || src.modifier == Shader::MODIFIER_X2_NEGATE))
-		{
-			mod.x = Min(mod.x, Short4(0x1000)); mod.x = Max(mod.x, Short4(-0x1000));
-			mod.y = Min(mod.y, Short4(0x1000)); mod.y = Max(mod.y, Short4(-0x1000));
-			mod.z = Min(mod.z, Short4(0x1000)); mod.z = Max(mod.z, Short4(-0x1000));
-			mod.w = Min(mod.w, Short4(0x1000)); mod.w = Max(mod.w, Short4(-0x1000));
-		}
-
-		return mod;
-	}
-
-	void PixelPipeline::MOV(Vector4s &dst, Vector4s &src0)
-	{
-		dst.x = src0.x;
-		dst.y = src0.y;
-		dst.z = src0.z;
-		dst.w = src0.w;
-	}
-
-	void PixelPipeline::ADD(Vector4s &dst, Vector4s &src0, Vector4s &src1)
-	{
-		dst.x = AddSat(src0.x, src1.x);
-		dst.y = AddSat(src0.y, src1.y);
-		dst.z = AddSat(src0.z, src1.z);
-		dst.w = AddSat(src0.w, src1.w);
-	}
-
-	void PixelPipeline::SUB(Vector4s &dst, Vector4s &src0, Vector4s &src1)
-	{
-		dst.x = SubSat(src0.x, src1.x);
-		dst.y = SubSat(src0.y, src1.y);
-		dst.z = SubSat(src0.z, src1.z);
-		dst.w = SubSat(src0.w, src1.w);
-	}
-
-	void PixelPipeline::MAD(Vector4s &dst, Vector4s &src0, Vector4s &src1, Vector4s &src2)
-	{
-		// FIXME: Long fixed-point multiply fixup
-		{ dst.x = MulHigh(src0.x, src1.x); dst.x = AddSat(dst.x, dst.x); dst.x = AddSat(dst.x, dst.x); dst.x = AddSat(dst.x, dst.x); dst.x = AddSat(dst.x, dst.x); dst.x = AddSat(dst.x, src2.x); }
-		{ dst.y = MulHigh(src0.y, src1.y); dst.y = AddSat(dst.y, dst.y); dst.y = AddSat(dst.y, dst.y); dst.y = AddSat(dst.y, dst.y); dst.y = AddSat(dst.y, dst.y); dst.y = AddSat(dst.y, src2.y); }
-		{ dst.z = MulHigh(src0.z, src1.z); dst.z = AddSat(dst.z, dst.z); dst.z = AddSat(dst.z, dst.z); dst.z = AddSat(dst.z, dst.z); dst.z = AddSat(dst.z, dst.z); dst.z = AddSat(dst.z, src2.z); }
-		{ dst.w = MulHigh(src0.w, src1.w); dst.w = AddSat(dst.w, dst.w); dst.w = AddSat(dst.w, dst.w); dst.w = AddSat(dst.w, dst.w); dst.w = AddSat(dst.w, dst.w); dst.w = AddSat(dst.w, src2.w); }
-	}
-
-	void PixelPipeline::MUL(Vector4s &dst, Vector4s &src0, Vector4s &src1)
-	{
-		// FIXME: Long fixed-point multiply fixup
-		{ dst.x = MulHigh(src0.x, src1.x); dst.x = AddSat(dst.x, dst.x); dst.x = AddSat(dst.x, dst.x); dst.x = AddSat(dst.x, dst.x); dst.x = AddSat(dst.x, dst.x); }
-		{ dst.y = MulHigh(src0.y, src1.y); dst.y = AddSat(dst.y, dst.y); dst.y = AddSat(dst.y, dst.y); dst.y = AddSat(dst.y, dst.y); dst.y = AddSat(dst.y, dst.y); }
-		{ dst.z = MulHigh(src0.z, src1.z); dst.z = AddSat(dst.z, dst.z); dst.z = AddSat(dst.z, dst.z); dst.z = AddSat(dst.z, dst.z); dst.z = AddSat(dst.z, dst.z); }
-		{ dst.w = MulHigh(src0.w, src1.w); dst.w = AddSat(dst.w, dst.w); dst.w = AddSat(dst.w, dst.w); dst.w = AddSat(dst.w, dst.w); dst.w = AddSat(dst.w, dst.w); }
-	}
-
-	void PixelPipeline::DP3(Vector4s &dst, Vector4s &src0, Vector4s &src1)
-	{
-		Short4 t0;
-		Short4 t1;
-
-		// FIXME: Long fixed-point multiply fixup
-		t0 = MulHigh(src0.x, src1.x); t0 = AddSat(t0, t0); t0 = AddSat(t0, t0); t0 = AddSat(t0, t0); t0 = AddSat(t0, t0);
-		t1 = MulHigh(src0.y, src1.y); t1 = AddSat(t1, t1); t1 = AddSat(t1, t1); t1 = AddSat(t1, t1); t1 = AddSat(t1, t1);
-		t0 = AddSat(t0, t1);
-		t1 = MulHigh(src0.z, src1.z); t1 = AddSat(t1, t1); t1 = AddSat(t1, t1); t1 = AddSat(t1, t1); t1 = AddSat(t1, t1);
-		t0 = AddSat(t0, t1);
-
-		dst.x = t0;
-		dst.y = t0;
-		dst.z = t0;
-		dst.w = t0;
-	}
-
-	void PixelPipeline::DP4(Vector4s &dst, Vector4s &src0, Vector4s &src1)
-	{
-		Short4 t0;
-		Short4 t1;
-
-		// FIXME: Long fixed-point multiply fixup
-		t0 = MulHigh(src0.x, src1.x); t0 = AddSat(t0, t0); t0 = AddSat(t0, t0); t0 = AddSat(t0, t0); t0 = AddSat(t0, t0);
-		t1 = MulHigh(src0.y, src1.y); t1 = AddSat(t1, t1); t1 = AddSat(t1, t1); t1 = AddSat(t1, t1); t1 = AddSat(t1, t1);
-		t0 = AddSat(t0, t1);
-		t1 = MulHigh(src0.z, src1.z); t1 = AddSat(t1, t1); t1 = AddSat(t1, t1); t1 = AddSat(t1, t1); t1 = AddSat(t1, t1);
-		t0 = AddSat(t0, t1);
-		t1 = MulHigh(src0.w, src1.w); t1 = AddSat(t1, t1); t1 = AddSat(t1, t1); t1 = AddSat(t1, t1); t1 = AddSat(t1, t1);
-		t0 = AddSat(t0, t1);
-
-		dst.x = t0;
-		dst.y = t0;
-		dst.z = t0;
-		dst.w = t0;
-	}
-
-	void PixelPipeline::LRP(Vector4s &dst, Vector4s &src0, Vector4s &src1, Vector4s &src2)
-	{
-		// FIXME: Long fixed-point multiply fixup
-		{ dst.x = SubSat(src1.x, src2.x); dst.x = MulHigh(dst.x, src0.x); dst.x = AddSat(dst.x, dst.x); dst.x = AddSat(dst.x, dst.x); dst.x = AddSat(dst.x, dst.x); dst.x = AddSat(dst.x, dst.x); dst.x = AddSat(dst.x, src2.x); }
-		{
-		dst.y = SubSat(src1.y, src2.y); dst.y = MulHigh(dst.y, src0.y); dst.y = AddSat(dst.y, dst.y); dst.y = AddSat(dst.y, dst.y); dst.y = AddSat(dst.y, dst.y); dst.y = AddSat(dst.y, dst.y); dst.y = AddSat(dst.y, src2.y);
-	}
-		{dst.z = SubSat(src1.z, src2.z); dst.z = MulHigh(dst.z, src0.z); dst.z = AddSat(dst.z, dst.z); dst.z = AddSat(dst.z, dst.z); dst.z = AddSat(dst.z, dst.z); dst.z = AddSat(dst.z, dst.z); dst.z = AddSat(dst.z, src2.z); }
-		{dst.w = SubSat(src1.w, src2.w); dst.w = MulHigh(dst.w, src0.w); dst.w = AddSat(dst.w, dst.w); dst.w = AddSat(dst.w, dst.w); dst.w = AddSat(dst.w, dst.w); dst.w = AddSat(dst.w, dst.w); dst.w = AddSat(dst.w, src2.w); }
-	}
-
-	void PixelPipeline::TEXCOORD(Vector4s &dst, Float4 &u, Float4 &v, Float4 &s, int coordinate)
-	{
-		Float4 uw;
-		Float4 vw;
-		Float4 sw;
-
-		if(state.interpolant[2 + coordinate].component & 0x01)
-		{
-			uw = Max(u, Float4(0.0f));
-			uw = Min(uw, Float4(1.0f));
-			dst.x = convertFixed12(uw);
-		}
-		else
-		{
-			dst.x = Short4(0x0000);
-		}
-
-		if(state.interpolant[2 + coordinate].component & 0x02)
-		{
-			vw = Max(v, Float4(0.0f));
-			vw = Min(vw, Float4(1.0f));
-			dst.y = convertFixed12(vw);
-		}
-		else
-		{
-			dst.y = Short4(0x0000);
-		}
-
-		if(state.interpolant[2 + coordinate].component & 0x04)
-		{
-			sw = Max(s, Float4(0.0f));
-			sw = Min(sw, Float4(1.0f));
-			dst.z = convertFixed12(sw);
-		}
-		else
-		{
-			dst.z = Short4(0x0000);
-		}
-
-		dst.w = Short4(0x1000);
-	}
-
-	void PixelPipeline::TEXCRD(Vector4s &dst, Float4 &u, Float4 &v, Float4 &s, int coordinate, bool project)
-	{
-		Float4 uw = u;
-		Float4 vw = v;
-		Float4 sw = s;
-
-		if(project)
-		{
-			uw *= Rcp_pp(s);
-			vw *= Rcp_pp(s);
-		}
-
-		if(state.interpolant[2 + coordinate].component & 0x01)
-		{
-			uw *= Float4(0x1000);
-			uw = Max(uw, Float4(-0x8000));
-			uw = Min(uw, Float4(0x7FFF));
-			dst.x = RoundShort4(uw);
-		}
-		else
-		{
-			dst.x = Short4(0x0000);
-		}
-
-		if(state.interpolant[2 + coordinate].component & 0x02)
-		{
-			vw *= Float4(0x1000);
-			vw = Max(vw, Float4(-0x8000));
-			vw = Min(vw, Float4(0x7FFF));
-			dst.y = RoundShort4(vw);
-		}
-		else
-		{
-			dst.y = Short4(0x0000);
-		}
-
-		if(state.interpolant[2 + coordinate].component & 0x04)
-		{
-			sw *= Float4(0x1000);
-			sw = Max(sw, Float4(-0x8000));
-			sw = Min(sw, Float4(0x7FFF));
-			dst.z = RoundShort4(sw);
-		}
-		else
-		{
-			dst.z = Short4(0x0000);
-		}
-	}
-
-	void PixelPipeline::TEXDP3(Vector4s &dst, Float4 &u, Float4 &v, Float4 &s, Vector4s &src)
-	{
-		TEXM3X3PAD(u, v, s, src, 0, false);
-
-		Short4 t0 = RoundShort4(u_ * Float4(0x1000));
-
-		dst.x = t0;
-		dst.y = t0;
-		dst.z = t0;
-		dst.w = t0;
-	}
-
-	void PixelPipeline::TEXDP3TEX(Vector4s &dst, Float4 &u, Float4 &v, Float4 &s, int stage, Vector4s &src0)
-	{
-		TEXM3X3PAD(u, v, s, src0, 0, false);
-
-		v_ = Float4(0.0f);
-		w_ = Float4(0.0f);
-
-		dst = sampleTexture(stage, u_, v_, w_, w_);
-	}
-
-	void PixelPipeline::TEXKILL(Int cMask[4], Float4 &u, Float4 &v, Float4 &s)
-	{
-		Int kill = SignMask(CmpNLT(u, Float4(0.0f))) &
-			SignMask(CmpNLT(v, Float4(0.0f))) &
-			SignMask(CmpNLT(s, Float4(0.0f)));
-
-		for(unsigned int q = 0; q < state.multiSample; q++)
-		{
-			cMask[q] &= kill;
-		}
-	}
-
-	void PixelPipeline::TEXKILL(Int cMask[4], Vector4s &src)
-	{
-		Short4 test = src.x | src.y | src.z;
-		Int kill = SignMask(PackSigned(test, test)) ^ 0x0000000F;
-
-		for(unsigned int q = 0; q < state.multiSample; q++)
-		{
-			cMask[q] &= kill;
-		}
-	}
-
-	void PixelPipeline::TEX(Vector4s &dst, Float4 &u, Float4 &v, Float4 &s, int sampler, bool project)
-	{
-		dst = sampleTexture(sampler, u, v, s, s, project);
-	}
-
-	void PixelPipeline::TEXLD(Vector4s &dst, Vector4s &src, int sampler, bool project)
-	{
-		Float4 u = Float4(src.x) * Float4(1.0f / 0x0FFE);
-		Float4 v = Float4(src.y) * Float4(1.0f / 0x0FFE);
-		Float4 s = Float4(src.z) * Float4(1.0f / 0x0FFE);
-
-		dst = sampleTexture(sampler, u, v, s, s, project);
-	}
-
-	void PixelPipeline::TEXBEM(Vector4s &dst, Vector4s &src, Float4 &u, Float4 &v, Float4 &s, int stage)
-	{
-		Float4 du = Float4(src.x) * Float4(1.0f / 0x0FFE);
-		Float4 dv = Float4(src.y) * Float4(1.0f / 0x0FFE);
-
-		Float4 du2 = du;
-		Float4 dv2 = dv;
-
-		du *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[0][0]));
-		dv2 *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[1][0]));
-		du += dv2;
-		dv *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[1][1]));
-		du2 *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[0][1]));
-		dv += du2;
-
-		Float4 u_ = u + du;
-		Float4 v_ = v + dv;
-
-		dst = sampleTexture(stage, u_, v_, s, s);
-	}
-
-	void PixelPipeline::TEXBEML(Vector4s &dst, Vector4s &src, Float4 &u, Float4 &v, Float4 &s, int stage)
-	{
-		Float4 du = Float4(src.x) * Float4(1.0f / 0x0FFE);
-		Float4 dv = Float4(src.y) * Float4(1.0f / 0x0FFE);
-
-		Float4 du2 = du;
-		Float4 dv2 = dv;
-
-		du *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[0][0]));
-		dv2 *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[1][0]));
-		du += dv2;
-		dv *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[1][1]));
-		du2 *= *Pointer<Float4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4F[0][1]));
-		dv += du2;
-
-		Float4 u_ = u + du;
-		Float4 v_ = v + dv;
-
-		dst = sampleTexture(stage, u_, v_, s, s);
-
-		Short4 L;
-
-		L = src.z;
-		L = MulHigh(L, *Pointer<Short4>(data + OFFSET(DrawData, textureStage[stage].luminanceScale4)));
-		L = L << 4;
-		L = AddSat(L, *Pointer<Short4>(data + OFFSET(DrawData, textureStage[stage].luminanceOffset4)));
-		L = Max(L, Short4(0x0000));
-		L = Min(L, Short4(0x1000));
-
-		dst.x = MulHigh(dst.x, L); dst.x = dst.x << 4;
-		dst.y = MulHigh(dst.y, L); dst.y = dst.y << 4;
-		dst.z = MulHigh(dst.z, L); dst.z = dst.z << 4;
-	}
-
-	void PixelPipeline::TEXREG2AR(Vector4s &dst, Vector4s &src0, int stage)
-	{
-		Float4 u = Float4(src0.w) * Float4(1.0f / 0x0FFE);
-		Float4 v = Float4(src0.x) * Float4(1.0f / 0x0FFE);
-		Float4 s = Float4(src0.z) * Float4(1.0f / 0x0FFE);
-
-		dst = sampleTexture(stage, u, v, s, s);
-	}
-
-	void PixelPipeline::TEXREG2GB(Vector4s &dst, Vector4s &src0, int stage)
-	{
-		Float4 u = Float4(src0.y) * Float4(1.0f / 0x0FFE);
-		Float4 v = Float4(src0.z) * Float4(1.0f / 0x0FFE);
-		Float4 s = v;
-
-		dst = sampleTexture(stage, u, v, s, s);
-	}
-
-	void PixelPipeline::TEXREG2RGB(Vector4s &dst, Vector4s &src0, int stage)
-	{
-		Float4 u = Float4(src0.x) * Float4(1.0f / 0x0FFE);
-		Float4 v = Float4(src0.y) * Float4(1.0f / 0x0FFE);
-		Float4 s = Float4(src0.z) * Float4(1.0f / 0x0FFE);
-
-		dst = sampleTexture(stage, u, v, s, s);
-	}
-
-	void PixelPipeline::TEXM3X2DEPTH(Vector4s &dst, Float4 &u, Float4 &v, Float4 &s, Vector4s &src, bool signedScaling)
-	{
-		TEXM3X2PAD(u, v, s, src, 1, signedScaling);
-
-		// z / w
-		u_ *= Rcp_pp(v_);   // FIXME: Set result to 1.0 when division by zero
-
-		oDepth = u_;
-	}
-
-	void PixelPipeline::TEXM3X2PAD(Float4 &u, Float4 &v, Float4 &s, Vector4s &src0, int component, bool signedScaling)
-	{
-		TEXM3X3PAD(u, v, s, src0, component, signedScaling);
-	}
-
-	void PixelPipeline::TEXM3X2TEX(Vector4s &dst, Float4 &u, Float4 &v, Float4 &s, int stage, Vector4s &src0, bool signedScaling)
-	{
-		TEXM3X2PAD(u, v, s, src0, 1, signedScaling);
-
-		w_ = Float4(0.0f);
-
-		dst = sampleTexture(stage, u_, v_, w_, w_);
-	}
-
-	void PixelPipeline::TEXM3X3(Vector4s &dst, Float4 &u, Float4 &v, Float4 &s, Vector4s &src0, bool signedScaling)
-	{
-		TEXM3X3PAD(u, v, s, src0, 2, signedScaling);
-
-		dst.x = RoundShort4(u_ * Float4(0x1000));
-		dst.y = RoundShort4(v_ * Float4(0x1000));
-		dst.z = RoundShort4(w_ * Float4(0x1000));
-		dst.w = Short4(0x1000);
-	}
-
-	void PixelPipeline::TEXM3X3PAD(Float4 &u, Float4 &v, Float4 &s, Vector4s &src0, int component, bool signedScaling)
-	{
-		if(component == 0 || previousScaling != signedScaling)   // FIXME: Other source modifiers?
-		{
-			U = Float4(src0.x);
-			V = Float4(src0.y);
-			W = Float4(src0.z);
-
-			previousScaling = signedScaling;
-		}
-
-		Float4 x = U * u + V * v + W * s;
-
-		x *= Float4(1.0f / 0x1000);
-
-		switch(component)
-		{
-		case 0:	u_ = x; break;
-		case 1:	v_ = x; break;
-		case 2: w_ = x; break;
-		default: ASSERT(false);
-		}
-	}
-
-	void PixelPipeline::TEXM3X3SPEC(Vector4s &dst, Float4 &u, Float4 &v, Float4 &s, int stage, Vector4s &src0, Vector4s &src1)
-	{
-		TEXM3X3PAD(u, v, s, src0, 2, false);
-
-		Float4 E[3];   // Eye vector
-
-		E[0] = Float4(src1.x) * Float4(1.0f / 0x0FFE);
-		E[1] = Float4(src1.y) * Float4(1.0f / 0x0FFE);
-		E[2] = Float4(src1.z) * Float4(1.0f / 0x0FFE);
-
-		// Reflection
-		Float4 u__;
-		Float4 v__;
-		Float4 w__;
-
-		// (u'', v'', w'') = 2 * (N . E) * N - E * (N . N)
-		u__ = u_ * E[0];
-		v__ = v_ * E[1];
-		w__ = w_ * E[2];
-		u__ += v__ + w__;
-		u__ += u__;
-		v__ = u__;
-		w__ = u__;
-		u__ *= u_;
-		v__ *= v_;
-		w__ *= w_;
-		u_ *= u_;
-		v_ *= v_;
-		w_ *= w_;
-		u_ += v_ + w_;
-		u__ -= E[0] * u_;
-		v__ -= E[1] * u_;
-		w__ -= E[2] * u_;
-
-		dst = sampleTexture(stage, u__, v__, w__, w__);
-	}
-
-	void PixelPipeline::TEXM3X3TEX(Vector4s &dst, Float4 &u, Float4 &v, Float4 &s, int stage, Vector4s &src0, bool signedScaling)
-	{
-		TEXM3X3PAD(u, v, s, src0, 2, signedScaling);
-
-		dst = sampleTexture(stage, u_, v_, w_, w_);
-	}
-
-	void PixelPipeline::TEXM3X3VSPEC(Vector4s &dst, Float4 &x, Float4 &y, Float4 &z, int stage, Vector4s &src0)
-	{
-		TEXM3X3PAD(x, y, z, src0, 2, false);
-
-		Float4 E[3];   // Eye vector
-
-		E[0] = v[2 + stage - 2].w;
-		E[1] = v[2 + stage - 1].w;
-		E[2] = v[2 + stage - 0].w;
-
-		// Reflection
-		Float4 u__;
-		Float4 v__;
-		Float4 w__;
-
-		// (u'', v'', w'') = 2 * (N . E) * N - E * (N . N)
-		u__ = u_ * E[0];
-		v__ = v_ * E[1];
-		w__ = w_ * E[2];
-		u__ += v__ + w__;
-		u__ += u__;
-		v__ = u__;
-		w__ = u__;
-		u__ *= u_;
-		v__ *= v_;
-		w__ *= w_;
-		u_ *= u_;
-		v_ *= v_;
-		w_ *= w_;
-		u_ += v_ + w_;
-		u__ -= E[0] * u_;
-		v__ -= E[1] * u_;
-		w__ -= E[2] * u_;
-
-		dst = sampleTexture(stage, u__, v__, w__, w__);
-	}
-
-	void PixelPipeline::TEXDEPTH()
-	{
-		u_ = Float4(rs[5].x);
-		v_ = Float4(rs[5].y);
-
-		// z / w
-		u_ *= Rcp_pp(v_);   // FIXME: Set result to 1.0 when division by zero
-
-		oDepth = u_;
-	}
-
-	void PixelPipeline::CND(Vector4s &dst, Vector4s &src0, Vector4s &src1, Vector4s &src2)
-	{
-		{Short4 t0; t0 = src0.x; t0 = CmpGT(t0, Short4(0x0800)); Short4 t1; t1 = src1.x; t1 = t1 & t0; t0 = ~t0 & src2.x; t0 = t0 | t1; dst.x = t0; };
-		{Short4 t0; t0 = src0.y; t0 = CmpGT(t0, Short4(0x0800)); Short4 t1; t1 = src1.y; t1 = t1 & t0; t0 = ~t0 & src2.y; t0 = t0 | t1; dst.y = t0; };
-		{Short4 t0; t0 = src0.z; t0 = CmpGT(t0, Short4(0x0800)); Short4 t1; t1 = src1.z; t1 = t1 & t0; t0 = ~t0 & src2.z; t0 = t0 | t1; dst.z = t0; };
-		{Short4 t0; t0 = src0.w; t0 = CmpGT(t0, Short4(0x0800)); Short4 t1; t1 = src1.w; t1 = t1 & t0; t0 = ~t0 & src2.w; t0 = t0 | t1; dst.w = t0; };
-	}
-
-	void PixelPipeline::CMP(Vector4s &dst, Vector4s &src0, Vector4s &src1, Vector4s &src2)
-	{
-		{Short4 t0 = CmpGT(Short4(0x0000), src0.x); Short4 t1; t1 = src2.x; t1 &= t0; t0 = ~t0 & src1.x; t0 |= t1; dst.x = t0; };
-		{Short4 t0 = CmpGT(Short4(0x0000), src0.y); Short4 t1; t1 = src2.y; t1 &= t0; t0 = ~t0 & src1.y; t0 |= t1; dst.y = t0; };
-		{Short4 t0 = CmpGT(Short4(0x0000), src0.z); Short4 t1; t1 = src2.z; t1 &= t0; t0 = ~t0 & src1.z; t0 |= t1; dst.z = t0; };
-		{Short4 t0 = CmpGT(Short4(0x0000), src0.w); Short4 t1; t1 = src2.w; t1 &= t0; t0 = ~t0 & src1.w; t0 |= t1; dst.w = t0; };
-	}
-
-	void PixelPipeline::BEM(Vector4s &dst, Vector4s &src0, Vector4s &src1, int stage)
-	{
-		Short4 t0;
-		Short4 t1;
-
-		// dst.x = src0.x + BUMPENVMAT00(stage) * src1.x + BUMPENVMAT10(stage) * src1.y
-		t0 = MulHigh(src1.x, *Pointer<Short4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4W[0][0]))); t0 = t0 << 4;   // FIXME: Matrix components range? Overflow hazard.
-		t1 = MulHigh(src1.y, *Pointer<Short4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4W[1][0]))); t1 = t1 << 4;   // FIXME: Matrix components range? Overflow hazard.
-		t0 = AddSat(t0, t1);
-		t0 = AddSat(t0, src0.x);
-		dst.x = t0;
-
-		// dst.y = src0.y + BUMPENVMAT01(stage) * src1.x + BUMPENVMAT11(stage) * src1.y
-		t0 = MulHigh(src1.x, *Pointer<Short4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4W[0][1]))); t0 = t0 << 4;   // FIXME: Matrix components range? Overflow hazard.
-		t1 = MulHigh(src1.y, *Pointer<Short4>(data + OFFSET(DrawData, textureStage[stage].bumpmapMatrix4W[1][1]))); t1 = t1 << 4;   // FIXME: Matrix components range? Overflow hazard.
-		t0 = AddSat(t0, t1);
-		t0 = AddSat(t0, src0.y);
-		dst.y = t0;
-	}
-}
-
diff --git a/src/Pipeline/PixelPipeline.hpp b/src/Pipeline/PixelPipeline.hpp
deleted file mode 100644
index 66f0ec7..0000000
--- a/src/Pipeline/PixelPipeline.hpp
+++ /dev/null
@@ -1,114 +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_PixelPipeline_hpp
-#define sw_PixelPipeline_hpp
-
-#include "PixelRoutine.hpp"
-
-namespace sw
-{
-	class PixelPipeline : public PixelRoutine
-	{
-	public:
-		PixelPipeline(const PixelProcessor::State &state, const PixelShader *shader) :
-			PixelRoutine(state, shader), current(rs[0]), diffuse(vs[0]), specular(vs[1]), perturbate(false), luminance(false), previousScaling(false) {}
-		virtual ~PixelPipeline() {}
-
-	protected:
-		virtual void setBuiltins(Int &x, Int &y, Float4(&z)[4], Float4 &w);
-		virtual void applyShader(Int cMask[4]);
-		virtual Bool alphaTest(Int cMask[4]);
-		virtual void rasterOperation(Float4 &fog, Pointer<Byte> cBuffer[4], Int &x, Int sMask[4], Int zMask[4], Int cMask[4]);
-
-	private:
-		Vector4s &current;
-		Vector4s &diffuse;
-		Vector4s &specular;
-
-		Vector4s rs[6];
-		Vector4s vs[2];
-		Vector4s ts[6];
-
-		// bem(l) offsets and luminance
-		Float4 du;
-		Float4 dv;
-		Short4 L;
-
-		// texm3x3 temporaries
-		Float4 u_; // FIXME
-		Float4 v_; // FIXME
-		Float4 w_; // FIXME
-		Float4 U;  // FIXME
-		Float4 V;  // FIXME
-		Float4 W;  // FIXME
-
-		void fixedFunction();
-		void blendTexture(Vector4s &temp, Vector4s &texture, int stage);
-		void fogBlend(Vector4s &current, Float4 &fog);
-		void specularPixel(Vector4s &current, Vector4s &specular);
-
-		Vector4s sampleTexture(int coordinates, int sampler, bool project = false);
-		Vector4s sampleTexture(int sampler, Float4 &u, Float4 &v, Float4 &w, Float4 &q, bool project = false);
-
-		Short4 convertFixed12(RValue<Float4> cf);
-		void convertFixed12(Vector4s &cs, Vector4f &cf);
-		Float4 convertSigned12(Short4 &cs);
-		void convertSigned12(Vector4f &cf, Vector4s &cs);
-
-		void writeDestination(Vector4s &d, const Dst &dst);
-		Vector4s fetchRegister(const Src &src);
-
-		// Instructions
-		void MOV(Vector4s &dst, Vector4s &src0);
-		void ADD(Vector4s &dst, Vector4s &src0, Vector4s &src1);
-		void SUB(Vector4s &dst, Vector4s &src0, Vector4s &src1);
-		void MAD(Vector4s &dst, Vector4s &src0, Vector4s &src1, Vector4s &src2);
-		void MUL(Vector4s &dst, Vector4s &src0, Vector4s &src1);
-		void DP3(Vector4s &dst, Vector4s &src0, Vector4s &src1);
-		void DP4(Vector4s &dst, Vector4s &src0, Vector4s &src1);
-		void LRP(Vector4s &dst, Vector4s &src0, Vector4s &src1, Vector4s &src2);
-		void TEXCOORD(Vector4s &dst, Float4 &u, Float4 &v, Float4 &s, int coordinate);
-		void TEXCRD(Vector4s &dst, Float4 &u, Float4 &v, Float4 &s, int coordinate, bool project);
-		void TEXDP3(Vector4s &dst, Float4 &u, Float4 &v, Float4 &s, Vector4s &src);
-		void TEXDP3TEX(Vector4s &dst, Float4 &u, Float4 &v, Float4 &s, int stage, Vector4s &src0);
-		void TEXKILL(Int cMask[4], Float4 &u, Float4 &v, Float4 &s);
-		void TEXKILL(Int cMask[4], Vector4s &dst);
-		void TEX(Vector4s &dst, Float4 &u, Float4 &v, Float4 &s, int stage, bool project);
-		void TEXLD(Vector4s &dst, Vector4s &src, int stage, bool project);
-		void TEXBEM(Vector4s &dst, Vector4s &src, Float4 &u, Float4 &v, Float4 &s, int stage);
-		void TEXBEML(Vector4s &dst, Vector4s &src, Float4 &u, Float4 &v, Float4 &s, int stage);
-		void TEXREG2AR(Vector4s &dst, Vector4s &src0, int stage);
-		void TEXREG2GB(Vector4s &dst, Vector4s &src0, int stage);
-		void TEXREG2RGB(Vector4s &dst, Vector4s &src0, int stage);
-		void TEXM3X2DEPTH(Vector4s &dst, Float4 &u, Float4 &v, Float4 &s, Vector4s &src, bool signedScaling);
-		void TEXM3X2PAD(Float4 &u, Float4 &v, Float4 &s, Vector4s &src0, int component, bool signedScaling);
-		void TEXM3X2TEX(Vector4s &dst, Float4 &u, Float4 &v, Float4 &s, int stage, Vector4s &src0, bool signedScaling);
-		void TEXM3X3(Vector4s &dst, Float4 &u, Float4 &v, Float4 &s, Vector4s &src0, bool signedScaling);
-		void TEXM3X3PAD(Float4 &u, Float4 &v, Float4 &s, Vector4s &src0, int component, bool signedScaling);
-		void TEXM3X3SPEC(Vector4s &dst, Float4 &u, Float4 &v, Float4 &s, int stage, Vector4s &src0, Vector4s &src1);
-		void TEXM3X3TEX(Vector4s &dst, Float4 &u, Float4 &v, Float4 &s, int stage, Vector4s &src0, bool singedScaling);
-		void TEXM3X3VSPEC(Vector4s &dst, Float4 &u, Float4 &v, Float4 &s, int stage, Vector4s &src0);
-		void TEXDEPTH();
-		void CND(Vector4s &dst, Vector4s &src0, Vector4s &src1, Vector4s &src2);
-		void CMP(Vector4s &dst, Vector4s &src0, Vector4s &src1, Vector4s &src2);
-		void BEM(Vector4s &dst, Vector4s &src0, Vector4s &src1, int stage);
-
-		bool perturbate;
-		bool luminance;
-		bool previousScaling;
-	};
-}
-
-#endif
diff --git a/src/Pipeline/PixelProgram.cpp b/src/Pipeline/PixelProgram.cpp
index 8f285f0..3d9cfe7 100644
--- a/src/Pipeline/PixelProgram.cpp
+++ b/src/Pipeline/PixelProgram.cpp
@@ -627,11 +627,6 @@
 				c[index].z = linearToSRGB(c[index].z);
 			}
 
-			if(index == 0)
-			{
-				fogBlend(c[index], fog);
-			}
-
 			switch(state.targetFormat[index])
 			{
 			case FORMAT_R5G6B5:
diff --git a/src/Pipeline/PixelRoutine.cpp b/src/Pipeline/PixelRoutine.cpp
index 31bcab3..0cf82cb 100644
--- a/src/Pipeline/PixelRoutine.cpp
+++ b/src/Pipeline/PixelRoutine.cpp
@@ -583,79 +583,6 @@
 		cMask[3] &= aMask3;
 	}
 
-	void PixelRoutine::fogBlend(Vector4f &c0, Float4 &fog)
-	{
-		if(!state.fogActive)
-		{
-			return;
-		}
-
-		if(state.pixelFogMode != FOG_NONE)
-		{
-			pixelFog(fog);
-
-			fog = Min(fog, Float4(1.0f));
-			fog = Max(fog, Float4(0.0f));
-		}
-
-		c0.x -= *Pointer<Float4>(data + OFFSET(DrawData,fog.colorF[0]));
-		c0.y -= *Pointer<Float4>(data + OFFSET(DrawData,fog.colorF[1]));
-		c0.z -= *Pointer<Float4>(data + OFFSET(DrawData,fog.colorF[2]));
-
-		c0.x *= fog;
-		c0.y *= fog;
-		c0.z *= fog;
-
-		c0.x += *Pointer<Float4>(data + OFFSET(DrawData,fog.colorF[0]));
-		c0.y += *Pointer<Float4>(data + OFFSET(DrawData,fog.colorF[1]));
-		c0.z += *Pointer<Float4>(data + OFFSET(DrawData,fog.colorF[2]));
-	}
-
-	void PixelRoutine::pixelFog(Float4 &visibility)
-	{
-		Float4 &zw = visibility;
-
-		if(state.pixelFogMode != FOG_NONE)
-		{
-			if(state.wBasedFog)
-			{
-				zw = rhw;
-			}
-			else
-			{
-				if(complementaryDepthBuffer)
-				{
-					zw = Float4(1.0f) - z[0];
-				}
-				else
-				{
-					zw = z[0];
-				}
-			}
-		}
-
-		switch(state.pixelFogMode)
-		{
-		case FOG_NONE:
-			break;
-		case FOG_LINEAR:
-			zw *= *Pointer<Float4>(data + OFFSET(DrawData,fog.scale));
-			zw += *Pointer<Float4>(data + OFFSET(DrawData,fog.offset));
-			break;
-		case FOG_EXP:
-			zw *= *Pointer<Float4>(data + OFFSET(DrawData,fog.densityE));
-			zw = exponential2(zw, true);
-			break;
-		case FOG_EXP2:
-			zw *= zw;
-			zw *= *Pointer<Float4>(data + OFFSET(DrawData,fog.density2E));
-			zw = exponential2(zw, true);
-			break;
-		default:
-			ASSERT(false);
-		}
-	}
-
 	void PixelRoutine::writeDepth(Pointer<Byte> &zBuffer, int q, Int &x, Float4 &z, Int &zMask)
 	{
 		if(!state.depthWriteEnable)
diff --git a/src/Pipeline/PixelRoutine.hpp b/src/Pipeline/PixelRoutine.hpp
index 0c5fd63..8e8e074 100644
--- a/src/Pipeline/PixelRoutine.hpp
+++ b/src/Pipeline/PixelRoutine.hpp
@@ -51,8 +51,6 @@
 
 		void alphaTest(Int &aMask, Short4 &alpha);
 		void alphaToCoverage(Int cMask[4], Float4 &alpha);
-		void fogBlend(Vector4f &c0, Float4 &fog);
-		void pixelFog(Float4 &visibility);
 
 		// Raster operations
 		void alphaBlend(int index, Pointer<Byte> &cBuffer, Vector4s &current, Int &x);
diff --git a/src/Pipeline/SetupRoutine.cpp b/src/Pipeline/SetupRoutine.cpp
index 7d12326..b5b31cd 100644
--- a/src/Pipeline/SetupRoutine.cpp
+++ b/src/Pipeline/SetupRoutine.cpp
@@ -47,10 +47,8 @@
 			Pointer<Byte> constants = *Pointer<Pointer<Byte> >(data + OFFSET(DrawData,constants));
 
 			const bool point = state.isDrawPoint;
-			const bool sprite = state.pointSprite;
 			const bool line = state.isDrawLine;
-			const bool triangle = state.isDrawSolidTriangle || sprite;
-			const bool solidTriangle = state.isDrawSolidTriangle;
+			const bool triangle = state.isDrawTriangle;
 
 			const int V0 = OFFSET(Triangle,v0);
 			const int V1 = (triangle || line) ? OFFSET(Triangle,v1) : OFFSET(Triangle,v0);
@@ -76,7 +74,7 @@
 			Int d = 1;     // Winding direction
 
 			// Culling
-			if(solidTriangle)
+			if(triangle)
 			{
 				Float x0 = Float(X[0]);
 				Float x1 = Float(X[1]);
@@ -141,7 +139,7 @@
 			Int n = *Pointer<Int>(polygon + OFFSET(Polygon,n));
 			Int m = *Pointer<Int>(polygon + OFFSET(Polygon,i));
 
-			If(m != 0 || Bool(!solidTriangle))   // Clipped triangle; reproject
+			If(m != 0 || Bool(!triangle))   // Clipped triangle; reproject
 			{
 				Pointer<Byte> V = polygon + OFFSET(Polygon,P) + m * sizeof(void*) * 16;
 
@@ -279,7 +277,7 @@
 			*Pointer<Int>(primitive + OFFSET(Primitive,yMax)) = yMax;
 
 			// Sort by minimum y
-			if(solidTriangle && logPrecision >= WHQL)
+			if(triangle)
 			{
 				Float y0 = *Pointer<Float>(v0 + pos * 16 + 4);
 				Float y1 = *Pointer<Float>(v1 + pos * 16 + 4);
@@ -292,7 +290,7 @@
 			}
 
 			// Sort by maximum w
-			if(solidTriangle)
+			if(triangle)
 			{
 				Float w0 = *Pointer<Float>(v0 + pos * 16 + 12);
 				Float w1 = *Pointer<Float>(v1 + pos * 16 + 12);
@@ -463,16 +461,11 @@
 
 					if(attribute != Unused)
 					{
-						setupGradient(primitive, tri, w012, M, v0, v1, v2, OFFSET(Vertex,v[attribute][component]), OFFSET(Primitive,V[interpolant][component]), flat, sprite, state.perspective, wrap, component);
+						setupGradient(primitive, tri, w012, M, v0, v1, v2, OFFSET(Vertex,v[attribute][component]), OFFSET(Primitive,V[interpolant][component]), flat, point, state.perspective, wrap, component);
 					}
 				}
 			}
 
-			if(state.fog.attribute == Fog)
-			{
-				setupGradient(primitive, tri, w012, M, v0, v1, v2, OFFSET(Vertex,f), OFFSET(Primitive,f), state.fog.flat, false, state.perspective, false, 0);
-			}
-
 			Return(true);
 		}
 
@@ -521,7 +514,7 @@
 				m = Max(m, *Pointer<Float>(v2 + attribute));
 				m -= 0.5f;
 
-				// FIXME: Vectorize
+				// TODO: Vectorize
 				If(Float(i.x) < m) i.x = i.x + 1.0f;
 				If(Float(i.y) < m) i.y = i.y + 1.0f;
 				If(Float(i.z) < m) i.z = i.z + 1.0f;
diff --git a/src/Pipeline/VertexPipeline.cpp b/src/Pipeline/VertexPipeline.cpp
deleted file mode 100644
index 129d8a8..0000000
--- a/src/Pipeline/VertexPipeline.cpp
+++ /dev/null
@@ -1,953 +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 "VertexPipeline.hpp"
-
-#include "Renderer/Vertex.hpp"
-#include "Renderer/Renderer.hpp"
-#include "Common/Debug.hpp"
-
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#undef max
-#undef min
-
-namespace sw
-{
-	extern bool secondaryColor;
-
-	VertexPipeline::VertexPipeline(const VertexProcessor::State &state) : VertexRoutine(state, 0)
-	{
-	}
-
-	VertexPipeline::~VertexPipeline()
-	{
-	}
-
-	Vector4f VertexPipeline::transformBlend(const Register &src, const Pointer<Byte> &matrix, bool homogeneous)
-	{
-		Vector4f dst;
-
-		if(state.vertexBlendMatrixCount == 0)
-		{
-			dst = transform(src, matrix, homogeneous);
-		}
-		else
-		{
-			UInt index0[4];
-			UInt index1[4];
-			UInt index2[4];
-			UInt index3[4];
-
-			if(state.indexedVertexBlendEnable)
-			{
-				for(int i = 0; i < 4; i++)
-				{
-					Float4 B = v[BlendIndices].x;
-					UInt indices;
-
-					switch(i)
-					{
-					case 0: indices = As<UInt>(Float(B.x)); break;
-					case 1: indices = As<UInt>(Float(B.y)); break;
-					case 2: indices = As<UInt>(Float(B.z)); break;
-					case 3: indices = As<UInt>(Float(B.w)); break;
-					}
-
-					index0[i] = (indices & 0x000000FF) << 6;
-					index1[i] = (indices & 0x0000FF00) >> 2;
-					index2[i] = (indices & 0x00FF0000) >> 10;
-					index3[i] = (indices & 0xFF000000) >> 18;
-				}
-			}
-			else
-			{
-				for(int i = 0; i < 4; i++)
-				{
-					index0[i] = 0 * 64;
-					index1[i] = 1 * 64;
-					index2[i] = 2 * 64;
-					index3[i] = 3 * 64;
-				}
-			}
-
-			Float4 weight0;
-			Float4 weight1;
-			Float4 weight2;
-			Float4 weight3;
-
-			switch(state.vertexBlendMatrixCount)
-			{
-			case 4: weight2 = v[BlendWeight].z;
-			case 3: weight1 = v[BlendWeight].y;
-			case 2: weight0 = v[BlendWeight].x;
-			case 1:
-				break;
-			}
-
-			if(state.vertexBlendMatrixCount == 1)
-			{
-				dst = transform(src, matrix, index0, homogeneous);
-			}
-			else if(state.vertexBlendMatrixCount == 2)
-			{
-				weight1 = Float4(1.0f) - weight0;
-
-				Vector4f pos0;
-				Vector4f pos1;
-
-				pos0 = transform(src, matrix, index0, homogeneous);
-				pos1 = transform(src, matrix, index1, homogeneous);
-
-				dst.x = pos0.x * weight0 + pos1.x * weight1;   // FIXME: Vector4f operators
-				dst.y = pos0.y * weight0 + pos1.y * weight1;
-				dst.z = pos0.z * weight0 + pos1.z * weight1;
-				dst.w = pos0.w * weight0 + pos1.w * weight1;
-			}
-			else if(state.vertexBlendMatrixCount == 3)
-			{
-				weight2 = Float4(1.0f) - (weight0 + weight1);
-
-				Vector4f pos0;
-				Vector4f pos1;
-				Vector4f pos2;
-
-				pos0 = transform(src, matrix, index0, homogeneous);
-				pos1 = transform(src, matrix, index1, homogeneous);
-				pos2 = transform(src, matrix, index2, homogeneous);
-
-				dst.x = pos0.x * weight0 + pos1.x * weight1 + pos2.x * weight2;
-				dst.y = pos0.y * weight0 + pos1.y * weight1 + pos2.y * weight2;
-				dst.z = pos0.z * weight0 + pos1.z * weight1 + pos2.z * weight2;
-				dst.w = pos0.w * weight0 + pos1.w * weight1 + pos2.w * weight2;
-			}
-			else if(state.vertexBlendMatrixCount == 4)
-			{
-				weight3 = Float4(1.0f) - (weight0 + weight1 + weight2);
-
-				Vector4f pos0;
-				Vector4f pos1;
-				Vector4f pos2;
-				Vector4f pos3;
-
-				pos0 = transform(src, matrix, index0, homogeneous);
-				pos1 = transform(src, matrix, index1, homogeneous);
-				pos2 = transform(src, matrix, index2, homogeneous);
-				pos3 = transform(src, matrix, index3, homogeneous);
-
-				dst.x = pos0.x * weight0 + pos1.x * weight1 + pos2.x * weight2 + pos3.x * weight3;
-				dst.y = pos0.y * weight0 + pos1.y * weight1 + pos2.y * weight2 + pos3.y * weight3;
-				dst.z = pos0.z * weight0 + pos1.z * weight1 + pos2.z * weight2 + pos3.z * weight3;
-				dst.w = pos0.w * weight0 + pos1.w * weight1 + pos2.w * weight2 + pos3.w * weight3;
-			}
-		}
-
-		return dst;
-	}
-
-	void VertexPipeline::pipeline(UInt &index)
-	{
-		Vector4f position;
-		Vector4f normal;
-
-		if(!state.preTransformed)
-		{
-			position = transformBlend(v[Position], Pointer<Byte>(data + OFFSET(DrawData,ff.transformT)), true);
-		}
-		else
-		{
-			position = v[PositionT];
-		}
-
-		o[Pos].x = position.x;
-		o[Pos].y = position.y;
-		o[Pos].z = position.z;
-		o[Pos].w = position.w;
-
-		Vector4f vertexPosition = transformBlend(v[Position], Pointer<Byte>(data + OFFSET(DrawData,ff.cameraTransformT)), true);
-
-		if(state.vertexNormalActive)
-		{
-			normal = transformBlend(v[Normal], Pointer<Byte>(data + OFFSET(DrawData,ff.normalTransformT)), false);
-
-			if(state.normalizeNormals)
-			{
-				normal = normalize(normal);
-			}
-		}
-
-		if(!state.vertexLightingActive)
-		{
-			// FIXME: Don't process if not used at all
-			if(state.diffuseActive && state.input[Color0])
-			{
-				Vector4f diffuse = v[Color0];
-
-				o[C0].x = diffuse.x;
-				o[C0].y = diffuse.y;
-				o[C0].z = diffuse.z;
-				o[C0].w = diffuse.w;
-			}
-			else
-			{
-				o[C0].x = Float4(1.0f);
-				o[C0].y = Float4(1.0f);
-				o[C0].z = Float4(1.0f);
-				o[C0].w = Float4(1.0f);
-			}
-
-			// FIXME: Don't process if not used at all
-			if(state.specularActive && state.input[Color1])
-			{
-				Vector4f specular = v[Color1];
-
-				o[C1].x = specular.x;
-				o[C1].y = specular.y;
-				o[C1].z = specular.z;
-				o[C1].w = specular.w;
-			}
-			else
-			{
-				o[C1].x = Float4(0.0f);
-				o[C1].y = Float4(0.0f);
-				o[C1].z = Float4(0.0f);
-				o[C1].w = Float4(1.0f);
-			}
-		}
-		else
-		{
-			o[C0].x = Float4(0.0f);
-			o[C0].y = Float4(0.0f);
-			o[C0].z = Float4(0.0f);
-			o[C0].w = Float4(0.0f);
-
-			o[C1].x = Float4(0.0f);
-			o[C1].y = Float4(0.0f);
-			o[C1].z = Float4(0.0f);
-			o[C1].w = Float4(0.0f);
-
-			Vector4f ambient;
-			Float4 globalAmbient = *Pointer<Float4>(data + OFFSET(DrawData,ff.globalAmbient));   // FIXME: Unpack
-
-			ambient.x = globalAmbient.x;
-			ambient.y = globalAmbient.y;
-			ambient.z = globalAmbient.z;
-
-			for(int i = 0; i < 8; i++)
-			{
-				if(!(state.vertexLightActive & (1 << i)))
-				{
-					continue;
-				}
-
-				Vector4f L;    // Light vector
-				Float4 att;   // Attenuation
-
-				// Attenuation
-				{
-					Float4 d;   // Distance
-
-					L.x = L.y = L.z = *Pointer<Float4>(data + OFFSET(DrawData,ff.lightPosition[i]));   // FIXME: Unpack
-					L.x = L.x.xxxx;
-					L.y = L.y.yyyy;
-					L.z = L.z.zzzz;
-
-					L.x -= vertexPosition.x;
-					L.y -= vertexPosition.y;
-					L.z -= vertexPosition.z;
-					d = dot3(L, L);
-					d = RcpSqrt_pp(d);     // FIXME: Sufficient precision?
-					L.x *= d;
-					L.y *= d;
-					L.z *= d;
-					d = Rcp_pp(d);       // FIXME: Sufficient precision?
-
-					Float4 q = *Pointer<Float4>(data + OFFSET(DrawData,ff.attenuationQuadratic[i]));
-					Float4 l = *Pointer<Float4>(data + OFFSET(DrawData,ff.attenuationLinear[i]));
-					Float4 c = *Pointer<Float4>(data + OFFSET(DrawData,ff.attenuationConstant[i]));
-
-					att = Rcp_pp((q * d + l) * d + c);
-				}
-
-				// Ambient per light
-				{
-					Float4 lightAmbient = *Pointer<Float4>(data + OFFSET(DrawData,ff.lightAmbient[i]));   // FIXME: Unpack
-
-					ambient.x = ambient.x + lightAmbient.x * att;
-					ambient.y = ambient.y + lightAmbient.y * att;
-					ambient.z = ambient.z + lightAmbient.z * att;
-				}
-
-				// Diffuse
-				if(state.vertexNormalActive)
-				{
-					Float4 dot;
-
-					dot = dot3(L, normal);
-					dot = Max(dot, Float4(0.0f));
-					dot *= att;
-
-					Vector4f diff;
-
-					if(state.vertexDiffuseMaterialSourceActive == MATERIAL_MATERIAL)
-					{
-						diff.x = diff.y = diff.z = *Pointer<Float4>(data + OFFSET(DrawData,ff.materialDiffuse));   // FIXME: Unpack
-						diff.x = diff.x.xxxx;
-						diff.y = diff.y.yyyy;
-						diff.z = diff.z.zzzz;
-					}
-					else if(state.vertexDiffuseMaterialSourceActive == MATERIAL_COLOR1)
-					{
-						diff = v[Color0];
-					}
-					else if(state.vertexDiffuseMaterialSourceActive == MATERIAL_COLOR2)
-					{
-						diff = v[Color1];
-					}
-					else ASSERT(false);
-
-					Float4 lightDiffuse = *Pointer<Float4>(data + OFFSET(DrawData,ff.lightDiffuse[i]));
-
-					o[C0].x = o[C0].x + diff.x * dot * lightDiffuse.x;   // FIXME: Clamp first?
-					o[C0].y = o[C0].y + diff.y * dot * lightDiffuse.y;   // FIXME: Clamp first?
-					o[C0].z = o[C0].z + diff.z * dot * lightDiffuse.z;   // FIXME: Clamp first?
-				}
-
-				// Specular
-				if(state.vertexSpecularActive)
-				{
-					Vector4f S;
-					Vector4f C;   // Camera vector
-					Float4 pow;
-
-					pow = *Pointer<Float>(data + OFFSET(DrawData,ff.materialShininess));
-
-					S.x = Float4(0.0f) - vertexPosition.x;
-					S.y = Float4(0.0f) - vertexPosition.y;
-					S.z = Float4(0.0f) - vertexPosition.z;
-					C = normalize(S);
-
-					S.x = L.x + C.x;
-					S.y = L.y + C.y;
-					S.z = L.z + C.z;
-					C = normalize(S);
-
-					Float4 dot = Max(dot3(C, normal), Float4(0.0f));   // FIXME: max(dot3(C, normal), 0)
-
-					Float4 P = power(dot, pow);
-					P *= att;
-
-					Vector4f spec;
-
-					if(state.vertexSpecularMaterialSourceActive == MATERIAL_MATERIAL)
-					{
-						Float4 materialSpecular = *Pointer<Float4>(data + OFFSET(DrawData,ff.materialSpecular));   // FIXME: Unpack
-
-						spec.x = materialSpecular.x;
-						spec.y = materialSpecular.y;
-						spec.z = materialSpecular.z;
-					}
-					else if(state.vertexSpecularMaterialSourceActive == MATERIAL_COLOR1)
-					{
-						spec = v[Color0];
-					}
-					else if(state.vertexSpecularMaterialSourceActive == MATERIAL_COLOR2)
-					{
-						spec = v[Color1];
-					}
-					else ASSERT(false);
-
-					Float4 lightSpecular = *Pointer<Float4>(data + OFFSET(DrawData,ff.lightSpecular[i]));
-
-					spec.x *= lightSpecular.x;
-					spec.y *= lightSpecular.y;
-					spec.z *= lightSpecular.z;
-
-					spec.x *= P;
-					spec.y *= P;
-					spec.z *= P;
-
-					spec.x = Max(spec.x, Float4(0.0f));
-					spec.y = Max(spec.y, Float4(0.0f));
-					spec.z = Max(spec.z, Float4(0.0f));
-
-					if(secondaryColor)
-					{
-						o[C1].x = o[C1].x + spec.x;
-						o[C1].y = o[C1].y + spec.y;
-						o[C1].z = o[C1].z + spec.z;
-					}
-					else
-					{
-						o[C0].x = o[C0].x + spec.x;
-						o[C0].y = o[C0].y + spec.y;
-						o[C0].z = o[C0].z + spec.z;
-					}
-				}
-			}
-
-			if(state.vertexAmbientMaterialSourceActive == MATERIAL_MATERIAL)
-			{
-				Float4 materialAmbient = *Pointer<Float4>(data + OFFSET(DrawData,ff.materialAmbient));   // FIXME: Unpack
-
-				ambient.x = ambient.x * materialAmbient.x;
-				ambient.y = ambient.y * materialAmbient.y;
-				ambient.z = ambient.z * materialAmbient.z;
-			}
-			else if(state.vertexAmbientMaterialSourceActive == MATERIAL_COLOR1)
-			{
-				Vector4f materialDiffuse = v[Color0];
-
-				ambient.x = ambient.x * materialDiffuse.x;
-				ambient.y = ambient.y * materialDiffuse.y;
-				ambient.z = ambient.z * materialDiffuse.z;
-			}
-			else if(state.vertexAmbientMaterialSourceActive == MATERIAL_COLOR2)
-			{
-				Vector4f materialSpecular = v[Color1];
-
-				ambient.x = ambient.x * materialSpecular.x;
-				ambient.y = ambient.y * materialSpecular.y;
-				ambient.z = ambient.z * materialSpecular.z;
-			}
-			else ASSERT(false);
-
-			o[C0].x = o[C0].x + ambient.x;
-			o[C0].y = o[C0].y + ambient.y;
-			o[C0].z = o[C0].z + ambient.z;
-
-			// Emissive
-			if(state.vertexEmissiveMaterialSourceActive == MATERIAL_MATERIAL)
-			{
-				Float4 materialEmission = *Pointer<Float4>(data + OFFSET(DrawData,ff.materialEmission));   // FIXME: Unpack
-
-				o[C0].x = o[C0].x + materialEmission.x;
-				o[C0].y = o[C0].y + materialEmission.y;
-				o[C0].z = o[C0].z + materialEmission.z;
-			}
-			else if(state.vertexEmissiveMaterialSourceActive == MATERIAL_COLOR1)
-			{
-				Vector4f materialSpecular = v[Color0];
-
-				o[C0].x = o[C0].x + materialSpecular.x;
-				o[C0].y = o[C0].y + materialSpecular.y;
-				o[C0].z = o[C0].z + materialSpecular.z;
-			}
-			else if(state.vertexEmissiveMaterialSourceActive == MATERIAL_COLOR2)
-			{
-				Vector4f materialSpecular = v[Color1];
-
-				o[C0].x = o[C0].x + materialSpecular.x;
-				o[C0].y = o[C0].y + materialSpecular.y;
-				o[C0].z = o[C0].z + materialSpecular.z;
-			}
-			else ASSERT(false);
-
-			// Diffuse alpha component
-			if(state.vertexDiffuseMaterialSourceActive == MATERIAL_MATERIAL)
-			{
-				o[C0].w = Float4(*Pointer<Float4>(data + OFFSET(DrawData,ff.materialDiffuse[0]))).wwww;   // FIXME: Unpack
-			}
-			else if(state.vertexDiffuseMaterialSourceActive == MATERIAL_COLOR1)
-			{
-				Vector4f alpha = v[Color0];
-				o[C0].w = alpha.w;
-			}
-			else if(state.vertexDiffuseMaterialSourceActive == MATERIAL_COLOR2)
-			{
-				Vector4f alpha = v[Color1];
-				o[C0].w = alpha.w;
-			}
-			else ASSERT(false);
-
-			if(state.vertexSpecularActive)
-			{
-				// Specular alpha component
-				if(state.vertexSpecularMaterialSourceActive == MATERIAL_MATERIAL)
-				{
-					o[C1].w = Float4(*Pointer<Float4>(data + OFFSET(DrawData,ff.materialSpecular[3]))).wwww;   // FIXME: Unpack
-				}
-				else if(state.vertexSpecularMaterialSourceActive == MATERIAL_COLOR1)
-				{
-					Vector4f alpha = v[Color0];
-					o[C1].w = alpha.w;
-				}
-				else if(state.vertexSpecularMaterialSourceActive == MATERIAL_COLOR2)
-				{
-					Vector4f alpha = v[Color1];
-					o[C1].w = alpha.w;
-				}
-				else ASSERT(false);
-			}
-		}
-
-		if(state.fogActive)
-		{
-			Float4 f;
-
-			if(!state.rangeFogActive)
-			{
-				f = Abs(vertexPosition.z);
-			}
-			else
-			{
-				f = Sqrt(dot3(vertexPosition, vertexPosition));   // FIXME: f = length(vertexPosition);
-			}
-
-			switch(state.vertexFogMode)
-			{
-			case FOG_NONE:
-				if(state.specularActive)
-				{
-					o[Fog].x = o[C1].w;
-				}
-				else
-				{
-					o[Fog].x = Float4(0.0f);
-				}
-				break;
-			case FOG_LINEAR:
-				o[Fog].x = f * *Pointer<Float4>(data + OFFSET(DrawData,fog.scale)) + *Pointer<Float4>(data + OFFSET(DrawData,fog.offset));
-				break;
-			case FOG_EXP:
-				o[Fog].x = exponential2(f * *Pointer<Float4>(data + OFFSET(DrawData,fog.densityE)), true);
-				break;
-			case FOG_EXP2:
-				o[Fog].x = exponential2((f * f) * *Pointer<Float4>(data + OFFSET(DrawData,fog.density2E)), true);
-				break;
-			default:
-				ASSERT(false);
-			}
-		}
-
-		for(int stage = 0; stage < 8; stage++)
-		{
-			processTextureCoordinate(stage, normal, position);
-		}
-
-		processPointSize();
-	}
-
-	void VertexPipeline::processTextureCoordinate(int stage, Vector4f &normal, Vector4f &position)
-	{
-		if(state.output[T0 + stage].write)
-		{
-			int i = state.textureState[stage].texCoordIndexActive;
-
-			switch(state.textureState[stage].texGenActive)
-			{
-			case TEXGEN_NONE:
-				{
-					Vector4f &&varying = v[TexCoord0 + i];
-
-					o[T0 + stage].x = varying.x;
-					o[T0 + stage].y = varying.y;
-					o[T0 + stage].z = varying.z;
-					o[T0 + stage].w = varying.w;
-				}
-				break;
-			case TEXGEN_PASSTHRU:
-				{
-					Vector4f &&varying = v[TexCoord0 + i];
-
-					o[T0 + stage].x = varying.x;
-					o[T0 + stage].y = varying.y;
-					o[T0 + stage].z = varying.z;
-					o[T0 + stage].w = varying.w;
-
-					if(state.input[TexCoord0 + i])
-					{
-						switch(state.input[TexCoord0 + i].count)
-						{
-						case 1:
-							o[T0 + stage].y = Float4(1.0f);
-							o[T0 + stage].z = Float4(0.0f);
-							o[T0 + stage].w = Float4(0.0f);
-							break;
-						case 2:
-							o[T0 + stage].z = Float4(1.0f);
-							o[T0 + stage].w = Float4(0.0f);
-							break;
-						case 3:
-							o[T0 + stage].w = Float4(1.0f);
-							break;
-						case 4:
-							break;
-						default:
-							ASSERT(false);
-						}
-					}
-				}
-				break;
-			case TEXGEN_NORMAL:
-				{
-					Vector4f Nc;   // Normal vector in camera space
-
-					if(state.vertexNormalActive)
-					{
-						Nc = normal;
-					}
-					else
-					{
-						Nc.x = Float4(0.0f);
-						Nc.y = Float4(0.0f);
-						Nc.z = Float4(0.0f);
-					}
-
-					Nc.w = Float4(1.0f);
-
-					o[T0 + stage].x = Nc.x;
-					o[T0 + stage].y = Nc.y;
-					o[T0 + stage].z = Nc.z;
-					o[T0 + stage].w = Nc.w;
-				}
-				break;
-			case TEXGEN_POSITION:
-				{
-					Vector4f Pn = transformBlend(v[Position], Pointer<Byte>(data + OFFSET(DrawData,ff.cameraTransformT)), true);   // Position in camera space
-
-					Pn.w = Float4(1.0f);
-
-					o[T0 + stage].x = Pn.x;
-					o[T0 + stage].y = Pn.y;
-					o[T0 + stage].z = Pn.z;
-					o[T0 + stage].w = Pn.w;
-				}
-				break;
-			case TEXGEN_REFLECTION:
-				{
-					Vector4f R;   // Reflection vector
-
-					if(state.vertexNormalActive)
-					{
-						Vector4f Nc;   // Normal vector in camera space
-
-						Nc = normal;
-
-						if(state.localViewerActive)
-						{
-							Vector4f Ec;   // Eye vector in camera space
-							Vector4f N2;
-
-							Ec = transformBlend(v[Position], Pointer<Byte>(data + OFFSET(DrawData,ff.cameraTransformT)), true);
-							Ec = normalize(Ec);
-
-							// R = E - 2 * N * (E . N)
-							Float4 dot = Float4(2.0f) * dot3(Ec, Nc);
-
-							R.x = Ec.x - Nc.x * dot;
-							R.y = Ec.y - Nc.y * dot;
-							R.z = Ec.z - Nc.z * dot;
-						}
-						else
-						{
-							// u = -2 * Nz * Nx
-							// v = -2 * Nz * Ny
-							// w = 1 - 2 * Nz * Nz
-
-							R.x = -Float4(2.0f) * Nc.z * Nc.x;
-							R.y = -Float4(2.0f) * Nc.z * Nc.y;
-							R.z = Float4(1.0f) - Float4(2.0f) * Nc.z * Nc.z;
-						}
-					}
-					else
-					{
-						R.x = Float4(0.0f);
-						R.y = Float4(0.0f);
-						R.z = Float4(0.0f);
-					}
-
-					R.w = Float4(1.0f);
-
-					o[T0 + stage].x = R.x;
-					o[T0 + stage].y = R.y;
-					o[T0 + stage].z = R.z;
-					o[T0 + stage].w = R.w;
-				}
-				break;
-			case TEXGEN_SPHEREMAP:
-				{
-					Vector4f R;   // Reflection vector
-
-					if(state.vertexNormalActive)
-					{
-						Vector4f Nc;   // Normal vector in camera space
-
-						Nc = normal;
-
-						if(state.localViewerActive)
-						{
-							Vector4f Ec;   // Eye vector in camera space
-							Vector4f N2;
-
-							Ec = transformBlend(v[Position], Pointer<Byte>(data + OFFSET(DrawData,ff.cameraTransformT)), true);
-							Ec = normalize(Ec);
-
-							// R = E - 2 * N * (E . N)
-							Float4 dot = Float4(2.0f) * dot3(Ec, Nc);
-
-							R.x = Ec.x - Nc.x * dot;
-							R.y = Ec.y - Nc.y * dot;
-							R.z = Ec.z - Nc.z * dot;
-						}
-						else
-						{
-							// u = -2 * Nz * Nx
-							// v = -2 * Nz * Ny
-							// w = 1 - 2 * Nz * Nz
-
-							R.x = -Float4(2.0f) * Nc.z * Nc.x;
-							R.y = -Float4(2.0f) * Nc.z * Nc.y;
-							R.z = Float4(1.0f) - Float4(2.0f) * Nc.z * Nc.z;
-						}
-					}
-					else
-					{
-						R.x = Float4(0.0f);
-						R.y = Float4(0.0f);
-						R.z = Float4(0.0f);
-					}
-
-					R.z -= Float4(1.0f);
-					R = normalize(R);
-					R.x = Float4(0.5f) * R.x + Float4(0.5f);
-					R.y = Float4(0.5f) * R.y + Float4(0.5f);
-
-					R.z = Float4(1.0f);
-					R.w = Float4(0.0f);
-
-					o[T0 + stage].x = R.x;
-					o[T0 + stage].y = R.y;
-					o[T0 + stage].z = R.z;
-					o[T0 + stage].w = R.w;
-				}
-				break;
-			default:
-				ASSERT(false);
-			}
-
-			Vector4f texTrans0;
-			Vector4f texTrans1;
-			Vector4f texTrans2;
-			Vector4f texTrans3;
-
-			Vector4f T;
-			Vector4f t;
-
-			T.x = o[T0 + stage].x;
-			T.y = o[T0 + stage].y;
-			T.z = o[T0 + stage].z;
-			T.w = o[T0 + stage].w;
-
-			switch(state.textureState[stage].textureTransformCountActive)
-			{
-			case 4:
-				texTrans3.x = texTrans3.y = texTrans3.z = texTrans3.w = *Pointer<Float4>(data + OFFSET(DrawData,ff.textureTransform[stage][3]));   // FIXME: Unpack
-				texTrans3.x = texTrans3.x.xxxx;
-				texTrans3.y = texTrans3.y.yyyy;
-				texTrans3.z = texTrans3.z.zzzz;
-				texTrans3.w = texTrans3.w.wwww;
-				t.w = dot4(T, texTrans3);
-			case 3:
-				texTrans2.x = texTrans2.y = texTrans2.z = texTrans2.w = *Pointer<Float4>(data + OFFSET(DrawData,ff.textureTransform[stage][2]));   // FIXME: Unpack
-				texTrans2.x = texTrans2.x.xxxx;
-				texTrans2.y = texTrans2.y.yyyy;
-				texTrans2.z = texTrans2.z.zzzz;
-				texTrans2.w = texTrans2.w.wwww;
-				t.z = dot4(T, texTrans2);
-			case 2:
-				texTrans1.x = texTrans1.y = texTrans1.z = texTrans1.w = *Pointer<Float4>(data + OFFSET(DrawData,ff.textureTransform[stage][1]));   // FIXME: Unpack
-				texTrans1.x = texTrans1.x.xxxx;
-				texTrans1.y = texTrans1.y.yyyy;
-				texTrans1.z = texTrans1.z.zzzz;
-				texTrans1.w = texTrans1.w.wwww;
-				t.y = dot4(T, texTrans1);
-			case 1:
-				texTrans0.x = texTrans0.y = texTrans0.z = texTrans0.w = *Pointer<Float4>(data + OFFSET(DrawData,ff.textureTransform[stage][0]));   // FIXME: Unpack
-				texTrans0.x = texTrans0.x.xxxx;
-				texTrans0.y = texTrans0.y.yyyy;
-				texTrans0.z = texTrans0.z.zzzz;
-				texTrans0.w = texTrans0.w.wwww;
-				t.x = dot4(T, texTrans0);
-
-				o[T0 + stage].x = t.x;
-				o[T0 + stage].y = t.y;
-				o[T0 + stage].z = t.z;
-				o[T0 + stage].w = t.w;
-			case 0:
-				break;
-			default:
-				ASSERT(false);
-			}
-		}
-	}
-
-	void VertexPipeline::processPointSize()
-	{
-		if(!state.pointSizeActive)
-		{
-			return;   // Use global pointsize
-		}
-
-		if(state.input[PointSize])
-		{
-			o[Pts].y = v[PointSize].x;
-		}
-		else
-		{
-			o[Pts].y = *Pointer<Float4>(data + OFFSET(DrawData,point.pointSize));
-		}
-
-		if(state.pointScaleActive && !state.preTransformed)
-		{
-			Vector4f p = transformBlend(v[Position], Pointer<Byte>(data + OFFSET(DrawData,ff.cameraTransformT)), true);
-
-			Float4 d = Sqrt(dot3(p, p));   // FIXME: length(p);
-
-			Float4 A = *Pointer<Float>(data + OFFSET(DrawData,point.pointScaleA));   // FIXME: Unpack
-			Float4 B = *Pointer<Float>(data + OFFSET(DrawData,point.pointScaleB));   // FIXME: Unpack
-			Float4 C = *Pointer<Float>(data + OFFSET(DrawData,point.pointScaleC));   // FIXME: Unpack
-
-			A = RcpSqrt_pp(A + d * (B + d * C));
-
-			o[Pts].y = o[Pts].y * Float4(*Pointer<Float>(data + OFFSET(DrawData,viewportHeight))) * A;   // FIXME: Unpack
-		}
-	}
-
-	Vector4f VertexPipeline::transform(const Register &src, const Pointer<Byte> &matrix, bool homogeneous)
-	{
-		Vector4f dst;
-
-		if(homogeneous)
-		{
-			Float4 m[4][4];
-
-			for(int j = 0; j < 4; j++)
-			{
-				for(int i = 0; i < 4; i++)
-				{
-					m[j][i].x = *Pointer<Float>(matrix + 16 * i + 4 * j);
-					m[j][i].y = *Pointer<Float>(matrix + 16 * i + 4 * j);
-					m[j][i].z = *Pointer<Float>(matrix + 16 * i + 4 * j);
-					m[j][i].w = *Pointer<Float>(matrix + 16 * i + 4 * j);
-				}
-			}
-
-			dst.x = src.x * m[0][0] + src.y * m[0][1] + src.z * m[0][2] + src.w * m[0][3];
-			dst.y = src.x * m[1][0] + src.y * m[1][1] + src.z * m[1][2] + src.w * m[1][3];
-			dst.z = src.x * m[2][0] + src.y * m[2][1] + src.z * m[2][2] + src.w * m[2][3];
-			dst.w = src.x * m[3][0] + src.y * m[3][1] + src.z * m[3][2] + src.w * m[3][3];
-		}
-		else
-		{
-			Float4 m[3][3];
-
-			for(int j = 0; j < 3; j++)
-			{
-				for(int i = 0; i < 3; i++)
-				{
-					m[j][i].x = *Pointer<Float>(matrix + 16 * i + 4 * j);
-					m[j][i].y = *Pointer<Float>(matrix + 16 * i + 4 * j);
-					m[j][i].z = *Pointer<Float>(matrix + 16 * i + 4 * j);
-					m[j][i].w = *Pointer<Float>(matrix + 16 * i + 4 * j);
-				}
-			}
-
-			dst.x = src.x * m[0][0] + src.y * m[0][1] + src.z * m[0][2];
-			dst.y = src.x * m[1][0] + src.y * m[1][1] + src.z * m[1][2];
-			dst.z = src.x * m[2][0] + src.y * m[2][1] + src.z * m[2][2];
-		}
-
-		return dst;
-	}
-
-	Vector4f VertexPipeline::transform(const Register &src, const Pointer<Byte> &matrix, UInt index[4], bool homogeneous)
-	{
-		Vector4f dst;
-
-		if(homogeneous)
-		{
-			Float4 m[4][4];
-
-			for(int j = 0; j < 4; j++)
-			{
-				for(int i = 0; i < 4; i++)
-				{
-					m[j][i].x = *Pointer<Float>(matrix + 16 * i + 4 * j + index[0]);
-					m[j][i].y = *Pointer<Float>(matrix + 16 * i + 4 * j + index[1]);
-					m[j][i].z = *Pointer<Float>(matrix + 16 * i + 4 * j + index[2]);
-					m[j][i].w = *Pointer<Float>(matrix + 16 * i + 4 * j + index[3]);
-				}
-			}
-
-			dst.x = src.x * m[0][0] + src.y * m[0][1] + src.z * m[0][2] + m[0][3];
-			dst.y = src.x * m[1][0] + src.y * m[1][1] + src.z * m[1][2] + m[1][3];
-			dst.z = src.x * m[2][0] + src.y * m[2][1] + src.z * m[2][2] + m[2][3];
-			dst.w = src.x * m[3][0] + src.y * m[3][1] + src.z * m[3][2] + m[3][3];
-		}
-		else
-		{
-			Float4 m[3][3];
-
-			for(int j = 0; j < 3; j++)
-			{
-				for(int i = 0; i < 3; i++)
-				{
-					m[j][i].x = *Pointer<Float>(matrix + 16 * i + 4 * j + index[0]);
-					m[j][i].y = *Pointer<Float>(matrix + 16 * i + 4 * j + index[1]);
-					m[j][i].z = *Pointer<Float>(matrix + 16 * i + 4 * j + index[2]);
-					m[j][i].w = *Pointer<Float>(matrix + 16 * i + 4 * j + index[3]);
-				}
-			}
-
-			dst.x = src.x * m[0][0] + src.y * m[0][1] + src.z * m[0][2];
-			dst.y = src.x * m[1][0] + src.y * m[1][1] + src.z * m[1][2];
-			dst.z = src.x * m[2][0] + src.y * m[2][1] + src.z * m[2][2];
-		}
-
-		return dst;
-	}
-
-	Vector4f VertexPipeline::normalize(Vector4f &src)
-	{
-		Vector4f dst;
-
-		Float4 rcpLength = RcpSqrt_pp(dot3(src, src));
-
-		dst.x = src.x * rcpLength;
-		dst.y = src.y * rcpLength;
-		dst.z = src.z * rcpLength;
-
-		return dst;
-	}
-
-	Float4 VertexPipeline::power(Float4 &src0, Float4 &src1)
-	{
-		Float4 dst = src0;
-
-		dst = dst * dst;
-		dst = dst * dst;
-		dst = Float4(As<Int4>(dst) - As<Int4>(Float4(1.0f)));
-
-		dst *= src1;
-
-		dst = As<Float4>(Int4(dst) + As<Int4>(Float4(1.0f)));
-		dst = RcpSqrt_pp(dst);
-		dst = RcpSqrt_pp(dst);
-
-		return dst;
-	}
-}
diff --git a/src/Pipeline/VertexPipeline.hpp b/src/Pipeline/VertexPipeline.hpp
deleted file mode 100644
index 852c76a..0000000
--- a/src/Pipeline/VertexPipeline.hpp
+++ /dev/null
@@ -1,45 +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_VertexPipeline_hpp
-#define sw_VertexPipeline_hpp
-
-#include "VertexRoutine.hpp"
-
-#include "Device/Context.hpp"
-#include "Device/VertexProcessor.hpp"
-
-namespace sw
-{
-	class VertexPipeline : public VertexRoutine
-	{
-	public:
-		VertexPipeline(const VertexProcessor::State &state);
-
-		virtual ~VertexPipeline();
-
-	private:
-		void pipeline(UInt &index) override;
-		void processTextureCoordinate(int stage, Vector4f &normal, Vector4f &position);
-		void processPointSize();
-
-		Vector4f transformBlend(const Register &src, const Pointer<Byte> &matrix, bool homogenous);
-		Vector4f transform(const Register &src, const Pointer<Byte> &matrix, bool homogenous);
-		Vector4f transform(const Register &src, const Pointer<Byte> &matrix, UInt index[4], bool homogenous);
-		Vector4f normalize(Vector4f &src);
-		Float4 power(Float4 &src0, Float4 &src1);
-	};
-};
-
-#endif   // sw_VertexPipeline_hpp
diff --git a/src/Pipeline/VertexProgram.cpp b/src/Pipeline/VertexProgram.cpp
index a24bb40..816af77 100644
--- a/src/Pipeline/VertexProgram.cpp
+++ b/src/Pipeline/VertexProgram.cpp
@@ -59,21 +59,9 @@
 	{
 	}
 
-	void VertexProgram::pipeline(UInt &index)
-	{
-		if(!state.preTransformed)
-		{
-			program(index);
-		}
-		else
-		{
-			passThrough();
-		}
-	}
-
 	void VertexProgram::program(UInt &index)
 	{
-	//	shader->print("VertexShader-%0.8X.txt", state.shaderID);
+		//	shader->print("VertexShader-%0.8X.txt", state.shaderID);
 
 		unsigned short shaderModel = shader->getShaderModel();
 
@@ -418,7 +406,7 @@
 						if(dst.w) pDst.w = o[C0 + dst.index].w;
 						break;
 					case Shader::PARAMETER_TEXCRDOUT:
-				//	case Shader::PARAMETER_OUTPUT:
+						//	case Shader::PARAMETER_OUTPUT:
 						if(shaderModel < 0x0300)
 						{
 							if(dst.x) pDst.x = o[T0 + dst.index].x;
@@ -564,7 +552,7 @@
 					if(dst.w) o[C0 + dst.index].w = d.w;
 					break;
 				case Shader::PARAMETER_TEXCRDOUT:
-			//	case Shader::PARAMETER_OUTPUT:
+					//	case Shader::PARAMETER_OUTPUT:
 					if(shaderModel < 0x0300)
 					{
 						if(dst.x) o[T0 + dst.index].x = d.x;
@@ -613,74 +601,6 @@
 		}
 	}
 
-	void VertexProgram::passThrough()
-	{
-		if(shader)
-		{
-			for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++)
-			{
-				unsigned char usage = shader->getOutput(i, 0).usage;
-
-				switch(usage)
-				{
-				case 0xFF:
-					continue;
-				case Shader::USAGE_PSIZE:
-					o[i].y = v[i].x;
-					break;
-				case Shader::USAGE_TEXCOORD:
-					o[i].x = v[i].x;
-					o[i].y = v[i].y;
-					o[i].z = v[i].z;
-					o[i].w = v[i].w;
-					break;
-				case Shader::USAGE_POSITION:
-					o[i].x = v[i].x;
-					o[i].y = v[i].y;
-					o[i].z = v[i].z;
-					o[i].w = v[i].w;
-					break;
-				case Shader::USAGE_COLOR:
-					o[i].x = v[i].x;
-					o[i].y = v[i].y;
-					o[i].z = v[i].z;
-					o[i].w = v[i].w;
-					break;
-				case Shader::USAGE_FOG:
-					o[i].x = v[i].x;
-					break;
-				default:
-					ASSERT(false);
-				}
-			}
-		}
-		else
-		{
-			o[Pos].x = v[PositionT].x;
-			o[Pos].y = v[PositionT].y;
-			o[Pos].z = v[PositionT].z;
-			o[Pos].w = v[PositionT].w;
-
-			for(int i = 0; i < 2; i++)
-			{
-				o[C0 + i].x = v[Color0 + i].x;
-				o[C0 + i].y = v[Color0 + i].y;
-				o[C0 + i].z = v[Color0 + i].z;
-				o[C0 + i].w = v[Color0 + i].w;
-			}
-
-			for(int i = 0; i < 8; i++)
-			{
-				o[T0 + i].x = v[TexCoord0 + i].x;
-				o[T0 + i].y = v[TexCoord0 + i].y;
-				o[T0 + i].z = v[TexCoord0 + i].z;
-				o[T0 + i].w = v[TexCoord0 + i].w;
-			}
-
-			o[Pts].y = v[PointSize].x;
-		}
-	}
-
 	Vector4f VertexProgram::fetchRegister(const Src &src, unsigned int offset)
 	{
 		Vector4f reg;
diff --git a/src/Pipeline/VertexProgram.hpp b/src/Pipeline/VertexProgram.hpp
index b008d91..9d46b6a 100644
--- a/src/Pipeline/VertexProgram.hpp
+++ b/src/Pipeline/VertexProgram.hpp
@@ -63,9 +63,7 @@
 		typedef Shader::Control Control;
 		typedef Shader::Usage Usage;
 
-		void pipeline(UInt &index) override;
-		void program(UInt &index);
-		void passThrough();
+		void program(UInt &index) override;
 
 		Vector4f fetchRegister(const Src &src, unsigned int offset = 0);
 		Vector4f readConstant(const Src &src, unsigned int offset = 0);
diff --git a/src/Pipeline/VertexRoutine.cpp b/src/Pipeline/VertexRoutine.cpp
index 916230f..592daa0 100644
--- a/src/Pipeline/VertexRoutine.cpp
+++ b/src/Pipeline/VertexRoutine.cpp
@@ -62,7 +62,7 @@
 				*Pointer<UInt>(tagCache + tagIndex) = indexQ;
 
 				readInput(indexQ);
-				pipeline(indexQ);
+				program(indexQ);
 				postTransform();
 				computeClipFlags();
 
@@ -130,11 +130,6 @@
 
 		Int4 finiteXYZ = finiteX & finiteY & finiteZ;
 		clipFlags |= *Pointer<Int>(constants + OFFSET(Constants,fini) + SignMask(finiteXYZ) * 4);
-
-		if(state.preTransformed)
-		{
-			clipFlags &= 0xFBFBFBFB;   // Don't clip against far clip plane
-		}
 	}
 
 	Vector4f VertexRoutine::readStream(Pointer<Byte> &buffer, UInt &stride, const Stream &stream, const UInt &index)
@@ -612,33 +607,11 @@
 	{
 		int pos = state.positionRegister;
 
-		// Backtransform
-		if(state.preTransformed)
-		{
-			Float4 rhw = Float4(1.0f) / o[pos].w;
-
-			Float4 W = *Pointer<Float4>(data + OFFSET(DrawData,Wx16)) * Float4(1.0f / 16.0f);
-			Float4 H = *Pointer<Float4>(data + OFFSET(DrawData,Hx16)) * Float4(1.0f / 16.0f);
-			Float4 L = *Pointer<Float4>(data + OFFSET(DrawData,X0x16)) * Float4(1.0f / 16.0f);
-			Float4 T = *Pointer<Float4>(data + OFFSET(DrawData,Y0x16)) * Float4(1.0f / 16.0f);
-
-			o[pos].x = (o[pos].x - L) / W * rhw;
-			o[pos].y = (o[pos].y - T) / H * rhw;
-			o[pos].z = o[pos].z * rhw;
-			o[pos].w = rhw;
-		}
-
-		if(!halfIntegerCoordinates && !state.preTransformed)
+		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;
 		}
-
-		if(state.superSampling)
-		{
-			o[pos].x = o[pos].x + *Pointer<Float4>(data + OFFSET(DrawData,XXXX)) * o[pos].w;
-			o[pos].y = o[pos].y + *Pointer<Float4>(data + OFFSET(DrawData,YYYY)) * o[pos].w;
-		}
 	}
 
 	void VertexRoutine::writeCache(Pointer<Byte> &cacheLine)
diff --git a/src/Pipeline/VertexRoutine.hpp b/src/Pipeline/VertexRoutine.hpp
index 9837fdc..f1f180d 100644
--- a/src/Pipeline/VertexRoutine.hpp
+++ b/src/Pipeline/VertexRoutine.hpp
@@ -54,7 +54,7 @@
 		const VertexProcessor::State &state;
 
 	private:
-		virtual void pipeline(UInt &index) = 0;
+		virtual void program(UInt &index) = 0;
 
 		typedef VertexProcessor::State::Input Stream;
 
diff --git a/src/Renderer/Context.hpp b/src/Renderer/Context.hpp
index d9110d8..8b5a8eb 100644
--- a/src/Renderer/Context.hpp
+++ b/src/Renderer/Context.hpp
@@ -455,8 +455,6 @@
 		float fogStart;
 		float fogEnd;
 
-		void computeIllumination();
-
 		bool textureWrapActive;
 		unsigned char textureWrap[TEXTURE_IMAGE_UNITS];
 		TexGen texGen[8];
diff --git a/src/Vulkan/Version.h b/src/Vulkan/Version.h
index 2629a34..002d880 100644
--- a/src/Vulkan/Version.h
+++ b/src/Vulkan/Version.h
@@ -15,7 +15,7 @@
 #define MAJOR_VERSION 5
 #define MINOR_VERSION 0
 #define BUILD_VERSION 0
-#define BUILD_REVISION 0
+#define BUILD_REVISION 1
 
 #define STRINGIFY(x) #x
 #define MACRO_STRINGIFY(x) STRINGIFY(x)
diff --git a/src/Vulkan/vulkan.vcxproj b/src/Vulkan/vulkan.vcxproj
index 252979f..5258dc6 100644
--- a/src/Vulkan/vulkan.vcxproj
+++ b/src/Vulkan/vulkan.vcxproj
@@ -127,11 +127,9 @@
     <ClCompile Include="..\Device\SetupProcessor.cpp" />

     <ClCompile Include="..\Device\Surface.cpp" />

     <ClCompile Include="..\Device\SwiftConfig.cpp" />

-    <ClCompile Include="..\Device\TextureStage.cpp" />

     <ClCompile Include="..\Device\Vector.cpp" />

     <ClCompile Include="..\Device\VertexProcessor.cpp" />

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

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

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

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

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

@@ -139,7 +137,6 @@
     <ClCompile Include="..\Pipeline\SetupRoutine.cpp" />

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

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

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

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

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

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

@@ -224,13 +221,11 @@
     <ClInclude Include="..\Device\Stream.hpp" />

     <ClInclude Include="..\Device\Surface.hpp" />

     <ClInclude Include="..\Device\SwiftConfig.hpp" />

-    <ClInclude Include="..\Device\TextureStage.hpp" />

     <ClInclude Include="..\Device\Triangle.hpp" />

     <ClInclude Include="..\Device\Vector.hpp" />

     <ClInclude Include="..\Device\Vertex.hpp" />

     <ClInclude Include="..\Device\VertexProcessor.hpp" />

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

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

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

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

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

diff --git a/src/Vulkan/vulkan.vcxproj.filters b/src/Vulkan/vulkan.vcxproj.filters
index f8661bd..297d7e3 100644
--- a/src/Vulkan/vulkan.vcxproj.filters
+++ b/src/Vulkan/vulkan.vcxproj.filters
@@ -51,9 +51,6 @@
     <ClCompile Include="..\Device\Vector.cpp">

       <Filter>Source Files\Device</Filter>

     </ClCompile>

-    <ClCompile Include="..\Device\TextureStage.cpp">

-      <Filter>Source Files\Device</Filter>

-    </ClCompile>

     <ClCompile Include="..\Device\SwiftConfig.cpp">

       <Filter>Source Files\Device</Filter>

     </ClCompile>

@@ -111,9 +108,6 @@
     <ClCompile Include="..\Pipeline\VertexProgram.cpp">

       <Filter>Source Files\Pipeline</Filter>

     </ClCompile>

-    <ClCompile Include="..\Pipeline\VertexPipeline.cpp">

-      <Filter>Source Files\Pipeline</Filter>

-    </ClCompile>

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

       <Filter>Source Files\Pipeline</Filter>

     </ClCompile>

@@ -135,9 +129,6 @@
     <ClCompile Include="..\Pipeline\PixelProgram.cpp">

       <Filter>Source Files\Pipeline</Filter>

     </ClCompile>

-    <ClCompile Include="..\Pipeline\PixelPipeline.cpp">

-      <Filter>Source Files\Pipeline</Filter>

-    </ClCompile>

     <ClCompile Include="..\Pipeline\Constants.cpp">

       <Filter>Source Files\Pipeline</Filter>

     </ClCompile>

@@ -302,9 +293,6 @@
     <ClInclude Include="..\Device\Triangle.hpp">

       <Filter>Header Files\Device</Filter>

     </ClInclude>

-    <ClInclude Include="..\Device\TextureStage.hpp">

-      <Filter>Header Files\Device</Filter>

-    </ClInclude>

     <ClInclude Include="..\Device\SwiftConfig.hpp">

       <Filter>Header Files\Device</Filter>

     </ClInclude>

@@ -431,9 +419,6 @@
     <ClInclude Include="..\Pipeline\PixelProgram.hpp">

       <Filter>Header Files\Pipeline</Filter>

     </ClInclude>

-    <ClInclude Include="..\Pipeline\PixelPipeline.hpp">

-      <Filter>Header Files\Pipeline</Filter>

-    </ClInclude>

     <ClInclude Include="..\Pipeline\Constants.hpp">

       <Filter>Header Files\Pipeline</Filter>

     </ClInclude>