SpirvShader: Implement constant variable initializers.

Non-constant initializers not yet implemented.

Tests: dEQP-VK.spirv_assembly.instruction.graphics.variable_init.*
Tests: dEQP-VK.spirv_assembly.instruction.compute.variable_init.*
Tests: dEQP-VK.spirv_assembly.instruction.compute.opunreachable.*
Tests: dEQP-VK.spirv_assembly.instruction.compute.shader_default_output.int.initialized

Bug: b/131681817
Change-Id: I8b283042d3be15028c2efe10988d6847c6256811
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/30213
Reviewed-by: Chris Forbes <chrisforbes@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Presubmit-Ready: Ben Clayton <bclayton@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Tested-by: Ben Clayton <bclayton@google.com>
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index c28f22e..b429df7 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -534,8 +534,6 @@
 				Type::ID typeId = insn.word(1);
 				Object::ID resultId = insn.word(2);
 				auto storageClass = static_cast<spv::StorageClass>(insn.word(3));
-				if (insn.wordCount() > 4)
-					UNIMPLEMENTED("Variable initializers not yet supported");
 
 				auto &object = defs[resultId];
 				object.kind = Object::Kind::Pointer;
@@ -2515,6 +2513,35 @@
 			break;
 		}
 
+		if (insn.wordCount() > 4)
+		{
+			Object::ID initializerId = insn.word(4);
+			if (getObject(initializerId).kind != Object::Kind::Constant)
+			{
+				UNIMPLEMENTED("Non-constant initializers not yet implemented");
+			}
+			switch (objectTy.storageClass)
+			{
+			case spv::StorageClassOutput:
+			case spv::StorageClassPrivate:
+			case spv::StorageClassFunction:
+			{
+				bool interleavedByLane = IsStorageInterleavedByLane(objectTy.storageClass);
+				auto ptr = routine->getPointer(resultId);
+				GenericValue initialValue(this, routine, initializerId);
+				VisitMemoryObject(resultId, [&](uint32_t i, uint32_t offset)
+				{
+					auto p = ptr + offset;
+					if (interleavedByLane) { p = interleaveByLane(p); }
+					SIMD::Store(p, initialValue.Float(i), state->activeLaneMask());
+				});
+				break;
+			}
+			default:
+				ASSERT_MSG(initializerId == 0, "Vulkan does not permit variables of storage class %d to have initializers", int(objectTy.storageClass));
+			}
+		}
+
 		return EmitResult::Continue;
 	}