Merge pull request #2718 from ZhiqianXia/AtomicOpsARB

Support the atomic_counter_xxxARB  built-in functons at #extension GL_ARB_shader_atomic_counter_ops.
diff --git a/Test/atomicCounterARBOps.vert b/Test/atomicCounterARBOps.vert
new file mode 100644
index 0000000..5eb6637
--- /dev/null
+++ b/Test/atomicCounterARBOps.vert
@@ -0,0 +1,28 @@
+#version 450 core
+#extension GL_ARB_shader_atomic_counters: enable
+#extension GL_ARB_shader_atomic_counter_ops:enable
+
+layout(binding = 0) uniform atomic_uint counter;
+
+out highp vec4 vsColor;
+
+void main(){
+    vec4 outColor = vec4(1.0);
+    uint ret;
+
+    ret = atomicCounterAddARB(counter, 4u);
+    ret = atomicCounterSubtractARB(counter, 4u);
+    ret = atomicCounterMinARB(counter, 4u);
+    ret = atomicCounterMaxARB(counter, 4u);
+    ret = atomicCounterAndARB(counter, 4u);
+    ret = atomicCounterOrARB(counter, 4u);
+    ret = atomicCounterXorARB(counter, 4u);
+    ret = atomicCounterExchangeARB(counter, 4u);
+    ret = atomicCounterCompSwapARB(counter, 4u, 4u);
+
+    uint after = atomicCounter(counter);
+    if (after == ret)
+        outColor = vec4(0.0);
+
+    vsColor = outColor;
+}
\ No newline at end of file
diff --git a/Test/baseResults/atomicCounterARBOps.vert.out b/Test/baseResults/atomicCounterARBOps.vert.out
new file mode 100644
index 0000000..ebb4411
--- /dev/null
+++ b/Test/baseResults/atomicCounterARBOps.vert.out
@@ -0,0 +1,201 @@
+atomicCounterARBOps.vert
+Shader version: 450
+Requested GL_ARB_shader_atomic_counter_ops
+Requested GL_ARB_shader_atomic_counters
+0:? Sequence
+0:9  Function Definition: main( ( global void)
+0:9    Function Parameters: 
+0:10    Sequence
+0:10      Sequence
+0:10        move second child to first child ( temp 4-component vector of float)
+0:10          'outColor' ( temp 4-component vector of float)
+0:10          Constant:
+0:10            1.000000
+0:10            1.000000
+0:10            1.000000
+0:10            1.000000
+0:13      move second child to first child ( temp uint)
+0:13        'ret' ( temp uint)
+0:13        AtomicCounterAdd ( global uint)
+0:13          'counter' (layout( binding=0 offset=0) uniform atomic_uint)
+0:13          Constant:
+0:13            4 (const uint)
+0:14      move second child to first child ( temp uint)
+0:14        'ret' ( temp uint)
+0:14        AtomicCounterSubtract ( global uint)
+0:14          'counter' (layout( binding=0 offset=0) uniform atomic_uint)
+0:14          Constant:
+0:14            4 (const uint)
+0:15      move second child to first child ( temp uint)
+0:15        'ret' ( temp uint)
+0:15        AtomicCounterMin ( global uint)
+0:15          'counter' (layout( binding=0 offset=0) uniform atomic_uint)
+0:15          Constant:
+0:15            4 (const uint)
+0:16      move second child to first child ( temp uint)
+0:16        'ret' ( temp uint)
+0:16        AtomicCounterMax ( global uint)
+0:16          'counter' (layout( binding=0 offset=0) uniform atomic_uint)
+0:16          Constant:
+0:16            4 (const uint)
+0:17      move second child to first child ( temp uint)
+0:17        'ret' ( temp uint)
+0:17        AtomicCounterAnd ( global uint)
+0:17          'counter' (layout( binding=0 offset=0) uniform atomic_uint)
+0:17          Constant:
+0:17            4 (const uint)
+0:18      move second child to first child ( temp uint)
+0:18        'ret' ( temp uint)
+0:18        AtomicCounterOr ( global uint)
+0:18          'counter' (layout( binding=0 offset=0) uniform atomic_uint)
+0:18          Constant:
+0:18            4 (const uint)
+0:19      move second child to first child ( temp uint)
+0:19        'ret' ( temp uint)
+0:19        AtomicCounterXor ( global uint)
+0:19          'counter' (layout( binding=0 offset=0) uniform atomic_uint)
+0:19          Constant:
+0:19            4 (const uint)
+0:20      move second child to first child ( temp uint)
+0:20        'ret' ( temp uint)
+0:20        AtomicCounterExchange ( global uint)
+0:20          'counter' (layout( binding=0 offset=0) uniform atomic_uint)
+0:20          Constant:
+0:20            4 (const uint)
+0:21      move second child to first child ( temp uint)
+0:21        'ret' ( temp uint)
+0:21        AtomicCounterCompSwap ( global uint)
+0:21          'counter' (layout( binding=0 offset=0) uniform atomic_uint)
+0:21          Constant:
+0:21            4 (const uint)
+0:21          Constant:
+0:21            4 (const uint)
+0:23      Sequence
+0:23        move second child to first child ( temp uint)
+0:23          'after' ( temp uint)
+0:23          AtomicCounter ( global uint)
+0:23            'counter' (layout( binding=0 offset=0) uniform atomic_uint)
+0:24      Test condition and select ( temp void)
+0:24        Condition
+0:24        Compare Equal ( temp bool)
+0:24          'after' ( temp uint)
+0:24          'ret' ( temp uint)
+0:24        true case
+0:25        move second child to first child ( temp 4-component vector of float)
+0:25          'outColor' ( temp 4-component vector of float)
+0:25          Constant:
+0:25            0.000000
+0:25            0.000000
+0:25            0.000000
+0:25            0.000000
+0:27      move second child to first child ( temp 4-component vector of float)
+0:27        'vsColor' ( smooth out 4-component vector of float)
+0:27        'outColor' ( temp 4-component vector of float)
+0:?   Linker Objects
+0:?     'counter' (layout( binding=0 offset=0) uniform atomic_uint)
+0:?     'vsColor' ( smooth out 4-component vector of float)
+0:?     'gl_VertexID' ( gl_VertexId int VertexId)
+0:?     'gl_InstanceID' ( gl_InstanceId int InstanceId)
+
+
+Linked vertex stage:
+
+
+Shader version: 450
+Requested GL_ARB_shader_atomic_counter_ops
+Requested GL_ARB_shader_atomic_counters
+0:? Sequence
+0:9  Function Definition: main( ( global void)
+0:9    Function Parameters: 
+0:10    Sequence
+0:10      Sequence
+0:10        move second child to first child ( temp 4-component vector of float)
+0:10          'outColor' ( temp 4-component vector of float)
+0:10          Constant:
+0:10            1.000000
+0:10            1.000000
+0:10            1.000000
+0:10            1.000000
+0:13      move second child to first child ( temp uint)
+0:13        'ret' ( temp uint)
+0:13        AtomicCounterAdd ( global uint)
+0:13          'counter' (layout( binding=0 offset=0) uniform atomic_uint)
+0:13          Constant:
+0:13            4 (const uint)
+0:14      move second child to first child ( temp uint)
+0:14        'ret' ( temp uint)
+0:14        AtomicCounterSubtract ( global uint)
+0:14          'counter' (layout( binding=0 offset=0) uniform atomic_uint)
+0:14          Constant:
+0:14            4 (const uint)
+0:15      move second child to first child ( temp uint)
+0:15        'ret' ( temp uint)
+0:15        AtomicCounterMin ( global uint)
+0:15          'counter' (layout( binding=0 offset=0) uniform atomic_uint)
+0:15          Constant:
+0:15            4 (const uint)
+0:16      move second child to first child ( temp uint)
+0:16        'ret' ( temp uint)
+0:16        AtomicCounterMax ( global uint)
+0:16          'counter' (layout( binding=0 offset=0) uniform atomic_uint)
+0:16          Constant:
+0:16            4 (const uint)
+0:17      move second child to first child ( temp uint)
+0:17        'ret' ( temp uint)
+0:17        AtomicCounterAnd ( global uint)
+0:17          'counter' (layout( binding=0 offset=0) uniform atomic_uint)
+0:17          Constant:
+0:17            4 (const uint)
+0:18      move second child to first child ( temp uint)
+0:18        'ret' ( temp uint)
+0:18        AtomicCounterOr ( global uint)
+0:18          'counter' (layout( binding=0 offset=0) uniform atomic_uint)
+0:18          Constant:
+0:18            4 (const uint)
+0:19      move second child to first child ( temp uint)
+0:19        'ret' ( temp uint)
+0:19        AtomicCounterXor ( global uint)
+0:19          'counter' (layout( binding=0 offset=0) uniform atomic_uint)
+0:19          Constant:
+0:19            4 (const uint)
+0:20      move second child to first child ( temp uint)
+0:20        'ret' ( temp uint)
+0:20        AtomicCounterExchange ( global uint)
+0:20          'counter' (layout( binding=0 offset=0) uniform atomic_uint)
+0:20          Constant:
+0:20            4 (const uint)
+0:21      move second child to first child ( temp uint)
+0:21        'ret' ( temp uint)
+0:21        AtomicCounterCompSwap ( global uint)
+0:21          'counter' (layout( binding=0 offset=0) uniform atomic_uint)
+0:21          Constant:
+0:21            4 (const uint)
+0:21          Constant:
+0:21            4 (const uint)
+0:23      Sequence
+0:23        move second child to first child ( temp uint)
+0:23          'after' ( temp uint)
+0:23          AtomicCounter ( global uint)
+0:23            'counter' (layout( binding=0 offset=0) uniform atomic_uint)
+0:24      Test condition and select ( temp void)
+0:24        Condition
+0:24        Compare Equal ( temp bool)
+0:24          'after' ( temp uint)
+0:24          'ret' ( temp uint)
+0:24        true case
+0:25        move second child to first child ( temp 4-component vector of float)
+0:25          'outColor' ( temp 4-component vector of float)
+0:25          Constant:
+0:25            0.000000
+0:25            0.000000
+0:25            0.000000
+0:25            0.000000
+0:27      move second child to first child ( temp 4-component vector of float)
+0:27        'vsColor' ( smooth out 4-component vector of float)
+0:27        'outColor' ( temp 4-component vector of float)
+0:?   Linker Objects
+0:?     'counter' (layout( binding=0 offset=0) uniform atomic_uint)
+0:?     'vsColor' ( smooth out 4-component vector of float)
+0:?     'gl_VertexID' ( gl_VertexId int VertexId)
+0:?     'gl_InstanceID' ( gl_InstanceId int InstanceId)
+
diff --git a/glslang/MachineIndependent/Initialize.cpp b/glslang/MachineIndependent/Initialize.cpp
index 08d0dc7..823406c 100644
--- a/glslang/MachineIndependent/Initialize.cpp
+++ b/glslang/MachineIndependent/Initialize.cpp
@@ -1864,6 +1864,22 @@
 
                 "\n");
         }
