From 48d6e798bc76b8e58be844a8cef8bc6f843a909e Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Fri, 6 Oct 2017 21:21:48 -0600 Subject: [PATCH] SPV: Correct semantics of atomic-counter decrement. The semantics differ between GLSL/HLSL and SPIR-V. Translate between these. --- SPIRV/GlslangToSpv.cpp | 10 ++- Test/baseResults/spv.atomic.comp.out | 137 ++++++++++++++++++----------------- glslang/Include/intermediate.h | 4 +- 3 files changed, 80 insertions(+), 71 deletions(-) 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 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv // - 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 spvAtomicOperands; // hold the spv operands auto opIt = operands.begin(); // walk the glslang operands spvAtomicOperands.push_back(*(opIt++)); @@ -4851,7 +4852,14 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv 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 @@ spv.atomic.comp 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 @@ spv.atomic.comp 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 @@ spv.atomic.comp 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 @@ spv.atomic.comp 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 @@ enum TOperator { EOpAtomicExchange, EOpAtomicCompSwap, - EOpAtomicCounterIncrement, - EOpAtomicCounterDecrement, + EOpAtomicCounterIncrement, // results in pre-increment value + EOpAtomicCounterDecrement, // results in post-decrement value EOpAtomicCounter, EOpAtomicCounterAdd, EOpAtomicCounterSubtract, -- 2.7.4