Turn on ESSL 3.1 for most features:
 - images: load/store, memory qualifiers
 - buffer blocks
 - compute shaders
 - atomic counters
 - texture gather
 - SSO
 - uniform locations
 - all the numeric-based version # comparisons


git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@27710 e7fa87d3-cd2b-0410-9028-fcbf551c1848
diff --git a/Test/300.vert b/Test/300.vert
index 11a0078..5abf450 100644
--- a/Test/300.vert
+++ b/Test/300.vert
@@ -168,3 +168,7 @@
 layout(std140) Binst;    // ERROR
 layout(std140) Bblock;   // ERROR
 layout(std140) Bfoo;     // ERROR
+
+struct SNA {
+    int a[];             // ERROR
+};
diff --git a/Test/310.comp b/Test/310.comp
new file mode 100644
index 0000000..2f172fe
--- /dev/null
+++ b/Test/310.comp
@@ -0,0 +1,141 @@
+#version 310 es

+

+layout(local_size_x = 2) in;

+layout(local_size_x = 16) in;     // ERROR, changing

+layout(local_size_z = 4096) in;   // ERROR, too large

+layout(local_size_x = 2) in;

+

+const int total = gl_MaxComputeWorkGroupCount.y 

+                + gl_MaxComputeUniformComponents

+                + gl_MaxComputeTextureImageUnits

+                + gl_MaxComputeImageUniforms

+                + gl_MaxComputeAtomicCounters

+                + gl_MaxComputeAtomicCounterBuffers;

+

+buffer ShaderStorageBlock

+{

+    int value;

+    float values[];

+};

+

+buffer InvalidShaderStorageBlock

+{

+    float values[];  // ERROR

+    int value;

+} invalid;

+

+void main()

+{

+    barrier();

+    memoryBarrier();

+    memoryBarrierAtomicCounter();

+    memoryBarrierBuffer();

+    memoryBarrierShared();

+    memoryBarrierImage();

+    groupMemoryBarrier();

+    value = int(values[gl_LocalInvocationIndex]);

+}

+

+layout(location = 2) in vec3 v3;      // ERROR

+in float f;                           // ERROR

+out float fo;                         // ERROR

+

+shared vec4 s;

+layout(location = 2) shared vec4 sl;  // ERROR

+shared float fs = 4.2;                // ERROR

+

+layout(local_size_x = 2, local_size_y = 3, local_size_z = 4) out;  // ERROR

+

+int arrX[gl_WorkGroupSize.x];

+int arrY[gl_WorkGroupSize.y];

+int arrZ[gl_WorkGroupSize.z];

+

+readonly buffer roblock

+{

+    int value;

+    float values[];

+} ro;

+

+void foo()

+{

+    ro.values[2] = 4.7;        // ERROR, readonly

+    ro.values.length();

+    ++s;

+}

+

+buffer vec4 v;  // ERROR

+

+uniform usampler2D us2dbad;  // ERROR, default precision

+

+precision highp usampler2D;

+precision highp iimage2DArray;

+precision highp iimage2D;

+

+uniform usampler2D us2d;

+

+uniform iimage2DArray ii2dabad;  // ERROR, not writeonly

+uniform writeonly iimage2DArray ii2da;

+

+layout(r32i) uniform iimage2D iimg2D;

+layout(rgba32i) uniform iimage2D iimg2Drgba;

+layout(rgba32f) uniform image2D img2Drgba;

+layout(r32ui) uniform uimage2D uimg2D;

+

+void qux()

+{

+    int i = 4;

+    imageAtomicCompSwap(iimg2D, ivec2(i,i), i, i);// ERROR no longer in 310

+    imageAtomicAdd(uimg2D, ivec2(i,i), uint(i));  // ERROR no longer in 310

+    imageAtomicMin(iimg2Drgba, ivec2(i,i), i);    // ERROR no longer in 310  // ERROR iimg2Drgba does not have r32i layout

+    imageAtomicMax(img2Drgba, ivec2(i,i), i);     // ERROR no longer in 310  // ERROR img2Drgba is not integer image

+    ivec4 pos = imageLoad(iimg2D, ivec2(i,i));

+    imageStore(ii2da, ivec3(i,i,i), ivec4(0));

+    imageLoad(img2Drgba, ivec2(i,i));

+    imageLoad(ii2da, ivec3(i,i,i));       // ERROR, drops writeonly

+}

+

+volatile float vol; // ERROR, not an image

+readonly int vol2;  // ERROR, not an image

+

+void passr(coherent readonly iimage2D image)

+{

+}

+

+layout(r32i) coherent readonly uniform iimage2D qualim1;

+layout(r32i) coherent restrict readonly uniform iimage2D qualim2;

+

+void passrc()

+{

+    passr(qualim1);

+    passr(qualim2);   // ERROR, drops restrict

+    passr(iimg2D);

+}

+

+layout(rg8i) uniform uimage2D i1bad;     // ERROR, type mismatch

+layout(rgba32i) uniform image2D i2bad;   // ERROR, type mismatch

+layout(rgba32f) uniform uimage2D i3bad;  // ERROR, type mismatch

+layout(r8_snorm) uniform iimage2D i4bad; // ERROR, type mismatch

+layout(rgba32ui) uniform iimage2D i5bad; // ERROR, type mismatch

+layout(r8ui) uniform iimage2D i6bad;     // ERROR, type mismatch

+

+layout(binding = 0) uniform atomic_uint counter;

+

+uint func(atomic_uint c)

+{

+    return atomicCounterIncrement(c);

+}

+

+uint func2(out atomic_uint c) // ERROR, output

+{

+    return counter;           // ERROR, type mismatch

+    return atomicCounter(counter);

+}

+

+void mainAC()

+{

+     atomic_uint non_uniform_counter; // ERROR

+     uint val = atomicCounter(counter);

+     atomicCounterDecrement(counter);

+}

+

+layout(binding = 1) uniform mediump atomic_uint counterBad;  // ERROR, not highp

diff --git a/Test/310.frag b/Test/310.frag
new file mode 100644
index 0000000..7399159
--- /dev/null
+++ b/Test/310.frag
@@ -0,0 +1,46 @@
+#version 310 es

+

+precision mediump float;

+precision highp usampler2D;

+precision highp sampler2D;

+precision highp isampler2DArray;

+

+layout(origin_upper_left, pixel_center_integer) in vec4 gl_FragCoord;  // ERROR, not supported

+

+layout(location = 2) in vec3 v3;

+layout(location = 2) in mat4 yi;  // ERROR, locations conflict with xi

+

+uniform sampler2D arrayedSampler[5];

+uniform usampler2D usamp2d;

+uniform usampler2DRect samp2dr;      // ERROR, reserved

+uniform isampler2DArray isamp2DA;

+

+in vec2 c2D;

+uniform int i;

+

+void main()

