Make the number of vertex outputs configurable.

Change-Id: I17ae53e5274232e9e3b482daac56d507788e822c
Reviewed-on: https://swiftshader-review.googlesource.com/5383
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
Tested-by: Nicolas Capens <capn@google.com>
diff --git a/src/Renderer/Renderer.cpp b/src/Renderer/Renderer.cpp
index 40d9de6..712d74a 100644
--- a/src/Renderer/Renderer.cpp
+++ b/src/Renderer/Renderer.cpp
@@ -400,7 +400,7 @@
 					draw->pUniformBuffers[i] = nullptr;
 				}
 			}
-			
+
 			if(context->pixelShaderVersion() <= 0x0104)
 			{
 				for(int stage = 0; stage < 8; stage++)
@@ -736,7 +736,7 @@
 				}
 			}
 		}
-	
+
 		// Find primitive tasks
 		if(currentDraw == nextDraw)
 		{
@@ -837,7 +837,7 @@
 		case Task::PRIMITIVES:
 			{
 				int unit = task[threadIndex].primitiveUnit;
-			
+
 				int input = primitiveProgress[unit].firstPrimitive;
 				int count = primitiveProgress[unit].primitiveCount;
 				DrawCall *draw = drawList[primitiveProgress[unit].drawCall % DRAW_COUNT];
@@ -1571,7 +1571,7 @@
 
 		return visible;
 	}
-	
+
 	int Renderer::setupVertexTriangle(Renderer *renderer, int unit, int count)
 	{
 		Triangle *triangle = renderer->triangleBatch[unit];
@@ -1878,7 +1878,7 @@
 
 		int pts = state.pointSizeRegister;
 
-		if(state.pointSizeRegister != 0xF)
+		if(state.pointSizeRegister != Unused)
 		{
 			pSize = v.v[pts].y;
 		}
@@ -1937,7 +1937,7 @@
 					return false;
 				}
 			}
-			
+
 			return setupRoutine(&primitive, &triangle, &polygon, &data);
 		}
 
@@ -2002,7 +2002,7 @@
 				exitThreads = true;
 				resume[thread]->signal();
 				worker[thread]->join();
-				
+
 				delete worker[thread];
 				worker[thread] = 0;
 				delete resume[thread];
@@ -2010,7 +2010,7 @@
 				delete suspend[thread];
 				suspend[thread] = 0;
 			}
-		
+
 			deallocate(vertexTask[thread]);
 			vertexTask[thread] = 0;
 		}
@@ -2137,7 +2137,7 @@
 				return true;
 			}
 		}
-	
+
 		if(context->depthBuffer && context->texture[sampler] == context->depthBuffer->getResource())
 		{
 			return true;
@@ -2145,7 +2145,7 @@
 
 		return false;
 	}
