Turn on ESSL 3.1 for most features:
authorJohn Kessenich <cepheus@frii.com>
Tue, 12 Aug 2014 22:07:22 +0000 (22:07 +0000)
committerJohn Kessenich <cepheus@frii.com>
Tue, 12 Aug 2014 22:07:22 +0000 (22:07 +0000)
 - 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

20 files changed:
Test/300.vert
Test/310.comp [new file with mode: 0644]
Test/310.frag [new file with mode: 0644]
Test/310.vert [new file with mode: 0644]
Test/430.vert
Test/atomic_uint.frag
Test/baseResults/300.frag.out
Test/baseResults/300.vert.out
Test/baseResults/300layout.frag.out
Test/baseResults/300layout.vert.out
Test/baseResults/atomic_uint.frag.out
Test/testlist
glslang/Include/Types.h
glslang/MachineIndependent/Initialize.cpp
glslang/MachineIndependent/ParseHelper.cpp
glslang/MachineIndependent/ParseHelper.h
glslang/MachineIndependent/Scan.cpp
glslang/MachineIndependent/ScanContext.h
glslang/MachineIndependent/ShaderLang.cpp
glslang/MachineIndependent/glslang.y

index 11a0078..5abf450 100644 (file)
@@ -168,3 +168,7 @@ int Bfoo;
 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 (file)
