SpirvShader: Use struct for MemoryVisitor callback.

Instead of calling a function with two uint32_t parameters, pass a MemoryElement structure that has named and documented fields.

This structure includes the Type field, which will be used by the debugger for knowing how to interpret the value.

Bug: b/145351270
Change-Id: I21e86b9ba117bcde21150b408d8a7552729203e2
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/38911
Presubmit-Ready: Ben Clayton <bclayton@google.com>
Tested-by: Ben Clayton <bclayton@google.com>
Reviewed-by: Chris Forbes <chrisforbes@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Pipeline/SpirvShader.hpp b/src/Pipeline/SpirvShader.hpp
index 899ff7e..827eefc 100644
--- a/src/Pipeline/SpirvShader.hpp
+++ b/src/Pipeline/SpirvShader.hpp
@@ -769,10 +769,23 @@
 
 		int VisitInterfaceInner(Type::ID id, Decorations d, const InterfaceVisitor& v) const;
 
-		using MemoryVisitor = std::function<void(uint32_t index, uint32_t offset)>;
+		// MemoryElement describes a scalar element within a structure, and is
+		// used by the callback function of VisitMemoryObject().
+		struct MemoryElement
+		{
+			uint32_t index;   // index of the scalar element
+			uint32_t offset;  // offset (in bytes) from the base of the object
+			const Type& type; // element type
+		};
 
+		using MemoryVisitor = std::function<void(const MemoryElement&)>;
+
+		// VisitMemoryObject() walks a type tree in an explicitly laid out
+		// storage class, calling the MemoryVisitor for each scalar element
+		// within the
 		void VisitMemoryObject(Object::ID id, const MemoryVisitor& v) const;
 
+		// VisitMemoryObjectInner() is internally called by VisitMemoryObject()
 		void VisitMemoryObjectInner(Type::ID id, Decorations d, uint32_t &index, uint32_t offset, const MemoryVisitor& v) const;
 
 		Object& CreateConstant(InsnIterator it);
diff --git a/src/Pipeline/SpirvShaderMemory.cpp b/src/Pipeline/SpirvShaderMemory.cpp
index 498c274..806fb78 100644
--- a/src/Pipeline/SpirvShaderMemory.cpp
+++ b/src/Pipeline/SpirvShaderMemory.cpp
@@ -57,11 +57,11 @@
 	auto &dst = state->createIntermediate(resultId, resultTy.sizeInComponents);
 	auto robustness = state->getOutOfBoundsBehavior(pointerTy.storageClass);
 