+        if (profile != EEsProfile && version == 450) {
+            commonBuiltins.append(
+                "uint atomicCounterAddARB(atomic_uint, uint);"
+                "uint atomicCounterSubtractARB(atomic_uint, uint);"
+                "uint atomicCounterMinARB(atomic_uint, uint);"
+                "uint atomicCounterMaxARB(atomic_uint, uint);"
+                "uint atomicCounterAndARB(atomic_uint, uint);"
+                "uint atomicCounterOrARB(atomic_uint, uint);"
+                "uint atomicCounterXorARB(atomic_uint, uint);"
+                "uint atomicCounterExchangeARB(atomic_uint, uint);"
+                "uint atomicCounterCompSwapARB(atomic_uint, uint, uint);"
+
+                "\n");
+        }
+
+
         if (profile != EEsProfile && version >= 460) {
             commonBuiltins.append(
                 "uint atomicCounterAdd(atomic_uint, uint);"
@@ -8267,6 +8283,19 @@
             symbolTable.setFunctionExtensions("atomicCounter"         , 1, &E_GL_ARB_shader_atomic_counters);
         }
 
+        // E_GL_ARB_shader_atomic_counter_ops
+        if (profile != EEsProfile && version == 450) {
+            symbolTable.setFunctionExtensions("atomicCounterAddARB"     , 1, &E_GL_ARB_shader_atomic_counter_ops);
+            symbolTable.setFunctionExtensions("atomicCounterSubtractARB", 1, &E_GL_ARB_shader_atomic_counter_ops);
+            symbolTable.setFunctionExtensions("atomicCounterMinARB"     , 1, &E_GL_ARB_shader_atomic_counter_ops);
+            symbolTable.setFunctionExtensions("atomicCounterMaxARB"     , 1, &E_GL_ARB_shader_atomic_counter_ops);
+            symbolTable.setFunctionExtensions("atomicCounterAndARB"     , 1, &E_GL_ARB_shader_atomic_counter_ops);
+            symbolTable.setFunctionExtensions("atomicCounterOrARB"      , 1, &E_GL_ARB_shader_atomic_counter_ops);
+            symbolTable.setFunctionExtensions("atomicCounterXorARB"     , 1, &E_GL_ARB_shader_atomic_counter_ops);
+            symbolTable.setFunctionExtensions("atomicCounterExchangeARB", 1, &E_GL_ARB_shader_atomic_counter_ops);
+            symbolTable.setFunctionExtensions("atomicCounterCompSwapARB", 1, &E_GL_ARB_shader_atomic_counter_ops);
+        }
+
         // E_GL_ARB_derivative_control
         if (profile != EEsProfile && version < 450) {
             symbolTable.setFunctionExtensions("dFdxFine",     1, &E_GL_ARB_derivative_control);
@@ -9270,6 +9299,18 @@
     symbolTable.relateToOperator("clockRealtimeEXT",     EOpReadClockDeviceKHR);
     symbolTable.relateToOperator("clockRealtime2x32EXT", EOpReadClockDeviceKHR);
 
+    if (profile != EEsProfile && version == 450) {
+        symbolTable.relateToOperator("atomicCounterAddARB",      EOpAtomicCounterAdd);
+        symbolTable.relateToOperator("atomicCounterSubtractARB", EOpAtomicCounterSubtract);
+        symbolTable.relateToOperator("atomicCounterMinARB",      EOpAtomicCounterMin);
+        symbolTable.relateToOperator("atomicCounterMaxARB",      EOpAtomicCounterMax);
+        symbolTable.relateToOperator("atomicCounterAndARB",      EOpAtomicCounterAnd);
+        symbolTable.relateToOperator("atomicCounterOrARB",       EOpAtomicCounterOr);
+        symbolTable.relateToOperator("atomicCounterXorARB",      EOpAtomicCounterXor);
+        symbolTable.relateToOperator("atomicCounterExchangeARB", EOpAtomicCounterExchange);
+        symbolTable.relateToOperator("atomicCounterCompSwapARB", EOpAtomicCounterCompSwap);
+    }
+
     if (profile != EEsProfile && version >= 460) {
         symbolTable.relateToOperator("atomicCounterAdd",      EOpAtomicCounterAdd);
         symbolTable.relateToOperator("atomicCounterSubtract", EOpAtomicCounterSubtract);
diff --git a/glslang/MachineIndependent/Versions.cpp b/glslang/MachineIndependent/Versions.cpp
index 832fb7a..097ee84 100644
--- a/glslang/MachineIndependent/Versions.cpp
+++ b/glslang/MachineIndependent/Versions.cpp
@@ -200,6 +200,7 @@
     extensionBehavior[E_GL_ARB_explicit_uniform_location]    = EBhDisable;
     extensionBehavior[E_GL_ARB_shader_image_load_store]      = EBhDisable;
     extensionBehavior[E_GL_ARB_shader_atomic_counters]       = EBhDisable;
+    extensionBehavior[E_GL_ARB_shader_atomic_counter_ops]    = EBhDisable;
     extensionBehavior[E_GL_ARB_shader_draw_parameters]       = EBhDisable;
     extensionBehavior[E_GL_ARB_shader_group_vote]            = EBhDisable;
     extensionBehavior[E_GL_ARB_derivative_control]           = EBhDisable;
diff --git a/glslang/MachineIndependent/Versions.h b/glslang/MachineIndependent/Versions.h
index 878c6f8..949a7a1 100644
--- a/glslang/MachineIndependent/Versions.h
+++ b/glslang/MachineIndependent/Versions.h
@@ -136,6 +136,7 @@
 const char* const E_GL_ARB_explicit_uniform_location    = "GL_ARB_explicit_uniform_location";
 const char* const E_GL_ARB_shader_image_load_store      = "GL_ARB_shader_image_load_store";
 const char* const E_GL_ARB_shader_atomic_counters       = "GL_ARB_shader_atomic_counters";
+const char* const E_GL_ARB_shader_atomic_counter_ops    = "GL_ARB_shader_atomic_counter_ops";
 const char* const E_GL_ARB_shader_draw_parameters       = "GL_ARB_shader_draw_parameters";
 const char* const E_GL_ARB_shader_group_vote            = "GL_ARB_shader_group_vote";
 const char* const E_GL_ARB_derivative_control           = "GL_ARB_derivative_control";
diff --git a/gtests/AST.FromFile.cpp b/gtests/AST.FromFile.cpp
index b63825b..6e7a659 100644
--- a/gtests/AST.FromFile.cpp
+++ b/gtests/AST.FromFile.cpp
@@ -284,6 +284,7 @@
         "textureoffset_sampler2darrayshadow.vert",
         "atomicAdd.comp",
         "GL_ARB_gpu_shader5.u2i.vert",
+        "atomicCounterARBOps.vert"
     })),
     FileNameAsCustomTestSuffix
 );