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.
diff --git a/Test/baseResults/spv.atomic.comp.out b/Test/baseResults/spv.atomic.comp.out
index beb0302..8d35d45 100755
--- a/Test/baseResults/spv.atomic.comp.out
+++ b/Test/baseResults/spv.atomic.comp.out
@@ -1,7 +1,7 @@
spv.atomic.comp
// Module Version 10000
// Generated by (magic number): 80001
-// Id's are bound by 73
+// Id's are bound by 74
Capability Shader
Capability AtomicStorage
@@ -17,29 +17,29 @@
Name 20 "counter"
Name 23 "val"
Name 27 "countArr"
- Name 35 "origi"
- Name 37 "atomi"
- Name 40 "origu"
- Name 42 "atomu"
- Name 43 "value"
- Name 60 "dataSSB"
- MemberName 60(dataSSB) 0 "f"
- MemberName 60(dataSSB) 1 "n_frames_rendered"
- Name 62 "result"
- Name 70 "arrX"
- Name 71 "arrY"
- Name 72 "arrZ"
+ Name 37 "origi"
+ Name 39 "atomi"
+ Name 42 "origu"
+ Name 44 "atomu"
+ Name 45 "value"
+ Name 62 "dataSSB"
+ MemberName 62(dataSSB) 0 "f"
+ MemberName 62(dataSSB) 1 "n_frames_rendered"
+ Name 64 "result"
+ Name 71 "arrX"
+ Name 72 "arrY"
+ Name 73 "arrZ"
Decorate 20(counter) Offset 0
Decorate 20(counter) Binding 0
Decorate 27(countArr) Offset 4
Decorate 27(countArr) Binding 0
- MemberDecorate 60(dataSSB) 0 Restrict
- MemberDecorate 60(dataSSB) 0 Offset 0
- MemberDecorate 60(dataSSB) 1 Restrict
- MemberDecorate 60(dataSSB) 1 Offset 16
- Decorate 60(dataSSB) BufferBlock
- Decorate 62(result) DescriptorSet 0
- Decorate 62(result) Binding 0
+ MemberDecorate 62(dataSSB) 0 Restrict
+ MemberDecorate 62(dataSSB) 0 Offset 0
+ MemberDecorate 62(dataSSB) 1 Restrict
+ MemberDecorate 62(dataSSB) 1 Offset 16
+ Decorate 62(dataSSB) BufferBlock
+ Decorate 64(result) DescriptorSet 0
+ Decorate 64(result) Binding 0
2: TypeVoid
3: TypeFunction 2
6: TypeInt 32 0
@@ -56,29 +56,29 @@
27(countArr): 26(ptr) Variable AtomicCounter
28: TypeInt 32 1
29: 28(int) Constant 2
- 34: TypePointer Function 28(int)
- 36: TypePointer Workgroup 28(int)
- 37(atomi): 36(ptr) Variable Workgroup
- 38: 28(int) Constant 3
- 41: TypePointer Workgroup 6(int)
- 42(atomu): 41(ptr) Variable Workgroup
- 43(value): 41(ptr) Variable Workgroup
- 46: 6(int) Constant 7
- 51: 28(int) Constant 7
- 55: 6(int) Constant 10
- 58: TypeFloat 32
- 59: TypeVector 28(int) 4
- 60(dataSSB): TypeStruct 58(float) 59(ivec4)
- 61: TypePointer Uniform 60(dataSSB)
- 62(result): 61(ptr) Variable Uniform
- 63: 28(int) Constant 1
- 64: 6(int) Constant 2
- 65: TypePointer Uniform 28(int)
- 68: TypeArray 28(int) 14
- 69: TypePointer Private 68
- 70(arrX): 69(ptr) Variable Private
- 71(arrY): 69(ptr) Variable Private
- 72(arrZ): 69(ptr) Variable Private
+ 33: 28(int) Constant 1
+ 36: TypePointer Function 28(int)
+ 38: TypePointer Workgroup 28(int)
+ 39(atomi): 38(ptr) Variable Workgroup
+ 40: 28(int) Constant 3
+ 43: TypePointer Workgroup 6(int)
+ 44(atomu): 43(ptr) Variable Workgroup
+ 45(value): 43(ptr) Variable Workgroup
+ 48: 6(int) Constant 7
+ 53: 28(int) Constant 7
+ 57: 6(int) Constant 10
+ 60: TypeFloat 32
+ 61: TypeVector 28(int) 4
+ 62(dataSSB): TypeStruct 60(float) 61(ivec4)
+ 63: TypePointer Uniform 62(dataSSB)
+ 64(result): 63(ptr) Variable Uniform
+ 65: 6(int) Constant 2
+ 66: TypePointer Uniform 28(int)
+ 69: TypeArray 28(int) 14
+ 70: TypePointer Private 69
+ 71(arrX): 70(ptr) Variable Private
+ 72(arrY): 70(ptr) Variable Private
+ 73(arrZ): 70(ptr) Variable Private
4(main): 2 Function None 3
5: Label
23(val): 22(ptr) Variable Function
@@ -88,7 +88,8 @@
31: 6(int) AtomicLoad 30 14 15
Store 23(val) 31
32: 6(int) AtomicIDecrement 20(counter) 14 15
- 33: 6(int) AtomicIIncrement 20(counter) 14 15
+ 34: 6(int) ISub 32 33
+ 35: 6(int) AtomicIIncrement 20(counter) 14 15
Return
FunctionEnd
10(func(au1;): 6(int) Function None 8
@@ -99,29 +100,29 @@
FunctionEnd
12(atoms(): 2 Function None 3
13: Label
- 35(origi): 34(ptr) Variable Function
- 40(origu): 22(ptr) Variable Function
- 39: 28(int) AtomicIAdd 37(atomi) 14 15 38
- Store 35(origi) 39
- 44: 6(int) Load 43(value)
- 45: 6(int) AtomicAnd 42(atomu) 14 15 44
- Store 40(origu) 45
- 47: 6(int) AtomicOr 42(atomu) 14 15 46
- Store 40(origu) 47
- 48: 6(int) AtomicXor 42(atomu) 14 15 46
- Store 40(origu) 48
- 49: 6(int) Load 43(value)
- 50: 6(int) AtomicUMin 42(atomu) 14 15 49
- Store 40(origu) 50
- 52: 28(int) AtomicSMax 37(atomi) 14 15 51
- Store 35(origi) 52
- 53: 28(int) Load 35(origi)
- 54: 28(int) AtomicExchange 37(atomi) 14 15 53
- Store 35(origi) 54
- 56: 6(int) Load 43(value)
- 57: 6(int) AtomicCompareExchange 42(atomu) 14 15 15 56 55
- Store 40(origu) 57
- 66: 65(ptr) AccessChain 62(result) 63 64
- 67: 28(int) AtomicIAdd 66 14 15 63
+ 37(origi): 36(ptr) Variable Function
+ 42(origu): 22(ptr) Variable Function
+ 41: 28(int) AtomicIAdd 39(atomi) 14 15 40
+ Store 37(origi) 41
+ 46: 6(int) Load 45(value)
+ 47: 6(int) AtomicAnd 44(atomu) 14 15 46
+ Store 42(origu) 47
+ 49: 6(int) AtomicOr 44(atomu) 14 15 48
+ Store 42(origu) 49
+ 50: 6(int) AtomicXor 44(atomu) 14 15 48
+ Store 42(origu) 50
+ 51: 6(int) Load 45(value)
+ 52: 6(int) AtomicUMin 44(atomu) 14 15 51
+ Store 42(origu) 52
+ 54: 28(int) AtomicSMax 39(atomi) 14 15 53
+ Store 37(origi) 54
+ 55: 28(int) Load 37(origi)
+ 56: 28(int) AtomicExchange 39(atomi) 14 15 55
+ Store 37(origi) 56
+ 58: 6(int) Load 45(value)
+ 59: 6(int) AtomicCompareExchange 44(atomu) 14 15 15 58 57
+ Store 42(origu) 59
+ 67: 66(ptr) AccessChain 64(result) 33 65
+ 68: 28(int) AtomicIAdd 67 14 15 33
Return
FunctionEnd
diff --git a/glslang/Include/intermediate.h b/glslang/Include/intermediate.h
index b6c7e89..12f17e3 100644
--- a/glslang/Include/intermediate.h
+++ b/glslang/Include/intermediate.h
@@ -417,8 +417,8 @@
EOpAtomicExchange,
EOpAtomicCompSwap,
- EOpAtomicCounterIncrement,
- EOpAtomicCounterDecrement,
+ EOpAtomicCounterIncrement, // results in pre-increment value
+ EOpAtomicCounterDecrement, // results in post-decrement value
EOpAtomicCounter,
EOpAtomicCounterAdd,
EOpAtomicCounterSubtract,