SpirvShader: Implement OpCopyMemory
Tests: dEQP-VK.spirv_assembly.instruction.compute.memory_access.*
Change-Id: I5281798468651c67ec038bdd8688f99c67654cb1
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/30215
Tested-by: Ben Clayton <bclayton@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index b429df7..0ed371a 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -857,6 +857,7 @@
case spv::OpStore:
case spv::OpAtomicStore:
case spv::OpImageWrite:
+ case spv::OpCopyMemory:
// Don't need to do anything during analysis pass
break;
@@ -2432,6 +2433,9 @@
case spv::OpImage:
return EmitSampledImageCombineOrSplit(insn, state);
+ case spv::OpCopyMemory:
+ return EmitCopyMemory(insn, state);
+
default:
UNIMPLEMENTED("%s", OpcodeName(opcode).c_str());
break;
@@ -5248,6 +5252,38 @@
return EmitResult::Continue;
}
+ SpirvShader::EmitResult SpirvShader::EmitCopyMemory(InsnIterator insn, EmitState *state) const
+ {
+ Object::ID dstPtrId = insn.word(1);
+ Object::ID srcPtrId = insn.word(2);
+ auto &dstPtrTy = getType(getObject(dstPtrId).type);
+ auto &srcPtrTy = getType(getObject(srcPtrId).type);
+ ASSERT(dstPtrTy.element == srcPtrTy.element);
+
+ bool dstInterleavedByLane = IsStorageInterleavedByLane(dstPtrTy.storageClass);
+ bool srcInterleavedByLane = IsStorageInterleavedByLane(srcPtrTy.storageClass);
+ auto dstPtr = state->routine->getPointer(dstPtrId);
+ auto srcPtr = state->routine->getPointer(srcPtrId);
+
+ std::unordered_map<uint32_t, uint32_t> srcOffsets;
+
+ VisitMemoryObject(srcPtrId, [&](uint32_t i, uint32_t srcOffset) { srcOffsets[i] = srcOffset; });
+
+ VisitMemoryObject(dstPtrId, [&](uint32_t i, uint32_t dstOffset)
+ {
+ auto it = srcOffsets.find(i);
+ ASSERT(it != srcOffsets.end());
+ auto srcOffset = it->second;
+
+ auto dst = dstPtr + dstOffset;
+ auto src = srcPtr + srcOffset;
+ if (dstInterleavedByLane) { dst = interleaveByLane(dst); }
+ if (srcInterleavedByLane) { src = interleaveByLane(src); }
+ SIMD::Store(dst, SIMD::Load<SIMD::Float>(src, state->activeLaneMask()), state->activeLaneMask());
+ });
+ return EmitResult::Continue;
+ }
+
void SpirvShader::emitEpilog(SpirvRoutine *routine) const
{
for (auto insn : *this)
diff --git a/src/Pipeline/SpirvShader.hpp b/src/Pipeline/SpirvShader.hpp
index 1d09f88..29372f3 100644
--- a/src/Pipeline/SpirvShader.hpp
+++ b/src/Pipeline/SpirvShader.hpp
@@ -905,6 +905,7 @@
EmitResult EmitAtomicOp(InsnIterator insn, EmitState *state) const;
EmitResult EmitAtomicCompareExchange(InsnIterator insn, EmitState *state) const;
EmitResult EmitSampledImageCombineOrSplit(InsnIterator insn, EmitState *state) const;
+ EmitResult EmitCopyMemory(InsnIterator insn, EmitState *state) const;
SIMD::Pointer GetTexelAddress(SpirvRoutine const * routine, SIMD::Pointer base, GenericValue const & coordinate, Type const & imageType, Pointer<Byte> descriptor, int texelSize) const;