Support SampleId and SamplePosition builtins

The sampleRateShading feature adds new builtins variables which have
to be supported: BuiltInSampleId and BuiltInSamplePosition. This cl
sets the values for these builtins properly and turns on per sample
rendering where either of these is persent in the shader.

Bug: b/171415086
Change-Id: I959e80722493d12213be349019a0cc3a108a7596
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/51735
Tested-by: Alexis Hétu <sugoi@google.com>
Commit-Queue: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Pipeline/PixelProgram.cpp b/src/Pipeline/PixelProgram.cpp
index 5066996..bdc3da7 100644
--- a/src/Pipeline/PixelProgram.cpp
+++ b/src/Pipeline/PixelProgram.cpp
@@ -170,6 +170,22 @@
 			routine.getVariable(it->second.Id)[it->second.FirstComponent + i] = Float4(0);
 	}
 
+	it = spirvShader->inputBuiltins.find(spv::BuiltInSampleId);
+	if(it != spirvShader->inputBuiltins.end())
+	{
+		routine.getVariable(it->second.Id)[it->second.FirstComponent] =
+		    As<SIMD::Float>(SIMD::Int((sampleId >= 0) ? sampleId : 0));
+	}
+
+	it = spirvShader->inputBuiltins.find(spv::BuiltInSamplePosition);
+	if(it != spirvShader->inputBuiltins.end())
+	{
+		routine.getVariable(it->second.Id)[it->second.FirstComponent + 0] =
+		    SIMD::Float(((sampleId >= 0) && (state.multiSampleCount > 1)) ? Constants::VkSampleLocations4[sampleId][0] : 0.5f);
+		routine.getVariable(it->second.Id)[it->second.FirstComponent + 1] =
+		    SIMD::Float(((sampleId >= 0) && (state.multiSampleCount > 1)) ? Constants::VkSampleLocations4[sampleId][1] : 0.5f);
+	}
+
 	// Note: all lanes initially active to facilitate derivatives etc. Actual coverage is
 	// handled separately, through the cMask.
 	auto activeLaneMask = SIMD::Int(0xFFFFFFFF);
diff --git a/src/Pipeline/PixelRoutine.cpp b/src/Pipeline/PixelRoutine.cpp
index 9864c01..7272825 100644
--- a/src/Pipeline/PixelRoutine.cpp
+++ b/src/Pipeline/PixelRoutine.cpp
@@ -62,9 +62,28 @@
 	Int zMask[4];  // Depth mask
 	Int sMask[4];  // Stencil mask
 
+	bool sampleShadingEnabled = state.sampleShadingEnabled;
+	float minSampleShading = state.minSampleShading;
+	if(spirvShader)
+	{
+		// SampleId and SamplePosition built-ins require the sampleRateShading feature, so the Vulkan spec
+		// requires turning on per sample shading if either of them is present in the shader.
+
+		// "If a fragment shader entry point's interface includes an input variable decorated with SampleId,
+		//  Sample Shading is considered enabled with a minSampleShading value of 1.0."
+
+		// "If a fragment shader entry point's interface includes an input variable decorated with SamplePosition,
+		//  Sample Shading is considered enabled with a minSampleShading value of 1.0."
+		if(spirvShader->hasBuiltinInput(spv::BuiltInSampleId) || spirvShader->hasBuiltinInput(spv::BuiltInSamplePosition))
+		{
+			sampleShadingEnabled = true;
+			minSampleShading = 1.0f;
+		}
+	}
+
 	bool shaderContainsInterpolation = spirvShader && spirvShader->getUsedCapabilities().InterpolationFunction;
 	bool shaderContainsSampleQualifier = spirvShader && spirvShader->getModes().ContainsSampleQualifier;
-	bool perSampleShading = (state.sampleShadingEnabled && (state.minSampleShading > 0.0f)) ||
+	bool perSampleShading = (sampleShadingEnabled && (minSampleShading > 0.0f)) ||
 	                        shaderContainsInterpolation || shaderContainsSampleQualifier;
 	unsigned int numSampleRenders = perSampleShading ? state.multiSampleCount : 1;