From 2d0cc786f3f830e898df863ce5092945f31e62f8 Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Thu, 7 Jul 2016 13:20:00 -0600 Subject: [PATCH] SPV: Turn on atomic-storage functionality for SPIR-V. This is used by OpenGL, but not Vulkan. Includes: - atomicCounter, atomicIncrement, atomicCounterDecrement - atomic_uint layout-offset checking - AtomicStorage capability --- SPIRV/GlslangToSpv.cpp | 2 +- Test/baseResults/spv.atomic.comp.out | 320 +++++++++------------- Test/spv.atomic.comp | 3 +- glslang/MachineIndependent/Initialize.cpp | 1 - gtests/AST.FromFile.cpp | 1 - gtests/Spv.FromFile.cpp | 28 +- 6 files changed, 152 insertions(+), 203 deletions(-) diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index de87763a..e9495475 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -1832,7 +1832,7 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty spvType = builder.makeUintType(64); break; case glslang::EbtAtomicUint: - logger->tbdFunctionality("Is atomic_uint an opaque handle in the uniform storage class, or an addresses in the atomic storage class?"); + builder.addCapability(spv::CapabilityAtomicStorage); spvType = builder.makeUintType(32); break; case glslang::EbtSampler: diff --git a/Test/baseResults/spv.atomic.comp.out b/Test/baseResults/spv.atomic.comp.out index 14a0fe31..e4cf2320 100755 --- a/Test/baseResults/spv.atomic.comp.out +++ b/Test/baseResults/spv.atomic.comp.out @@ -1,203 +1,131 @@ spv.atomic.comp -Warning, version 310 is not yet complete; most version-specific features are present, but some are missing. - -Shader version: 310 -local_size = (1, 1, 1) -0:? Sequence -0:14 Function Definition: func(au1; (global highp uint) -0:14 Function Parameters: -0:14 'c' (in highp atomic_uint) -0:16 Sequence -0:16 Branch: Return with expression -0:16 AtomicCounterIncrement (global highp uint) -0:16 'c' (in highp atomic_uint) -0:19 Function Definition: main( (global void) -0:19 Function Parameters: -0:21 Sequence -0:21 MemoryBarrierAtomicCounter (global void) -0:22 Function Call: func(au1; (global highp uint) -0:22 'counter' (layout(binding=0 offset=0 ) uniform highp atomic_uint) -0:23 Sequence -0:23 move second child to first child (temp highp uint) -0:23 'val' (temp highp uint) -0:23 AtomicCounter (global highp uint) -0:23 direct index (layout(binding=0 offset=4 ) temp highp atomic_uint) -0:23 'countArr' (layout(binding=0 offset=4 ) uniform 4-element array of highp atomic_uint) -0:23 Constant: -0:23 2 (const int) -0:24 AtomicCounterDecrement (global highp uint) -0:24 'counter' (layout(binding=0 offset=0 ) uniform highp atomic_uint) -0:36 Function Definition: atoms( (global void) -0:36 Function Parameters: -0:38 Sequence -0:38 Sequence -0:38 move second child to first child (temp highp int) -0:38 'origi' (temp highp int) -0:38 AtomicAdd (global highp int) -0:38 'atomi' (shared highp int) -0:38 Constant: -0:38 3 (const int) -0:39 Sequence -0:39 move second child to first child (temp highp uint) -0:39 'origu' (temp highp uint) -0:39 AtomicAnd (global highp uint) -0:39 'atomu' (shared highp uint) -0:39 'value' (shared highp uint) -0:40 move second child to first child (temp highp uint) -0:40 'origu' (temp highp uint) -0:40 AtomicOr (global highp uint) -0:40 'atomu' (shared highp uint) -0:40 Constant: -0:40 7 (const uint) -0:41 move second child to first child (temp highp uint) -0:41 'origu' (temp highp uint) -0:41 AtomicXor (global highp uint) -0:41 'atomu' (shared highp uint) -0:41 Constant: -0:41 7 (const uint) -0:42 move second child to first child (temp highp uint) -0:42 'origu' (temp highp uint) -0:42 AtomicMin (global highp uint) -0:42 'atomu' (shared highp uint) -0:42 'value' (shared highp uint) -0:43 move second child to first child (temp highp int) -0:43 'origi' (temp highp int) -0:43 AtomicMax (global highp int) -0:43 'atomi' (shared highp int) -0:43 Constant: -0:43 7 (const int) -0:44 move second child to first child (temp highp int) -0:44 'origi' (temp highp int) -0:44 AtomicExchange (global highp int) -0:44 'atomi' (shared highp int) -0:44 'origi' (temp highp int) -0:45 move second child to first child (temp highp uint) -0:45 'origu' (temp highp uint) -0:45 AtomicCompSwap (global highp uint) -0:45 'atomu' (shared highp uint) -0:45 Constant: -0:45 10 (const uint) -0:45 'value' (shared highp uint) -0:46 AtomicAdd (global highp int) -0:46 direct index (temp highp int) -0:46 n_frames_rendered: direct index for structure (layout(column_major std140 offset=16 ) buffer highp 4-component vector of int) -0:46 'result' (layout(binding=0 column_major std140 ) restrict buffer block{layout(column_major std140 offset=0 ) buffer highp float f, layout(column_major std140 offset=16 ) buffer highp 4-component vector of int n_frames_rendered}) -0:46 Constant: -0:46 1 (const int) -0:46 Constant: -0:46 2 (const int) -0:46 Constant: -0:46 1 (const int) -0:? Linker Objects -0:? 'counter' (layout(binding=0 offset=0 ) uniform highp atomic_uint) -0:? 'countArr' (layout(binding=0 offset=4 ) uniform 4-element array of highp atomic_uint) -0:? 'value' (shared highp uint) -0:? 'arrX' (global 1-element array of highp int) -0:? 'arrY' (global 1-element array of highp int) -0:? 'arrZ' (global 1-element array of highp int) -0:? 'atomi' (shared highp int) -0:? 'atomu' (shared highp uint) -0:? 'result' (layout(binding=0 column_major std140 ) restrict buffer block{layout(column_major std140 offset=0 ) buffer highp float f, layout(column_major std140 offset=16 ) buffer highp 4-component vector of int n_frames_rendered}) +Warning, version 450 is not yet complete; most version-specific features are present, but some are missing. Linked compute stage: -Shader version: 310 -local_size = (1, 1, 1) -0:? Sequence -0:14 Function Definition: func(au1; (global highp uint) -0:14 Function Parameters: -0:14 'c' (in highp atomic_uint) -0:16 Sequence -0:16 Branch: Return with expression -0:16 AtomicCounterIncrement (global highp uint) -0:16 'c' (in highp atomic_uint) -0:19 Function Definition: main( (global void) -0:19 Function Parameters: -0:21 Sequence -0:21 MemoryBarrierAtomicCounter (global void) -0:22 Function Call: func(au1; (global highp uint) -0:22 'counter' (layout(binding=0 offset=0 ) uniform highp atomic_uint) -0:23 Sequence -0:23 move second child to first child (temp highp uint) -0:23 'val' (temp highp uint) -0:23 AtomicCounter (global highp uint) -0:23 direct index (layout(binding=0 offset=4 ) temp highp atomic_uint) -0:23 'countArr' (layout(binding=0 offset=4 ) uniform 4-element array of highp atomic_uint) -0:23 Constant: -0:23 2 (const int) -0:24 AtomicCounterDecrement (global highp uint) -0:24 'counter' (layout(binding=0 offset=0 ) uniform highp atomic_uint) -0:36 Function Definition: atoms( (global void) -0:36 Function Parameters: -0:38 Sequence -0:38 Sequence -0:38 move second child to first child (temp highp int) -0:38 'origi' (temp highp int) -0:38 AtomicAdd (global highp int) -0:38 'atomi' (shared highp int) -0:38 Constant: -0:38 3 (const int) -0:39 Sequence -0:39 move second child to first child (temp highp uint) -0:39 'origu' (temp highp uint) -0:39 AtomicAnd (global highp uint) -0:39 'atomu' (shared highp uint) -0:39 'value' (shared highp uint) -0:40 move second child to first child (temp highp uint) -0:40 'origu' (temp highp uint) -0:40 AtomicOr (global highp uint) -0:40 'atomu' (shared highp uint) -0:40 Constant: -0:40 7 (const uint) -0:41 move second child to first child (temp highp uint) -0:41 'origu' (temp highp uint) -0:41 AtomicXor (global highp uint) -0:41 'atomu' (shared highp uint) -0:41 Constant: -0:41 7 (const uint) -0:42 move second child to first child (temp highp uint) -0:42 'origu' (temp highp uint) -0:42 AtomicMin (global highp uint) -0:42 'atomu' (shared highp uint) -0:42 'value' (shared highp uint) -0:43 move second child to first child (temp highp int) -0:43 'origi' (temp highp int) -0:43 AtomicMax (global highp int) -0:43 'atomi' (shared highp int) -0:43 Constant: -0:43 7 (const int) -0:44 move second child to first child (temp highp int) -0:44 'origi' (temp highp int) -0:44 AtomicExchange (global highp int) -0:44 'atomi' (shared highp int) -0:44 'origi' (temp highp int) -0:45 move second child to first child (temp highp uint) -0:45 'origu' (temp highp uint) -0:45 AtomicCompSwap (global highp uint) -0:45 'atomu' (shared highp uint) -0:45 Constant: -0:45 10 (const uint) -0:45 'value' (shared highp uint) -0:46 AtomicAdd (global highp int) -0:46 direct index (temp highp int) -0:46 n_frames_rendered: direct index for structure (layout(column_major std140 offset=16 ) buffer highp 4-component vector of int) -0:46 'result' (layout(binding=0 column_major std140 ) restrict buffer block{layout(column_major std140 offset=0 ) buffer highp float f, layout(column_major std140 offset=16 ) buffer highp 4-component vector of int n_frames_rendered}) -0:46 Constant: -0:46 1 (const int) -0:46 Constant: -0:46 2 (const int) -0:46 Constant: -0:46 1 (const int) -0:? Linker Objects -0:? 'counter' (layout(binding=0 offset=0 ) uniform highp atomic_uint) -0:? 'countArr' (layout(binding=0 offset=4 ) uniform 4-element array of highp atomic_uint) -0:? 'value' (shared highp uint) -0:? 'arrX' (global 1-element array of highp int) -0:? 'arrY' (global 1-element array of highp int) -0:? 'arrZ' (global 1-element array of highp int) -0:? 'atomi' (shared highp int) -0:? 'atomu' (shared highp uint) -0:? 'result' (layout(binding=0 column_major std140 ) restrict buffer block{layout(column_major std140 offset=0 ) buffer highp float f, layout(column_major std140 offset=16 ) buffer highp 4-component vector of int n_frames_rendered}) +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 73 + Capability Shader + Capability AtomicStorage + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint GLCompute 4 "main" + ExecutionMode 4 LocalSize 1 1 1 + Source GLSL 450 + Name 4 "main" + Name 10 "func(au1;" + Name 9 "c" + Name 12 "atoms(" + 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" + Decorate 20(counter) Binding 0 + 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 + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeInt 32 0 + 7: TypePointer AtomicCounter 6(int) + 8: TypeFunction 6(int) 7(ptr) + 14: 6(int) Constant 1 + 15: 6(int) Constant 0 + 19: 6(int) Constant 1024 + 20(counter): 7(ptr) Variable AtomicCounter + 22: TypePointer Function 6(int) + 24: 6(int) Constant 4 + 25: TypeArray 6(int) 24 + 26: TypePointer AtomicCounter 25 + 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 + 4(main): 2 Function None 3 + 5: Label + 23(val): 22(ptr) Variable Function + MemoryBarrier 14 19 + 21: 6(int) FunctionCall 10(func(au1;) 20(counter) + 30: 7(ptr) AccessChain 27(countArr) 29 + 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 + Return + FunctionEnd + 10(func(au1;): 6(int) Function None 8 + 9(c): 7(ptr) FunctionParameter + 11: Label + 16: 6(int) AtomicIIncrement 9(c) 14 15 + ReturnValue 16 + 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 + Return + FunctionEnd diff --git a/Test/spv.atomic.comp b/Test/spv.atomic.comp index dc1fe6e8..8ab846e4 100644 --- a/Test/spv.atomic.comp +++ b/Test/spv.atomic.comp @@ -1,4 +1,4 @@ -#version 310 es +#version 450 @@ -22,6 +22,7 @@ void main() func(counter); uint val = atomicCounter(countArr[2]); atomicCounterDecrement(counter); + atomicCounterIncrement(counter); } shared int atomi; diff --git a/glslang/MachineIndependent/Initialize.cpp b/glslang/MachineIndependent/Initialize.cpp index 6de3a99d..2e016a85 100644 --- a/glslang/MachineIndependent/Initialize.cpp +++ b/glslang/MachineIndependent/Initialize.cpp @@ -1259,7 +1259,6 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV } if (spvVersion.vulkan == 0) { - // gl_spirv TODO // // Atomic counter functions. // diff --git a/gtests/AST.FromFile.cpp b/gtests/AST.FromFile.cpp index 3e5ea373..6f4abef1 100644 --- a/gtests/AST.FromFile.cpp +++ b/gtests/AST.FromFile.cpp @@ -186,7 +186,6 @@ INSTANTIATE_TEST_CASE_P( "whileLoop.frag", "nonVulkan.frag", "negativeArraySize.comp", - "spv.atomic.comp", "precise.tesc", "precise_struct_block.vert", "maxClipDistances.vert", diff --git a/gtests/Spv.FromFile.cpp b/gtests/Spv.FromFile.cpp index 04787eaf..00f4a987 100644 --- a/gtests/Spv.FromFile.cpp +++ b/gtests/Spv.FromFile.cpp @@ -41,19 +41,29 @@ namespace glslangtest { namespace { -using CompileToSpirvTest = GlslangTest<::testing::TestWithParam>; +using CompileVulkanToSpirvTest = GlslangTest<::testing::TestWithParam>; +using CompileOpenGLToSpirvTest = GlslangTest<::testing::TestWithParam>; using VulkanSemantics = GlslangTest<::testing::TestWithParam>; using VulkanAstSemantics = GlslangTest<::testing::TestWithParam>; // Compiling GLSL to SPIR-V under Vulkan semantics. Expected to successfully // generate SPIR-V. -TEST_P(CompileToSpirvTest, FromFile) +TEST_P(CompileVulkanToSpirvTest, FromFile) { loadFileCompileAndCheck(GLSLANG_TEST_DIRECTORY, GetParam(), Source::GLSL, Semantics::Vulkan, Target::Spv); } +// Compiling GLSL to SPIR-V under OpenGL semantics. Expected to successfully +// generate SPIR-V. +TEST_P(CompileOpenGLToSpirvTest, FromFile) +{ + loadFileCompileAndCheck(GLSLANG_TEST_DIRECTORY, GetParam(), + Source::GLSL, Semantics::OpenGL, + Target::Spv); +} + // GLSL-level Vulkan semantics test. Expected to error out before generating // SPIR-V. TEST_P(VulkanSemantics, FromFile) @@ -73,7 +83,7 @@ TEST_P(VulkanAstSemantics, FromFile) // clang-format off INSTANTIATE_TEST_CASE_P( - Glsl, CompileToSpirvTest, + Glsl, CompileVulkanToSpirvTest, ::testing::ValuesIn(std::vector({ // Test looping constructs. // No tests yet for making sure break and continue from a nested loop @@ -192,6 +202,18 @@ INSTANTIATE_TEST_CASE_P( FileNameAsCustomTestSuffix ); +// clang-format off +INSTANTIATE_TEST_CASE_P( + Glsl, CompileOpenGLToSpirvTest, + ::testing::ValuesIn(std::vector({ + // Test looping constructs. + // No tests yet for making sure break and continue from a nested loop + // goes to the innermost target. + "spv.atomic.comp", + })), + FileNameAsCustomTestSuffix +); + INSTANTIATE_TEST_CASE_P( Glsl, VulkanSemantics, ::testing::ValuesIn(std::vector({