diff --git a/Test/300.vert b/Test/300.vert index 11a0078565e2a54728e97125fe3330770579d16e..5abf450846aed75f54c9731948b009384d8ded84 100644 --- a/Test/300.vert +++ b/Test/300.vert @@ -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 index 0000000000000000000000000000000000000000..2f172feb86695d3f3787925c504a24d796df121d --- /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 0000000000000000000000000000000000000000..7399159ef08feb2ed539605269d0c25dae424aba --- /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 0000000000000000000000000000000000000000..8f0dee495ea882982e92e8121d8752c3cf5722ee --- /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 4cc8d29ee7344d63ab74be3cd98fdb8e6905879c..d1d31f4498c243670bad9253785e49531c87d6e0 100644 --- a/Test/430.vert +++ b/Test/430.vert @@ -143,7 +143,7 @@ out bblck5 { 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 972cf28287350bafd34d05c5c4729f3e9d41fb75..a8371503c2e0e783f1a92fe04a1d9bea0c3713d5 100644 --- a/Test/atomic_uint.frag +++ b/Test/atomic_uint.frag @@ -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() diff --git a/Test/baseResults/300.frag.out b/Test/baseResults/300.frag.out index e0fda14f15b192663350a8539b57e06495431747..43fbe097113e5993581572cda359bbb04109eb43 100644 --- a/Test/baseResults/300.frag.out +++ b/Test/baseResults/300.frag.out @@ -19,11 +19,11 @@ ERROR: 0:85: 'dvec3' : Reserved word. 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 d9d8c2fbe57baf0397041fbbae3c927c9adbe105..87f630e9eaf96c9eb680717f694bd96801364e2c 100644 --- a/Test/baseResults/300.vert.out +++ b/Test/baseResults/300.vert.out @@ -16,8 +16,8 @@ ERROR: 0:18: 'uniform' : too many storage qualifiers 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: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 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 a7a7da897a7fc62575d910b56b402e54224b081d..21f12dd84a3b3f14ed05dc09c6d4dc28d038e078 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 b5b1e26294fd8e5bdf8f640a107d1f71cbf429aa..f64db3bdc24cb7ab159afd716a63eca4237c0bcc 100644 --- a/Test/baseResults/300layout.vert.out +++ b/Test/baseResults/300layout.vert.out @@ -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 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 246cf8b0131733a89417eb938736a158ded459f3..248df2e6a92d600a47b3aa9d4872bd134483e0a8 100644 --- a/Test/baseResults/atomic_uint.frag.out +++ b/Test/baseResults/atomic_uint.frag.out @@ -2,7 +2,7 @@ atomic_uint.frag 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 @@ ERROR: node is still EOpNull! 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 @@ ERROR: node is still EOpNull! 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 286c1fd0c2ebc1c0ad62b27501993dbdba241533..ba21ea1fcaef1ae16e5f104951a5abde57bed98a 100644 --- a/Test/testlist +++ b/Test/testlist @@ -36,6 +36,9 @@ comment.frag 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 bc89e1fb243dd2905824954c32a6766ccc11a465..40c6b45c5694cd98fef5979c232174cb21138d12 100644 --- a/glslang/Include/Types.h +++ b/glslang/Include/Types.h @@ -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, diff --git a/glslang/MachineIndependent/Initialize.cpp b/glslang/MachineIndependent/Initialize.cpp index 73466e7ccb4447179f89d4e320400d33995ce029..42e5c7f2507702957dff9014932c1058fd8955ed 100644 --- a/glslang/MachineIndependent/Initialize.cpp +++ b/glslang/MachineIndependent/Initialize.cpp @@ -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); } diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index efc5d938c73b8f851d9f2190b73b767729ec1fac..df0f34a30fcd7ec1d561e56709b41b0f8294c1c9 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -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) diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index 2c36c2ea677b25677915f017c8b0baabebb76d1e..b129e60fed117d849aefce5711babb1d35f5d685 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -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*); diff --git a/glslang/MachineIndependent/Scan.cpp b/glslang/MachineIndependent/Scan.cpp index a7a72e278210148f3e3d3929550824a21ec34017..1a459ba8ac1a5b4810e987a625ec1613834d3842 100644 --- a/glslang/MachineIndependent/Scan.cpp +++ b/glslang/MachineIndependent/Scan.cpp @@ -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) || diff --git a/glslang/MachineIndependent/ScanContext.h b/glslang/MachineIndependent/ScanContext.h index cf2ad2a33bba09d5146645f6514cbc8b73189f22..bb8c42bbb56148d4d52fbfd01c174d845ad47b99 100644 --- a/glslang/MachineIndependent/ScanContext.h +++ b/glslang/MachineIndependent/ScanContext.h @@ -64,7 +64,7 @@ protected: 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 b7c89f8e21d7967384def6799268745cffd3def0..4d3f22476dfbaa81d1adbb9bf1015735ea2cc164 100644 --- a/glslang/MachineIndependent/ShaderLang.cpp +++ b/glslang/MachineIndependent/ShaderLang.cpp @@ -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; diff --git a/glslang/MachineIndependent/glslang.y b/glslang/MachineIndependent/glslang.y index e34231c4c6700bbdcb83930ec0425974e63517d2..c71c6e213d144db7cf35cbc6a6ccc95786a273af 100644 --- a/glslang/MachineIndependent/glslang.y +++ b/glslang/MachineIndependent/glslang.y @@ -1216,8 +1216,8 @@ storage_qualifier $$.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 @@ precision_qualifier 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 @@ struct_declarator $$.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);