Implement some common forms of OpStore

Bug: b/124388146
Change-Id: Ia3c4e6c81432dcfbca5bdd21c857108ee14bda9b
Reviewed-on: https://swiftshader-review.googlesource.com/c/24788
Reviewed-by: Ben Clayton <bclayton@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Chris Forbes <chrisforbes@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index 3b2fac8..cdd3a63 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -660,6 +660,50 @@
 				}
 				break;
 			}
+			case spv::OpStore:
+			{
+				auto &object = getObject(insn.word(2));
+				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)
+				{
+					UNIMPLEMENTED("Descriptor-backed store not yet implemented");
+				}
+
+				SpirvRoutine::Value& ptrBase = *(routine->lvalues)[pointer.pointerBase];
+				auto & src = *(routine->lvalues)[insn.word(2)];
+
+				if (pointer.kind == Object::Kind::Value)
+				{
+					auto offsets = As<Int4>(*(routine->lvalues)[insn.word(1)]);
+					for (auto i = 0u; i < object.sizeInComponents; i++)
+					{
+						// Scattered store
+						for (int j = 0; j < 4; j++)
+						{
+							auto dst = ptrBase[Int(i) + Extract(offsets, j)];
+							dst = Insert(dst, Extract(src[i], j), j);
+						}
+					}
+				}
+				else
+				{
+					// no divergent offsets
+					for (auto i = 0u; i < object.sizeInComponents; i++)
+					{
+						ptrBase[i] = src[i];
+					}
+				}
+				break;
+			}
 			default:
 				printf("emit: ignoring opcode %d\n", insn.opcode());
 				break;