BuiltInPointCoord implementation

BuiltInPointCoord is defined as:

"The following formulas are used to evaluate s and t:

s = 1/2 + (xp - xf) / size
t = 1/2 + (yp - yf) / size

where size is the point’s size; (xp,yp) is the location at which the
point sprite coordinates are evaluated - this may be the framebuffer
coordinates of the fragment center, or the location of a sample; and
(xf,yf) is the exact, unrounded framebuffer coordinate of the vertex
for the point."

So it was implemented by writing (xf,yf) in SetupRoutine, where this
information is present and using the fragment's x and y coordinates
as (xp,yp), which passes the test.

Tests: dEQP-VK.glsl.builtin_var.simple.pointcoord

Change-Id: I9146349bcce0f7c31dd0464c0f210a7306d5d033
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/31992
Presubmit-Ready: Alexis Hétu <sugoi@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Reviewed-by: Chris Forbes <chrisforbes@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/Device/Primitive.hpp b/src/Device/Primitive.hpp
index f72fe32..1dbc4a6 100644
--- a/src/Device/Primitive.hpp
+++ b/src/Device/Primitive.hpp
@@ -42,6 +42,9 @@
 		float4 xQuad;
 		float4 yQuad;
 
+		float pointCoordX;
+		float pointCoordY;
+
 		PlaneEquation z;
 		PlaneEquation w;
 
diff --git a/src/Pipeline/PixelProgram.cpp b/src/Pipeline/PixelProgram.cpp
index de2758f..a086774 100644
--- a/src/Pipeline/PixelProgram.cpp
+++ b/src/Pipeline/PixelProgram.cpp
@@ -37,6 +37,16 @@
 			var[it->second.FirstComponent+3] = w;
 		}
 
+		it = spirvShader->inputBuiltins.find(spv::BuiltInPointCoord);
+		if(it != spirvShader->inputBuiltins.end())
+		{
+			auto &var = routine.getVariable(it->second.Id);
+			var[it->second.FirstComponent] = SIMD::Float(0.5f) +
+				SIMD::Float(Float(x) - (*Pointer<Float>(primitive + OFFSET(Primitive, pointCoordX))));
+			var[it->second.FirstComponent + 1] = SIMD::Float(0.5f) +
+				SIMD::Float(Float(y) - (*Pointer<Float>(primitive + OFFSET(Primitive, pointCoordY))));
+		}
+
 		it = spirvShader->inputBuiltins.find(spv::BuiltInSubgroupSize);
 		if (it != spirvShader->inputBuiltins.end())
 		{
diff --git a/src/Pipeline/SetupRoutine.cpp b/src/Pipeline/SetupRoutine.cpp
index 5f76fe0..c697411 100644
--- a/src/Pipeline/SetupRoutine.cpp
+++ b/src/Pipeline/SetupRoutine.cpp
@@ -293,6 +293,11 @@
 				conditionalRotate2(wMax == w2, v0, v1, v2);
 			}
 
+			*Pointer<Float>(primitive + OFFSET(Primitive, pointCoordX)) =
+				*Pointer<Float>(v0 + OFFSET(Vertex, builtins.position.x));
+			*Pointer<Float>(primitive + OFFSET(Primitive, pointCoordY)) =
+				*Pointer<Float>(v0 + OFFSET(Vertex, builtins.position.y));
+
 			Float w0 = *Pointer<Float>(v0 + OFFSET(Vertex, builtins.position.w));
 			Float w1 = *Pointer<Float>(v1 + OFFSET(Vertex, builtins.position.w));
 			Float w2 = *Pointer<Float>(v2 + OFFSET(Vertex, builtins.position.w));