Add support for barriers in the compiler

The patch adds support for barriers in vertex, fragment and compute
shaders.

BUG:angleproject:1442
TEST:angle_unittests

Change-Id: Ic85c3337911851a93a3f56bd935774181600eddd
Reviewed-on: https://chromium-review.googlesource.com/380641
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/compiler/translator/Initialize.cpp b/src/compiler/translator/Initialize.cpp
index c787883..9f288db 100644
--- a/src/compiler/translator/Initialize.cpp
+++ b/src/compiler/translator/Initialize.cpp
@@ -589,6 +589,25 @@
     symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int3, "imageSize", gimage2DArray);
     symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int2, "imageSize", gimageCube);
 
+    symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpMemoryBarrier, voidType,
+                                                  "memoryBarrier");
+    symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpMemoryBarrierAtomicCounter,
+                                                  voidType, "memoryBarrierAtomicCounter");
+    symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpMemoryBarrierBuffer,
+                                                  voidType, "memoryBarrierBuffer");
+    symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpMemoryBarrierImage, voidType,
+                                                  "memoryBarrierImage");
+
+    if (type == GL_COMPUTE_SHADER)
+    {
+        symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpBarrier, voidType,
+                                                      "barrier");
+        symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpMemoryBarrierShared,
+                                                      voidType, "memoryBarrierShared");
+        symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpGroupMemoryBarrier,
+                                                      voidType, "groupMemoryBarrier");
+    }
+
     //
     // Depth range in window coordinates
     //
diff --git a/src/compiler/translator/Operator.cpp b/src/compiler/translator/Operator.cpp
index 2b8435d..2f91f6f 100644
--- a/src/compiler/translator/Operator.cpp
+++ b/src/compiler/translator/Operator.cpp
@@ -333,7 +333,20 @@
             return "^=";
         case EOpBitwiseOrAssign:
             return "|=";
-
+        case EOpBarrier:
+            return "barrier";
+        case EOpMemoryBarrier:
+            return "memoryBarrier";
+        case EOpMemoryBarrierAtomicCounter:
+            return "memoryBarrierAtomicCounter";
+        case EOpMemoryBarrierBuffer:
+            return "memoryBarrierBuffer";
+        case EOpMemoryBarrierImage:
+            return "memoryBarrierImage";
+        case EOpMemoryBarrierShared:
+            return "memoryBarrierShared";
+        case EOpGroupMemoryBarrier:
+            return "groupMemoryBarrier";
         default:
             break;
     }
diff --git a/src/compiler/translator/Operator.h b/src/compiler/translator/Operator.h
index a9959ce..288d6cf 100644
--- a/src/compiler/translator/Operator.h
+++ b/src/compiler/translator/Operator.h
@@ -216,7 +216,16 @@
     EOpBitShiftRightAssign,
     EOpBitwiseAndAssign,
     EOpBitwiseXorAssign,
-    EOpBitwiseOrAssign
+    EOpBitwiseOrAssign,
+
+    //  barriers
+    EOpBarrier,
+    EOpMemoryBarrier,
+    EOpMemoryBarrierAtomicCounter,
+    EOpMemoryBarrierBuffer,
+    EOpMemoryBarrierImage,
+    EOpMemoryBarrierShared,
+    EOpGroupMemoryBarrier
 };
 
 // Returns the string corresponding to the operator in GLSL
diff --git a/src/compiler/translator/OutputGLSLBase.cpp b/src/compiler/translator/OutputGLSLBase.cpp
index 839ceb6..9256faa 100644
--- a/src/compiler/translator/OutputGLSLBase.cpp
+++ b/src/compiler/translator/OutputGLSLBase.cpp
@@ -1113,7 +1113,27 @@
         case EOpMul:
             writeBuiltInFunctionTriplet(visit, "matrixCompMult(", useEmulatedFunction);
             break;
-
+        case EOpBarrier:
+            writeBuiltInFunctionTriplet(visit, "barrier(", useEmulatedFunction);
+            break;
+        case EOpMemoryBarrier:
+            writeBuiltInFunctionTriplet(visit, "memoryBarrier(", useEmulatedFunction);
+            break;
+        case EOpMemoryBarrierAtomicCounter:
+            writeBuiltInFunctionTriplet(visit, "memoryBarrierAtomicCounter(", useEmulatedFunction);
+            break;
+        case EOpMemoryBarrierBuffer:
+            writeBuiltInFunctionTriplet(visit, "memoryBarrierBuffer(", useEmulatedFunction);
+            break;
+        case EOpMemoryBarrierImage:
+            writeBuiltInFunctionTriplet(visit, "memoryBarrierImage(", useEmulatedFunction);
+            break;
+        case EOpMemoryBarrierShared:
+            writeBuiltInFunctionTriplet(visit, "memoryBarrierShared(", useEmulatedFunction);
+            break;
+        case EOpGroupMemoryBarrier:
+            writeBuiltInFunctionTriplet(visit, "groupMemoryBarrier(", useEmulatedFunction);
+            break;
         default:
             UNREACHABLE();
     }
diff --git a/src/compiler/translator/SymbolTable.cpp b/src/compiler/translator/SymbolTable.cpp
index ad4484a..857873c 100644
--- a/src/compiler/translator/SymbolTable.cpp
+++ b/src/compiler/translator/SymbolTable.cpp
@@ -382,6 +382,15 @@
     }
 }
 
+void TSymbolTable::insertBuiltInFunctionNoParameters(ESymbolLevel level,
+                                                     TOperator op,
+                                                     const TType *rvalue,
+                                                     const char *name)
+{
+    insertUnmangledBuiltInName(name, level);
+    insert(level, new TFunction(NewPoolTString(name), rvalue, op));
+}
+
 TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const
 {
     if (!SupportsPrecision(type))
diff --git a/src/compiler/translator/SymbolTable.h b/src/compiler/translator/SymbolTable.h
index d0792c5..1fba212 100644
--- a/src/compiler/translator/SymbolTable.h
+++ b/src/compiler/translator/SymbolTable.h
@@ -405,6 +405,11 @@
         insertBuiltIn(level, op, "", rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5);
     }
 
+    void insertBuiltInFunctionNoParameters(ESymbolLevel level,
+                                           TOperator op,
+                                           const TType *rvalue,
+                                           const char *name);
+
     TSymbol *find(const TString &name,
                   int shaderVersion,
                   bool *builtIn   = NULL,