index 0000000..2f172fe
--- /dev/null
@@ -0,0 +1,141 @@
+#version 310 es\r
+\r
+layout(local_size_x = 2) in;\r
+layout(local_size_x = 16) in;     // ERROR, changing\r
+layout(local_size_z = 4096) in;   // ERROR, too large\r
+layout(local_size_x = 2) in;\r
+\r
+const int total = gl_MaxComputeWorkGroupCount.y \r
+                + gl_MaxComputeUniformComponents\r
+                + gl_MaxComputeTextureImageUnits\r
+                + gl_MaxComputeImageUniforms\r
+                + gl_MaxComputeAtomicCounters\r
+                + gl_MaxComputeAtomicCounterBuffers;\r
+\r
+buffer ShaderStorageBlock\r
+{\r
+    int value;\r
+    float values[];\r
+};\r
+\r
+buffer InvalidShaderStorageBlock\r
+{\r
+    float values[];  // ERROR\r
+    int value;\r
+} invalid;\r
+\r
+void main()\r
+{\r
+    barrier();\r
+    memoryBarrier();\r
+    memoryBarrierAtomicCounter();\r
+    memoryBarrierBuffer();\r
+    memoryBarrierShared();\r
+    memoryBarrierImage();\r
+    groupMemoryBarrier();\r
+    value = int(values[gl_LocalInvocationIndex]);\r
+}\r
+\r
+layout(location = 2) in vec3 v3;      // ERROR\r
+in float f;                           // ERROR\r
+out float fo;                         // ERROR\r
+\r
+shared vec4 s;\r
+layout(location = 2) shared vec4 sl;  // ERROR\r
+shared float fs = 4.2;                // ERROR\r
+\r
+layout(local_size_x = 2, local_size_y = 3, local_size_z = 4) out;  // ERROR\r
+\r
+int arrX[gl_WorkGroupSize.x];\r
+int arrY[gl_WorkGroupSize.y];\r
+int arrZ[gl_WorkGroupSize.z];\r
+\r
+readonly buffer roblock\r
+{\r
+    int value;\r
+    float values[];\r
+} ro;\r
+\r
+void foo()\r
+{\r
+    ro.values[2] = 4.7;        // ERROR, readonly\r
+    ro.values.length();\r
+    ++s;\r
+}\r
+\r
+buffer vec4 v;  // ERROR\r
+\r
+uniform usampler2D us2dbad;  // ERROR, default precision\r
+\r
+precision highp usampler2D;\r
+precision highp iimage2DArray;\r
+precision highp iimage2D;\r
+\r
+uniform usampler2D us2d;\r
+\r
+uniform iimage2DArray ii2dabad;  // ERROR, not writeonly\r
+uniform writeonly iimage2DArray ii2da;\r
+\r
+layout(r32i) uniform iimage2D iimg2D;\r
+layout(rgba32i) uniform iimage2D iimg2Drgba;\r
+layout(rgba32f) uniform image2D img2Drgba;\r
+layout(r32ui) uniform uimage2D uimg2D;\r
+\r
+void qux()\r
+{\r
+    int i = 4;\r
+    imageAtomicCompSwap(iimg2D, ivec2(i,i), i, i);// ERROR no longer in 310\r
+    imageAtomicAdd(uimg2D, ivec2(i,i), uint(i));  // ERROR no longer in 310\r
+    imageAtomicMin(iimg2Drgba, ivec2(i,i), i);    // ERROR no longer in 310  // ERROR iimg2Drgba does not have r32i layout\r
+    imageAtomicMax(img2Drgba, ivec2(i,i), i);     // ERROR no longer in 310  // ERROR img2Drgba is not integer image\r
+    ivec4 pos = imageLoad(iimg2D, ivec2(i,i));\r
+    imageStore(ii2da, ivec3(i,i,i), ivec4(0));\r
+    imageLoad(img2Drgba, ivec2(i,i));\r
+    imageLoad(ii2da, ivec3(i,i,i));       // ERROR, drops writeonly\r
+}\r
+\r
+volatile float vol; // ERROR, not an image\r
+readonly int vol2;  // ERROR, not an image\r
+\r
+void passr(coherent readonly iimage2D image)\r
+{\r
+}\r
+\r
+layout(r32i) coherent readonly uniform iimage2D qualim1;\r
+layout(r32i) coherent restrict readonly uniform iimage2D qualim2;\r
+\r
+void passrc()\r
+{\r
+    passr(qualim1);\r
+    passr(qualim2);   // ERROR, drops restrict\r
+    passr(iimg2D);\r
+}\r
+\r
+layout(rg8i) uniform uimage2D i1bad;     // ERROR, type mismatch\r
+layout(rgba32i) uniform image2D i2bad;   // ERROR, type mismatch\r
+layout(rgba32f) uniform uimage2D i3bad;  // ERROR, type mismatch\r
+layout(r8_snorm) uniform iimage2D i4bad; // ERROR, type mismatch\r
+layout(rgba32ui) uniform iimage2D i5bad; // ERROR, type mismatch\r
+layout(r8ui) uniform iimage2D i6bad;     // ERROR, type mismatch\r
+\r
+layout(binding = 0) uniform atomic_uint counter;\r
+\r
+uint func(atomic_uint c)\r
+{\r
+    return atomicCounterIncrement(c);\r
+}\r
+\r
+uint func2(out atomic_uint c) // ERROR, output\r
+{\r
+    return counter;           // ERROR, type mismatch\r
+    return atomicCounter(counter);\r
+}\r
+\r
+void mainAC()\r
+{\r
+     atomic_uint non_uniform_counter; // ERROR\r
+     uint val = atomicCounter(counter);\r
+     atomicCounterDecrement(counter);\r
+}\r
+\r
+layout(binding = 1) uniform mediump atomic_uint counterBad;  // ERROR, not highp\r
diff --git a/Test/310.frag b/Test/310.frag
new file mode 100644 (file)
index 0000000..7399159
--- /dev/null
@@ -0,0 +1,46 @@
+#version 310 es\r
+\r
+precision mediump float;\r
+precision highp usampler2D;\r
+precision highp sampler2D;\r
+precision highp isampler2DArray;\r
+\r
+layout(origin_upper_left, pixel_center_integer) in vec4 gl_FragCoord;  // ERROR, not supported\r
+\r
+layout(location = 2) in vec3 v3;\r
+layout(location = 2) in mat4 yi;  // ERROR, locations conflict with xi\r
+\r
+uniform sampler2D arrayedSampler[5];\r
+uniform usampler2D usamp2d;\r
+uniform usampler2DRect samp2dr;      // ERROR, reserved\r
+uniform isampler2DArray isamp2DA;\r
+\r
+in vec2 c2D;\r
+uniform int i;\r
+\r
+void main()\r
+{\r
+    vec4 v = texture(arrayedSampler[i], c2D);  // ERROR\r
+\r
+    ivec2 offsets[4];\r
+    const ivec2 constOffsets[4] = ivec2[4](ivec2(1,2), ivec2(3,4), ivec2(15,16), ivec2(-2,0));\r
+    uvec4 uv4 = textureGatherOffsets(samp2dr, c2D, offsets, 2);  // ERROR, not supported\r
+    vec4 v4 = textureGather(arrayedSampler[0], c2D);\r
+    ivec4 iv4 = textureGatherOffset(isamp2DA, vec3(0.1), ivec2(1), 3);\r
+    iv4 = textureGatherOffset(isamp2DA, vec3(0.1), ivec2(1), i);  // ERROR, last argument not const\r
+    iv4 = textureGatherOffset(isamp2DA, vec3(0.1), ivec2(1), 4);  // ERROR, last argument out of range\r
+    iv4 = textureGatherOffset(isamp2DA, vec3(0.1), ivec2(1), 1+2);\r
+    iv4 = textureGatherOffset(isamp2DA, vec3(0.1), ivec2(i));\r
+}\r
+\r
+out vec4 outp;\r
+\r
+void foo23()\r
+{\r
+    const ivec2[3] offsets = ivec2[3](ivec2(1,2), ivec2(3,4), ivec2(15,16));\r
+\r
+    textureProjGradOffset(usamp2d, outp, vec2(0.0), vec2(0.0), ivec2(c2D));     // ERROR, offset not constant\r
+    textureProjGradOffset(usamp2d, outp, vec2(0.0), vec2(0.0), offsets[1]);\r
+    textureProjGradOffset(usamp2d, outp, vec2(0.0), vec2(0.0), offsets[2]);     // ERROR, offset out of range\r
+    textureProjGradOffset(usamp2d, outp, vec2(0.0), vec2(0.0), ivec2(-10, 20)); // ERROR, offset out of range\r
+}\r
diff --git a/Test/310.vert b/Test/310.vert
new file mode 100644 (file)
index 0000000..8f0dee4
--- /dev/null
@@ -0,0 +1,10 @@
+#version 310 es\r
+\r
+shared vec4 s;   // ERROR\r
+layout(local_size_x = 2) out;  // ERROR\r
+buffer vec4 v;  // ERROR\r
+\r
+layout(location = 2) uniform mat4 x;\r
+layout(location = 3) uniform mat4 y;\r
+layout(location = 2) out mat4 xi;\r
+layout(location = 3) out mat4 yi;  // ERROR, locations conflict with xi\r
index 4cc8d29..d1d31f4 100644 (file)
@@ -143,7 +143,7 @@ out bblck5 {
     layout(xfb_stride=80, xfb_buffer=1, xfb_offset=64) vec4 bbv2;\r
 } bbinst5;\r
 \r
