Support for fragment output location

Fragment output layout qualifiers may contain location,
which was currently ignored by SwiftShader. Pre-declared
fragment outputs that have a valid location at the correct
location within the fragmentOutputs array to solve this.

Fixes all failures in WebGL 2 tests:
all/deqp/functional/gles3/fragmentoutput/*

Change-Id: I30e004449fb90713984b3481abb24c5d0cd6e867
Reviewed-on: https://swiftshader-review.googlesource.com/16788
Tested-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 5f05e46..fbdc113 100644
--- a/src/OpenGL/compiler/OutputASM.cpp
+++ b/src/OpenGL/compiler/OutputASM.cpp
@@ -676,6 +676,9 @@
 				declareVarying(symbol, -1);
 			}
 			break;
+		case EvqFragmentOut:
+			declareFragmentOutput(symbol);
+			break;
 		default:
 			break;
 		}
@@ -3148,6 +3151,34 @@
 		}
 	}
 
+	void OutputASM::declareFragmentOutput(TIntermTyped *fragmentOutput)
+	{
+		int requestedLocation = fragmentOutput->getType().getLayoutQualifier().location;
+		if((requestedLocation >= 0) && (requestedLocation < sw::RENDERTARGETS))
+		{
+			if(fragmentOutputs.size() <= requestedLocation)
+			{
+				while(fragmentOutputs.size() < requestedLocation)
+				{
+					fragmentOutputs.push_back(nullptr);
+				}
+				fragmentOutputs.push_back(fragmentOutput);
+			}
+			else if(!fragmentOutputs[requestedLocation])
+			{
+				fragmentOutputs[requestedLocation] = fragmentOutput;
+			}
+			else
+			{
+				mContext.error(fragmentOutput->getLine(), "Fragment output location aliasing", "fragment shader");
+			}
+		}
+		else if(requestedLocation >= sw::RENDERTARGETS)
+		{
+			mContext.error(fragmentOutput->getLine(), "Fragment output location larger or equal to MAX_DRAW_BUFFERS", "fragment shader");
+		}
+	}
+
 	int OutputASM::uniformRegister(TIntermTyped *uniform)
 	{
 		const TType &type = uniform->getType();
diff --git a/src/OpenGL/compiler/OutputASM.h b/src/OpenGL/compiler/OutputASM.h
index 642508a..c315ef1 100644
--- a/src/OpenGL/compiler/OutputASM.h
+++ b/src/OpenGL/compiler/OutputASM.h
@@ -297,6 +297,7 @@
 		void setPixelShaderInputs(const TType& type, int var, bool flat);
 		void declareVarying(TIntermTyped *varying, int reg);
 		void declareVarying(const TType &type, const TString &name, int registerIndex);
+		void declareFragmentOutput(TIntermTyped *fragmentOutput);
 		int uniformRegister(TIntermTyped *uniform);
 		int attributeRegister(TIntermTyped *attribute);
 		int fragmentOutputRegister(TIntermTyped *fragmentOutput);