GLSL 4.6: Implement atomic counter ops and SPV_KHR_shader_atomic_counter_ops.
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index 36b2707..1661d5b 100755
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -1745,6 +1745,20 @@
atomic = true;
break;
+ case glslang::EOpAtomicCounterAdd:
+ case glslang::EOpAtomicCounterSubtract:
+ case glslang::EOpAtomicCounterMin:
+ case glslang::EOpAtomicCounterMax:
+ case glslang::EOpAtomicCounterAnd:
+ case glslang::EOpAtomicCounterOr:
+ case glslang::EOpAtomicCounterXor:
+ case glslang::EOpAtomicCounterExchange:
+ case glslang::EOpAtomicCounterCompSwap:
+ builder.addExtension("SPV_KHR_shader_atomic_counter_ops");
+ builder.addCapability(spv::CapabilityAtomicStorageOps);
+ atomic = true;
+ break;
+
default:
break;
}
@@ -1815,6 +1829,15 @@
case glslang::EOpAtomicXor:
case glslang::EOpAtomicExchange:
case glslang::EOpAtomicCompSwap:
+ case glslang::EOpAtomicCounterAdd:
+ case glslang::EOpAtomicCounterSubtract:
+ case glslang::EOpAtomicCounterMin:
+ case glslang::EOpAtomicCounterMax:
+ case glslang::EOpAtomicCounterAnd:
+ case glslang::EOpAtomicCounterOr:
+ case glslang::EOpAtomicCounterXor:
+ case glslang::EOpAtomicCounterExchange:
+ case glslang::EOpAtomicCounterCompSwap:
if (arg == 0)
lvalue = true;
break;
@@ -4619,34 +4642,45 @@
switch (op) {
case glslang::EOpAtomicAdd:
case glslang::EOpImageAtomicAdd:
+ case glslang::EOpAtomicCounterAdd:
opCode = spv::OpAtomicIAdd;
break;
+ case glslang::EOpAtomicCounterSubtract:
+ opCode = spv::OpAtomicISub;
+ break;
case glslang::EOpAtomicMin:
case glslang::EOpImageAtomicMin:
+ case glslang::EOpAtomicCounterMin:
opCode = typeProxy == glslang::EbtUint ? spv::OpAtomicUMin : spv::OpAtomicSMin;
break;
case glslang::EOpAtomicMax:
case glslang::EOpImageAtomicMax:
+ case glslang::EOpAtomicCounterMax:
opCode = typeProxy == glslang::EbtUint ? spv::OpAtomicUMax : spv::OpAtomicSMax;
break;
case glslang::EOpAtomicAnd:
case glslang::EOpImageAtomicAnd:
+ case glslang::EOpAtomicCounterAnd:
opCode = spv::OpAtomicAnd;
break;
case glslang::EOpAtomicOr:
case glslang::EOpImageAtomicOr:
+ case glslang::EOpAtomicCounterOr:
opCode = spv::OpAtomicOr;
break;
case glslang::EOpAtomicXor:
case glslang::EOpImageAtomicXor:
+ case glslang::EOpAtomicCounterXor:
opCode = spv::OpAtomicXor;
break;
case glslang::EOpAtomicExchange:
case glslang::EOpImageAtomicExchange:
+ case glslang::EOpAtomicCounterExchange:
opCode = spv::OpAtomicExchange;
break;
case glslang::EOpAtomicCompSwap:
case glslang::EOpImageAtomicCompSwap:
+ case glslang::EOpAtomicCounterCompSwap:
opCode = spv::OpAtomicCompareExchange;
break;
case glslang::EOpAtomicCounterIncrement:
diff --git a/SPIRV/doc.cpp b/SPIRV/doc.cpp
index fb0cc36..b47fa48 100755
--- a/SPIRV/doc.cpp
+++ b/SPIRV/doc.cpp
@@ -846,6 +846,8 @@
case 5009: return "ImageGatherBiasLodAMD";
#endif
+ case 4445: return "AtomicStorageOps";
+
case 4447: return "SampleMaskPostDepthCoverage";
#ifdef NV_EXTENSIONS
case 5251: return "GeometryShaderPassthroughNV";
diff --git a/Test/450.vert b/Test/450.vert
index 4a376a3..17d1abb 100644
--- a/Test/450.vert
+++ b/Test/450.vert
@@ -22,8 +22,20 @@
struct SS { float f; S s; };
out SS outSS;
+layout(binding = 0) uniform atomic_uint aui;
+uint ui;
+
void foo()
{
SS::f;
+ atomicCounterAdd(aui, ui); // ERROR, need 4.6
+ atomicCounterSubtract(aui, ui); // ERROR, need 4.6
+ atomicCounterMin(aui, ui); // ERROR, need 4.6
+ atomicCounterMax(aui, ui); // ERROR, need 4.6
+ atomicCounterAnd(aui, ui); // ERROR, need 4.6
+ atomicCounterOr(aui, ui); // ERROR, need 4.6
+ atomicCounterXor(aui, ui); // ERROR, need 4.6
+ atomicCounterExchange(aui, ui); // ERROR, need 4.6
+ atomicCounterCompSwap(aui, ui, ui); // ERROR, need 4.6
}
; // ERROR: no extraneous semicolons
diff --git a/Test/baseResults/450.vert.out b/Test/baseResults/450.vert.out
index cd150e3..1005642 100644
--- a/Test/baseResults/450.vert.out
+++ b/Test/baseResults/450.vert.out
@@ -1,9 +1,18 @@
450.vert
ERROR: 0:12: 'out' : cannot be bool
ERROR: 0:13: 'sampler2D' : sampler/image types can only be used in uniform variables or function parameters: outo
-ERROR: 0:27: '::' : not supported
-ERROR: 0:29: 'extraneous semicolon' : not supported for this version or the enabled extensions
-ERROR: 4 compilation errors. No code generated.
+ERROR: 0:30: '::' : not supported
+ERROR: 0:31: 'atomicCounterAdd' : no matching overloaded function found
+ERROR: 0:32: 'atomicCounterSubtract' : no matching overloaded function found
+ERROR: 0:33: 'atomicCounterMin' : no matching overloaded function found
+ERROR: 0:34: 'atomicCounterMax' : no matching overloaded function found
+ERROR: 0:35: 'atomicCounterAnd' : no matching overloaded function found
+ERROR: 0:36: 'atomicCounterOr' : no matching overloaded function found
+ERROR: 0:37: 'atomicCounterXor' : no matching overloaded function found
+ERROR: 0:38: 'atomicCounterExchange' : no matching overloaded function found
+ERROR: 0:39: 'atomicCounterCompSwap' : no matching overloaded function found
+ERROR: 0:41: 'extraneous semicolon' : not supported for this version or the enabled extensions
+ERROR: 13 compilation errors. No code generated.
Shader version: 450
@@ -21,8 +30,27 @@
0:9 2 (const int)
0:9 Constant:
0:9 4.500000
-0:25 Function Definition: foo( ( global void)
-0:25 Function Parameters:
+0:28 Function Definition: foo( ( global void)
+0:28 Function Parameters:
+0:? Sequence
+0:31 Constant:
+0:31 0.000000
+0:32 Constant:
+0:32 0.000000
+0:33 Constant:
+0:33 0.000000
+0:34 Constant:
+0:34 0.000000
+0:35 Constant:
+0:35 0.000000
+0:36 Constant:
+0:36 0.000000
+0:37 Constant:
+0:37 0.000000
+0:38 Constant:
+0:38 0.000000
+0:39 Constant:
+0:39 0.000000
0:? Linker Objects
0:? 'anon@0' ( out block{ out 3-element array of float CullDistance gl_CullDistance})
0:? 'outb' ( smooth out bool)
@@ -34,6 +62,8 @@
0:? 'outsa' ( smooth out 4-element array of structure{ global float f})
0:? 'outSA' ( smooth out structure{ global 4-element array of float f})
0:? 'outSS' ( smooth out structure{ global float f, global structure{ global float f} s})
+0:? 'aui' (layout( binding=0 offset=0) uniform atomic_uint)
+0:? 'ui' ( global uint)
0:? 'gl_VertexID' ( gl_VertexId int VertexId)
0:? 'gl_InstanceID' ( gl_InstanceId int InstanceId)
@@ -67,6 +97,8 @@
0:? 'outsa' ( smooth out 4-element array of structure{ global float f})
0:? 'outSA' ( smooth out structure{ global 4-element array of float f})
0:? 'outSS' ( smooth out structure{ global float f, global structure{ global float f} s})
+0:? 'aui' (layout( binding=0 offset=0) uniform atomic_uint)
+0:? 'ui' ( global uint)
0:? 'gl_VertexID' ( gl_VertexId int VertexId)
0:? 'gl_InstanceID' ( gl_InstanceId int InstanceId)
diff --git a/Test/baseResults/spv.460.frag.out b/Test/baseResults/spv.460.frag.out
new file mode 100755
index 0000000..4e827a0
--- /dev/null
+++ b/Test/baseResults/spv.460.frag.out
@@ -0,0 +1,51 @@
+spv.460.frag
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 32
+
+ Capability Shader
+ Capability AtomicStorage
+ Capability AtomicStorageOps
+ Extension "SPV_KHR_shader_atomic_counter_ops"
+ 1: ExtInstImport "GLSL.std.450"
+ MemoryModel Logical GLSL450
+ EntryPoint Fragment 4 "main"
+ ExecutionMode 4 OriginLowerLeft
+ Source GLSL 460
+ Name 4 "main"
+ Name 8 "aui"
+ Name 10 "ui"
+ Decorate 8(aui) Offset 0
+ Decorate 8(aui) Binding 0
+ 2: TypeVoid
+ 3: TypeFunction 2
+ 6: TypeInt 32 0
+ 7: TypePointer AtomicCounter 6(int)
+ 8(aui): 7(ptr) Variable AtomicCounter
+ 9: TypePointer Private 6(int)
+ 10(ui): 9(ptr) Variable Private
+ 12: 6(int) Constant 1
+ 13: 6(int) Constant 0
+ 4(main): 2 Function None 3
+ 5: Label
+ 11: 6(int) Load 10(ui)
+ 14: 6(int) AtomicIAdd 8(aui) 12 13 11
+ 15: 6(int) Load 10(ui)
+ 16: 6(int) AtomicISub 8(aui) 12 13 15
+ 17: 6(int) Load 10(ui)
+ 18: 6(int) AtomicUMin 8(aui) 12 13 17
+ 19: 6(int) Load 10(ui)
+ 20: 6(int) AtomicUMax 8(aui) 12 13 19
+ 21: 6(int) Load 10(ui)
+ 22: 6(int) AtomicAnd 8(aui) 12 13 21
+ 23: 6(int) Load 10(ui)
+ 24: 6(int) AtomicOr 8(aui) 12 13 23
+ 25: 6(int) Load 10(ui)
+ 26: 6(int) AtomicXor 8(aui) 12 13 25
+ 27: 6(int) Load 10(ui)
+ 28: 6(int) AtomicExchange 8(aui) 12 13 27
+ 29: 6(int) Load 10(ui)
+ 30: 6(int) Load 10(ui)
+ 31: 6(int) AtomicCompareExchange 8(aui) 12 13 13 30 29
+ Return
+ FunctionEnd
diff --git a/Test/spv.460.frag b/Test/spv.460.frag
new file mode 100644
index 0000000..9eb8bf4
--- /dev/null
+++ b/Test/spv.460.frag
@@ -0,0 +1,17 @@
+#version 460 core
+
+layout(binding = 0) uniform atomic_uint aui;
+uint ui;
+
+void main()
+{
+ atomicCounterAdd(aui, ui);
+ atomicCounterSubtract(aui, ui);
+ atomicCounterMin(aui, ui);
+ atomicCounterMax(aui, ui);
+ atomicCounterAnd(aui, ui);
+ atomicCounterOr(aui, ui);
+ atomicCounterXor(aui, ui);
+ atomicCounterExchange(aui, ui);
+ atomicCounterCompSwap(aui, ui, ui);
+}
diff --git a/glslang/Include/intermediate.h b/glslang/Include/intermediate.h
index 0922d12..e289efd 100644
--- a/glslang/Include/intermediate.h
+++ b/glslang/Include/intermediate.h
@@ -420,6 +420,15 @@
EOpAtomicCounterIncrement,
EOpAtomicCounterDecrement,
EOpAtomicCounter,
+ EOpAtomicCounterAdd,
+ EOpAtomicCounterSubtract,
+ EOpAtomicCounterMin,
+ EOpAtomicCounterMax,
+ EOpAtomicCounterAnd,
+ EOpAtomicCounterOr,
+ EOpAtomicCounterXor,
+ EOpAtomicCounterExchange,
+ EOpAtomicCounterCompSwap,
EOpAny,
EOpAll,
diff --git a/glslang/MachineIndependent/Initialize.cpp b/glslang/MachineIndependent/Initialize.cpp
index 5cd167e..921d83a 100644
--- a/glslang/MachineIndependent/Initialize.cpp
+++ b/glslang/MachineIndependent/Initialize.cpp
@@ -1375,9 +1375,23 @@
if ((profile != EEsProfile && version >= 300) ||
(profile == EEsProfile && version >= 310)) {
commonBuiltins.append(
- "uint atomicCounterIncrement(atomic_uint x);"
- "uint atomicCounterDecrement(atomic_uint x);"
- "uint atomicCounter(atomic_uint x);"
+ "uint atomicCounterIncrement(atomic_uint);"
+ "uint atomicCounterDecrement(atomic_uint);"
+ "uint atomicCounter(atomic_uint);"
+
+ "\n");
+ }
+ if (profile != EEsProfile && version >= 460) {
+ commonBuiltins.append(
+ "uint atomicCounterAdd(atomic_uint, uint);"
+ "uint atomicCounterSubtract(atomic_uint, uint);"
+ "uint atomicCounterMin(atomic_uint, uint);"
+ "uint atomicCounterMax(atomic_uint, uint);"
+ "uint atomicCounterAnd(atomic_uint, uint);"
+ "uint atomicCounterOr(atomic_uint, uint);"
+ "uint atomicCounterXor(atomic_uint, uint);"
+ "uint atomicCounterExchange(atomic_uint, uint);"
+ "uint atomicCounterCompSwap(atomic_uint, uint, uint);"
"\n");
}
@@ -5909,6 +5923,18 @@
symbolTable.relateToOperator("atomicCounterDecrement", EOpAtomicCounterDecrement);
symbolTable.relateToOperator("atomicCounter", EOpAtomicCounter);
+ if (profile != EEsProfile && version >= 460) {
+ symbolTable.relateToOperator("atomicCounterAdd", EOpAtomicCounterAdd);
+ symbolTable.relateToOperator("atomicCounterSubtract", EOpAtomicCounterSubtract);
+ symbolTable.relateToOperator("atomicCounterMin", EOpAtomicCounterMin);
+ symbolTable.relateToOperator("atomicCounterMax", EOpAtomicCounterMax);
+ symbolTable.relateToOperator("atomicCounterAnd", EOpAtomicCounterAnd);
+ symbolTable.relateToOperator("atomicCounterOr", EOpAtomicCounterOr);
+ symbolTable.relateToOperator("atomicCounterXor", EOpAtomicCounterXor);
+ symbolTable.relateToOperator("atomicCounterExchange", EOpAtomicCounterExchange);
+ symbolTable.relateToOperator("atomicCounterCompSwap", EOpAtomicCounterCompSwap);
+ }
+
symbolTable.relateToOperator("fma", EOpFma);
symbolTable.relateToOperator("frexp", EOpFrexp);
symbolTable.relateToOperator("ldexp", EOpLdexp);
diff --git a/glslang/MachineIndependent/intermOut.cpp b/glslang/MachineIndependent/intermOut.cpp
index ba7e0f5..479f15d 100644
--- a/glslang/MachineIndependent/intermOut.cpp
+++ b/glslang/MachineIndependent/intermOut.cpp
@@ -682,6 +682,16 @@
case EOpAtomicExchange: out.debug << "AtomicExchange"; break;
case EOpAtomicCompSwap: out.debug << "AtomicCompSwap"; break;
+ case EOpAtomicCounterAdd: out.debug << "AtomicCounterAdd"; break;
+ case EOpAtomicCounterSubtract: out.debug << "AtomicCounterSubtract"; break;
+ case EOpAtomicCounterMin: out.debug << "AtomicCounterMin"; break;
+ case EOpAtomicCounterMax: out.debug << "AtomicCounterMax"; break;
+ case EOpAtomicCounterAnd: out.debug << "AtomicCounterAnd"; break;
+ case EOpAtomicCounterOr: out.debug << "AtomicCounterOr"; break;
+ case EOpAtomicCounterXor: out.debug << "AtomicCounterXor"; break;
+ case EOpAtomicCounterExchange: out.debug << "AtomicCounterExchange"; break;
+ case EOpAtomicCounterCompSwap: out.debug << "AtomicCounterCompSwap"; break;
+
case EOpImageQuerySize: out.debug << "imageQuerySize"; break;
case EOpImageQuerySamples: out.debug << "imageQuerySamples"; break;
case EOpImageLoad: out.debug << "imageLoad"; break;
diff --git a/gtests/Spv.FromFile.cpp b/gtests/Spv.FromFile.cpp
index dfad30c..3a236b7 100644
--- a/gtests/Spv.FromFile.cpp
+++ b/gtests/Spv.FromFile.cpp
@@ -360,6 +360,7 @@
INSTANTIATE_TEST_CASE_P(
Glsl, CompileOpenGLToSpirvTest,
::testing::ValuesIn(std::vector<std::string>({
+ "spv.460.frag",
"spv.atomic.comp",
"spv.glFragColor.frag",
"spv.specConst.vert",