diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /gfx/angle/src/tests/compiler_tests/MalformedShader_test.cpp | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'gfx/angle/src/tests/compiler_tests/MalformedShader_test.cpp')
-rwxr-xr-x | gfx/angle/src/tests/compiler_tests/MalformedShader_test.cpp | 3158 |
1 files changed, 3158 insertions, 0 deletions
diff --git a/gfx/angle/src/tests/compiler_tests/MalformedShader_test.cpp b/gfx/angle/src/tests/compiler_tests/MalformedShader_test.cpp new file mode 100755 index 000000000..e84fc7014 --- /dev/null +++ b/gfx/angle/src/tests/compiler_tests/MalformedShader_test.cpp @@ -0,0 +1,3158 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// MalformedShader_test.cpp: +// Tests that malformed shaders fail compilation. +// + +#include "angle_gl.h" +#include "gtest/gtest.h" +#include "GLSLANG/ShaderLang.h" +#include "compiler/translator/TranslatorESSL.h" + +using namespace sh; + +class MalformedShaderTest : public testing::Test +{ + public: + MalformedShaderTest() : mExtraCompileOptions(0) {} + + protected: + virtual void SetUp() + { + ShBuiltInResources resources; + sh::InitBuiltInResources(&resources); + + mTranslator = new TranslatorESSL(GL_FRAGMENT_SHADER, SH_GLES3_SPEC); + ASSERT_TRUE(mTranslator->Init(resources)); + } + + virtual void TearDown() + { + delete mTranslator; + } + + // Return true when compilation succeeds + bool compile(const std::string& shaderString) + { + const char *shaderStrings[] = { shaderString.c_str() }; + bool compilationSuccess = + mTranslator->compile(shaderStrings, 1, SH_INTERMEDIATE_TREE | mExtraCompileOptions); + TInfoSink &infoSink = mTranslator->getInfoSink(); + mInfoLog = infoSink.info.c_str(); + return compilationSuccess; + } + + bool hasWarning() const + { + return mInfoLog.find("WARNING: ") != std::string::npos; + } + + protected: + std::string mInfoLog; + TranslatorESSL *mTranslator; + ShCompileOptions mExtraCompileOptions; +}; + +class MalformedVertexShaderTest : public MalformedShaderTest +{ + public: + MalformedVertexShaderTest() {} + + protected: + void SetUp() override + { + ShBuiltInResources resources; + sh::InitBuiltInResources(&resources); + + mTranslator = new TranslatorESSL(GL_VERTEX_SHADER, SH_GLES3_SPEC); + ASSERT_TRUE(mTranslator->Init(resources)); + } +}; + +class MalformedWebGL2ShaderTest : public MalformedShaderTest +{ + public: + MalformedWebGL2ShaderTest() {} + + protected: + void SetUp() override + { + ShBuiltInResources resources; + sh::InitBuiltInResources(&resources); + + mTranslator = new TranslatorESSL(GL_FRAGMENT_SHADER, SH_WEBGL2_SPEC); + ASSERT_TRUE(mTranslator->Init(resources)); + } +}; + +class MalformedWebGL1ShaderTest : public MalformedShaderTest +{ + public: + MalformedWebGL1ShaderTest() {} + + protected: + void SetUp() override + { + ShBuiltInResources resources; + sh::InitBuiltInResources(&resources); + + mTranslator = new TranslatorESSL(GL_FRAGMENT_SHADER, SH_WEBGL_SPEC); + ASSERT_TRUE(mTranslator->Init(resources)); + } +}; + +class MalformedVertexShaderGLES31Test : public MalformedShaderTest +{ + public: + MalformedVertexShaderGLES31Test() {} + + private: + void SetUp() override + { + ShBuiltInResources resources; + sh::InitBuiltInResources(&resources); + mTranslator = new TranslatorESSL(GL_VERTEX_SHADER, SH_GLES3_1_SPEC); + ASSERT_TRUE(mTranslator->Init(resources)); + } +}; + +class MalformedFragmentShaderGLES31Test : public MalformedShaderTest +{ + public: + MalformedFragmentShaderGLES31Test() {} + + private: + void SetUp() override + { + ShBuiltInResources resources; + sh::InitBuiltInResources(&resources); + mTranslator = new TranslatorESSL(GL_FRAGMENT_SHADER, SH_GLES3_1_SPEC); + ASSERT_TRUE(mTranslator->Init(resources)); + } +}; + +class MalformedComputeShaderTest : public MalformedShaderTest +{ + public: + MalformedComputeShaderTest() {} + + private: + void SetUp() override + { + ShBuiltInResources resources; + sh::InitBuiltInResources(&resources); + mTranslator = new TranslatorESSL(GL_COMPUTE_SHADER, SH_GLES3_1_SPEC); + ASSERT_TRUE(mTranslator->Init(resources)); + } +}; + +class UnrollForLoopsTest : public MalformedShaderTest +{ + public: + UnrollForLoopsTest() { mExtraCompileOptions = SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX; } +}; + +// This is a test for a bug that used to exist in ANGLE: +// Calling a function with all parameters missing should not succeed. +TEST_F(MalformedShaderTest, FunctionParameterMismatch) +{ + const std::string &shaderString = + "precision mediump float;\n" + "float fun(float a) {\n" + " return a * 2.0;\n" + "}\n" + "void main() {\n" + " float ff = fun();\n" + " gl_FragColor = vec4(ff);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Functions can't be redeclared as variables in the same scope (ESSL 1.00 section 4.2.7) +TEST_F(MalformedShaderTest, RedeclaringFunctionAsVariable) +{ + const std::string &shaderString = + "precision mediump float;\n" + "float fun(float a) {\n" + " return a * 2.0;\n" + "}\n" + "float fun;\n" + "void main() {\n" + " gl_FragColor = vec4(0.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Functions can't be redeclared as structs in the same scope (ESSL 1.00 section 4.2.7) +TEST_F(MalformedShaderTest, RedeclaringFunctionAsStruct) +{ + const std::string &shaderString = + "precision mediump float;\n" + "float fun(float a) {\n" + " return a * 2.0;\n" + "}\n" + "struct fun { float a; };\n" + "void main() {\n" + " gl_FragColor = vec4(0.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Functions can't be redeclared with different qualifiers (ESSL 1.00 section 6.1.0) +TEST_F(MalformedShaderTest, RedeclaringFunctionWithDifferentQualifiers) +{ + const std::string &shaderString = + "precision mediump float;\n" + "float fun(out float a);\n" + "float fun(float a) {\n" + " return a * 2.0;\n" + "}\n" + "void main() {\n" + " gl_FragColor = vec4(0.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Assignment and equality are undefined for structures containing arrays (ESSL 1.00 section 5.7) +TEST_F(MalformedShaderTest, CompareStructsContainingArrays) +{ + const std::string &shaderString = + "precision mediump float;\n" + "struct s { float a[3]; };\n" + "void main() {\n" + " s a;\n" + " s b;\n" + " bool c = (a == b);\n" + " gl_FragColor = vec4(c ? 1.0 : 0.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Assignment and equality are undefined for structures containing arrays (ESSL 1.00 section 5.7) +TEST_F(MalformedShaderTest, AssignStructsContainingArrays) +{ + const std::string &shaderString = + "precision mediump float;\n" + "struct s { float a[3]; };\n" + "void main() {\n" + " s a;\n" + " s b;\n" + " b.a[0] = 0.0;\n" + " a = b;\n" + " gl_FragColor = vec4(a.a[0]);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Assignment and equality are undefined for structures containing samplers (ESSL 1.00 sections 5.7 and 5.9) +TEST_F(MalformedShaderTest, CompareStructsContainingSamplers) +{ + const std::string &shaderString = + "precision mediump float;\n" + "struct s { sampler2D foo; };\n" + "uniform s a;\n" + "uniform s b;\n" + "void main() {\n" + " bool c = (a == b);\n" + " gl_FragColor = vec4(c ? 1.0 : 0.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Samplers are not allowed as l-values (ESSL 3.00 section 4.1.7), our interpretation is that this +// extends to structs containing samplers. ESSL 1.00 spec is clearer about this. +TEST_F(MalformedShaderTest, AssignStructsContainingSamplers) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "struct s { sampler2D foo; };\n" + "uniform s a;\n" + "out vec4 my_FragColor;\n" + "void main() {\n" + " s b;\n" + " b = a;\n" + " my_FragColor = vec4(1.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// This is a regression test for a particular bug that was in ANGLE. +// It also verifies that ESSL3 functionality doesn't leak to ESSL1. +TEST_F(MalformedShaderTest, ArrayWithNoSizeInInitializerList) +{ + const std::string &shaderString = + "precision mediump float;\n" + "void main() {\n" + " float a[2], b[];\n" + " gl_FragColor = vec4(1.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Const variables need an initializer. +TEST_F(MalformedShaderTest, ConstVarNotInitialized) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 my_FragColor;\n" + "void main() {\n" + " const float a;\n" + " my_FragColor = vec4(1.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Const variables need an initializer. In ESSL1 const structs containing +// arrays are not allowed at all since it's impossible to initialize them. +// Even though this test is for ESSL3 the only thing that's critical for +// ESSL1 is the non-initialization check that's used for both language versions. +// Whether ESSL1 compilation generates the most helpful error messages is a +// secondary concern. +TEST_F(MalformedShaderTest, ConstStructNotInitialized) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "struct S {\n" + " float a[3];\n" + "};\n" + "out vec4 my_FragColor;\n" + "void main() {\n" + " const S b;\n" + " my_FragColor = vec4(1.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Const variables need an initializer. In ESSL1 const arrays are not allowed +// at all since it's impossible to initialize them. +// Even though this test is for ESSL3 the only thing that's critical for +// ESSL1 is the non-initialization check that's used for both language versions. +// Whether ESSL1 compilation generates the most helpful error messages is a +// secondary concern. +TEST_F(MalformedShaderTest, ConstArrayNotInitialized) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 my_FragColor;\n" + "void main() {\n" + " const float a[3];\n" + " my_FragColor = vec4(1.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Block layout qualifiers can't be used on non-block uniforms (ESSL 3.00 section 4.3.8.3) +TEST_F(MalformedShaderTest, BlockLayoutQualifierOnRegularUniform) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "layout(packed) uniform mat2 x;\n" + "out vec4 my_FragColor;\n" + "void main() {\n" + " my_FragColor = vec4(1.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Block layout qualifiers can't be used on non-block uniforms (ESSL 3.00 section 4.3.8.3) +TEST_F(MalformedShaderTest, BlockLayoutQualifierOnUniformWithEmptyDecl) +{ + // Yes, the comma in the declaration below is not a typo. + // Empty declarations are allowed in GLSL. + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "layout(packed) uniform mat2, x;\n" + "out vec4 my_FragColor;\n" + "void main() {\n" + " my_FragColor = vec4(1.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Arrays of arrays are not allowed (ESSL 3.00 section 4.1.9) +TEST_F(MalformedShaderTest, ArraysOfArrays1) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 my_FragColor;\n" + "void main() {\n" + " float[5] a[3];\n" + " my_FragColor = vec4(1.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Arrays of arrays are not allowed (ESSL 3.00 section 4.1.9) +TEST_F(MalformedShaderTest, ArraysOfArrays2) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 my_FragColor;\n" + "void main() {\n" + " float[2] a, b[3];\n" + " my_FragColor = vec4(1.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Implicitly sized arrays need to be initialized (ESSL 3.00 section 4.1.9) +TEST_F(MalformedShaderTest, UninitializedImplicitArraySize) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 my_FragColor;\n" + "void main() {\n" + " float[] a;\n" + " my_FragColor = vec4(1.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// An operator can only form a constant expression if all the operands are constant expressions +// - even operands of ternary operator that are never evaluated. (ESSL 3.00 section 4.3.3) +TEST_F(MalformedShaderTest, TernaryOperatorNotConstantExpression) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 my_FragColor;\n" + "uniform bool u;\n" + "void main() {\n" + " const bool a = true ? true : u;\n" + " my_FragColor = vec4(1.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Ternary operator can't operate on arrays (ESSL 3.00 section 5.7) +TEST_F(MalformedShaderTest, TernaryOperatorOnArrays) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 my_FragColor;\n" + "void main() {\n" + " float[1] a = float[1](0.0);\n" + " float[1] b = float[1](1.0);\n" + " float[1] c = true ? a : b;\n" + " my_FragColor = vec4(1.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Ternary operator can't operate on structs (ESSL 3.00 section 5.7) +TEST_F(MalformedShaderTest, TernaryOperatorOnStructs) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 my_FragColor;\n" + "struct S { float foo; };\n" + "void main() {\n" + " S a = S(0.0);\n" + " S b = S(1.0);\n" + " S c = true ? a : b;\n" + " my_FragColor = vec4(1.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Array length() returns a constant signed integral expression (ESSL 3.00 section 4.1.9) +// Assigning it to unsigned should result in an error. +TEST_F(MalformedShaderTest, AssignArrayLengthToUnsigned) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 my_FragColor;\n" + "void main() {\n" + " int[1] arr;\n" + " uint l = arr.length();\n" + " my_FragColor = vec4(float(l));\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3) +// Initializing with a varying should be an error. +TEST_F(MalformedShaderTest, AssignVaryingToGlobal) +{ + const std::string &shaderString = + "precision mediump float;\n" + "varying float a;\n" + "float b = a * 2.0;\n" + "void main() {\n" + " gl_FragColor = vec4(b);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Global variable initializers need to be constant expressions (ESSL 3.00 section 4.3) +// Initializing with an uniform should be an error. +TEST_F(MalformedShaderTest, AssignUniformToGlobalESSL3) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "uniform float a;\n" + "float b = a * 2.0;\n" + "out vec4 my_FragColor;\n" + "void main() {\n" + " my_FragColor = vec4(b);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3) +// Initializing with an uniform should generate a warning +// (we don't generate an error on ESSL 1.00 because of legacy compatibility) +TEST_F(MalformedShaderTest, AssignUniformToGlobalESSL1) +{ + const std::string &shaderString = + "precision mediump float;\n" + "uniform float a;\n" + "float b = a * 2.0;\n" + "void main() {\n" + " gl_FragColor = vec4(b);\n" + "}\n"; + if (compile(shaderString)) + { + if (!hasWarning()) + { + FAIL() << "Shader compilation succeeded without warnings, expecting warning " << mInfoLog; + } + } + else + { + FAIL() << "Shader compilation failed, expecting success with warning " << mInfoLog; + } +} + +// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3) +// Initializing with an user-defined function call should be an error. +TEST_F(MalformedShaderTest, AssignFunctionCallToGlobal) +{ + const std::string &shaderString = + "precision mediump float;\n" + "float foo() { return 1.0; }\n" + "float b = foo();\n" + "void main() {\n" + " gl_FragColor = vec4(b);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3) +// Initializing with an assignment to another global should be an error. +TEST_F(MalformedShaderTest, AssignAssignmentToGlobal) +{ + const std::string &shaderString = + "precision mediump float;\n" + "float c = 1.0;\n" + "float b = (c = 0.0);\n" + "void main() {\n" + " gl_FragColor = vec4(b);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3) +// Initializing with incrementing another global should be an error. +TEST_F(MalformedShaderTest, AssignIncrementToGlobal) +{ + const std::string &shaderString = + "precision mediump float;\n" + "float c = 1.0;\n" + "float b = (c++);\n" + "void main() {\n" + " gl_FragColor = vec4(b);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3) +// Initializing with a texture lookup function call should be an error. +TEST_F(MalformedShaderTest, AssignTexture2DToGlobal) +{ + const std::string &shaderString = + "precision mediump float;\n" + "uniform mediump sampler2D s;\n" + "float b = texture2D(s, vec2(0.5, 0.5)).x;\n" + "void main() {\n" + " gl_FragColor = vec4(b);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Global variable initializers need to be constant expressions (ESSL 3.00 section 4.3) +// Initializing with a non-constant global should be an error. +TEST_F(MalformedShaderTest, AssignNonConstGlobalToGlobal) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "float a = 1.0;\n" + "float b = a * 2.0;\n" + "out vec4 my_FragColor;\n" + "void main() {\n" + " my_FragColor = vec4(b);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Global variable initializers need to be constant expressions (ESSL 3.00 section 4.3) +// Initializing with a constant global should be fine. +TEST_F(MalformedShaderTest, AssignConstGlobalToGlobal) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "const float a = 1.0;\n" + "float b = a * 2.0;\n" + "out vec4 my_FragColor;\n" + "void main() {\n" + " my_FragColor = vec4(b);\n" + "}\n"; + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// Statically assigning to both gl_FragData and gl_FragColor is forbidden (ESSL 1.00 section 7.2) +TEST_F(MalformedShaderTest, WriteBothFragDataAndFragColor) +{ + const std::string &shaderString = + "precision mediump float;\n" + "void foo() {\n" + " gl_FragData[0].a++;\n" + "}\n" + "void main() {\n" + " gl_FragColor.x += 0.0;\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Version directive must be on the first line (ESSL 3.00 section 3.3) +TEST_F(MalformedShaderTest, VersionOnSecondLine) +{ + const std::string &shaderString = + "\n" + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 my_FragColor;\n" + "void main() {\n" + " my_FragColor = vec4(0.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Layout qualifier can only appear in global scope (ESSL 3.00 section 4.3.8) +TEST_F(MalformedShaderTest, LayoutQualifierInCondition) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "uniform vec4 u;\n" + "out vec4 my_FragColor;\n" + "void main() {\n" + " int i = 0;\n" + " for (int j = 0; layout(location = 0) bool b = false; ++j) {\n" + " ++i;\n" + " }\n" + " my_FragColor = u;\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Layout qualifier can only appear where specified (ESSL 3.00 section 4.3.8) +TEST_F(MalformedShaderTest, LayoutQualifierInFunctionReturnType) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "uniform vec4 u;\n" + "out vec4 my_FragColor;\n" + "layout(location = 0) vec4 foo() {\n" + " return u;\n" + "}\n" + "void main() {\n" + " my_FragColor = foo();\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// If there is more than one output, the location must be specified for all outputs. +// (ESSL 3.00.04 section 4.3.8.2) +TEST_F(MalformedShaderTest, TwoOutputsNoLayoutQualifiers) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "uniform vec4 u;\n" + "out vec4 my_FragColor;\n" + "out vec4 my_SecondaryFragColor;\n" + "void main() {\n" + " my_FragColor = vec4(1.0);\n" + " my_SecondaryFragColor = vec4(0.5);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// (ESSL 3.00.04 section 4.3.8.2) +TEST_F(MalformedShaderTest, TwoOutputsFirstLayoutQualifier) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "uniform vec4 u;\n" + "layout(location = 0) out vec4 my_FragColor;\n" + "out vec4 my_SecondaryFragColor;\n" + "void main() {\n" + " my_FragColor = vec4(1.0);\n" + " my_SecondaryFragColor = vec4(0.5);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// (ESSL 3.00.04 section 4.3.8.2) +TEST_F(MalformedShaderTest, TwoOutputsSecondLayoutQualifier) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "uniform vec4 u;\n" + "out vec4 my_FragColor;\n" + "layout(location = 0) out vec4 my_SecondaryFragColor;\n" + "void main() {\n" + " my_FragColor = vec4(1.0);\n" + " my_SecondaryFragColor = vec4(0.5);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Uniforms can be arrays (ESSL 3.00 section 4.3.5) +TEST_F(MalformedShaderTest, UniformArray) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "uniform vec4[2] u;\n" + "out vec4 my_FragColor;\n" + "void main() {\n" + " my_FragColor = u[0];\n" + "}\n"; + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// Fragment shader input variables cannot be arrays of structs (ESSL 3.00 section 4.3.4) +TEST_F(MalformedShaderTest, FragmentInputArrayOfStructs) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "struct S {\n" + " vec4 foo;\n" + "};\n" + "in S i[2];\n" + "out vec4 my_FragColor;\n" + "void main() {\n" + " my_FragColor = i[0].foo;\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Vertex shader inputs can't be arrays (ESSL 3.00 section 4.3.4) +// This test is testing the case where the array brackets are after the variable name, so +// the arrayness isn't known when the type and qualifiers are initially parsed. +TEST_F(MalformedVertexShaderTest, VertexShaderInputArray) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "in vec4 i[2];\n" + "void main() {\n" + " gl_Position = i[0];\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Vertex shader inputs can't be arrays (ESSL 3.00 section 4.3.4) +// This test is testing the case where the array brackets are after the type. +TEST_F(MalformedVertexShaderTest, VertexShaderInputArrayType) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "in vec4[2] i;\n" + "void main() {\n" + " gl_Position = i[0];\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Fragment shader inputs can't contain booleans (ESSL 3.00 section 4.3.4) +TEST_F(MalformedShaderTest, FragmentShaderInputStructWithBool) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "struct S {\n" + " bool foo;\n" + "};\n" + "in S s;\n" + "out vec4 my_FragColor;\n" + "void main() {\n" + " my_FragColor = vec4(0.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Fragment shader inputs without a flat qualifier can't contain integers (ESSL 3.00 section 4.3.4) +TEST_F(MalformedShaderTest, FragmentShaderInputStructWithInt) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "struct S {\n" + " int foo;\n" + "};\n" + "in S s;\n" + "out vec4 my_FragColor;\n" + "void main() {\n" + " my_FragColor = vec4(0.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Selecting a field of a vector that's the result of dynamic indexing a constant array should work. +TEST_F(MalformedShaderTest, ShaderSelectingFieldOfVectorIndexedFromArray) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 my_FragColor;\n" + "uniform int i;\n" + "void main() {\n" + " float f = vec2[1](vec2(0.0, 0.1))[i].x;\n" + " my_FragColor = vec4(f);\n" + "}\n"; + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// Passing an array into a function and then passing a value from that array into another function +// should work. This is a regression test for a bug where the mangled name of a TType was not +// properly updated when determining the type resulting from array indexing. +TEST_F(MalformedShaderTest, ArrayValueFromFunctionParameterAsParameter) +{ + const std::string &shaderString = + "precision mediump float;\n" + "uniform float u;\n" + "float foo(float f) {\n" + " return f * 2.0;\n" + "}\n" + "float bar(float[2] f) {\n" + " return foo(f[0]);\n" + "}\n" + "void main()\n" + "{\n" + " float arr[2];\n" + " arr[0] = u;\n" + " gl_FragColor = vec4(bar(arr));\n" + "}\n"; + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// Test that out-of-range integer literal generates an error in ESSL 3.00. +TEST_F(MalformedShaderTest, OutOfRangeIntegerLiteral) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "precision highp int;\n" + "out vec4 my_FragColor;\n" + "void main() {\n" + " my_FragColor = vec4(0x100000000);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Test that vector field selection from a value taken from an array constructor is accepted as a +// constant expression. +TEST_F(MalformedShaderTest, FieldSelectionFromVectorArrayConstructorIsConst) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 my_FragColor;\n" + "void main()\n" + "{\n" + " const float f = vec2[1](vec2(0.0, 1.0))[0].x;\n" + " my_FragColor = vec4(f);\n" + "}\n"; + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// Test that structure field selection from a value taken from an array constructor is accepted as a +// constant expression. +TEST_F(MalformedShaderTest, FieldSelectionFromStructArrayConstructorIsConst) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 my_FragColor;\n" + "struct S { float member; };\n" + "void main()\n" + "{\n" + " const float f = S[1](S(0.0))[0].member;\n" + " my_FragColor = vec4(f);\n" + "}\n"; + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// Test that a reference to a const array is accepted as a constant expression. +TEST_F(MalformedShaderTest, ArraySymbolIsConst) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 my_FragColor;\n" + "void main()\n" + "{\n" + " const float[2] arr = float[2](0.0, 1.0);\n" + " const float f = arr[0];\n" + " my_FragColor = vec4(f);\n" + "}\n"; + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// Test that using an array constructor in a parameter to a built-in function is accepted as a +// constant expression. +TEST_F(MalformedShaderTest, BuiltInFunctionAppliedToArrayConstructorIsConst) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 my_FragColor;\n" + "void main()\n" + "{\n" + " const float f = sin(float[2](0.0, 1.0)[0]);\n" + " my_FragColor = vec4(f);\n" + "}\n"; + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// Test that using an array constructor in a parameter to a built-in function is accepted as a +// constant expression. +TEST_F(MalformedShaderTest, BuiltInFunctionWithMultipleParametersAppliedToArrayConstructorIsConst) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 my_FragColor;\n" + "void main()\n" + "{\n" + " const float f = pow(1.0, float[2](0.0, 1.0)[0]);\n" + " my_FragColor = vec4(f);\n" + "}\n"; + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// Test that using an array constructor in a parameter to a constructor is accepted as a constant +// expression. +TEST_F(MalformedShaderTest, ConstructorWithMultipleParametersAppliedToArrayConstructorIsConst) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 my_FragColor;\n" + "void main()\n" + "{\n" + " const vec2 f = vec2(1.0, float[2](0.0, 1.0)[0]);\n" + " my_FragColor = vec4(f.x);\n" + "}\n"; + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// Test that using an array constructor in an operand of the ternary selection operator is accepted +// as a constant expression. +TEST_F(MalformedShaderTest, TernaryOperatorAppliedToArrayConstructorIsConst) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 my_FragColor;\n" + "void main()\n" + "{\n" + " const float f = true ? float[2](0.0, 1.0)[0] : 1.0;\n" + " my_FragColor = vec4(f);\n" + "}\n"; + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// Test that a ternary operator with one unevaluated non-constant operand is not a constant +// expression. +TEST_F(MalformedShaderTest, TernaryOperatorNonConstantOperand) +{ + const std::string &shaderString = + "precision mediump float;\n" + "uniform float u;\n" + "void main()\n" + "{\n" + " const float f = true ? 1.0 : u;\n" + " gl_FragColor = vec4(f);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Test that a sampler can't be used in constructor argument list +TEST_F(MalformedShaderTest, SamplerInConstructorArguments) +{ + const std::string &shaderString = + "precision mediump float;\n" + "uniform sampler2D s;\n" + "void main()\n" + "{\n" + " vec2 v = vec2(0.0, s);\n" + " gl_FragColor = vec4(v, 0.0, 0.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Test that void can't be used in constructor argument list +TEST_F(MalformedShaderTest, VoidInConstructorArguments) +{ + const std::string &shaderString = + "precision mediump float;\n" + "void foo() {}\n" + "void main()\n" + "{\n" + " vec2 v = vec2(0.0, foo());\n" + " gl_FragColor = vec4(v, 0.0, 0.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Test that a shader passing a struct into a constructor of array of structs with 1 element works. +TEST_F(MalformedShaderTest, SingleStructArrayConstructor) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 my_FragColor;\n" + "uniform float u;\n" + "struct S { float member; };\n" + "void main()\n" + "{\n" + " S[1] sarr = S[1](S(u));\n" + " my_FragColor = vec4(sarr[0].member);\n" + "}\n"; + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// Test that a shader with empty constructor parameter list is not accepted. +TEST_F(MalformedShaderTest, EmptyArrayConstructor) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 my_FragColor;\n" + "uniform float u;\n" + "const float[] f = f[]();\n" + "void main()\n" + "{\n" + " my_FragColor = vec4(0.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Test that indexing fragment outputs with a non-constant expression is forbidden, even if ANGLE +// is able to constant fold the index expression. ESSL 3.00 section 4.3.6. +TEST_F(MalformedShaderTest, DynamicallyIndexedFragmentOutput) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "uniform int a;\n" + "out vec4[2] my_FragData;\n" + "void main()\n" + "{\n" + " my_FragData[true ? 0 : a] = vec4(0.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Test that indexing an interface block array with a non-constant expression is forbidden, even if +// ANGLE is able to constant fold the index expression. ESSL 3.00 section 4.3.7. +TEST_F(MalformedShaderTest, DynamicallyIndexedInterfaceBlock) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "uniform int a;\n" + "uniform B\n" + "{\n" + " vec4 f;\n" + "}\n" + "blocks[2];\n" + "out vec4 my_FragColor;\n" + "void main()\n" + "{\n" + " my_FragColor = blocks[true ? 0 : a].f;\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Test that a shader that uses a struct definition in place of a struct constructor does not +// compile. See GLSL ES 1.00 section 5.4.3. +TEST_F(MalformedShaderTest, StructConstructorWithStructDefinition) +{ + const std::string &shaderString = + "precision mediump float;\n" + "void main()\n" + "{\n" + " struct s { float f; } (0.0);\n" + " gl_FragColor = vec4(0.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Test that indexing gl_FragData with a non-constant expression is forbidden in WebGL 2.0, even +// when ANGLE is able to constant fold the index. +// WebGL 2.0 spec section 'GLSL ES 1.00 Fragment Shader Output' +TEST_F(MalformedWebGL2ShaderTest, IndexFragDataWithNonConstant) +{ + const std::string &shaderString = + "precision mediump float;\n" + "void main()\n" + "{\n" + " for (int i = 0; i < 2; ++i) {\n" + " gl_FragData[true ? 0 : i] = vec4(0.0);\n" + " }\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Test that a non-constant texture offset is not accepted for textureOffset. +// ESSL 3.00 section 8.8 +TEST_F(MalformedShaderTest, TextureOffsetNonConst) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 my_FragColor;\n" + "uniform vec3 u_texCoord;\n" + "uniform mediump sampler3D u_sampler;\n" + "uniform int x;\n" + "void main()\n" + "{\n" + " my_FragColor = textureOffset(u_sampler, u_texCoord, ivec3(x, 3, -8));\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Test that a non-constant texture offset is not accepted for textureProjOffset with bias. +// ESSL 3.00 section 8.8 +TEST_F(MalformedShaderTest, TextureProjOffsetNonConst) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 my_FragColor;\n" + "uniform vec4 u_texCoord;\n" + "uniform mediump sampler3D u_sampler;\n" + "uniform int x;\n" + "void main()\n" + "{\n" + " my_FragColor = textureProjOffset(u_sampler, u_texCoord, ivec3(x, 3, -8), 0.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Test that an out-of-range texture offset is not accepted. +// GLES 3.0.4 section 3.8.10 specifies that out-of-range offset has undefined behavior. +TEST_F(MalformedShaderTest, TextureLodOffsetOutOfRange) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 my_FragColor;\n" + "uniform vec3 u_texCoord;\n" + "uniform mediump sampler3D u_sampler;\n" + "void main()\n" + "{\n" + " my_FragColor = textureLodOffset(u_sampler, u_texCoord, 0.0, ivec3(0, 0, 8));\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Test that default precision qualifier for uint is not accepted. +// ESSL 3.00.4 section 4.5.4: Only allowed for float, int and sampler types. +TEST_F(MalformedShaderTest, DefaultPrecisionUint) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "precision mediump uint;\n" + "out vec4 my_FragColor;\n" + "void main()\n" + "{\n" + " my_FragColor = vec4(0.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Test that sampler3D needs to be precision qualified. +// ESSL 3.00.4 section 4.5.4: New ESSL 3.00 sampler types don't have predefined precision. +TEST_F(MalformedShaderTest, NoPrecisionSampler3D) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "uniform sampler3D s;\n" + "out vec4 my_FragColor;\n" + "void main()\n" + "{\n" + " my_FragColor = vec4(0.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Test that using a non-constant expression in a for loop initializer is forbidden in WebGL 1.0, +// even when ANGLE is able to constant fold the initializer. +// ESSL 1.00 Appendix A. +TEST_F(MalformedWebGL1ShaderTest, NonConstantLoopIndex) +{ + const std::string &shaderString = + "precision mediump float;\n" + "uniform int u;\n" + "void main()\n" + "{\n" + " for (int i = (true ? 1 : u); i < 5; ++i) {\n" + " gl_FragColor = vec4(0.0);\n" + " }\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Regression test for an old crash bug in ANGLE. +// ForLoopUnroll used to crash when it encountered a while loop. +TEST_F(UnrollForLoopsTest, WhileLoop) +{ + const std::string &shaderString = + "precision mediump float;\n" + "void main()\n" + "{\n" + " while (true) {\n" + " gl_FragColor = vec4(0.0);\n" + " break;\n" + " }\n" + "}\n"; + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// Regression test for an old crash bug in ANGLE. +// ForLoopUnroll used to crash when it encountered a loop that didn't fit the ESSL 1.00 +// Appendix A limitations. +TEST_F(UnrollForLoopsTest, UnlimitedForLoop) +{ + const std::string &shaderString = + "precision mediump float;\n" + "void main()\n" + "{\n" + " for (;true;) {\n" + " gl_FragColor = vec4(0.0);\n" + " break;\n" + " }\n" + "}\n"; + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// Check that indices that are not integers are rejected. +// The check should be done even if ESSL 1.00 Appendix A limitations are not applied. +TEST_F(MalformedShaderTest, NonIntegerIndex) +{ + const std::string &shaderString = + "precision mediump float;\n" + "void main()\n" + "{\n" + " float f[3];\n" + " const float i = 2.0;\n" + " gl_FragColor = vec4(f[i]);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// ESSL1 shaders with a duplicate function prototype should be rejected. +// ESSL 1.00.17 section 4.2.7. +TEST_F(MalformedShaderTest, DuplicatePrototypeESSL1) +{ + const std::string &shaderString = + "precision mediump float;\n" + "void foo();\n" + "void foo();\n" + "void foo() {}\n" + "void main()\n" + "{\n" + " gl_FragColor = vec4(0.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// ESSL3 shaders with a duplicate function prototype should be allowed. +// ESSL 3.00.4 section 4.2.3. +TEST_F(MalformedShaderTest, DuplicatePrototypeESSL3) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 my_FragColor;\n" + "void foo();\n" + "void foo();\n" + "void foo() {}\n" + "void main()\n" + "{\n" + " my_FragColor = vec4(0.0);\n" + "}\n"; + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// Shaders with a local function prototype should be rejected. +// ESSL 3.00.4 section 4.2.4. +TEST_F(MalformedShaderTest, LocalFunctionPrototype) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 my_FragColor;\n" + "void main()\n" + "{\n" + " void foo();\n" + " my_FragColor = vec4(0.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// ESSL 3.00 fragment shaders can not use #pragma STDGL invariant(all). +// ESSL 3.00.4 section 4.6.1. Does not apply to other versions of ESSL. +TEST_F(MalformedShaderTest, ESSL300FragmentInvariantAll) +{ + const std::string &shaderString = + "#version 300 es\n" + "#pragma STDGL invariant(all)\n" + "precision mediump float;\n" + "out vec4 my_FragColor;\n" + "void main()\n" + "{\n" + " my_FragColor = vec4(0.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Built-in functions can be overloaded in ESSL 1.00. +TEST_F(MalformedShaderTest, ESSL100BuiltInFunctionOverload) +{ + const std::string &shaderString = + "precision mediump float;\n" + "int sin(int x)\n" + "{\n" + " return int(sin(float(x)));\n" + "}\n" + "void main()\n" + "{\n" + " gl_FragColor = vec4(sin(1));" + "}\n"; + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// Built-in functions can not be overloaded in ESSL 3.00. +TEST_F(MalformedShaderTest, ESSL300BuiltInFunctionOverload) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 my_FragColor;\n" + "int sin(int x)\n" + "{\n" + " return int(sin(float(x)));\n" + "}\n" + "void main()\n" + "{\n" + " my_FragColor = vec4(sin(1));" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Multiplying a 4x2 matrix with a 4x2 matrix should not work. +TEST_F(MalformedShaderTest, CompoundMultiplyMatrixIdenticalNonSquareDimensions) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 my_FragColor;\n" + "void main()\n" + "{\n" + " mat4x2 foo;\n" + " foo *= mat4x2(4.0);\n" + " my_FragColor = vec4(0.0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Multiplying a matrix with 2 columns and 4 rows with a 2x2 matrix should work. +TEST_F(MalformedShaderTest, CompoundMultiplyMatrixValidNonSquareDimensions) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 my_FragColor;\n" + "void main()\n" + "{\n" + " mat2x4 foo;\n" + " foo *= mat2x2(4.0);\n" + " my_FragColor = vec4(0.0);\n" + "}\n"; + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// Covers a bug where we would set the incorrect result size on an out-of-bounds vector swizzle. +TEST_F(MalformedShaderTest, OutOfBoundsVectorSwizzle) +{ + const std::string &shaderString = + "void main() {\n" + " vec2(0).qq;\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Covers a bug where strange preprocessor defines could trigger asserts. +TEST_F(MalformedShaderTest, DefineWithSemicolon) +{ + const std::string &shaderString = + "#define Def; highp\n" + "uniform Def vec2 a;\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Covers a bug in our parsing of malformed shift preprocessor expressions. +TEST_F(MalformedShaderTest, LineDirectiveUndefinedShift) +{ + const std::string &shaderString = "#line x << y"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Covers a bug in our parsing of malformed shift preprocessor expressions. +TEST_F(MalformedShaderTest, LineDirectiveNegativeShift) +{ + const std::string &shaderString = "#line x << -1"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// gl_MaxImageUnits is only available in ES 3.1 shaders. +TEST_F(MalformedShaderTest, MaxImageUnitsInES3Shader) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 myOutput;" + "void main() {\n" + " float ff = float(gl_MaxImageUnits);\n" + " myOutput = vec4(ff);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// struct += struct is an invalid operation. +TEST_F(MalformedShaderTest, StructCompoundAssignStruct) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 myOutput;\n" + "struct S { float foo; };\n" + "void main() {\n" + " S a, b;\n" + " a += b;\n" + " myOutput = vec4(0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// struct == different struct is an invalid operation. +TEST_F(MalformedShaderTest, StructEqDifferentStruct) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 myOutput;\n" + "struct S { float foo; };\n" + "struct S2 { float foobar; };\n" + "void main() {\n" + " S a;\n" + " S2 b;\n" + " a == b;\n" + " myOutput = vec4(0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Compute shaders are not supported in versions lower than 310. +TEST_F(MalformedComputeShaderTest, Version100) +{ + const std::string &shaderString = + "void main()\n" + "layout(local_size_x=1) in;\n" + "{\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Compute shaders are not supported in versions lower than 310. +TEST_F(MalformedComputeShaderTest, Version300) +{ + const std::string &shaderString = + "#version 300 es\n" + "void main()\n" + "layout(local_size_x=1) in;\n" + "{\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Compute shaders should have work group size specified. However, it is not a compile time error +// to not have the size specified, but rather a link time one. +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_F(MalformedComputeShaderTest, NoWorkGroupSizeSpecified) +{ + const std::string &shaderString = + "#version 310 es\n" + "void main()\n" + "{\n" + "}\n"; + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// Work group size is less than 1. It should be at least 1. +// GLSL ES 3.10 Revision 4, 7.1.3 Compute Shader Special Variables +// The spec is not clear whether having a local size qualifier equal zero +// is correct. +// TODO (mradev): Ask people from Khronos to clarify the spec. +TEST_F(MalformedComputeShaderTest, WorkGroupSizeTooSmallXdimension) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 0) in;\n" + "void main()\n" + "{\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Work group size is correct for the x and y dimensions, but not for the z dimension. +// GLSL ES 3.10 Revision 4, 7.1.3 Compute Shader Special Variables +TEST_F(MalformedComputeShaderTest, WorkGroupSizeTooSmallZDimension) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 4, local_size_y = 6, local_size_z = 0) in;\n" + "void main()\n" + "{\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Work group size is bigger than the minimum in the x dimension. +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_F(MalformedComputeShaderTest, WorkGroupSizeTooBigXDimension) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 9989899) in;\n" + "void main()\n" + "{\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Work group size is bigger than the minimum in the y dimension. +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_F(MalformedComputeShaderTest, WorkGroupSizeTooBigYDimension) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 5, local_size_y = 9989899) in;\n" + "void main()\n" + "{\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Work group size is definitely bigger than the minimum in the z dimension. +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_F(MalformedComputeShaderTest, WorkGroupSizeTooBigZDimension) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 5, local_size_y = 5, local_size_z = 9989899) in;\n" + "void main()\n" + "{\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Work group size specified through macro expansion. +TEST_F(MalformedComputeShaderTest, WorkGroupSizeMacro) +{ + const std::string &shaderString = + "#version 310 es\n" + "#define MYDEF(x) x" + "layout(local_size_x = MYDEF(127)) in;\n" + "void main()\n" + "{\n" + "}\n"; + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// Work group size specified as an unsigned integer. +TEST_F(MalformedComputeShaderTest, WorkGroupSizeUnsignedInteger) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 123u) in;\n" + "void main()\n" + "{\n" + "}\n"; + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// Work group size specified in hexadecimal. +TEST_F(MalformedComputeShaderTest, WorkGroupSizeHexadecimal) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 0x3A) in;\n" + "void main()\n" + "{\n" + "}\n"; + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// local_size_x is -1 in hexadecimal format. +// -1 is used as unspecified value in the TLayoutQualifier structure. +TEST_F(MalformedComputeShaderTest, WorkGroupSizeMinusOneHexadecimal) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 0xFFFFFFFF) in;\n" + "void main()\n" + "{\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Work group size specified in octal. +TEST_F(MalformedComputeShaderTest, WorkGroupSizeOctal) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 013) in;\n" + "void main()\n" + "{\n" + "}\n"; + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// Work group size is negative. It is specified in hexadecimal. +TEST_F(MalformedComputeShaderTest, WorkGroupSizeNegativeHexadecimal) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 0xFFFFFFEC) in;\n" + "void main()\n" + "{\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Multiple work group layout qualifiers with differing values. +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_F(MalformedComputeShaderTest, DifferingLayoutQualifiers) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 5, local_size_x = 6) in;\n" + "void main()\n" + "{\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Multiple work group input variables with differing local size values. +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_F(MalformedComputeShaderTest, MultipleInputVariablesDifferingLocalSize) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 5, local_size_y = 6) in;\n" + "layout(local_size_x = 5, local_size_y = 7) in;\n" + "void main()\n" + "{\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Multiple work group input variables with differing local size values. +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_F(MalformedComputeShaderTest, MultipleInputVariablesDifferingLocalSize2) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 5) in;\n" + "layout(local_size_x = 5, local_size_y = 7) in;\n" + "void main()\n" + "{\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Multiple work group input variables with the same local size values. It should compile. +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_F(MalformedComputeShaderTest, MultipleInputVariablesSameLocalSize) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 5, local_size_y = 6) in;\n" + "layout(local_size_x = 5, local_size_y = 6) in;\n" + "void main()\n" + "{\n" + "}\n"; + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// Multiple work group input variables with the same local size values. It should compile. +// Since the default value is 1, it should compile. +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_F(MalformedComputeShaderTest, MultipleInputVariablesSameLocalSize2) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 5) in;\n" + "layout(local_size_x = 5, local_size_y = 1) in;\n" + "void main()\n" + "{\n" + "}\n"; + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// Multiple work group input variables with the same local size values. It should compile. +// Since the default value is 1, it should compile. +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_F(MalformedComputeShaderTest, MultipleInputVariablesSameLocalSize3) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 5, local_size_y = 1) in;\n" + "layout(local_size_x = 5) in;\n" + "void main()\n" + "{\n" + "}\n"; + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// Specifying row_major qualifier in a work group size layout. +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_F(MalformedComputeShaderTest, RowMajorInComputeInputLayout) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 5, row_major) in;\n" + "void main()\n" + "{\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// local size layout can be used only with compute input variables +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_F(MalformedComputeShaderTest, UniformComputeInputLayout) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 5) uniform;\n" + "void main()\n" + "{\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// local size layout can be used only with compute input variables +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_F(MalformedComputeShaderTest, UniformBufferComputeInputLayout) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 5) uniform SomeBuffer { vec4 something; };\n" + "void main()\n" + "{\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// local size layout can be used only with compute input variables +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_F(MalformedComputeShaderTest, StructComputeInputLayout) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 5) struct SomeBuffer { vec4 something; };\n" + "void main()\n" + "{\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// local size layout can be used only with compute input variables +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_F(MalformedComputeShaderTest, StructBodyComputeInputLayout) +{ + const std::string &shaderString = + "#version 310 es\n" + "struct S {\n" + " layout(local_size_x = 12) vec4 foo;\n" + "};\n" + "void main()" + "{" + "}"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// local size layout can be used only with compute input variables +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_F(MalformedComputeShaderTest, TypeComputeInputLayout) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 5) vec4;\n" + "void main()\n" + "{\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Invalid use of the out storage qualifier in a compute shader. +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_F(MalformedComputeShaderTest, InvalidOutStorageQualifier) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 15) in;\n" + "out vec4 myOutput;\n" + "void main() {\n" + "}\n"; + + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Invalid use of the out storage qualifier in a compute shader. +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_F(MalformedComputeShaderTest, InvalidOutStorageQualifier2) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 15) in;\n" + "out myOutput;\n" + "void main() {\n" + "}\n"; + + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Invalid use of the in storage qualifier. Can be only used to describe the local block size. +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_F(MalformedComputeShaderTest, InvalidInStorageQualifier) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 15) in;\n" + "in vec4 myInput;\n" + "void main() {\n" + "}\n"; + + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Invalid use of the in storage qualifier. Can be only used to describe the local block size. +// The test checks a different part of the GLSL grammar than what InvalidInStorageQualifier checks. +// GLSL ES 3.10 Revision 4, 4.4.1.1 Compute Shader Inputs +TEST_F(MalformedComputeShaderTest, InvalidInStorageQualifier2) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 15) in;\n" + "in myInput;\n" + "void main() {\n" + "}\n"; + + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// The local_size layout qualifier is only available in compute shaders. +TEST_F(MalformedVertexShaderGLES31Test, InvalidUseOfLocalSizeX) +{ + const std::string &shaderString = + "#version 310 es\n" + "precision mediump float;\n" + "layout(local_size_x = 15) in vec4 myInput;\n" + "out vec4 myOutput;\n" + "void main() {\n" + " myOutput = myInput;\n" + "}\n"; + + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// The local_size layout qualifier is only available in compute shaders. +TEST_F(MalformedFragmentShaderGLES31Test, InvalidUseOfLocalSizeX) +{ + const std::string &shaderString = + "#version 310 es\n" + "precision mediump float;\n" + "layout(local_size_x = 15) in vec4 myInput;\n" + "out vec4 myOutput;\n" + "void main() {\n" + " myOutput = myInput;\n" + "}\n"; + + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// It is a compile time error to use the gl_WorkGroupSize constant if +// the local size has not been declared yet. +// GLSL ES 3.10 Revision 4, 7.1.3 Compute Shader Special Variables +TEST_F(MalformedComputeShaderTest, InvalidUsageOfWorkGroupSize) +{ + const std::string &shaderString = + "#version 310 es\n" + "void main()\n" + "{\n" + " uvec3 WorkGroupSize = gl_WorkGroupSize;\n" + "}\n" + "layout(local_size_x = 12) in;\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// The test covers the compute shader built-in variables and constants. +TEST_F(MalformedComputeShaderTest, CorrectUsageOfComputeBuiltins) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 12) in;\n" + "void main()\n" + "{\n" + " uvec3 NumWorkGroups = gl_NumWorkGroups;\n" + " uvec3 WorkGroupSize = gl_WorkGroupSize;\n" + " uvec3 WorkGroupID = gl_WorkGroupID;\n" + " uvec3 GlobalInvocationID = gl_GlobalInvocationID;\n" + " uvec3 LocalInvocationID = gl_LocalInvocationID;\n" + " uint LocalInvocationIndex = gl_LocalInvocationIndex;\n" + "}\n"; + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// It is illegal to write to a special variable. +TEST_F(MalformedComputeShaderTest, SpecialVariableNumWorkGroups) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 12) in;\n" + "void main()\n" + "{\n" + " gl_NumWorkGroups = uvec3(1); \n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// It is illegal to write to a special variable. +TEST_F(MalformedComputeShaderTest, SpecialVariableWorkGroupID) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 12) in;\n" + "void main()\n" + "{\n" + " gl_WorkGroupID = uvec3(1); \n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// It is illegal to write to a special variable. +TEST_F(MalformedComputeShaderTest, SpecialVariableLocalInvocationID) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 12) in;\n" + "void main()\n" + "{\n" + " gl_LocalInvocationID = uvec3(1); \n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// It is illegal to write to a special variable. +TEST_F(MalformedComputeShaderTest, SpecialVariableGlobalInvocationID) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 12) in;\n" + "void main()\n" + "{\n" + " gl_GlobalInvocationID = uvec3(1); \n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// It is illegal to write to a special variable. +TEST_F(MalformedComputeShaderTest, SpecialVariableLocalInvocationIndex) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 12) in;\n" + "void main()\n" + "{\n" + " gl_LocalInvocationIndex = 1; \n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// It is illegal to write to a special variable. +TEST_F(MalformedComputeShaderTest, SpecialVariableWorkGroupSize) +{ + const std::string &shaderString = + "#version 310 es\n" + "layout(local_size_x = 12) in;\n" + "void main()\n" + "{\n" + " gl_WorkGroupSize = uvec3(1); \n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// It is illegal to apply an unary operator to a sampler. +TEST_F(MalformedShaderTest, SamplerUnaryOperator) +{ + const std::string &shaderString = + "precision mediump float;\n" + "uniform sampler2D s;\n" + "void main()\n" + "{\n" + " -s;\n" + " gl_FragColor = vec4(0);\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Invariant cannot be used with a work group size declaration. +TEST_F(MalformedComputeShaderTest, InvariantBlockSize) +{ + const std::string &shaderString = + "#version 310 es\n" + "invariant layout(local_size_x = 15) in;\n" + "void main() {\n" + "}\n"; + + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Invariant cannot be used with a non-output variable in ESSL3. +TEST_F(MalformedShaderTest, InvariantNonOuput) +{ + const std::string &shaderString = + "#version 300 es\n" + "invariant int value;\n" + "void main() {\n" + "}\n"; + + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Invariant declaration should follow the following format "invariant <out variable name>". +// Test having an incorrect qualifier in the invariant declaration. +TEST_F(MalformedShaderTest, InvariantDeclarationWithStorageQualifier) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 foo;\n" + "invariant centroid foo;\n" + "void main() {\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Invariant declaration should follow the following format "invariant <out variable name>". +// Test having an incorrect precision qualifier in the invariant declaration. +TEST_F(MalformedShaderTest, InvariantDeclarationWithPrecisionQualifier) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 foo;\n" + "invariant highp foo;\n" + "void main() {\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Invariant declaration should follow the following format "invariant <out variable name>". +// Test having an incorrect layout qualifier in the invariant declaration. +TEST_F(MalformedShaderTest, InvariantDeclarationWithLayoutQualifier) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 foo;\n" + "invariant layout(location=0) foo;\n" + "void main() {\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Variable declaration with both invariant and layout qualifiers is not valid in the formal grammar +// provided in the ESSL 3.00 spec. ESSL 3.10 starts allowing this combination, but ESSL 3.00 should +// still disallow it. +TEST_F(MalformedShaderTest, VariableDeclarationWithInvariantAndLayoutQualifierESSL300) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "invariant layout(location = 0) out vec4 my_FragColor;\n" + "void main() {\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Bit shift with a rhs value > 31 has an undefined result in the GLSL spec. We disallow it. +// ESSL 3.00.6 section 5.9. +TEST_F(MalformedShaderTest, ShiftBy32) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "void main() {\n" + " uint u = 1u << 32u;\n" + "}\n"; + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Test that deferring global variable init works with an empty main(). +TEST_F(MalformedShaderTest, DeferGlobalVariableInitWithEmptyMain) +{ + const std::string &shaderString = + "precision mediump float;\n" + "uniform float u;\n" + "float foo = u;\n" + "void main() {}\n"; + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// Test that pruning empty declarations from loop init expression works. +TEST_F(MalformedShaderTest, EmptyDeclarationAsLoopInit) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "out vec4 my_FragColor;\n" + "void main()\n" + "{\n" + " int i = 0;\n" + " for (int; i < 3; i++)\n" + " {\n" + " my_FragColor = vec4(i);\n" + " }\n" + "}\n"; + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} +// r32f, r32i, r32ui do not require either the writeonly or readonly memory qualifiers. +// GLSL ES 3.10, Revision 4, 4.9 Memory Access Qualifiers +TEST_F(MalformedFragmentShaderGLES31Test, ImageR32FNoMemoryQualifier) +{ + const std::string &shaderString = + "#version 310 es\n" + "precision mediump float;\n" + "precision mediump image2D;\n" + "in vec4 myInput;\n" + "layout(r32f) uniform image2D myImage;\n" + "void main() {\n" + "}\n"; + + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// Images which do not have r32f, r32i or r32ui as internal format, must have readonly or writeonly +// specified. +// GLSL ES 3.10, Revision 4, 4.9 Memory Access Qualifiers +TEST_F(MalformedFragmentShaderGLES31Test, ImageR32FWithCorrectMemoryQualifier) +{ + const std::string &shaderString = + "#version 310 es\n" + "precision mediump float;\n" + "precision mediump image2D;\n" + "in vec4 myInput;\n" + "layout(rgba32f) uniform image2D myImage;\n" + "void main() {\n" + "}\n"; + + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// It is a compile-time error to call imageStore when the image is qualified as readonly. +// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers +TEST_F(MalformedFragmentShaderGLES31Test, StoreInReadOnlyImage) +{ + const std::string &shaderString = + "#version 310 es\n" + "precision mediump float;\n" + "precision mediump image2D;\n" + "in vec4 myInput;\n" + "layout(r32f) uniform readonly image2D myImage;\n" + "void main() {\n" + " imageStore(myImage, ivec2(0), vec4(1.0));\n" + "}\n"; + + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// It is a compile-time error to call imageLoad when the image is qualified as writeonly. +// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers +TEST_F(MalformedFragmentShaderGLES31Test, LoadFromWriteOnlyImage) +{ + const std::string &shaderString = + "#version 310 es\n" + "precision mediump float;\n" + "precision mediump image2D;\n" + "in vec4 myInput;\n" + "layout(r32f) uniform writeonly image2D myImage;\n" + "void main() {\n" + " imageLoad(myImage, ivec2(0));\n" + "}\n"; + + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// A valid declaration and usage of an image3D. +TEST_F(MalformedFragmentShaderGLES31Test, ValidImage3D) +{ + const std::string &shaderString = + "#version 310 es\n" + "precision mediump float;\n" + "precision mediump image3D;\n" + "in vec4 myInput;\n" + "layout(rgba32f) uniform readonly image3D myImage;\n" + "void main() {\n" + " imageLoad(myImage, ivec3(0));\n" + "}\n"; + + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// A valid declaration and usage of an imageCube. +TEST_F(MalformedFragmentShaderGLES31Test, ValidImageCube) +{ + const std::string &shaderString = + "#version 310 es\n" + "precision mediump float;\n" + "precision mediump imageCube;\n" + "in vec4 myInput;\n" + "layout(rgba32f) uniform readonly imageCube myImage;\n" + "void main() {\n" + " imageLoad(myImage, ivec3(0));\n" + "}\n"; + + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// A valid declaration and usage of an image2DArray. +TEST_F(MalformedFragmentShaderGLES31Test, ValidImage2DArray) +{ + const std::string &shaderString = + "#version 310 es\n" + "precision mediump float;\n" + "precision mediump image2DArray;\n" + "in vec4 myInput;\n" + "layout(rgba32f) uniform readonly image2DArray myImage;\n" + "void main() {\n" + " imageLoad(myImage, ivec3(0));\n" + "}\n"; + + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// Images cannot be l-values. +// GLSL ES 3.10 Revision 4, 4.1.7 Opaque Types +TEST_F(MalformedFragmentShaderGLES31Test, ImageLValueFunctionDefinitionInOut) +{ + const std::string &shaderString = + "#version 310 es\n" + "precision mediump float;\n" + "precision mediump image2D;\n" + "void myFunc(inout image2D someImage) {}\n" + "void main() {\n" + "}\n"; + + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Cannot assign to images. +// GLSL ES 3.10 Revision 4, 4.1.7 Opaque Types +TEST_F(MalformedFragmentShaderGLES31Test, ImageAssignment) +{ + const std::string &shaderString = + "#version 310 es\n" + "precision mediump float;\n" + "precision mediump image2D;\n" + "layout(rgba32f) uniform readonly image2D myImage;\n" + "layout(rgba32f) uniform readonly image2D myImage2;\n" + "void main() {\n" + " myImage = myImage2;\n" + "}\n"; + + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Passing an image qualifier to a function should not be able to discard the readonly qualifier. +// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers +TEST_F(MalformedFragmentShaderGLES31Test, ReadOnlyQualifierMissingInFunctionArgument) +{ + const std::string &shaderString = + "#version 310 es\n" + "precision mediump float;\n" + "precision mediump image2D;\n" + "layout(rgba32f) uniform readonly image2D myImage;\n" + "void myFunc(in image2D someImage) {}\n" + "void main() {\n" + " myFunc(myImage);\n" + "}\n"; + + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Passing an image qualifier to a function should not be able to discard the writeonly qualifier. +// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers +TEST_F(MalformedFragmentShaderGLES31Test, WriteOnlyQualifierMissingInFunctionArgument) +{ + const std::string &shaderString = + "#version 310 es\n" + "precision mediump float;\n" + "precision mediump image2D;\n" + "layout(rgba32f) uniform writeonly image2D myImage;\n" + "void myFunc(in image2D someImage) {}\n" + "void main() {\n" + " myFunc(myImage);\n" + "}\n"; + + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Passing an image parameter as an argument to another function should not be able to discard the +// writeonly qualifier. +// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers +TEST_F(MalformedFragmentShaderGLES31Test, DiscardWriteonlyInFunctionBody) +{ + const std::string &shaderString = + "#version 310 es\n" + "precision mediump float;\n" + "precision mediump image2D;\n" + "layout(rgba32f) uniform writeonly image2D myImage;\n" + "void myFunc1(in image2D someImage) {}\n" + "void myFunc2(in writeonly image2D someImage) { myFunc1(someImage); }\n" + "void main() {\n" + " myFunc2(myImage);\n" + "}\n"; + + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// The memory qualifiers for the image declaration and function argument match and the test should +// pass. +TEST_F(MalformedFragmentShaderGLES31Test, CorrectImageMemoryQualifierSpecified) +{ + const std::string &shaderString = + "#version 310 es\n" + "precision mediump float;\n" + "precision mediump image2D;\n" + "layout(r32f) uniform image2D myImage;\n" + "void myFunc(in image2D someImage) {}\n" + "void main() {\n" + " myFunc(myImage);\n" + "}\n"; + + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// The test adds additional qualifiers to the argument in the function header. +// This is correct since no memory qualifiers are discarded upon the function call. +// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers +TEST_F(MalformedFragmentShaderGLES31Test, CorrectImageMemoryQualifierSpecified2) +{ + const std::string &shaderString = + "#version 310 es\n" + "precision mediump float;\n" + "precision mediump image2D;\n" + "layout(r32f) uniform image2D myImage;\n" + "void myFunc(in readonly writeonly image2D someImage) {}\n" + "void main() {\n" + " myFunc(myImage);\n" + "}\n"; + + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// Images are not allowed in structs. +// GLSL ES 3.10 Revision 4, 4.1.8 Structures +TEST_F(MalformedFragmentShaderGLES31Test, ImageInStruct) +{ + const std::string &shaderString = + "#version 310 es\n" + "precision mediump float;\n" + "precision mediump image2D;\n" + "struct myStruct { layout(r32f) image2D myImage; };\n" + "void main() {\n" + "}\n"; + + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Images are not allowed in interface blocks. +// GLSL ES 3.10 Revision 4, 4.3.9 Interface Blocks +TEST_F(MalformedFragmentShaderGLES31Test, ImageInInterfaceBlock) +{ + const std::string &shaderString = + "#version 310 es\n" + "precision mediump float;\n" + "precision mediump image2D;\n" + "uniform myBlock { layout(r32f) image2D myImage; };\n" + "void main() {\n" + "}\n"; + + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Readonly used with an interface block. +TEST_F(MalformedFragmentShaderGLES31Test, ReadonlyWithInterfaceBlock) +{ + const std::string &shaderString = + "#version 310 es\n" + "precision mediump float;\n" + "uniform readonly myBlock { float something; };\n" + "void main() {\n" + "}\n"; + + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Readonly used with an invariant. +TEST_F(MalformedFragmentShaderGLES31Test, ReadonlyWithInvariant) +{ + const std::string &shaderString = + "#version 310 es\n" + "precision mediump float;\n" + "out vec4 something;\n" + "invariant readonly something;\n" + "void main() {\n" + "}\n"; + + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Readonly used with a member of a structure. +TEST_F(MalformedFragmentShaderGLES31Test, ReadonlyWithStructMember) +{ + const std::string &shaderString = + "#version 310 es\n" + "precision mediump float;\n" + "out vec4 something;\n" + "struct MyStruct { readonly float myMember; };\n" + "void main() {\n" + "}\n"; + + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// It should not be possible to use an internal format layout qualifier with an interface block. +TEST_F(MalformedFragmentShaderGLES31Test, ImageInternalFormatWithInterfaceBlock) +{ + const std::string &shaderString = + "#version 310 es\n" + "precision mediump float;\n" + "out vec4 something;\n" + "layout(rgba32f) uniform MyStruct { float myMember; };\n" + "void main() {\n" + "}\n"; + + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// It should not be possible to use an internal format layout qualifier with a uniform without a +// type. +TEST_F(MalformedFragmentShaderGLES31Test, ImageInternalFormatInGlobalLayoutQualifier) +{ + const std::string &shaderString = + "#version 310 es\n" + "precision mediump float;\n" + "out vec4 something;\n" + "layout(rgba32f) uniform;\n" + "void main() {\n" + "}\n"; + + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// ESSL 1.00 section 4.1.7. +// Samplers are not allowed as operands for most operations. Test this for ternary operator. +TEST_F(MalformedShaderTest, SamplerAsTernaryOperand) +{ + const std::string &shaderString = + "precision mediump float;\n" + "uniform bool u;\n" + "uniform sampler2D s1;\n" + "uniform sampler2D s2;\n" + "void main() {\n" + " gl_FragColor = texture2D(u ? s1 : s2, vec2(0, 0));\n" + "}\n"; + + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// ESSL 1.00.17 section 4.5.2. +// ESSL 3.00.6 section 4.5.3. +// Precision must be specified for floats. Test this with a declaration with no qualifiers. +TEST_F(MalformedShaderTest, FloatDeclarationNoQualifiersNoPrecision) +{ + const std::string &shaderString = + "vec4 foo = vec4(0.0);\n" + "void main()\n" + "{\n" + " gl_FragColor = foo;\n" + "}\n"; + + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Check compiler doesn't crash on incorrect unsized array declarations. +TEST_F(MalformedShaderTest, IncorrectUnsizedArray) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision mediump float;\n" + "float foo[] = 0.0;\n" + "out vec4 my_FragColor;\n" + "void main()\n" + "{\n" + " foo[0] = 1.0;\n" + " my_FragColor = vec4(foo[0]);\n" + "}\n"; + + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Check compiler doesn't crash when a bvec is on the right hand side of a logical operator. +// ESSL 3.00.6 section 5.9. +TEST_F(MalformedShaderTest, LogicalOpRHSIsBVec) +{ + const std::string &shaderString = + "#version 300 es\n" + "void main()\n" + "{\n" + " bool b;\n" + " bvec3 b3;\n" + " b && b3;\n" + "}\n"; + + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Check compiler doesn't crash when there's an unsized array constructor with no parameters. +// ESSL 3.00.6 section 4.1.9: Array size must be greater than zero. +TEST_F(MalformedShaderTest, UnsizedArrayConstructorNoParameters) +{ + const std::string &shaderString = + "#version 300 es\n" + "void main()\n" + "{\n" + " int[]();\n" + "}\n"; + + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Passing an image parameter as an argument to another function should not be able to discard the +// coherent qualifier. +TEST_F(MalformedFragmentShaderGLES31Test, CoherentQualifierMissingInFunctionArgument) +{ + const std::string &shaderString = + "#version 310 es\n" + "precision mediump float;\n" + "precision mediump image2D;\n" + "layout(r32f) uniform coherent image2D myImage;\n" + "void myFunc(in image2D someImage) {}\n" + "void main() {\n" + " myFunc(myImage);\n" + "}\n"; + + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// Passing an image parameter as an argument to another function should not be able to discard the +// volatile qualifier. +TEST_F(MalformedFragmentShaderGLES31Test, VolatileQualifierMissingInFunctionArgument) +{ + const std::string &shaderString = + "#version 310 es\n" + "precision mediump float;\n" + "precision mediump image2D;\n" + "layout(r32f) uniform volatile image2D myImage;\n" + "void myFunc(in image2D someImage) {}\n" + "void main() {\n" + " myFunc(myImage);\n" + "}\n"; + + if (compile(shaderString)) + { + FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; + } +} + +// The restrict qualifier can be discarded from a function argument. +// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers +TEST_F(MalformedFragmentShaderGLES31Test, RestrictQualifierDiscardedInFunctionArgument) +{ + const std::string &shaderString = + "#version 310 es\n" + "precision mediump float;\n" + "precision mediump image2D;\n" + "layout(r32f) uniform restrict image2D myImage;\n" + "void myFunc(in image2D someImage) {}\n" + "void main() {\n" + " myFunc(myImage);\n" + "}\n"; + + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +} + +// Function image arguments can be overqualified. +// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers +TEST_F(MalformedFragmentShaderGLES31Test, OverqualifyingImageParameter) +{ + const std::string &shaderString = + "#version 310 es\n" + "precision mediump float;\n" + "precision mediump image2D;\n" + "layout(r32f) uniform image2D myImage;\n" + "void myFunc(in coherent volatile image2D someImage) {}\n" + "void main() {\n" + " myFunc(myImage);\n" + "}\n"; + + if (!compile(shaderString)) + { + FAIL() << "Shader compilation failed, expecting success " << mInfoLog; + } +}
\ No newline at end of file |