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
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index de87763..e949547 100755
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -1832,7 +1832,7 @@
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 14a0fe3..e4cf232 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 dc1fe6e..8ab846e 100644
--- a/Test/spv.atomic.comp
+++ b/Test/spv.atomic.comp
@@ -1,4 +1,4 @@
-#version 310 es
+#version 450
@@ -22,6 +22,7 @@
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 6de3a99..2e016a8 100644
--- a/glslang/MachineIndependent/Initialize.cpp
+++ b/glslang/MachineIndependent/Initialize.cpp
@@ -1259,7 +1259,6 @@
}
if (spvVersion.vulkan == 0) {
- // gl_spirv TODO
//
// Atomic counter functions.
//
diff --git a/gtests/AST.FromFile.cpp b/gtests/AST.FromFile.cpp
index 3e5ea37..6f4abef 100644
--- a/gtests/AST.FromFile.cpp
+++ b/gtests/AST.FromFile.cpp
@@ -186,7 +186,6 @@
"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 04787ea..00f4a98 100644
--- a/gtests/Spv.FromFile.cpp
+++ b/gtests/Spv.FromFile.cpp
@@ -41,19 +41,29 @@
namespace glslangtest {
namespace {
-using CompileToSpirvTest = GlslangTest<::testing::TestWithParam<std::string>>;
+using CompileVulkanToSpirvTest = GlslangTest<::testing::TestWithParam<std::string>>;
+using CompileOpenGLToSpirvTest = GlslangTest<::testing::TestWithParam<std::string>>;
using VulkanSemantics = GlslangTest<::testing::TestWithParam<std::string>>;
using VulkanAstSemantics = GlslangTest<::testing::TestWithParam<std::string>>;
// 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 @@
// clang-format off
INSTANTIATE_TEST_CASE_P(
- Glsl, CompileToSpirvTest,
+ Glsl, CompileVulkanToSpirvTest,
::testing::ValuesIn(std::vector<std::string>({
// Test looping constructs.
// No tests yet for making sure break and continue from a nested loop
@@ -192,6 +202,18 @@
FileNameAsCustomTestSuffix
);
+// clang-format off
+INSTANTIATE_TEST_CASE_P(
+ Glsl, CompileOpenGLToSpirvTest,
+ ::testing::ValuesIn(std::vector<std::string>({
+ // 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<std::string>({