-	VisitMemoryObject(pointerId, [&](uint32_t i, uint32_t offset)
+	VisitMemoryObject(pointerId, [&](const MemoryElement& el)
 	{
-		auto p = ptr + offset;
+		auto p = ptr + el.offset;
 		if (interleavedByLane) { p = InterleaveByLane(p); }  // TODO: Interleave once, then add offset?
-		dst.move(i, p.Load<SIMD::Float>(robustness, state->activeLaneMask(), atomic, memoryOrder));
+		dst.move(el.index, p.Load<SIMD::Float>(robustness, state->activeLaneMask(), atomic, memoryOrder));
 	});
 
 	return EmitResult::Continue;
@@ -101,22 +101,22 @@
 	{
 		// Constant source data.
 		const uint32_t *src = object.constantValue.get();
-		VisitMemoryObject(pointerId, [&](uint32_t i, uint32_t offset)
+		VisitMemoryObject(pointerId, [&](const MemoryElement& el)
 		{
-			auto p = ptr + offset;
+			auto p = ptr + el.offset;
 			if (interleavedByLane) { p = InterleaveByLane(p); }
-			p.Store(SIMD::Int(src[i]), robustness, mask, atomic, memoryOrder);
+			p.Store(SIMD::Int(src[el.index]), robustness, mask, atomic, memoryOrder);
 		});
 	}
 	else
 	{
 		// Intermediate source data.
 		auto &src = state->getIntermediate(objectId);
-		VisitMemoryObject(pointerId, [&](uint32_t i, uint32_t offset)
+		VisitMemoryObject(pointerId, [&](const MemoryElement& el)
 		{
-			auto p = ptr + offset;
+			auto p = ptr + el.offset;
 			if (interleavedByLane) { p = InterleaveByLane(p); }
-			p.Store(src.Float(i), robustness, mask, atomic, memoryOrder);
+			p.Store(src.Float(el.index), robustness, mask, atomic, memoryOrder);
 		});
 	}
 
@@ -239,12 +239,12 @@
 			bool interleavedByLane = IsStorageInterleavedByLane(objectTy.storageClass);
 			auto ptr = GetPointerToData(resultId, 0, state);
 			GenericValue initialValue(this, state, initializerId);
-			VisitMemoryObject(resultId, [&](uint32_t i, uint32_t offset)
+			VisitMemoryObject(resultId, [&](const MemoryElement& el)
 			{
-				auto p = ptr + offset;
+				auto p = ptr + el.offset;
 				if (interleavedByLane) { p = InterleaveByLane(p); }
 				auto robustness = OutOfBoundsBehavior::UndefinedBehavior;  // Local variables are always within bounds.
-				p.Store(initialValue.Float(i), robustness, state->activeLaneMask());
+				p.Store(initialValue.Float(el.index), robustness, state->activeLaneMask());
 			});
 			break;
 		}
@@ -271,13 +271,14 @@
 
 	std::unordered_map<uint32_t, uint32_t> srcOffsets;
 
-	VisitMemoryObject(srcPtrId, [&](uint32_t i, uint32_t srcOffset) { srcOffsets[i] = srcOffset; });
+	VisitMemoryObject(srcPtrId, [&](const MemoryElement& el) { srcOffsets[el.index] = el.offset; });
 
-	VisitMemoryObject(dstPtrId, [&](uint32_t i, uint32_t dstOffset)
+	VisitMemoryObject(dstPtrId, [&](const MemoryElement& el)
 	{
-		auto it = srcOffsets.find(i);
+		auto it = srcOffsets.find(el.index);
 		ASSERT(it != srcOffsets.end());
 		auto srcOffset = it->second;
+		auto dstOffset = el.offset;
 
 		auto dst = dstPtr + dstOffset;
 		auto src = srcPtr + srcOffset;
@@ -302,15 +303,8 @@
 	return EmitResult::Continue;
 }
 
-void SpirvShader::VisitMemoryObjectInner(sw::SpirvShader::Type::ID id, sw::SpirvShader::Decorations d, uint32_t& index, uint32_t offset, const MemoryVisitor &f) const
+void SpirvShader::VisitMemoryObjectInner(sw::SpirvShader::Type::ID id, sw::SpirvShader::Decorations d, uint32_t& index, uint32_t offset, const MemoryVisitor& f) const
 {
-	// Walk a type tree in an explicitly laid out storage class, calling
-	// a functor for each scalar element within the object.
-
-	// The functor's first parameter is the index of the scalar element;
-	// the second parameter is the offset (in bytes) from the base of the
-	// object.
-
 	ApplyDecorationsForId(&d, id);
 	auto const &type = getType(id);
 
@@ -327,7 +321,8 @@
 		break;
 	case spv::OpTypeInt:
 	case spv::OpTypeFloat:
-		f(index++, offset);
+	case spv::OpTypeRuntimeArray:
+		f(MemoryElement{index++, offset, type});
 		break;
 	case spv::OpTypeVector:
 	{
@@ -371,7 +366,7 @@
 	}
 }
 
-void SpirvShader::VisitMemoryObject(sw::SpirvShader::Object::ID id, const MemoryVisitor &f) const
+void SpirvShader::VisitMemoryObject(sw::SpirvShader::Object::ID id, const MemoryVisitor& f) const
 {
 	auto typeId = getObject(id).type;
 	auto const & type = getType(typeId);
@@ -385,9 +380,11 @@
 	else
 	{
 		// Objects without explicit layout are tightly packed.
-		for (auto i = 0u; i < getType(type.element).sizeInComponents; i++)
+		auto &elType = getType(type.element);
+		for (auto index = 0u; index < elType.sizeInComponents; index++)
 		{
-			f(i, i * sizeof(float));
+			auto offset = static_cast<uint32_t>(index * sizeof(float));
+			f({index, offset, elType});
 		}
 	}
 }