Implement input coverage mask

- Take the pipeline's multisample mask into account when generating
cMask
- Wire up cMask to the BuiltInSampleMask input

Bug: b/118386749
Test: dEQP-VK.pipeline.multisample_shader_builtin.sample_mask.pattern.*
Change-Id: Ia65ba31c6a73f87f537164c69e2d3086b82ea27e
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/32528
Tested-by: Chris Forbes <chrisforbes@google.com>
Presubmit-Ready: Chris Forbes <chrisforbes@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Device/QuadRasterizer.cpp b/src/Device/QuadRasterizer.cpp
index 9e0d5da..b52c276 100644
--- a/src/Device/QuadRasterizer.cpp
+++ b/src/Device/QuadRasterizer.cpp
@@ -199,8 +199,15 @@
 
 					for(unsigned int q = 0; q < state.multiSample; q++)
 					{
-						Short4 mask = CmpGT(xxxx, xLeft[q]) & CmpGT(xRight[q], xxxx);
-						cMask[q] = SignMask(PackSigned(mask, mask)) & 0x0000000F;
+						if (state.multiSampleMask & (1<<q))
+						{
+							Short4 mask = CmpGT(xxxx, xLeft[q]) & CmpGT(xRight[q], xxxx);
+							cMask[q] = SignMask(PackSigned(mask, mask)) & 0x0000000F;
+						}
+						else
+						{
+							cMask[q] = 0;
+						}
 					}
 
 					quad(cBuffer, zBuffer, sBuffer, cMask, x, y);
diff --git a/src/Pipeline/PixelProgram.cpp b/src/Pipeline/PixelProgram.cpp
index a086774..38f7222 100644
--- a/src/Pipeline/PixelProgram.cpp
+++ b/src/Pipeline/PixelProgram.cpp
@@ -85,6 +85,25 @@
 			routine.getVariable(it->second.Id)[it->second.FirstComponent] = As<Float4>(frontFacing);
 		}
 
+		it = spirvShader->inputBuiltins.find(spv::BuiltInSampleMask);
+		if (it != spirvShader->inputBuiltins.end())
+		{
+			static_assert(SIMD::Width == 4, "Expects SIMD width to be 4");
+			Int4 laneBits = Int4(1, 2, 4, 8);
+
+			Int4 inputSampleMask = Int4(1) & CmpNEQ(Int4(cMask[0]) & laneBits, Int4(0));
+			for (auto i = 1u; i < state.multiSample; i++)
+			{
+				inputSampleMask |= Int4(1 << i) & CmpNEQ(Int4(cMask[i]) & laneBits, Int4(0));
+			}
+
+			routine.getVariable(it->second.Id)[it->second.FirstComponent] = As<Float4>(inputSampleMask);
+			// Sample mask input is an array, as the spec contemplates MSAA levels higher than 32.
+			// Fill any non-zero indices with 0.
+			for (auto i = 1u; i < it->second.SizeInComponents; i++)
+				routine.getVariable(it->second.Id)[it->second.FirstComponent + i] = Float4(0);
+		}
+
 		// Note: all lanes initially active to facilitate derivatives etc. Actual coverage is
 		// handled separately, through the cMask.
 		auto activeLaneMask = SIMD::Int(0xFFFFFFFF);