+{

+    vec4 v = texture(arrayedSampler[i], c2D);  // ERROR

+

+    ivec2 offsets[4];

+    const ivec2 constOffsets[4] = ivec2[4](ivec2(1,2), ivec2(3,4), ivec2(15,16), ivec2(-2,0));

+    uvec4 uv4 = textureGatherOffsets(samp2dr, c2D, offsets, 2);  // ERROR, not supported

+    vec4 v4 = textureGather(arrayedSampler[0], c2D);

+    ivec4 iv4 = textureGatherOffset(isamp2DA, vec3(0.1), ivec2(1), 3);

+    iv4 = textureGatherOffset(isamp2DA, vec3(0.1), ivec2(1), i);  // ERROR, last argument not const

+    iv4 = textureGatherOffset(isamp2DA, vec3(0.1), ivec2(1), 4);  // ERROR, last argument out of range

+    iv4 = textureGatherOffset(isamp2DA, vec3(0.1), ivec2(1), 1+2);

+    iv4 = textureGatherOffset(isamp2DA, vec3(0.1), ivec2(i));

+}

+

+out vec4 outp;

+

+void foo23()

+{

+    const ivec2[3] offsets = ivec2[3](ivec2(1,2), ivec2(3,4), ivec2(15,16));

+

+    textureProjGradOffset(usamp2d, outp, vec2(0.0), vec2(0.0), ivec2(c2D));     // ERROR, offset not constant

+    textureProjGradOffset(usamp2d, outp, vec2(0.0), vec2(0.0), offsets[1]);

+    textureProjGradOffset(usamp2d, outp, vec2(0.0), vec2(0.0), offsets[2]);     // ERROR, offset out of range

+    textureProjGradOffset(usamp2d, outp, vec2(0.0), vec2(0.0), ivec2(-10, 20)); // ERROR, offset out of range

+}

diff --git a/Test/310.vert b/Test/310.vert
new file mode 100644
index 0000000..8f0dee4
--- /dev/null
+++ b/Test/310.vert
@@ -0,0 +1,10 @@
+#version 310 es

+

+shared vec4 s;   // ERROR

+layout(local_size_x = 2) out;  // ERROR

+buffer vec4 v;  // ERROR

+

+layout(location = 2) uniform mat4 x;

+layout(location = 3) uniform mat4 y;

+layout(location = 2) out mat4 xi;

+layout(location = 3) out mat4 yi;  // ERROR, locations conflict with xi

diff --git a/Test/430.vert b/Test/430.vert
index 4cc8d29..d1d31f4 100644
--- a/Test/430.vert
+++ b/Test/430.vert
@@ -143,7 +143,7 @@
     layout(xfb_stride=80, xfb_buffer=1, xfb_offset=64) vec4 bbv2;

 } bbinst5;

 

-shared vec4 sharedv;