-	
+
 	void Renderer::updateClipper()
 	{
 		if(updateClipPlanes)
@@ -2185,7 +2185,7 @@
 	void Renderer::setTextureLevel(unsigned int sampler, unsigned int face, unsigned int level, Surface *surface, TextureType type)
 	{
 		ASSERT(sampler < TOTAL_IMAGE_UNITS && face < 6 && level < MIPMAP_LEVELS);
-		
+
 		context->sampler[sampler].setTextureLevel(face, level, surface, type);
 	}
 
@@ -2530,7 +2530,7 @@
 	{
 		queries.push_back(query);
 	}
-	
+
 	void Renderer::removeQuery(Query *query)
 	{
 		queries.remove(query);
@@ -2541,7 +2541,7 @@
 		{
 			return threadCount;
 		}
-		
+
 		int64_t Renderer::getVertexTime(int thread)
 		{
 			return vertexTime[thread];
@@ -2551,7 +2551,7 @@
 		{
 			return setupTime[thread];
 		}
-			
+
 		int64_t Renderer::getPixelTime(int thread)
 		{
 			return pixelTime[thread];
diff --git a/src/Renderer/SetupProcessor.cpp b/src/Renderer/SetupProcessor.cpp
index 08e52c9..6dccc8d 100644
--- a/src/Renderer/SetupProcessor.cpp
+++ b/src/Renderer/SetupProcessor.cpp
@@ -89,7 +89,7 @@
 		state.vFace = context->pixelShader && context->pixelShader->vFaceDeclared;
 
 		state.positionRegister = Pos;
-		state.pointSizeRegister = 0xF;   // No vertex point size
+		state.pointSizeRegister = Unused;
 
 		state.multiSample = context->getMultiSampleCount();
 		state.rasterizerDiscard = context->rasterizerDiscard;
@@ -133,7 +133,7 @@
 					if(context->pixelShader->semantic[interpolant][component - project].active())
 					{
 						int input = interpolant;
-						for(int i = 0; i < 12; i++)
+						for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++)
 						{
 							if(context->pixelShader->semantic[interpolant][component - project] == context->vertexShader->output[i][component - project])
 							{
diff --git a/src/Renderer/SetupProcessor.hpp b/src/Renderer/SetupProcessor.hpp
index 06e4ce9..2ef9fdf 100644
--- a/src/Renderer/SetupProcessor.hpp
+++ b/src/Renderer/SetupProcessor.hpp
@@ -45,8 +45,8 @@
 			bool interpolateW              : 1;
 			bool perspective               : 1;
 			bool pointSprite               : 1;
-			unsigned int positionRegister  : 4;
-			unsigned int pointSizeRegister : 4;
+			unsigned int positionRegister  : BITS(VERTEX_OUTPUT_LAST);
+			unsigned int pointSizeRegister : BITS(VERTEX_OUTPUT_LAST);
 			CullMode cullMode              : BITS(CULL_LAST);
 			bool twoSidedStencil           : 1;
 			bool slopeDepthBias            : 1;
@@ -56,7 +56,7 @@
 
 			struct Gradient
 			{
-				unsigned char attribute : BITS(Unused);
+				unsigned char attribute : BITS(VERTEX_OUTPUT_LAST);
 				bool flat               : 1;
 				bool wrap               : 1;
 			};
diff --git a/src/Renderer/Vertex.hpp b/src/Renderer/Vertex.hpp
index 5c9e504..78bcf14 100644
--- a/src/Renderer/Vertex.hpp
+++ b/src/Renderer/Vertex.hpp
@@ -18,11 +18,13 @@
 #include "Color.hpp"
 #include "Common/MetaMacro.hpp"
 #include "Common/Types.hpp"
+#include "Main/Config.hpp"
 
 namespace sw
 {
-	enum Out   // Default vertex output semantic
+	enum Out
 	{
+		// Default vertex output semantics
 		Pos = 0,
 		C0 = 1,   // Diffuse
 		C1 = 2,   // Specular
@@ -36,7 +38,13 @@
 		T7 = 10,
 		Fog = 11,    // x component
 		Pts = Fog,   // y component
-		Unused
+
+		// Variable semantics
+		V0 = 0,
+		Vn_1 = MAX_VERTEX_OUTPUTS - 1,
+
+		Unused,
+		VERTEX_OUTPUT_LAST = Unused,
 	};
 
 	struct UVWQ
@@ -72,7 +80,7 @@
 				float pSize;         // Point size
 			};
 
-			float4 v[12];   // Generic components using semantic declaration
+			float4 v[MAX_VERTEX_OUTPUTS];   // Generic components using semantic declaration
 		};
 
 		// Projected coordinates
diff --git a/src/Renderer/VertexProcessor.cpp b/src/Renderer/VertexProcessor.cpp
index fa13b2b..291e532 100644
--- a/src/Renderer/VertexProcessor.cpp
+++ b/src/Renderer/VertexProcessor.cpp
@@ -942,7 +942,7 @@
 
 		if(context->vertexShader)   // FIXME: Also when pre-transformed?
 		{
-			for(int i = 0; i < 12; i++)
+			for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++)
 			{
 				state.output[i].xWrite = context->vertexShader->output[i][0].active();
 				state.output[i].yWrite = context->vertexShader->output[i][1].active();
diff --git a/src/Renderer/VertexProcessor.hpp b/src/Renderer/VertexProcessor.hpp
index 14758bb..bcbf4fd 100644
--- a/src/Renderer/VertexProcessor.hpp
+++ b/src/Renderer/VertexProcessor.hpp
@@ -52,8 +52,8 @@
 
 			bool fixedFunction             : 1;
 			bool textureSampling           : 1;
-			unsigned int positionRegister  : 4;
-			unsigned int pointSizeRegister : 4;   // 0xF signifies no vertex point size
+			unsigned int positionRegister  : BITS(MAX_VERTEX_OUTPUTS);
+			unsigned int pointSizeRegister : BITS(MAX_VERTEX_OUTPUTS);
 
 			unsigned int vertexBlendMatrixCount               : 3;
 			bool indexedVertexBlendEnable                     : 1;
@@ -134,7 +134,7 @@
 			};
 
 			Input input[VERTEX_ATTRIBUTES];
-			Output output[12];
+			Output output[MAX_VERTEX_OUTPUTS];
 		};
 
 		struct State : States