Implement atomic load/store
SIMD vector load and store are already atomic on x86 and ARM, and
Vulkan only supports atomic operations on "scalar 32-bit integer type".
Memory order semantics are handled in a follow-up change.
Bug b/127472316
Test: dEQP-VK.spirv_assembly.instruction.compute.opatomic.load
Test: dEQP-VK.spirv_assembly.instruction.compute.opatomic.store
Change-Id: I4481fe7b7aa792b63f516bd3cb1aab1d773bbcbd
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/27649
Presubmit-Ready: Nicolas Capens <nicolascapens@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Reviewed-by: Chris Forbes <chrisforbes@google.com>
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index 15307d4..930cff6 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -410,6 +410,7 @@
case spv::OpDPdxFine:
case spv::OpDPdyFine:
case spv::OpFwidthFine:
+ case spv::OpAtomicLoad:
// Instructions that yield an intermediate value
{
Type::ID typeId = insn.word(1);
@@ -431,6 +432,7 @@
}
case spv::OpStore:
+ case spv::OpAtomicStore:
// Don't need to do anything during analysis pass
break;
@@ -1187,10 +1189,12 @@
break;
case spv::OpLoad:
+ case spv::OpAtomicLoad:
EmitLoad(insn, routine);
break;
case spv::OpStore:
+ case spv::OpAtomicStore:
EmitStore(insn, routine);
break;
@@ -1393,6 +1397,7 @@
ASSERT(getType(pointer.type).element == object.type);
ASSERT(Type::ID(insn.word(1)) == object.type);
+ ASSERT((insn.opcode() != spv::OpAtomicLoad) || getType(getType(pointer.type).element).opcode() == spv::OpTypeInt); // Vulkan 1.1: "Atomic instructions must declare a scalar 32-bit integer type, for the value pointed to by Pointer."
if (pointerBaseTy.storageClass == spv::StorageClassImage)
{
@@ -1490,8 +1495,9 @@
void SpirvShader::EmitStore(InsnIterator insn, SpirvRoutine *routine) const
{
+ bool atomic = (insn.opcode() == spv::OpAtomicStore);
Object::ID pointerId = insn.word(1);
- Object::ID objectId = insn.word(2);
+ Object::ID objectId = insn.word(atomic ? 4 : 2);
auto &object = getObject(objectId);
auto &pointer = getObject(pointerId);
auto &pointerTy = getType(pointer.type);
@@ -1499,6 +1505,8 @@
auto &pointerBase = getObject(pointer.pointerBase);
auto &pointerBaseTy = getType(pointerBase.type);
+ ASSERT(!atomic || elementTy.opcode() == spv::OpTypeInt); // Vulkan 1.1: "Atomic instructions must declare a scalar 32-bit integer type, for the value pointed to by Pointer."
+
if (pointerBaseTy.storageClass == spv::StorageClassImage)
{
UNIMPLEMENTED("StorageClassImage store not yet implemented");