Add support for multiview rendering

This is a mandatory feature for 1.1, but Vulkan CTS 1.1.3 doesn't
enforce that -- it only tests the feature if it is present.

Highlights:
- Multiple views implemented by running each draw multiple times. We
  could do something more efficient, but this is a fringe feature so
  far.
- Render targets and input attachments are adjusted to use the layer
  corresponding to the current view.
- Explicit attachment clears and end-of-subpass resolves are broadcast
  to the layers corresponding to the current subpass's view mask.
- Renderpass attachment load ops are executed for the layers corresponding
  to the union of the subpass view masks for all subpasses which use the
  attachment. The actual load ops are still performed together at the
  beginning of the renderpass.
- ViewIndex builtin variable is exposed to the shaders. In a
  non-multiview draw call, ViewIndex is still available, but is always
  zero.

Bug: b/139862810
Test: dEQP-VK.*multiview*
Change-Id: Iaf40cfdb2f5afa61253cc756f97c0db30fb4d813
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/35408
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Chris Forbes <chrisforbes@google.com>
diff --git a/src/Pipeline/PixelProgram.cpp b/src/Pipeline/PixelProgram.cpp
index 424b129..2391e19 100644
--- a/src/Pipeline/PixelProgram.cpp
+++ b/src/Pipeline/PixelProgram.cpp
@@ -24,6 +24,12 @@
 	{
 		routine.setImmutableInputBuiltins(spirvShader);
 
+		routine.setInputBuiltin(spirvShader, spv::BuiltInViewIndex, [&](const SpirvShader::BuiltinMapping& builtin, Array<SIMD::Float>& value)
+		{
+			assert(builtin.SizeInComponents == 1);
+			value[builtin.FirstComponent] = As<Float4>(Int4((*Pointer<Int>(data + OFFSET(DrawData, viewID)))));
+		});
+
 		routine.setInputBuiltin(spirvShader, spv::BuiltInFragCoord, [&](const SpirvShader::BuiltinMapping& builtin, Array<SIMD::Float>& value)
 		{
 			assert(builtin.SizeInComponents == 4);
@@ -50,6 +56,7 @@
 
 		routine.windowSpacePosition[0] = x + SIMD::Int(0,1,0,1);
 		routine.windowSpacePosition[1] = y + SIMD::Int(0,0,1,1);
+		routine.viewID = *Pointer<Int>(data + OFFSET(DrawData, viewID));
 	}
 
 	void PixelProgram::applyShader(Int cMask[4])