Fix interpolation functions for push constants

When using push constants, we end up having dynamic offsets on the
input parameter of the interpolation functions, so we need to be able
to handle this case. Since this is for push constants, we assume that
all dynamic offsets will be the same, for simplicity.

Bug: b/171415086
Change-Id: I5de1720e383c234c9392421d507a66e6d7ba2445
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/52930
Presubmit-Ready: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Tested-by: Alexis Hétu <sugoi@google.com>
Commit-Queue: Alexis Hétu <sugoi@google.com>
diff --git a/src/Pipeline/SpirvShaderGLSLstd450.cpp b/src/Pipeline/SpirvShaderGLSLstd450.cpp
index 7455029..f1644a5 100644
--- a/src/Pipeline/SpirvShaderGLSLstd450.cpp
+++ b/src/Pipeline/SpirvShaderGLSLstd450.cpp
@@ -54,6 +54,16 @@
 	return offset;
 }
 
+rr::Int ComputeInterpolantOffset(rr::Int offset, uint32_t components_per_row, bool useArrayOffset)
+{
+	if(useArrayOffset)
+	{
+		rr::Int interpolant_offset = offset / rr::Int(components_per_row);
+		offset = (interpolant_offset << 2) + (offset - interpolant_offset * rr::Int(components_per_row));
+	}
+	return offset;
+}
+
 }  // namespace
 
 namespace sw {
@@ -1064,13 +1074,26 @@
 			return SIMD::Float(0.0f);
 	}
 
-	uint32_t offset = ComputeInterpolantOffset((ptr.staticOffsets[0] >> 2) + component, components_per_row, useArrayOffset);
-	if((interpolant + offset) >= inputs.size())
+	Pointer<Byte> planeEquation = interpolationData.primitive + OFFSET(Primitive, V[interpolant]);
+	if(ptr.hasDynamicOffsets)
 	{
-		return SIMD::Float(0.0f);
+		// This code assumes all dynamic offsets are equal
+		Int offset = ComputeInterpolantOffset(((Extract(ptr.dynamicOffsets, 0) + ptr.staticOffsets[0]) >> 2) + component, components_per_row, useArrayOffset);
+		offset = Min(offset, Int(inputs.size() - interpolant - 1));
+		planeEquation += (offset * sizeof(PlaneEquation));
+	}
+	else
+	{
+		ASSERT(ptr.hasStaticEqualOffsets());
+
+		uint32_t offset = ComputeInterpolantOffset((ptr.staticOffsets[0] >> 2) + component, components_per_row, useArrayOffset);
+		if((interpolant + offset) >= inputs.size())
+		{
+			return SIMD::Float(0.0f);
+		}
+		planeEquation += offset * sizeof(PlaneEquation);
 	}
 
-	Pointer<Byte> planeEquation = interpolationData.primitive + OFFSET(Primitive, V[interpolant]) + offset * sizeof(PlaneEquation);
 	return SpirvRoutine::interpolateAtXY(x, y, rhw, planeEquation, false, true);
 }