ES31: Add std430 support for OpenGL backend

BUG=angleproject:1920
TEST=angle_unittests

Change-Id: Ie8e171abec053c2c5dca93d6e79db534f74520e7
Reviewed-on: https://chromium-review.googlesource.com/737532
Commit-Queue: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/compiler/translator/BaseTypes.h b/src/compiler/translator/BaseTypes.h
index 470b282..ec0fde2 100644
--- a/src/compiler/translator/BaseTypes.h
+++ b/src/compiler/translator/BaseTypes.h
@@ -721,7 +721,8 @@
     EbsUnspecified,
     EbsShared,
     EbsPacked,
-    EbsStd140
+    EbsStd140,
+    EbsStd430
 };
 
 enum TYuvCscStandardEXT
@@ -970,6 +971,8 @@
             return "packed";
         case EbsStd140:
             return "std140";
+        case EbsStd430:
+            return "std430";
         default:
             UNREACHABLE();
             return "unknown block storage";
diff --git a/src/compiler/translator/CollectVariables.cpp b/src/compiler/translator/CollectVariables.cpp
index 692cf73..51a4145 100644
--- a/src/compiler/translator/CollectVariables.cpp
+++ b/src/compiler/translator/CollectVariables.cpp
@@ -29,7 +29,9 @@
         case EbsShared:
             return BLOCKLAYOUT_SHARED;
         case EbsStd140:
-            return BLOCKLAYOUT_STANDARD;
+            return BLOCKLAYOUT_STD140;
+        case EbsStd430:
+            return BLOCKLAYOUT_STD430;
         default:
             UNREACHABLE();
             return BLOCKLAYOUT_SHARED;
diff --git a/src/compiler/translator/Compiler.cpp b/src/compiler/translator/Compiler.cpp
index ea30da4..30b026f 100644
--- a/src/compiler/translator/Compiler.cpp
+++ b/src/compiler/translator/Compiler.cpp
@@ -1033,7 +1033,7 @@
     for (auto block : uniformBlocks)
     {
         if (!block.staticUse &&
-            (block.layout == sh::BLOCKLAYOUT_STANDARD || block.layout == sh::BLOCKLAYOUT_SHARED))
+            (block.layout == sh::BLOCKLAYOUT_STD140 || block.layout == sh::BLOCKLAYOUT_SHARED))
         {
             list.push_back(block);
         }
diff --git a/src/compiler/translator/OutputGLSLBase.cpp b/src/compiler/translator/OutputGLSLBase.cpp
index 642a371..bc4867a 100644
--- a/src/compiler/translator/OutputGLSLBase.cpp
+++ b/src/compiler/translator/OutputGLSLBase.cpp
@@ -1186,6 +1186,10 @@
             out << "std140";
             break;
 
+        case EbsStd430:
+            out << "std430";
+            break;
+
         default:
             UNREACHABLE();
             break;
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index 43e0cad..13f9354 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -908,6 +908,16 @@
     }
 }
 
+void TParseContext::checkStd430IsForShaderStorageBlock(const TSourceLoc &location,
+                                                       const TLayoutBlockStorage &blockStorage,
+                                                       const TQualifier &qualifier)
+{
+    if (blockStorage == EbsStd430 && qualifier != EvqBuffer)
+    {
+        error(location, "The std430 layout is supported only for shader storage blocks.", "std430");
+    }
+}
+
 void TParseContext::checkOutParameterIsNotOpaqueType(const TSourceLoc &line,
                                                      TQualifier qualifier,
                                                      const TType &type)
@@ -2913,6 +2923,9 @@
 
     checkOffsetIsNotSpecified(typeQualifier.line, layoutQualifier.offset);
 
+    checkStd430IsForShaderStorageBlock(typeQualifier.line, layoutQualifier.blockStorage,
+                                       typeQualifier.qualifier);
+
     if (typeQualifier.qualifier == EvqComputeIn)
     {
         if (mComputeShaderLocalSizeDeclared &&
@@ -3577,6 +3590,8 @@
 
     TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
     checkLocationIsNotSpecified(typeQualifier.line, blockLayoutQualifier);
+    checkStd430IsForShaderStorageBlock(typeQualifier.line, blockLayoutQualifier.blockStorage,
+                                       typeQualifier.qualifier);
 
     if (blockLayoutQualifier.matrixPacking == EmpUnspecified)
     {
@@ -4120,6 +4135,11 @@
         }
         qualifier.blockStorage = EbsPacked;
     }
+    else if (qualifierType == "std430")
+    {
+        checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+        qualifier.blockStorage = EbsStd430;
+    }
     else if (qualifierType == "std140")
     {
         qualifier.blockStorage = EbsStd140;
diff --git a/src/compiler/translator/ParseContext.h b/src/compiler/translator/ParseContext.h
index 4a63c8d..27eb0cc 100644
--- a/src/compiler/translator/ParseContext.h
+++ b/src/compiler/translator/ParseContext.h
@@ -135,6 +135,9 @@
     void checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line, const TPublicType &pType);
     void checkLocationIsNotSpecified(const TSourceLoc &location,
                                      const TLayoutQualifier &layoutQualifier);
+    void checkStd430IsForShaderStorageBlock(const TSourceLoc &location,
+                                            const TLayoutBlockStorage &blockStorage,
+                                            const TQualifier &qualifier);
     void checkIsParameterQualifierValid(const TSourceLoc &line,
                                         const TTypeQualifierBuilder &typeQualifierBuilder,
                                         TType *type);