Store interpolation data in routine

When the shader contains interpolation instruction, interpolation
related data needs to be stored in the routine in order to be able
to perform the interpolation operations in the middle of running
the spirv shader.

Bug: b/171415086
Change-Id: I08fc6befdca1df92fa50326d9047926ac3417aa5
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/51734
Tested-by: Alexis Hétu <sugoi@google.com>
Commit-Queue: Alexis Hétu <sugoi@google.com>
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Pipeline/PixelRoutine.cpp b/src/Pipeline/PixelRoutine.cpp
index 5a53a82..9864c01 100644
--- a/src/Pipeline/PixelRoutine.cpp
+++ b/src/Pipeline/PixelRoutine.cpp
@@ -62,8 +62,10 @@
 	Int zMask[4];  // Depth mask
 	Int sMask[4];  // Stencil mask
 
+	bool shaderContainsInterpolation = spirvShader && spirvShader->getUsedCapabilities().InterpolationFunction;
+	bool shaderContainsSampleQualifier = spirvShader && spirvShader->getModes().ContainsSampleQualifier;
 	bool perSampleShading = (state.sampleShadingEnabled && (state.minSampleShading > 0.0f)) ||
-	                        (spirvShader && spirvShader->getModes().ContainsSampleQualifier);
+	                        shaderContainsInterpolation || shaderContainsSampleQualifier;
 	unsigned int numSampleRenders = perSampleShading ? state.multiSampleCount : 1;
 
 	for(unsigned int i = 0; i < numSampleRenders; ++i)
@@ -131,7 +133,7 @@
 			Float4 XXXX = Float4(0.0f);
 			Float4 YYYY = Float4(0.0f);
 
-			if(state.centroid)
+			if(state.centroid || shaderContainsInterpolation)
 			{
 				Float4 WWWW(1.0e-9f);
 
@@ -155,7 +157,7 @@
 				w = interpolate(xxxx, Dw, rhw, primitive + OFFSET(Primitive, w), false, false);
 				rhw = reciprocal(w, false, false, true);
 
-				if(state.centroid)
+				if(state.centroid || shaderContainsInterpolation)
 				{
 					rhwCentroid = reciprocal(SpirvRoutine::interpolateAtXY(XXXX, YYYY, rhwCentroid, primitive + OFFSET(Primitive, w), false, false));
 				}
@@ -163,6 +165,19 @@
 
 			if(spirvShader)
 			{
+				if(shaderContainsInterpolation)
+				{
+					routine.interpolationData.primitive = primitive;
+
+					routine.interpolationData.x = xxxx;
+					routine.interpolationData.y = yyyy;
+					routine.interpolationData.rhw = rhw;
+
+					routine.interpolationData.xCentroid = XXXX;
+					routine.interpolationData.yCentroid = YYYY;
+					routine.interpolationData.rhwCentroid = rhwCentroid;
+				}
+
 				if(perSampleShading && (state.multiSampleCount > 1))
 				{
 					xxxx += Float4(Constants::SampleLocationsX[sampleId]);
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index c5c11dd..41beb88 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -397,6 +397,7 @@
 					case spv::CapabilityStorageImageExtendedFormats: capabilities.StorageImageExtendedFormats = true; break;
 					case spv::CapabilityImageQuery: capabilities.ImageQuery = true; break;
 					case spv::CapabilityDerivativeControl: capabilities.DerivativeControl = true; break;
+					case spv::CapabilityInterpolationFunction: capabilities.InterpolationFunction = true; break;
 					case spv::CapabilityGroupNonUniform: capabilities.GroupNonUniform = true; break;
 					case spv::CapabilityGroupNonUniformVote: capabilities.GroupNonUniformVote = true; break;
 					case spv::CapabilityGroupNonUniformArithmetic: capabilities.GroupNonUniformArithmetic = true; break;
diff --git a/src/Pipeline/SpirvShader.hpp b/src/Pipeline/SpirvShader.hpp
index da40075..93a01f4 100644
--- a/src/Pipeline/SpirvShader.hpp
+++ b/src/Pipeline/SpirvShader.hpp
@@ -584,6 +584,7 @@
 		bool StorageImageExtendedFormats : 1;
 		bool ImageQuery : 1;
 		bool DerivativeControl : 1;
+		bool InterpolationFunction : 1;
 		bool GroupNonUniform : 1;
 		bool GroupNonUniformVote : 1;
 		bool GroupNonUniformBallot : 1;
@@ -1352,12 +1353,24 @@
 		Pointer<Byte> function;
 	};
 
+	struct InterpolationData
+	{
+		Pointer<Byte> primitive;
+		SIMD::Float x;
+		SIMD::Float y;
+		SIMD::Float rhw;
+		SIMD::Float xCentroid;
+		SIMD::Float yCentroid;
+		SIMD::Float rhwCentroid;
+	};
+
 	vk::PipelineLayout const *const pipelineLayout;
 
 	std::unordered_map<SpirvShader::Object::ID, Variable> variables;
 	std::unordered_map<SpirvShader::Object::ID, SamplerCache> samplerCache;
 	Variable inputs = Variable{ MAX_INTERFACE_COMPONENTS };
 	Variable outputs = Variable{ MAX_INTERFACE_COMPONENTS };
+	InterpolationData interpolationData;
 
 	Pointer<Byte> workgroupMemory;
 	Pointer<Pointer<Byte>> descriptorSets;