SPV: Correct semantics of atomic-counter decrement.
The semantics differ between GLSL/HLSL and SPIR-V.
Translate between these.
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index b73e538..6600ab1 100755
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -4833,6 +4833,7 @@
// - there are extra SPV operands with no glslang source
// - compare-exchange swaps the value and comparator
// - compare-exchange has an extra memory semantics
+ // - EOpAtomicCounterDecrement needs a post decrement
std::vector<spv::Id> spvAtomicOperands; // hold the spv operands
auto opIt = operands.begin(); // walk the glslang operands
spvAtomicOperands.push_back(*(opIt++));
@@ -4851,7 +4852,14 @@
for (; opIt != operands.end(); ++opIt)
spvAtomicOperands.push_back(*opIt);
- return builder.createOp(opCode, typeId, spvAtomicOperands);
+ spv::Id resultId = builder.createOp(opCode, typeId, spvAtomicOperands);
+
+ // GLSL and HLSL atomic-counter decrement return post-decrement value,
+ // while SPIR-V returns pre-decrement value. Translate between these semantics.
+ if (op == glslang::EOpAtomicCounterDecrement)
+ resultId = builder.createBinOp(spv::OpISub, typeId, resultId, builder.makeIntConstant(1));
+
+ return resultId;
}
// Create group invocation operations.