Fix validation of statically referenced varyings.

Varyings and in/out variables that are passed between shader pipeline
stages are verified to have matching types at link-time, even when only
statically referenced (this includes trivially optimized out branches)
or even just declared.

GLSL ES 3.00 - 4.3.10 Linking of Vertex Outputs and Fragment Inputs

Change-Id: I122b1cdcc4630c86a8ebfb4d4e37f3a7a335afbe
Reviewed-on: https://swiftshader-review.googlesource.com/16070
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/OpenGL/compiler/OutputASM.cpp b/src/OpenGL/compiler/OutputASM.cpp
index 8edd099..6afc880 100644
--- a/src/OpenGL/compiler/OutputASM.cpp
+++ b/src/OpenGL/compiler/OutputASM.cpp
@@ -661,14 +661,23 @@
 
 	void OutputASM::visitSymbol(TIntermSymbol *symbol)
 	{
-		// Vertex varyings don't have to be actively used to successfully link
-		// against pixel shaders that use them. So make sure they're declared.
-		if(symbol->getQualifier() == EvqVaryingOut || symbol->getQualifier() == EvqInvariantVaryingOut || symbol->getQualifier() == EvqVertexOut)
+		// The type of vertex outputs and fragment inputs with the same name must match (validated at link time),
+		// so declare them but don't assign a register index yet (one will be assigned when referenced in reachable code).
+		switch(symbol->getQualifier())
 		{
+		case EvqVaryingIn:
+		case EvqVaryingOut:
+		case EvqInvariantVaryingIn:
+		case EvqInvariantVaryingOut:
+		case EvqVertexOut:
+		case EvqFragmentIn:
 			if(symbol->getBasicType() != EbtInvariant)   // Typeless declarations are not new varyings
 			{
 				declareVarying(symbol, -1);
 			}
+			break;
+		default:
+			break;
 		}
 
 		TInterfaceBlock* block = symbol->getType().getInterfaceBlock();
diff --git a/src/OpenGL/compiler/SymbolTable.h b/src/OpenGL/compiler/SymbolTable.h
index 3bc7ff4..3466f2f 100644
--- a/src/OpenGL/compiler/SymbolTable.h
+++ b/src/OpenGL/compiler/SymbolTable.h
@@ -208,10 +208,10 @@
 
 	bool insert(TSymbol *symbol);
 
-    // Insert a function using its unmangled name as the key.
-    bool insertUnmangled(TFunction *function);
+	// Insert a function using its unmangled name as the key.
+	bool insertUnmangled(TFunction *function);
 
-    TSymbol *find(const TString &name) const;
+	TSymbol *find(const TString &name) const;
 
 	static int nextUniqueId()
 	{
diff --git a/src/OpenGL/libGLESv2/Program.cpp b/src/OpenGL/libGLESv2/Program.cpp
index 42cf1b3..0d43096 100644
--- a/src/OpenGL/libGLESv2/Program.cpp
+++ b/src/OpenGL/libGLESv2/Program.cpp
@@ -1349,9 +1349,13 @@
 
 			if(!matched)
 			{
-				appendToInfoLog("Fragment varying %s does not match any vertex varying", input.name.c_str());
+				// If a fragment varying is declared but not statically used, it's not an error to not have a matching vertex varying.
+				if(input.registerIndex >= 0)
+				{
+					appendToInfoLog("Fragment varying %s does not match any vertex varying", input.name.c_str());
 
-				return false;
+					return false;
+				}
 			}
 		}