SPV: Correct semantics of atomic-counter decrement.

The semantics differ between GLSL/HLSL and SPIR-V.
Translate between these.
This commit is contained in:
John Kessenich 2017-10-06 21:21:48 -06:00
parent 592e8f0441
commit 48d6e798bc
3 changed files with 80 additions and 71 deletions

View File

@ -4833,6 +4833,7 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv
// - there are extra SPV operands with no glslang source // - there are extra SPV operands with no glslang source
// - compare-exchange swaps the value and comparator // - compare-exchange swaps the value and comparator
// - compare-exchange has an extra memory semantics // - compare-exchange has an extra memory semantics
// - EOpAtomicCounterDecrement needs a post decrement
std::vector<spv::Id> spvAtomicOperands; // hold the spv operands std::vector<spv::Id> spvAtomicOperands; // hold the spv operands
auto opIt = operands.begin(); // walk the glslang operands auto opIt = operands.begin(); // walk the glslang operands
spvAtomicOperands.push_back(*(opIt++)); spvAtomicOperands.push_back(*(opIt++));
@ -4851,7 +4852,14 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv
for (; opIt != operands.end(); ++opIt) for (; opIt != operands.end(); ++opIt)
spvAtomicOperands.push_back(*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. // Create group invocation operations.

View File

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

View File

@ -417,8 +417,8 @@ enum TOperator {
EOpAtomicExchange, EOpAtomicExchange,
EOpAtomicCompSwap, EOpAtomicCompSwap,
EOpAtomicCounterIncrement, EOpAtomicCounterIncrement, // results in pre-increment value
EOpAtomicCounterDecrement, EOpAtomicCounterDecrement, // results in post-decrement value
EOpAtomicCounter, EOpAtomicCounter,
EOpAtomicCounterAdd, EOpAtomicCounterAdd,
EOpAtomicCounterSubtract, EOpAtomicCounterSubtract,