-shared vec4 sharedv;\r
+shared vec4 sharedv;                // ERROR\r
 \r
 void fooBarrier()\r
 {\r
index 972cf28..a837150 100644 (file)
@@ -9,7 +9,8 @@ uint func(atomic_uint c)
 
 uint func2(out atomic_uint c) // ERROR
 {
-    return counter;
+    return counter;           // ERROR, type mismatch
+    return atomicCounter(counter);
 }
 
 void main()
index e0fda14..43fbe09 100644 (file)
@@ -19,11 +19,11 @@ ERROR: 0:85: 'dvec3' : Reserved word.
 ERROR: 0:85: 'double vector' : not supported with this profile: es\r
 ERROR: 0:86: 'dvec4' : Reserved word. \r
 ERROR: 0:86: 'double vector' : not supported with this profile: es\r
-ERROR: 0:101: 'arrays of arrays' : not supported with this profile: es\r
-ERROR: 0:102: 'arrays of arrays' : not supported with this profile: es\r
-ERROR: 0:102: 'arrays of arrays' : not supported with this profile: es\r
-ERROR: 0:103: 'arrays of arrays' : not supported with this profile: es\r
-ERROR: 0:100: 'arrays of arrays' : not supported with this profile: es\r
+ERROR: 0:101: 'arrays of arrays' : not supported for this version or the enabled extensions \r
+ERROR: 0:102: 'arrays of arrays' : not supported for this version or the enabled extensions \r
+ERROR: 0:102: 'arrays of arrays' : not supported for this version or the enabled extensions \r
+ERROR: 0:103: 'arrays of arrays' : not supported for this version or the enabled extensions \r
+ERROR: 0:100: 'arrays of arrays' : not supported for this version or the enabled extensions \r
 ERROR: 0:111: 'variable indexing fragment shader ouput array' : not supported with this profile: es\r
 ERROR: 0:119: '==' : can't use with samplers or structs containing samplers \r
 ERROR: 0:120: '!=' : can't use with samplers or structs containing samplers \r
index d9d8c2f..87f630e 100644 (file)
@@ -16,8 +16,8 @@ ERROR: 0:18: 'uniform' : too many storage qualifiers
 ERROR: 0:56: '#error' : GL_ES is set  \r
 ERROR: 0:62: '' : array size required \r
 ERROR: 0:63: '' : array size required \r
-ERROR: 0:65: '' : array size required \r
 ERROR: 0:64: '' : array size required \r
+ERROR: 0:65: 'implicitly-sized array in a block' : not supported with this profile: es\r
 ERROR: 0:67: '' : array size required \r
 ERROR: 0:76: 'invariant' : cannot change qualification after use \r
 ERROR: 0:78: 'invariant' : can only apply to an output: invIn\r
@@ -38,7 +38,8 @@ ERROR: 0:149: 'float' : cannot apply precision statement to this type; use 'floa
 ERROR: 0:168: 'Binst' : cannot add storage, auxiliary, memory, interpolation, layout, or precision qualifier to an existing variable \r
 ERROR: 0:169: 'Bblock' : cannot add storage, auxiliary, memory, interpolation, layout, or precision qualifier to an existing variable \r
 ERROR: 0:170: 'Bfoo' : cannot add storage, auxiliary, memory, interpolation, layout, or precision qualifier to an existing variable \r
-ERROR: 39 compilation errors.  No code generated.\r
+ERROR: 0:173: '' : array size required \r
+ERROR: 40 compilation errors.  No code generated.\r
 \r
 \r
 Shader version: 300\r
index a7a7da8..21f12dd 100644 (file)
@@ -1,8 +1,9 @@
 300layout.frag\r
 ERROR: 0:4: 'location qualifier on input' : not supported in this stage: fragment\r
+ERROR: 0:4: 'location qualifier on input' : not supported for this version or the enabled extensions \r
 ERROR: 0:18: 'location' : overlapping use of location 41\r
 ERROR: 0:19: 'location' : overlapping use of location 40\r
-ERROR: 3 compilation errors.  No code generated.\r
+ERROR: 4 compilation errors.  No code generated.\r
 \r
 \r
 Shader version: 300\r
index b5b1e26..f64db3b 100644 (file)
@@ -13,11 +13,12 @@ ERROR: 0:23: 'bad3' : member of block cannot have a packing layout qualifier
 ERROR: 0:31: 'T3' : nameless block contains a member that already has a name at global scope \r
 ERROR: 0:38: 'output block' : not supported with this profile: es\r
 ERROR: 0:42: 'location qualifier on output' : not supported in this stage: vertex\r
-ERROR: 0:50: 'shared' : not supported with this profile: es\r
+ERROR: 0:42: 'location qualifier on output' : not supported for this version or the enabled extensions \r
+ERROR: 0:50: 'shared' : not supported for this version or the enabled extensions \r
 ERROR: 0:50: 'shared' : not supported in this stage: vertex\r
 ERROR: 0:54: 'layout' : cannot specify packing on a variable declaration \r
 ERROR: 0:57: 'location' : overlapping use of location 40\r
-ERROR: 18 compilation errors.  No code generated.\r
+ERROR: 19 compilation errors.  No code generated.\r
 \r
 \r
 Shader version: 300\r
index 246cf8b..248df2e 100644 (file)
@@ -2,7 +2,7 @@ atomic_uint.frag
 Warning, version 420 is not yet complete; most version-specific features are present, but some are missing.\r
 ERROR: 0:10: 'atomic_uint' : samplers and atomic_uints cannot be output parameters \r
 ERROR: 0:12: 'return' : type does not match, or is not convertible to, the function's return type \r
-ERROR: 0:17: 'atomic_uint' : atomic_uints can only be used in uniform variables or function parameters: non_uniform_counter\r
+ERROR: 0:18: 'atomic_uint' : atomic_uints can only be used in uniform variables or function parameters: non_uniform_counter\r
 ERROR: 3 compilation errors.  No code generated.\r
 \r
 \r
@@ -21,16 +21,19 @@ ERROR: node is still EOpNull!
 0:12    Sequence\r
 0:12      Branch: Return with expression\r
 0:12        'counter' (layout(binding=0 ) uniform atomic_uint)\r
-0:15  Function Definition: main( (void)\r
-0:15    Function Parameters: \r
+0:13      Branch: Return with expression\r
+0:13        Function Call: atomicCounter(au1; (uint)\r
+0:13          'counter' (layout(binding=0 ) uniform atomic_uint)\r
+0:16  Function Definition: main( (void)\r
+0:16    Function Parameters: \r
 0:?     Sequence\r
-0:18      Sequence\r
-0:18        move second child to first child (uint)\r
-0:18          'val' (uint)\r
-0:18          Function Call: atomicCounter(au1; (uint)\r
-0:18            'counter' (layout(binding=0 ) uniform atomic_uint)\r
-0:19      Function Call: atomicCounterDecrement(au1; (uint)\r
-0:19        'counter' (layout(binding=0 ) uniform atomic_uint)\r
+0:19      Sequence\r
+0:19        move second child to first child (uint)\r
+0:19          'val' (uint)\r
+0:19          Function Call: atomicCounter(au1; (uint)\r
+0:19            'counter' (layout(binding=0 ) uniform atomic_uint)\r
+0:20      Function Call: atomicCounterDecrement(au1; (uint)\r
+0:20        'counter' (layout(binding=0 ) uniform atomic_uint)\r
 0:?   Linker Objects\r
 0:?     'counter' (layout(binding=0 ) uniform atomic_uint)\r
 \r
@@ -53,16 +56,19 @@ ERROR: node is still EOpNull!
 0:12    Sequence\r
 0:12      Branch: Return with expression\r
 0:12        'counter' (layout(binding=0 ) uniform atomic_uint)\r
-0:15  Function Definition: main( (void)\r
-0:15    Function Parameters: \r
+0:13      Branch: Return with expression\r
+0:13        Function Call: atomicCounter(au1; (uint)\r
+0:13          'counter' (layout(binding=0 ) uniform atomic_uint)\r
+0:16  Function Definition: main( (void)\r
+0:16    Function Parameters: \r
 0:?     Sequence\r
-0:18      Sequence\r
-0:18        move second child to first child (uint)\r
-0:18          'val' (uint)\r
-0:18          Function Call: atomicCounter(au1; (uint)\r
-0:18            'counter' (layout(binding=0 ) uniform atomic_uint)\r
-0:19      Function Call: atomicCounterDecrement(au1; (uint)\r
-0:19        'counter' (layout(binding=0 ) uniform atomic_uint)\r
+0:19      Sequence\r
+0:19        move second child to first child (uint)\r
+0:19          'val' (uint)\r
+0:19          Function Call: atomicCounter(au1; (uint)\r
+0:19            'counter' (layout(binding=0 ) uniform atomic_uint)\r
+0:20      Function Call: atomicCounterDecrement(au1; (uint)\r
+0:20        'counter' (layout(binding=0 ) uniform atomic_uint)\r
 0:?   Linker Objects\r
 0:?     'counter' (layout(binding=0 ) uniform atomic_uint)\r
 \r
index 286c1fd..ba21ea1 100644 (file)
@@ -36,6 +36,9 @@ comment.frag
 300layout.frag
 300operations.frag
 300block.frag
+310.comp
+310.vert
+310.frag
 330.frag
 330comp.frag
 constErrors.frag
index bc89e1f..40c6b45 100644 (file)
@@ -248,20 +248,23 @@ enum TLayoutFormat {
     // 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 @@ enum TLayoutFormat {
     ElfRgba32i,
     ElfRgba16i,
     ElfRgba8i,
+    ElfR32i,
+
+    ElfEsIntGuard,     // to help with comparisons
+
     ElfRg32i,
     ElfRg16i,
     ElfRg8i,
-    ElfR32i,
     ElfR16i,
     ElfR8i,
 
@@ -286,10 +292,13 @@ enum TLayoutFormat {
     ElfRgba32ui,
     ElfRgba16ui,
     ElfRgba8ui,
+    ElfR32ui,
+
+    ElfEsUintGuard,    // to help with comparisons
+
     ElfRg32ui,
     ElfRg16ui,
     ElfRg8ui,
-    ElfR32ui,
     ElfR16ui,
     ElfR8ui,
 
index 73466e7..42e5c7f 100644 (file)
@@ -743,7 +743,8 @@ void TBuiltIns::initialize(int version, EProfile profile)
     //
     // 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 @@ void TBuiltIns::initialize(int version, EProfile profile)
             
             "\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 @@ void TBuiltIns::initialize(int version, EProfile profile)
     //
     //============================================================================
 
-    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 @@ void TBuiltIns::initialize(int version, EProfile profile)
             "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 @@ void TBuiltIns::initialize(int version, EProfile profile)
                 "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 @@ void TBuiltIns::initialize(int version, EProfile profile)
                 "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 @@ void TBuiltIns::addQueryFunctions(TSampler sampler, TString& typeName, int versi
     // 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 @@ void TBuiltIns::addImageFunctions(TSampler sampler, TString& typeName, int versi
     commonBuiltins.append(prefixes[sampler.type]);
     commonBuiltins.append("vec4);\n");
 
-    if (sampler.type == EbtInt || sampler.type == EbtUint) {
-        const char* dataType = sampler.type == EbtInt ? "int" : "uint";
-
-        const int numBuiltins = 7;
-
-        static const char* atomicFunc[numBuiltins] = {
-            " imageAtomicAdd(",
-            " imageAtomicMin(",
-            " imageAtomicMax(",
-            " imageAtomicAnd(",
-            " imageAtomicOr(",
-            " imageAtomicXor(",
-            " imageAtomicExchange("
-        }; 
+    if (profile != EEsProfile) {
+        if (sampler.type == EbtInt || sampler.type == EbtUint) {
+            const char* dataType = sampler.type == EbtInt ? "int" : "uint";
+
+            const int numBuiltins = 7;
+
+            static const char* atomicFunc[numBuiltins] = {
+                " imageAtomicAdd(",
+                " imageAtomicMin(",
+                " imageAtomicMax(",
+                " imageAtomicAnd(",
+                " imageAtomicOr(",
+                " imageAtomicXor(",
+                " imageAtomicExchange("
+            }; 
+
+            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");
+            }
 
-        for (size_t i = 0; i < numBuiltins; ++i) {
             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 @@ void TBuiltIns::addGatherFunctions(TSampler sampler, TString& typeName, int vers
 
     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 @@ void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProf
             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 @@ void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProf
             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 @@ void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProf
         }
     }
 
+    // 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 @@ void IdentifyBuiltIns(int version, EProfile profile, EShLanguage language, TSymb
         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 @@ void IdentifyBuiltIns(int version, EProfile profile, EShLanguage language, TSymb
         }
 
         // 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, TSymb
 //
 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);
     }
index efc5d93..df0f34a 100644 (file)
@@ -82,15 +82,16 @@ TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, bool pb,
         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 @@ void TParseContext::nonOpBuiltInCheck(TSourceLoc loc, const TFunction& fnCandida
         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 @@ void TParseContext::mergeQualifiers(TSourceLoc loc, TQualifier& dst, const TQual
         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 @@ void TParseContext::precisionQualifierCheck(TSourceLoc loc, TPublicType& publicT
     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::arraySizeRequiredCheck(TSourceLoc loc, int size)
     }
 }
 
+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 @@ void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType,
         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 @@ void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType,
     
     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 @@ void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType,
             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 @@ void TParseContext::layoutQualifierCheck(TSourceLoc loc, const TQualifier& quali
         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 @@ void TParseContext::declareBlock(TSourceLoc loc, TTypeList& typeList, const TStr
         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 @@ void TParseContext::declareBlock(TSourceLoc loc, TTypeList& typeList, const TStr
             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)
index 2c36c2e..b129e60 100644 (file)
@@ -117,6 +117,7 @@ public:
     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*);
index a7a72e2..1a459ba 100644 (file)
@@ -668,18 +668,25 @@ int TScanContext::tokenizeIdentifier()
         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 @@ int TScanContext::tokenizeIdentifier()
     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 @@ int TScanContext::dMat()
     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) ||
index cf2ad2a..bb8c42b 100644 (file)
@@ -64,7 +64,7 @@ protected:
     int precisionKeyword();
     int matNxM();
     int dMat();
-    int firstGenerationImage();
+    int firstGenerationImage(bool inEs310);
     int secondGenerationImage();
 
     TParseContext& parseContext;
index b7c89f8..4d3f224 100644 (file)
@@ -78,11 +78,13 @@ int MapVersionToIndex(int version)
         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 @@ bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable,  TS
     }
     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 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
 
     // 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 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
                 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 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
         }
         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 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
         // 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;
index e34231c..c71c6e2 100644 (file)
@@ -1216,8 +1216,8 @@ storage_qualifier
         $$.qualifier.storage = EvqBuffer;\r
     }\r
     | SHARED {\r
-        parseContext.requireProfile($1.loc, ~EEsProfile, "shared");\r
-        parseContext.profileRequires($1.loc, ECoreProfile, 430, 0, "shared");\r
+        parseContext.profileRequires($1.loc, ECoreProfile | ECompatibilityProfile, 430, 0, "shared");\r
+        parseContext.profileRequires($1.loc, EEsProfile, 310, 0, "shared");\r
         parseContext.requireStage($1.loc, EShLangCompute, "shared");\r
         $$.init($1.loc);\r
         $$.qualifier.storage = EvqShared;\r
@@ -1964,6 +1964,7 @@ precision_qualifier
 struct_specifier\r
     : STRUCT IDENTIFIER LEFT_BRACE { parseContext.nestedStructCheck($1.loc); } struct_declaration_list RIGHT_BRACE {\r
         TType* structure = new TType($5, *$2.string);\r
+        parseContext.structArrayCheck($2.loc, structure);\r
         TVariable* userTypeDef = new TVariable($2.string, *structure, true);\r
         if (! parseContext.symbolTable.insert(*userTypeDef))\r
             parseContext.error($2.loc, "redefinition", $2.string->c_str(), "struct");\r
@@ -2055,8 +2056,6 @@ struct_declarator
         $$.type->setFieldName(*$1.string);\r
     }\r
     | IDENTIFIER array_specifier {        \r
-        if (parseContext.profile == EEsProfile)\r
-            parseContext.arraySizeRequiredCheck($2.loc, $2.arraySizes->getSize());\r
         parseContext.arrayDimCheck($1.loc, $2.arraySizes, 0);\r
 \r
         $$.type = new TType(EbtVoid);\r