Support loads and stores of interface variables

Bug: b/124388146
Change-Id: I2c422dc2f85730f4c4bef45388e77028465ea9ba
Reviewed-on: https://swiftshader-review.googlesource.com/c/24828
Tested-by: Chris Forbes <chrisforbes@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index bfa5894..87dfbf2 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -642,12 +642,11 @@
 			{
 			case spv::OpVariable:
 			{
-				auto &object = getObject(insn.word(2));
-				// Want to exclude: location-oriented interface variables; special things that consume zero slots.
+				auto resultId = insn.word(2);
+				auto &object = getObject(resultId);
 				// TODO: what to do about zero-slot objects?
-				if (object.kind != Object::Kind::InterfaceVariable && object.sizeInComponents > 0)
+				if (object.sizeInComponents > 0)
 				{
-					// any variable not in a location-oriented interface
 					routine->createLvalue(insn.word(2), object.sizeInComponents);
 				}
 				break;
@@ -665,6 +664,22 @@
 		{
 			switch (insn.opcode())
 			{
+			case spv::OpVariable:
+			{
+				auto resultId = insn.word(2);
+				auto &object = getObject(resultId);
+				if (object.kind == Object::Kind::InterfaceVariable && object.storageClass == spv::StorageClassInput)
+				{
+					auto &dst = routine->getValue(resultId);
+					int offset = 0;
+					VisitInterface(resultId,
+								   [&](Decorations const &d, AttribType type) {
+									   auto scalarSlot = d.Location << 2 | d.Component;
+									   dst[offset++] = (*routine->inputs)[scalarSlot];
+								   });
+				}
+				break;
+			}
 			case spv::OpLoad:
 			{
 				auto &object = getObject(insn.word(2));
@@ -673,11 +688,6 @@
 				routine->createLvalue(insn.word(2), type.sizeInComponents);		// TODO: this should be an ssavalue!
 				auto &pointerBase = getObject(pointer.pointerBase);
 
-				if (pointerBase.kind == Object::Kind::InterfaceVariable)
-				{
-					UNIMPLEMENTED("Location-based load not yet implemented");
-				}
-
 				if (pointerBase.storageClass == spv::StorageClassImage ||
 					pointerBase.storageClass == spv::StorageClassUniform ||
 					pointerBase.storageClass == spv::StorageClassUniformConstant)
@@ -720,11 +730,6 @@
 				assert(type.sizeInComponents == 1);
 				assert(base.pointerBase == object.pointerBase);
 
-				if (pointerBase.kind == Object::Kind::InterfaceVariable)
-				{
-					UNIMPLEMENTED("Location-based OpAccessChain not yet implemented");
-				}
-
 				if (pointerBase.storageClass == spv::StorageClassImage ||
 					pointerBase.storageClass == spv::StorageClassUniform ||
 					pointerBase.storageClass == spv::StorageClassUniformConstant)
@@ -742,11 +747,6 @@
 				auto &pointer = getObject(insn.word(1));
 				auto &pointerBase = getObject(pointer.pointerBase);
 
-				if (pointerBase.kind == Object::Kind::InterfaceVariable)
-				{
-					UNIMPLEMENTED("Location-based store not yet implemented");
-				}
-
 				if (pointerBase.storageClass == spv::StorageClassImage ||
 					pointerBase.storageClass == spv::StorageClassUniform ||
 					pointerBase.storageClass == spv::StorageClassUniformConstant)