+shared vec4 sharedv;                // ERROR

 

 void fooBarrier()

 {

diff --git a/Test/atomic_uint.frag b/Test/atomic_uint.frag
index 972cf28..a837150 100644
--- a/Test/atomic_uint.frag
+++ b/Test/atomic_uint.frag
@@ -9,7 +9,8 @@
 
 uint func2(out atomic_uint c) // ERROR
 {
-    return counter;
+    return counter;           // ERROR, type mismatch
+    return atomicCounter(counter);
 }
 
 void main()
diff --git a/Test/baseResults/300.frag.out b/Test/baseResults/300.frag.out
index e0fda14..43fbe09 100644
--- a/Test/baseResults/300.frag.out
+++ b/Test/baseResults/300.frag.out
@@ -19,11 +19,11 @@
 ERROR: 0:85: 'double vector' : not supported with this profile: es

 ERROR: 0:86: 'dvec4' : Reserved word. 

 ERROR: 0:86: 'double vector' : not supported with this profile: es

-ERROR: 0:101: 'arrays of arrays' : not supported with this profile: es

-ERROR: 0:102: 'arrays of arrays' : not supported with this profile: es

-ERROR: 0:102: 'arrays of arrays' : not supported with this profile: es

-ERROR: 0:103: 'arrays of arrays' : not supported with this profile: es

-ERROR: 0:100: 'arrays of arrays' : not supported with this profile: es

+ERROR: 0:101: 'arrays of arrays' : not supported for this version or the enabled extensions 

+ERROR: 0:102: 'arrays of arrays' : not supported for this version or the enabled extensions 

+ERROR: 0:102: 'arrays of arrays' : not supported for this version or the enabled extensions 

+ERROR: 0:103: 'arrays of arrays' : not supported for this version or the enabled extensions 

+ERROR: 0:100: 'arrays of arrays' : not supported for this version or the enabled extensions 

 ERROR: 0:111: 'variable indexing fragment shader ouput array' : not supported with this profile: es

 ERROR: 0:119: '==' : can't use with samplers or structs containing samplers 

 ERROR: 0:120: '!=' : can't use with samplers or structs containing samplers 

diff --git a/Test/baseResults/300.vert.out b/Test/baseResults/300.vert.out
index d9d8c2f..87f630e 100644
--- a/Test/baseResults/300.vert.out
+++ b/Test/baseResults/300.vert.out
@@ -16,8 +16,8 @@
 ERROR: 0:56: '#error' : GL_ES is set  

 ERROR: 0:62: '' : array size required 

 ERROR: 0:63: '' : array size required 

-ERROR: 0:65: '' : array size required 

 ERROR: 0:64: '' : array size required 

+ERROR: 0:65: 'implicitly-sized array in a block' : not supported with this profile: es

 ERROR: 0:67: '' : array size required 

 ERROR: 0:76: 'invariant' : cannot change qualification after use 

 ERROR: 0:78: 'invariant' : can only apply to an output: invIn

@@ -38,7 +38,8 @@
 ERROR: 0:168: 'Binst' : cannot add storage, auxiliary, memory, interpolation, layout, or precision qualifier to an existing variable 

 ERROR: 0:169: 'Bblock' : cannot add storage, auxiliary, memory, interpolation, layout, or precision qualifier to an existing variable 

 ERROR: 0:170: 'Bfoo' : cannot add storage, auxiliary, memory, interpolation, layout, or precision qualifier to an existing variable 

-ERROR: 39 compilation errors.  No code generated.

+ERROR: 0:173: '' : array size required 

+ERROR: 40 compilation errors.  No code generated.

 

 

 Shader version: 300

diff --git a/Test/baseResults/300layout.frag.out b/Test/baseResults/300layout.frag.out
index a7a7da8..21f12dd 100644
--- a/Test/baseResults/300layout.frag.out
+++ b/Test/baseResults/300layout.frag.out
@@ -1,8 +1,9 @@
 300layout.frag

 ERROR: 0:4: 'location qualifier on input' : not supported in this stage: fragment

+ERROR: 0:4: 'location qualifier on input' : not supported for this version or the enabled extensions 

 ERROR: 0:18: 'location' : overlapping use of location 41

 ERROR: 0:19: 'location' : overlapping use of location 40

-ERROR: 3 compilation errors.  No code generated.

+ERROR: 4 compilation errors.  No code generated.

 

 

 Shader version: 300

diff --git a/Test/baseResults/300layout.vert.out b/Test/baseResults/300layout.vert.out
index b5b1e26..f64db3b 100644
--- a/Test/baseResults/300layout.vert.out
+++ b/Test/baseResults/300layout.vert.out
@@ -13,11 +13,12 @@
 ERROR: 0:31: 'T3' : nameless block contains a member that already has a name at global scope 

 ERROR: 0:38: 'output block' : not supported with this profile: es

 ERROR: 0:42: 'location qualifier on output' : not supported in this stage: vertex

-ERROR: 0:50: 'shared' : not supported with this profile: es

+ERROR: 0:42: 'location qualifier on output' : not supported for this version or the enabled extensions 

+ERROR: 0:50: 'shared' : not supported for this version or the enabled extensions 

 ERROR: 0:50: 'shared' : not supported in this stage: vertex

 ERROR: 0:54: 'layout' : cannot specify packing on a variable declaration 

 ERROR: 0:57: 'location' : overlapping use of location 40

-ERROR: 18 compilation errors.  No code generated.

+ERROR: 19 compilation errors.  No code generated.

 

 

 Shader version: 300

diff --git a/Test/baseResults/atomic_uint.frag.out b/Test/baseResults/atomic_uint.frag.out
index 246cf8b..248df2e 100644
--- a/Test/baseResults/atomic_uint.frag.out
+++ b/Test/baseResults/atomic_uint.frag.out
@@ -2,7 +2,7 @@
 Warning, version 420 is not yet complete; most version-specific features are present, but some are missing.

 ERROR: 0:10: 'atomic_uint' : samplers and atomic_uints cannot be output parameters 

 ERROR: 0:12: 'return' : type does not match, or is not convertible to, the function's return type 

-ERROR: 0:17: 'atomic_uint' : atomic_uints can only be used in uniform variables or function parameters: non_uniform_counter

+ERROR: 0:18: 'atomic_uint' : atomic_uints can only be used in uniform variables or function parameters: non_uniform_counter

 ERROR: 3 compilation errors.  No code generated.

 

 

@@ -21,16 +21,19 @@
 0:12    Sequence

 0:12      Branch: Return with expression

 0:12        'counter' (layout(binding=0 ) uniform atomic_uint)

-0:15  Function Definition: main( (void)

-0:15    Function Parameters: 

+0:13      Branch: Return with expression

+0:13        Function Call: atomicCounter(au1; (uint)

+0:13          'counter' (layout(binding=0 ) uniform atomic_uint)

+0:16  Function Definition: main( (void)

+0:16    Function Parameters: 

 0:?     Sequence

-0:18      Sequence

-0:18        move second child to first child (uint)

-0:18          'val' (uint)

-0:18          Function Call: atomicCounter(au1; (uint)

-0:18            'counter' (layout(binding=0 ) uniform atomic_uint)

-0:19      Function Call: atomicCounterDecrement(au1; (uint)

-0:19        'counter' (layout(binding=0 ) uniform atomic_uint)

+0:19      Sequence

+0:19        move second child to first child (uint)

+0:19          'val' (uint)

+0:19          Function Call: atomicCounter(au1; (uint)

+0:19            'counter' (layout(binding=0 ) uniform atomic_uint)

+0:20      Function Call: atomicCounterDecrement(au1; (uint)

+0:20        'counter' (layout(binding=0 ) uniform atomic_uint)

 0:?   Linker Objects

 0:?     'counter' (layout(binding=0 ) uniform atomic_uint)

 

@@ -53,16 +56,19 @@
 0:12    Sequence

 0:12      Branch: Return with expression

 0:12        'counter' (layout(binding=0 ) uniform atomic_uint)

-0:15  Function Definition: main( (void)

-0:15    Function Parameters: 

+0:13      Branch: Return with expression

+0:13        Function Call: atomicCounter(au1; (uint)

+0:13          'counter' (layout(binding=0 ) uniform atomic_uint)

+0:16  Function Definition: main( (void)

+0:16    Function Parameters: 

 0:?     Sequence

-0:18      Sequence

-0:18        move second child to first child (uint)

-0:18          'val' (uint)

-0:18          Function Call: atomicCounter(au1; (uint)

-0:18            'counter' (layout(binding=0 ) uniform atomic_uint)

-0:19      Function Call: atomicCounterDecrement(au1; (uint)

-0:19        'counter' (layout(binding=0 ) uniform atomic_uint)

+0:19      Sequence

+0:19        move second child to first child (uint)

+0:19          'val' (uint)

+0:19          Function Call: atomicCounter(au1; (uint)

+0:19            'counter' (layout(binding=0 ) uniform atomic_uint)

+0:20      Function Call: atomicCounterDecrement(au1; (uint)

+0:20        'counter' (layout(binding=0 ) uniform atomic_uint)

 0:?   Linker Objects

 0:?     'counter' (layout(binding=0 ) uniform atomic_uint)

 

diff --git a/Test/testlist b/Test/testlist
index 286c1fd..ba21ea1 100644
--- a/Test/testlist
+++ b/Test/testlist
@@ -36,6 +36,9 @@
 300layout.frag
 300operations.frag
 300block.frag
+310.comp
+310.vert
+310.frag
 330.frag
 330comp.frag
 constErrors.frag
diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h
index bc89e1f..40c6b45 100644
--- a/glslang/Include/Types.h
+++ b/glslang/Include/Types.h
@@ -248,20 +248,23 @@
     // Float image
     ElfRgba32f,
     ElfRgba16f,
+    ElfR32f,
+    ElfRgba8,
+    ElfRgba8Snorm,
+
+    ElfEsFloatGuard,    // to help with comparisons
+
     ElfRg32f,
     ElfRg16f,
     ElfR11fG11fB10f,
-    ElfR32f,
     ElfR16f,
     ElfRgba16,
     ElfRgb10A2,
-    ElfRgba8,
     ElfRg16,
     ElfRg8,
     ElfR16,
     ElfR8,
     ElfRgba16Snorm,
-    ElfRgba8Snorm,
     ElfRg16Snorm,
     ElfRg8Snorm,
     ElfR16Snorm,
@@ -273,10 +276,13 @@
     ElfRgba32i,
     ElfRgba16i,
     ElfRgba8i,
+    ElfR32i,
+
+    ElfEsIntGuard,     // to help with comparisons
+
     ElfRg32i,
     ElfRg16i,
     ElfRg8i,
-    ElfR32i,
     ElfR16i,
     ElfR8i,
 
@@ -286,10 +292,13 @@
     ElfRgba32ui,
     ElfRgba16ui,
     ElfRgba8ui,
+    ElfR32ui,
+
+    ElfEsUintGuard,    // to help with comparisons
+
     ElfRg32ui,
     ElfRg16ui,
     ElfRg8ui,
-    ElfR32ui,
     ElfR16ui,
     ElfR8ui,
 
diff --git a/glslang/MachineIndependent/Initialize.cpp b/glslang/MachineIndependent/Initialize.cpp
index 73466e7..42e5c7f 100644
--- a/glslang/MachineIndependent/Initialize.cpp
+++ b/glslang/MachineIndependent/Initialize.cpp
@@ -743,7 +743,8 @@
     //
     // Atomic counter functions.
     //
-    if (profile != EEsProfile && version >= 420) {
+    if ((profile != EEsProfile && version >= 420) ||
+        (profile == EEsProfile && version >= 310)) {
         commonBuiltins.append(
             "uint atomicCounterIncrement(atomic_uint x);"
             "uint atomicCounterDecrement(atomic_uint x);"
@@ -841,38 +842,37 @@
             
             "\n");
     }
-    if (profile != EEsProfile) {
-        //============================================================================
-        //
-        // Prototypes for all control functions.
-        //
-        //============================================================================
 
-        if (version >= 150)
-            stageBuiltins[EShLangTessControl].append(
-                "void barrier();"
-                );
-        if (version >= 430)
-            stageBuiltins[EShLangCompute].append(
-                "void barrier();"
-                );
-
-        if (version >= 130)
-            commonBuiltins.append(
-                "void memoryBarrier();"
-                );
-        if (version >= 430) {
-            commonBuiltins.append(
-                "void memoryBarrierAtomicCounter();"
-                "void memoryBarrierBuffer();"
-                "void memoryBarrierImage();"
-                );
-            stageBuiltins[EShLangCompute].append(
-                "void memoryBarrierShared();"
-                "void groupMemoryBarrier();"
-                );
-        }
+    //============================================================================
+    //
+    // Prototypes for all control functions.
+    //
+    //============================================================================
+    bool esBarrier = (profile == EEsProfile && version >= 310);
+    if (profile != EEsProfile && version >= 150)
+        stageBuiltins[EShLangTessControl].append(
+            "void barrier();"
+            );
+    if ((profile != EEsProfile && version >= 430) || esBarrier)
+        stageBuiltins[EShLangCompute].append(
+            "void barrier();"
+            );
+    if ((profile != EEsProfile && version >= 130) || esBarrier)
+        commonBuiltins.append(
+            "void memoryBarrier();"
+            );
+    if ((profile != EEsProfile && version >= 430) || esBarrier) {
+        commonBuiltins.append(
+            "void memoryBarrierAtomicCounter();"
+            "void memoryBarrierBuffer();"
+            "void memoryBarrierImage();"
+            );
+        stageBuiltins[EShLangCompute].append(
+            "void memoryBarrierShared();"
+            "void groupMemoryBarrier();"
+            );
     }
+
     //============================================================================
     //
     // Prototypes for built-in functions seen by fragment shaders only.
@@ -1088,7 +1088,8 @@
     //
     //============================================================================
 
-    if (version >= 430) {
+    if (profile != EEsProfile && version >= 430 ||
+        profile == EEsProfile && version >= 310) {
         stageBuiltins[EShLangCompute].append(
             "in uvec3 gl_NumWorkGroups;"
             "const uvec3 gl_WorkGroupSize = uvec3(1,1,1);"
@@ -1276,11 +1277,11 @@
             "out vec4 gl_ClipVertex;"
             );
 
-        if (version >= 400)
+        if (version >= 400 && profile != EEsProfile)
             stageBuiltins[EShLangGeometry].append(
             "in int gl_InvocationID;"
             );
-        if (version >= 410)
+        if (version >= 410 && profile != EEsProfile)
             stageBuiltins[EShLangGeometry].append(
             "out int gl_ViewportIndex;"
             );
@@ -1434,6 +1435,11 @@
                 "flat in int gl_Layer;"
                 "flat in int gl_ViewportIndex;"
                 );
+
+        if (version >= 450)
+            stageBuiltins[EShLangFragment].append(
+                "bool gl_HelperInvocation;"     // needs qualifier fixed later
+                );
     } else {
         // ES profile
 
@@ -1444,13 +1450,18 @@
                 "mediump vec4 gl_FragColor;"    // needs qualifier fixed later
                 "mediump vec2 gl_PointCoord;"   // needs qualifier fixed later
                 );
-        else if (version == 300)
+        else if (version >= 300) {
             stageBuiltins[EShLangFragment].append(
                 "highp   vec4  gl_FragCoord;"    // needs qualifier fixed later
                 "        bool  gl_FrontFacing;"  // needs qualifier fixed later
                 "mediump vec2  gl_PointCoord;"   // needs qualifier fixed later
                 "highp   float gl_FragDepth;"    // needs qualifier fixed later
                 );
+            if (version >= 310)
+                stageBuiltins[EShLangFragment].append(
+                        "bool  gl_HelperInvocation;"  // needs qualifier fixed later
+                    );
+        }
         stageBuiltins[EShLangFragment].append(
             "highp float gl_FragDepthEXT;"       // GL_EXT_frag_depth
             );
@@ -1554,7 +1565,7 @@
     // textureSize
     //
 
-    if (version < 430 && sampler.image)
+    if (sampler.image && ((profile == EEsProfile && version < 310) || (profile != EEsProfile && version < 430)))
         return;
 
     if (profile == EEsProfile)
@@ -1607,40 +1618,42 @@
     commonBuiltins.append(prefixes[sampler.type]);
     commonBuiltins.append("vec4);\n");
 
-    if (sampler.type == EbtInt || sampler.type == EbtUint) {
-        const char* dataType = sampler.type == EbtInt ? "int" : "uint";
+    if (profile != EEsProfile) {
+        if (sampler.type == EbtInt || sampler.type == EbtUint) {
+            const char* dataType = sampler.type == EbtInt ? "int" : "uint";
 
-        const int numBuiltins = 7;
+            const int numBuiltins = 7;
 
-        static const char* atomicFunc[numBuiltins] = {
-            " imageAtomicAdd(",
-            " imageAtomicMin(",
-            " imageAtomicMax(",
-            " imageAtomicAnd(",
-            " imageAtomicOr(",
-            " imageAtomicXor(",
-            " imageAtomicExchange("
-        }; 
+            static const char* atomicFunc[numBuiltins] = {
+                " imageAtomicAdd(",
+                " imageAtomicMin(",
+                " imageAtomicMax(",
+                " imageAtomicAnd(",
+                " imageAtomicOr(",
+                " imageAtomicXor(",
+                " imageAtomicExchange("
+            }; 
 
-        for (size_t i = 0; i < numBuiltins; ++i) {
+            for (size_t i = 0; i < numBuiltins; ++i) {
+                commonBuiltins.append(dataType);
+                commonBuiltins.append(atomicFunc[i]);
+                if (version >= 450)
+                    commonBuiltins.append("coherent ");
+                commonBuiltins.append(imageParams);
+                commonBuiltins.append(", ");
+                commonBuiltins.append(dataType);
+                commonBuiltins.append(");\n");
+            }
+
             commonBuiltins.append(dataType);
-            commonBuiltins.append(atomicFunc[i]);
-            if (version >= 450)
-                commonBuiltins.append("coherent ");
+            commonBuiltins.append(" imageAtomicCompSwap(");
             commonBuiltins.append(imageParams);
             commonBuiltins.append(", ");
             commonBuiltins.append(dataType);
+            commonBuiltins.append(", ");
+            commonBuiltins.append(dataType);
             commonBuiltins.append(");\n");
         }
-
-        commonBuiltins.append(dataType);
-        commonBuiltins.append(" imageAtomicCompSwap(");
-        commonBuiltins.append(imageParams);
-        commonBuiltins.append(", ");
-        commonBuiltins.append(dataType);
-        commonBuiltins.append(", ");
-        commonBuiltins.append(dataType);
-        commonBuiltins.append(");\n");
     }
 }
 
@@ -1848,6 +1861,9 @@
 
     for (int offset = 0; offset < 3; ++offset) { // loop over three forms of offset in the call name:  none, Offset, and Offsets
 
+        if (profile == EEsProfile && offset == 2)
+            continue;
+
         for (int comp = 0; comp < 2; ++comp) { // loop over presence of comp argument
 
             if (comp > 0 && sampler.shadow)
@@ -2156,24 +2172,6 @@
             s.append(builtInConstant);
         }
 
-        // atomic counters
-        if (version >= 420) {
-            //snprintf(builtInConstant, maxSize, "const int gl_MaxVertexAtomicCounters = %d;", resources.);
-            //snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlAtomicCounters = %d;", resources.);
-            //snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationAtomicCounters = %d;", resources.);
-            //snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryAtomicCounters = %d;", resources.);
-            //snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentAtomicCounters = %d;", resources.);
-            //snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedAtomicCounters = %d;", resources.);
-            //snprintf(builtInConstant, maxSize, "const int gl_MaxAtomicCounterBindings = %d;", resources.);
-            //snprintf(builtInConstant, maxSize, "const int gl_MaxVertexAtomicCounterBuffers = %d;", resources.);
-            //snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlAtomicCounterBuffers = %d;", resources.);
-            //snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationAtomicCounterBuffers = %d;", resources.);
-            //snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryAtomicCounterBuffers = %d;", resources.);
-            //snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentAtomicCounterBuffers = %d;", resources.);
-            //snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedAtomicCounterBuffers = %d;", resources.);
-            //snprintf(builtInConstant, maxSize, "const int gl_MaxAtomicCounterBufferSize = %d;", resources.);
-        }
-
         // images
         if (version >= 130) {
             snprintf(builtInConstant, maxSize, "const int gl_MaxImageUnits = %d;", resources.maxImageUnits);
@@ -2198,29 +2196,6 @@
             s.append(builtInConstant);
         }
 
-        // compute
-        if (version >= 430) {
-            snprintf(builtInConstant, maxSize, "const ivec3 gl_MaxComputeWorkGroupCount = {%d,%d,%d};", resources.maxComputeWorkGroupCountX,
-                                                                                                        resources.maxComputeWorkGroupCountY,
-                                                                                                        resources.maxComputeWorkGroupCountZ);                
-            s.append(builtInConstant);
-            snprintf(builtInConstant, maxSize, "const ivec3 gl_MaxComputeWorkGroupSize = {%d,%d,%d};", resources.maxComputeWorkGroupSizeX,
-                                                                                                        resources.maxComputeWorkGroupSizeY,
-                                                                                                        resources.maxComputeWorkGroupSizeZ);
-            s.append(builtInConstant);
-
-            snprintf(builtInConstant, maxSize, "const int gl_MaxComputeUniformComponents = %d;", resources.maxComputeUniformComponents);
-            s.append(builtInConstant);
-            snprintf(builtInConstant, maxSize, "const int gl_MaxComputeTextureImageUnits = %d;", resources.maxComputeTextureImageUnits);
-            s.append(builtInConstant);
-            snprintf(builtInConstant, maxSize, "const int gl_MaxComputeImageUniforms = %d;", resources.maxComputeImageUniforms);
-            s.append(builtInConstant);
-            snprintf(builtInConstant, maxSize, "const int gl_MaxComputeAtomicCounters = %d;", resources.maxComputeAtomicCounters);
-            s.append(builtInConstant);
-            snprintf(builtInConstant, maxSize, "const int gl_MaxComputeAtomicCounterBuffers = %d;", resources.maxComputeAtomicCounterBuffers);
-            s.append(builtInConstant);
-        }
-
         // enhanced layouts
         if (version >= 430) {
             snprintf(builtInConstant, maxSize, "const int gl_MaxTransformFeedbackBuffers = %d;", resources.maxTransformFeedbackBuffers);
@@ -2230,6 +2205,50 @@
         }
     }
 
+    // TODO: atomic counters 
+    if (profile == EEsProfile && version >= 310 || profile != EEsProfile && version >= 420) {
+        //snprintf(builtInConstant, maxSize, "const int gl_MaxVertexAtomicCounters = %d;", resources.);
+        //snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentAtomicCounters = %d;", resources.);
+        //snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedAtomicCounters = %d;", resources.);
+        //snprintf(builtInConstant, maxSize, "const int gl_MaxAtomicCounterBindings = %d;", resources.);
+        //snprintf(builtInConstant, maxSize, "const int gl_MaxVertexAtomicCounterBuffers = %d;", resources.);
+        //snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentAtomicCounterBuffers = %d;", resources.);
+        //snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedAtomicCounterBuffers = %d;", resources.);
+        //snprintf(builtInConstant, maxSize, "const int gl_MaxAtomicCounterBufferSize = %d;", resources.);
+    }
+    if (profile != EEsProfile && version >= 420) {
+        //snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlAtomicCounters = %d;", resources.);
+        //snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationAtomicCounters = %d;", resources.);
+        //snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryAtomicCounters = %d;", resources.);
+        //snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlAtomicCounterBuffers = %d;", resources.);
+        //snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationAtomicCounterBuffers = %d;", resources.);
+        //snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryAtomicCounterBuffers = %d;", resources.);
+    }
+
+
+    // compute
+    if ((profile == EEsProfile && version >= 310) || (profile != EEsProfile && version >= 430)) {
+        snprintf(builtInConstant, maxSize, "const ivec3 gl_MaxComputeWorkGroupCount = ivec3(%d,%d,%d);", resources.maxComputeWorkGroupCountX,
+                                                                                                    resources.maxComputeWorkGroupCountY,
+                                                                                                    resources.maxComputeWorkGroupCountZ);                
+        s.append(builtInConstant);
+        snprintf(builtInConstant, maxSize, "const ivec3 gl_MaxComputeWorkGroupSize = ivec3(%d,%d,%d);", resources.maxComputeWorkGroupSizeX,
+                                                                                                    resources.maxComputeWorkGroupSizeY,
+                                                                                                    resources.maxComputeWorkGroupSizeZ);
+        s.append(builtInConstant);
+
+        snprintf(builtInConstant, maxSize, "const int gl_MaxComputeUniformComponents = %d;", resources.maxComputeUniformComponents);
+        s.append(builtInConstant);
+        snprintf(builtInConstant, maxSize, "const int gl_MaxComputeTextureImageUnits = %d;", resources.maxComputeTextureImageUnits);
+        s.append(builtInConstant);
+        snprintf(builtInConstant, maxSize, "const int gl_MaxComputeImageUniforms = %d;", resources.maxComputeImageUniforms);
+        s.append(builtInConstant);
+        snprintf(builtInConstant, maxSize, "const int gl_MaxComputeAtomicCounters = %d;", resources.maxComputeAtomicCounters);
+        s.append(builtInConstant);
+        snprintf(builtInConstant, maxSize, "const int gl_MaxComputeAtomicCounterBuffers = %d;", resources.maxComputeAtomicCounterBuffers);
+        s.append(builtInConstant);
+    }
+
     s.append("\n");
 }
 
@@ -2284,12 +2303,13 @@
         break;
 
     case EShLangFragment:
-        SpecialQualifier("gl_FrontFacing",  EvqFace, symbolTable);
-        SpecialQualifier("gl_FragCoord",    EvqFragCoord, symbolTable);
-        SpecialQualifier("gl_PointCoord",   EvqPointCoord, symbolTable);
-        SpecialQualifier("gl_FragColor",    EvqFragColor, symbolTable);
-        SpecialQualifier("gl_FragDepth",    EvqFragDepth, symbolTable);
-        SpecialQualifier("gl_FragDepthEXT", EvqFragDepth, symbolTable);
+        SpecialQualifier("gl_FrontFacing",      EvqFace, symbolTable);
+        SpecialQualifier("gl_FragCoord",        EvqFragCoord, symbolTable);
+        SpecialQualifier("gl_PointCoord",       EvqPointCoord, symbolTable);
+        SpecialQualifier("gl_FragColor",        EvqFragColor, symbolTable);
+        SpecialQualifier("gl_FragDepth",        EvqFragDepth, symbolTable);
+        SpecialQualifier("gl_FragDepthEXT",     EvqFragDepth, symbolTable);
+        SpecialQualifier("gl_HelperInvocation", EvqIn, symbolTable);
         if (version == 100) {
             symbolTable.setFunctionExtensions("dFdx",   1, &GL_OES_standard_derivatives);
             symbolTable.setFunctionExtensions("dFdy",   1, &GL_OES_standard_derivatives);
@@ -2339,7 +2359,7 @@
         }
 
         // GL_ARB_shader_image_load_store
-        if (version < 420)
+        if (profile != EEsProfile && version < 420)
             symbolTable.setFunctionExtensions("memoryBarrier", 1, &GL_ARB_shader_image_load_store);
         // All the image access functions are protected by checks on the type of the first argument.
 
@@ -2495,7 +2515,7 @@
 //
 void IdentifyBuiltIns(int version, EProfile profile, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources)
 {
-    if (version >= 430 && version < 440) {
+    if (profile != EEsProfile && version >= 430 && version < 440) {
         symbolTable.setVariableExtensions("gl_MaxTransformFeedbackBuffers", 1, &GL_ARB_enhanced_layouts);
         symbolTable.setVariableExtensions("gl_MaxTransformFeedbackInterleavedComponents", 1, &GL_ARB_enhanced_layouts);
     }
diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp
index efc5d93..df0f34a 100644
--- a/glslang/MachineIndependent/ParseHelper.cpp
+++ b/glslang/MachineIndependent/ParseHelper.cpp
@@ -82,15 +82,16 @@
         case EShLangFragment:
             defaultPrecision[EbtInt] = EpqMedium;
             defaultPrecision[EbtUint] = EpqMedium;
-            defaultPrecision[EbtSampler] = EpqLow;
             break;
         default:
             defaultPrecision[EbtInt] = EpqHigh;
             defaultPrecision[EbtUint] = EpqHigh;
             defaultPrecision[EbtFloat] = EpqHigh;
-            defaultPrecision[EbtSampler] = EpqLow;
             break;
         }
+
+        defaultPrecision[EbtSampler] = EpqLow;
+        defaultPrecision[EbtAtomicUint] = EpqHigh;
     }
 
     globalUniformDefaults.clear();
@@ -1216,7 +1217,7 @@
         if (fnCandidate.getName().compare(0, 13, "textureGather") == 0) {
             TString featureString = fnCandidate.getName() + "(...)";
             const char* feature = featureString.c_str();
-            requireProfile(loc, ~EEsProfile, feature);
+            profileRequires(loc, EEsProfile, 310, 0, feature);
 
             int compArg = -1;  // track which argument, if any, is the constant component argument
             if (fnCandidate.getName().compare("textureGatherOffset") == 0) {
@@ -2067,7 +2068,9 @@
         error(loc, "can only have one interpolation qualifier (flat, smooth, noperspective)", "", "");
 
     // Ordering
-    if (! force && version < 420 && ! extensionsTurnedOn(1, &GL_ARB_shading_language_420pack)) {
+    if (! force && ((profile != EEsProfile && version < 420) || 
+                     profile == EEsProfile && version < 310)
+                && ! extensionsTurnedOn(1, &GL_ARB_shading_language_420pack)) {
         // non-function parameters
         if (src.invariant && (dst.isInterpolation() || dst.isAuxiliary() || dst.storage != EvqTemporary || dst.precision != EpqNone))
             error(loc, "invariant qualifier must appear first", "", "");
@@ -2173,7 +2176,10 @@
     if (profile != EEsProfile || parsingBuiltins)
         return;
 
-    if (publicType.basicType == EbtFloat || publicType.basicType == EbtUint || publicType.basicType == EbtInt || publicType.basicType == EbtSampler) {
+    if (publicType.basicType == EbtAtomicUint && publicType.qualifier.precision != EpqNone && publicType.qualifier.precision != EpqHigh)
+        error(loc, "atomic counters can only be highp", "atomic_uint", "");
+
+    if (publicType.basicType == EbtFloat || publicType.basicType == EbtUint || publicType.basicType == EbtInt || publicType.basicType == EbtSampler || publicType.basicType == EbtAtomicUint) {
         if (publicType.qualifier.precision == EpqNone) {
             if (messages & EShMsgRelaxedErrors)
                 warn(loc, "type requires declaration of default precision qualifier", TType::getBasicString(publicType.basicType), "substituting 'mediump'");
@@ -2262,10 +2268,21 @@
     }
 }
 
+void TParseContext::structArrayCheck(TSourceLoc loc, TType* type)
+{
+    const TTypeList& structure = *type->getStruct();
+    for (int m = 0; m < (int)structure.size(); ++m) {
+        const TType& member = *structure[m].type;
+        if (member.isArray() && ! member.isExplicitlySizedArray())
+            arraySizeRequiredCheck(structure[m].loc, 0);
+    }
+}
+
 void TParseContext::arrayDimError(TSourceLoc loc)
 {
-    requireProfile(loc, ECoreProfile | ECompatibilityProfile, "arrays of arrays");
+    requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, "arrays of arrays");
     profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, 0, "arrays of arrays");
+    profileRequires(loc, EEsProfile, 310, 0, "arrays of arrays");
 }
 
 void TParseContext::arrayDimCheck(TSourceLoc loc, TArraySizes* sizes1, TArraySizes* sizes2)
@@ -2955,15 +2972,20 @@
         return;
     }
     if (id == TQualifier::getLayoutPackingString(ElpStd430)) {
-        requireProfile(loc, ECoreProfile | ECompatibilityProfile, "std430");
+        requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, "std430");
         profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, 0, "std430");
+        profileRequires(loc, EEsProfile, 310, 0, "std430");
         publicType.qualifier.layoutPacking = ElpStd430;
         return;
     }
     for (TLayoutFormat format = (TLayoutFormat)(ElfNone + 1); format < ElfCount; format = (TLayoutFormat)(format + 1)) {
         if (id == TQualifier::getLayoutFormatString(format)) {
-            requireProfile(loc, ENoProfile | ECoreProfile | ECompatibilityProfile, "image load store");
+            if ((format > ElfEsFloatGuard && format < ElfFloatGuard) ||
+                (format > ElfEsIntGuard && format < ElfIntGuard) ||
+                (format > ElfEsUintGuard && format < ElfCount))
+                requireProfile(loc, ENoProfile | ECoreProfile | ECompatibilityProfile, "image load-store format");
             profileRequires(loc, ENoProfile | ECoreProfile | ECompatibilityProfile, 420, GL_ARB_shader_image_load_store, "image load store");
+            profileRequires(loc, EEsProfile, 310, GL_ARB_shader_image_load_store, "image load store");
             publicType.qualifier.layoutFormat = format;
             return;
         }
@@ -3097,8 +3119,9 @@
     
     if (id == "offset") {
         const char* feature = "uniform buffer-member offset";
-        requireProfile(loc, ECoreProfile | ECompatibilityProfile, feature);
+        requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, feature);
         profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, GL_ARB_enhanced_layouts, feature);
+        profileRequires(loc, EEsProfile, 310, 0, feature);
         publicType.qualifier.layoutOffset = value;
         return;
     } else if (id == "align") {
@@ -3121,8 +3144,8 @@
             publicType.qualifier.layoutLocation = value;
         return;
     } else if (id == "binding") {
-        requireProfile(loc, ~EEsProfile, "binding");
         profileRequires(loc, ~EEsProfile, 420, GL_ARB_shading_language_420pack, "binding");
+        profileRequires(loc, EEsProfile, 310, 0, "binding");
         if ((unsigned int)value >= TQualifier::layoutBindingEnd)
             error(loc, "binding is too large", id.c_str(), "");
         else
@@ -3460,35 +3483,44 @@
         case EvqVaryingIn:
         {
             const char* feature = "location qualifier on input";
-            if (profile == EEsProfile)
+            if (profile == EEsProfile && version < 310)
                 requireStage(loc, EShLangVertex, feature);
-            requireStage(loc, (EShLanguageMask)~EShLangComputeMask, feature);
+            else
+                requireStage(loc, (EShLanguageMask)~EShLangComputeMask, feature);
             if (language == EShLangVertex) {
                 const char* exts[2] = { GL_ARB_separate_shader_objects, GL_ARB_explicit_attrib_location };
                 profileRequires(loc, ~EEsProfile, 330, 2, exts, feature);
-            } else
+                profileRequires(loc, EEsProfile, 300, 0, feature);
+            } else {
                 profileRequires(loc, ~EEsProfile, 410, GL_ARB_separate_shader_objects, feature);
+                profileRequires(loc, EEsProfile, 310, 0, feature);
+            }
             break;
         }
         case EvqVaryingOut:
         {
             const char* feature = "location qualifier on output";
-            if (profile == EEsProfile)
+            if (profile == EEsProfile && version < 310)
                 requireStage(loc, EShLangFragment, feature);
-            requireStage(loc, (EShLanguageMask)~EShLangComputeMask, feature);
+            else
+                requireStage(loc, (EShLanguageMask)~EShLangComputeMask, feature);
             if (language == EShLangFragment) {
                 const char* exts[2] = { GL_ARB_separate_shader_objects, GL_ARB_explicit_attrib_location };
                 profileRequires(loc, ~EEsProfile, 330, 2, exts, feature);
-            } else
+                profileRequires(loc, EEsProfile, 300, 0, feature);
+            } else {
                 profileRequires(loc, ~EEsProfile, 410, GL_ARB_separate_shader_objects, feature);
+                profileRequires(loc, EEsProfile, 310, 0, feature);
+            }
             break;
         }
         case EvqUniform:
         case EvqBuffer:
         {
             const char* feature = "location qualifier on uniform or buffer";
-            requireProfile(loc, ECoreProfile | ECompatibilityProfile, feature);
+            requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, feature);
             profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, 0, feature);
+            profileRequires(loc, EEsProfile, 310, 0, feature);
             break;
         }
         default:
@@ -4155,8 +4187,9 @@
         profileRequires(loc, ENoProfile, 140, 0, "uniform block");
         break;
     case EvqBuffer:
-        requireProfile(loc, ECoreProfile | ECompatibilityProfile, "buffer block");
+        requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, "buffer block");
         profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, 0, "buffer block");
+        profileRequires(loc, EEsProfile, 310, 0, "buffer block");
         break;
     case EvqVaryingIn:
         requireProfile(loc, ~EEsProfile, "input block");
@@ -4186,6 +4219,8 @@
             error(memberLoc, "member of uniform or buffer block cannot have an auxiliary or interpolation qualifier", memberType.getFieldName().c_str(), "");
         if (memberType.isRuntimeSizedArray() && member < typeList.size() - 1)
             error(memberLoc, "only the last member of a buffer block can be run-time sized", memberType.getFieldName().c_str(), "");
+        if (memberType.isImplicitlySizedArray())
+            requireProfile(memberLoc, ~EEsProfile, "implicitly-sized array in a block");
 
         TBasicType basicType = memberType.getBasicType();
         if (basicType == EbtSampler)
diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h
index 2c36c2e..b129e60 100644
--- a/glslang/MachineIndependent/ParseHelper.h
+++ b/glslang/MachineIndependent/ParseHelper.h
@@ -117,6 +117,7 @@
     void arraySizeCheck(TSourceLoc, TIntermTyped* expr, int& size);
     bool arrayQualifierError(TSourceLoc, const TQualifier&);
     void arraySizeRequiredCheck(TSourceLoc, int size);
+    void structArrayCheck(TSourceLoc, TType* structure);
     void arrayDimError(TSourceLoc);
     void arrayDimCheck(TSourceLoc, TArraySizes* sizes1, TArraySizes* sizes2);
     void arrayDimCheck(TSourceLoc, const TType*, TArraySizes*);
diff --git a/glslang/MachineIndependent/Scan.cpp b/glslang/MachineIndependent/Scan.cpp
index a7a72e2..1a459ba 100644
--- a/glslang/MachineIndependent/Scan.cpp
+++ b/glslang/MachineIndependent/Scan.cpp
@@ -668,18 +668,25 @@
         return keyword;
 
     case BUFFER:
-        if (parseContext.version < 430)
+        if ((parseContext.profile == EEsProfile && parseContext.version < 310) || 
+            (parseContext.profile != EEsProfile && parseContext.version < 430))
             return identifierOrType();
         return keyword;
 
     case ATOMIC_UINT:
-        return es30ReservedFromGLSL(420);
+        if (parseContext.profile == EEsProfile && parseContext.version >= 310)
+            return keyword;
+        else
+            return es30ReservedFromGLSL(420);
 
     case COHERENT:
     case RESTRICT:
     case READONLY:
     case WRITEONLY:
-        return es30ReservedFromGLSL(parseContext.extensionsTurnedOn(1, &GL_ARB_shader_image_load_store) ? 130 : 420);
+        if (parseContext.profile == EEsProfile && parseContext.version >= 310)
+            return keyword;
+        else
+            return es30ReservedFromGLSL(parseContext.extensionsTurnedOn(1, &GL_ARB_shader_image_load_store) ? 130 : 420);
 
     case VOLATILE:
         if (! parseContext.symbolTable.atBuiltInLevel() && (parseContext.profile == EEsProfile || (parseContext.version < 420 && ! parseContext.extensionsTurnedOn(1, &GL_ARB_shader_image_load_store))))
@@ -743,28 +750,30 @@
     case IMAGE1D:
     case IIMAGE1D:
     case UIMAGE1D:
+    case IMAGE1DARRAY:
+    case IIMAGE1DARRAY:
+    case UIMAGE1DARRAY:
+    case IMAGE2DRECT:
+    case IIMAGE2DRECT:
+    case UIMAGE2DRECT:
+    case IMAGEBUFFER:
+    case IIMAGEBUFFER:
+    case UIMAGEBUFFER:
+        return firstGenerationImage(false);
+
     case IMAGE2D:
     case IIMAGE2D:
     case UIMAGE2D:
     case IMAGE3D:
     case IIMAGE3D:
     case UIMAGE3D:
-    case IMAGE2DRECT:
-    case IIMAGE2DRECT:
-    case UIMAGE2DRECT:
     case IMAGECUBE:
     case IIMAGECUBE:
     case UIMAGECUBE:
-    case IMAGEBUFFER:
-    case IIMAGEBUFFER:
-    case UIMAGEBUFFER:
-    case IMAGE1DARRAY:
-    case IIMAGE1DARRAY:
-    case UIMAGE1DARRAY:
     case IMAGE2DARRAY:
     case IIMAGE2DARRAY:
     case UIMAGE2DARRAY:
-        return firstGenerationImage();
+        return firstGenerationImage(true);
 
     case IMAGECUBEARRAY:
     case IIMAGECUBEARRAY:
@@ -1068,11 +1077,13 @@
     return identifierOrType();
 }
 
-int TScanContext::firstGenerationImage()
+int TScanContext::firstGenerationImage(bool inEs310)
 {
     afterType = true;
 
-    if (parseContext.symbolTable.atBuiltInLevel() || (parseContext.profile != EEsProfile && (parseContext.version >= 420 || parseContext.extensionsTurnedOn(1, &GL_ARB_shader_image_load_store))))
+    if (parseContext.symbolTable.atBuiltInLevel() || 
+        (parseContext.profile != EEsProfile && (parseContext.version >= 420 || parseContext.extensionsTurnedOn(1, &GL_ARB_shader_image_load_store))) ||                                                     
+        (inEs310 && parseContext.profile == EEsProfile && parseContext.version >= 310))
         return keyword;
 
     if ((parseContext.profile == EEsProfile && parseContext.version >= 300) ||
diff --git a/glslang/MachineIndependent/ScanContext.h b/glslang/MachineIndependent/ScanContext.h
index cf2ad2a..bb8c42b 100644
--- a/glslang/MachineIndependent/ScanContext.h
+++ b/glslang/MachineIndependent/ScanContext.h
@@ -64,7 +64,7 @@
     int precisionKeyword();
     int matNxM();
     int dMat();
-    int firstGenerationImage();
+    int firstGenerationImage(bool inEs310);
     int secondGenerationImage();
 
     TParseContext& parseContext;
diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp
index b7c89f8..4d3f224 100644
--- a/glslang/MachineIndependent/ShaderLang.cpp
+++ b/glslang/MachineIndependent/ShaderLang.cpp
@@ -78,11 +78,13 @@
         case 420: return 10;
         case 430: return 11;
         case 440: return 12;
+        case 310: return 13;
+        case 450: return 14;
         default:       // |
             return  0; // |
         }              // |
 }                      // V
-const int VersionCount = 13;  // number of case statements above
+const int VersionCount = 15;  // number of case statements above
 
 int MapProfileToIndex(EProfile profile)
 {
@@ -197,7 +199,8 @@
     }
     if (profile != EEsProfile && version >= 150)
         InitializeStageSymbolTable(builtIns, version, profile, EShLangGeometry, infoSink, commonTable, symbolTables);
-    if (profile != EEsProfile && version >= 430)
+    if ((profile != EEsProfile && version >= 430) ||
+        (profile == EEsProfile && version >= 310))
         InitializeStageSymbolTable(builtIns, version, profile, EShLangCompute, infoSink, commonTable, symbolTables);
 
     return true;
@@ -303,9 +306,9 @@
 
     // Get a good profile...
     if (profile == ENoProfile) {
-        if (version == 300) {
+        if (version == 300 || version == 310) {
             correct = false;
-            infoSink.info.message(EPrefixError, "#version: version 300 requires specifying the 'es' profile");
+            infoSink.info.message(EPrefixError, "#version: versions 300 and 310 require specifying the 'es' profile");
             profile = EEsProfile;
         } else if (version == 100)
             profile = EEsProfile;
@@ -322,16 +325,16 @@
                 profile = EEsProfile;
             else
                 profile = ENoProfile;
-        } else if (version == 300) {
+        } else if (version == 300 || version == 310) {
             if (profile != EEsProfile) {
                 correct = false;
-                infoSink.info.message(EPrefixError, "#version: version 300 supports only the es profile");
+                infoSink.info.message(EPrefixError, "#version: versions 300 and 310 support only the es profile");
             }
             profile = EEsProfile;
         } else {
             if (profile == EEsProfile) {
                 correct = false;
-                infoSink.info.message(EPrefixError, "#version: only version 300 supports the es profile");
+                infoSink.info.message(EPrefixError, "#version: only version 300 and 310 support the es profile");
                 if (version >= FirstProfileVersion)
                     profile = ECoreProfile;
                 else
@@ -361,10 +364,11 @@
         }
         break;
     case EShLangCompute:
-        if (version < 430 || (profile != ECoreProfile && profile != ECompatibilityProfile)) {
+        if ((profile == EEsProfile && version < 310) ||
+            (profile != EEsProfile && version < 430)) {
             correct = false;
-            infoSink.info.message(EPrefixError, "#version: compute shaders require non-es profile and version 430 or above");
-            version = 430;
+            infoSink.info.message(EPrefixError, "#version: compute shaders require es profile with version 310 or above, or non-es profile with version 430 or above");
+            version = profile == EEsProfile ? 310 : 430;
             profile = ECoreProfile;
         }
         break;
@@ -395,9 +399,21 @@
         // versions are complete
         break;
 
-    default:
+    case 310:
+    case 330:
+    case 400:
+    case 410:
+    case 420:
+    case 430:
+    case 440:
+    case 450:
         infoSink.info << "Warning, version " << version << " is not yet complete; most version-specific features are present, but some are missing.\n";
         break;
+
+    default:
+        infoSink.info << "Warning, version " << version << " is unknown.\n";
+        break;
+
     }
 
     return correct;
diff --git a/glslang/MachineIndependent/glslang.y b/glslang/MachineIndependent/glslang.y
index e34231c..c71c6e2 100644
--- a/glslang/MachineIndependent/glslang.y
+++ b/glslang/MachineIndependent/glslang.y
@@ -1216,8 +1216,8 @@
         $$.qualifier.storage = EvqBuffer;

     }

     | SHARED {

-        parseContext.requireProfile($1.loc, ~EEsProfile, "shared");

-        parseContext.profileRequires($1.loc, ECoreProfile, 430, 0, "shared");

+        parseContext.profileRequires($1.loc, ECoreProfile | ECompatibilityProfile, 430, 0, "shared");

+        parseContext.profileRequires($1.loc, EEsProfile, 310, 0, "shared");

         parseContext.requireStage($1.loc, EShLangCompute, "shared");

         $$.init($1.loc);

         $$.qualifier.storage = EvqShared;

@@ -1964,6 +1964,7 @@
 struct_specifier

     : STRUCT IDENTIFIER LEFT_BRACE { parseContext.nestedStructCheck($1.loc); } struct_declaration_list RIGHT_BRACE {

         TType* structure = new TType($5, *$2.string);

+        parseContext.structArrayCheck($2.loc, structure);

         TVariable* userTypeDef = new TVariable($2.string, *structure, true);

         if (! parseContext.symbolTable.insert(*userTypeDef))

             parseContext.error($2.loc, "redefinition", $2.string->c_str(), "struct");

@@ -2055,8 +2056,6 @@
         $$.type->setFieldName(*$1.string);

     }

     | IDENTIFIER array_specifier {        

-        if (parseContext.profile == EEsProfile)

-            parseContext.arraySizeRequiredCheck($2.loc, $2.arraySizes->getSize());

         parseContext.arrayDimCheck($1.loc, $2.arraySizes, 0);

 

         $$.type = new TType(EbtVoid);