// // Copyright (c) 2016 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. // // QualificationOrder_test.cpp: // OpenGL ES 3.1 removes the strict order of qualifiers imposed by the grammar. // This file contains tests for invalid order and usage of qualifiers. #include "angle_gl.h" #include "gtest/gtest.h" #include "GLSLANG/ShaderLang.h" #include "compiler/translator/TranslatorESSL.h" using namespace sh; class QualificationOrderShaderTest : public testing::Test { public: QualificationOrderShaderTest() {} protected: virtual void SetUp() {} virtual void TearDown() {} // Return true when compilation succeeds bool compile(const std::string &shaderString, ::GLenum shaderType, ShShaderSpec spec) { ShBuiltInResources resources; InitBuiltInResources(&resources); resources.MaxDrawBuffers = (spec == SH_GLES2_SPEC) ? 1 : 8; TranslatorESSL *translator = new TranslatorESSL(shaderType, spec); EXPECT_TRUE(translator->Init(resources)); const char *shaderStrings[] = {shaderString.c_str()}; bool compilationSuccess = translator->compile(shaderStrings, 1, SH_INTERMEDIATE_TREE); TInfoSink &infoSink = translator->getInfoSink(); mInfoLog = infoSink.info.c_str(); delete translator; return compilationSuccess; } protected: std::string mInfoLog; }; // Repeating centroid qualifier is invalid. TEST_F(QualificationOrderShaderTest, RepeatingCentroid) { const std::string &shaderString = "#version 300 es\n" "precision mediump float;\n" "flat centroid centroid in float myValue;\n" "void main() {\n" "}\n"; if (compile(shaderString, GL_FRAGMENT_SHADER, SH_GLES3_1_SPEC)) { FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; } } // Repeating uniform storage qualifiers is invalid. TEST_F(QualificationOrderShaderTest, RepeatingUniforms) { const std::string &shaderString = "#version 300 es\n" "precision mediump float;\n" "uniform uniform float myValue;\n" "void main() {\n" "}\n"; if (compile(shaderString, GL_FRAGMENT_SHADER, SH_GLES3_1_SPEC)) { FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; } } // Repeating varying storage qualifiers is invalid. TEST_F(QualificationOrderShaderTest, RepeatingVaryings) { const std::string &shaderString = "precision mediump float;\n" "varying varying vec4 myColor;\n" "void main() {\n" "}\n"; if (compile(shaderString, GL_FRAGMENT_SHADER, SH_GLES3_1_SPEC)) { FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; } } // Layout qualifier should be before the storage qualifiers. TEST_F(QualificationOrderShaderTest, WrongOrderQualifiers) { const std::string &shaderString = "#version 300 es\n" "precision mediump float;\n" "out layout(location=1) vec4 myColor;\n" "void main() {\n" "}\n"; if (compile(shaderString, GL_FRAGMENT_SHADER, SH_GLES3_1_SPEC)) { FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; } } // Centroid out is the correct order. Out centroid is incorrect. TEST_F(QualificationOrderShaderTest, WrongOrderCentroidOut) { const std::string &shaderString = "#version 300 es\n" "precision mediump float;\n" "in vec4 uv;\n" "out centroid vec4 position;\n" "void main() {\n" "position = uv;\n" "gl_Position = uv;\n" "}\n"; if (compile(shaderString, GL_VERTEX_SHADER, SH_GLES3_SPEC)) { FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; } } // Centroid in is the correct order. In centroid is incorrect. TEST_F(QualificationOrderShaderTest, WrongOrderCentroidIn) { const std::string &shaderString = "#version 300 es\n" "precision mediump float;\n" "in centroid vec4 colorIN;\n" "out vec4 colorOUT;\n" "void main() {\n" "colorOUT = colorIN;\n" "}\n"; if (compile(shaderString, GL_FRAGMENT_SHADER, SH_GLES3_SPEC)) { FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; } } // Type cannot be before the storage qualifier. TEST_F(QualificationOrderShaderTest, WrongOrderTypeStorage) { const std::string &shaderString = "#version 300 es\n" "precision mediump float;\n" "centroid in vec4 colorIN;\n" "vec4 out colorOUT;\n" "void main() {\n" "colorOUT = colorIN;\n" "}\n"; if (compile(shaderString, GL_FRAGMENT_SHADER, SH_GLES3_SPEC)) { FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; } } // A variable cannot have two conflicting storage qualifiers. TEST_F(QualificationOrderShaderTest, RepeatingDifferentStorageQualifiers) { const std::string &shaderString = "#version 300 es\n" "precision mediump float;\n" "centroid in vec4 colorIN;\n" "uniform out vec4 colorOUT;\n" "void main() {\n" "colorOUT = colorIN;\n" "}\n"; if (compile(shaderString, GL_FRAGMENT_SHADER, SH_GLES3_SPEC)) { FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; } } // A variable cannot have two different layout qualifiers. TEST_F(QualificationOrderShaderTest, RepeatingLayoutQualifiers) { const std::string &shaderString = "#version 300 es\n" "precision mediump float;\n" "in vec4 colorIN;\n" "layout(location=0) layout(location=0) out vec4 colorOUT;\n" "void main() {\n" "colorOUT = colorIN;\n" "}\n"; if (compile(shaderString, GL_FRAGMENT_SHADER, SH_GLES3_SPEC)) { FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; } } // A variable cannot have repeating invariant qualifiers. TEST_F(QualificationOrderShaderTest, RepeatingInvariantQualifiers) { const std::string &shaderString = "#version 300 es\n" "precision mediump float;\n" "in vec4 colorIN;\n" "invariant invariant out vec4 colorOUT;\n" "void main() {\n" "colorOUT = colorIN;\n" "}\n"; if (compile(shaderString, GL_FRAGMENT_SHADER, SH_GLES3_SPEC)) { FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; } } // A variable cannot have repeating storage qualifiers. TEST_F(QualificationOrderShaderTest, RepeatingAttributes) { const std::string &shaderString = "precision mediump float;\n" "attribute attribute vec4 positionIN;\n" "void main() {\n" "gl_Position = positionIN;\n" "}\n"; if (compile(shaderString, GL_VERTEX_SHADER, SH_GLES3_SPEC)) { FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; } } // Wrong order for invariant varying. It should be 'invariant varying', not 'varying invariant'. TEST_F(QualificationOrderShaderTest, VaryingInvariantWrongOrder) { const std::string &shaderString = "precision mediump float;\n" "attribute vec4 positionIN;\n" "varying invariant vec4 dataOUT;\n" "void main() {\n" "gl_Position = positionIN;\n" "dataOUT = 0.5 * dataOUT + vec4(0.5);\n" "}\n"; if (compile(shaderString, GL_VERTEX_SHADER, SH_GLES3_SPEC)) { FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; } } // A variable cannot have repeating storage qualifiers. TEST_F(QualificationOrderShaderTest, AttributeVaryingMix) { const std::string &shaderString1 = "precision mediump float;\n" "attribute varying vec4 positionIN;\n" "void main() {\n" "gl_Position = positionIN;\n" "}\n"; const std::string &shaderString2 = "precision mediump float;\n" "varying attribute vec4 positionIN;\n" "void main() {\n" "gl_Position = positionIN;\n" "}\n"; if (compile(shaderString1, GL_VERTEX_SHADER, SH_GLES3_SPEC)) { FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; } if (compile(shaderString2, GL_VERTEX_SHADER, SH_GLES3_SPEC)) { FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; } } // A variable cannot have repeating interpolation qualifiers. TEST_F(QualificationOrderShaderTest, RepeatingInterpolationQualifiers) { const std::string &shaderString = "#version 300 es\n" "precision mediump float;\n" "in vec4 positionIN;\n" "flat flat out vec4 dataOUT;\n" "void main() {\n" "gl_Position = positionIN;\n" "dataOUT = 0.5 * dataOUT + vec4(0.5);\n" "}\n"; if (compile(shaderString, GL_VERTEX_SHADER, SH_GLES3_SPEC)) { FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; } } // Wrong order for the interpolation and storage qualifier. The correct order is interpolation // qualifier and then storage qualifier. TEST_F(QualificationOrderShaderTest, WrongOrderInterpolationStorageQualifiers) { const std::string &shaderString = "#version 300 es\n" "precision mediump float;\n" "in vec4 positionIN;\n" "out flat vec4 dataOUT;\n" "void main() {\n" "gl_Position = positionIN;\n" "dataOUT = 0.5 * dataOUT + vec4(0.5);\n" "}\n"; if (compile(shaderString, GL_VERTEX_SHADER, SH_GLES3_SPEC)) { FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; } } // The correct order is invariant, interpolation, storage. TEST_F(QualificationOrderShaderTest, WrongOrderInvariantInterpolationStorageQualifiers) { const std::string &shaderString = "#version 300 es\n" "precision mediump float;\n" "in vec4 positionIN;\n" "flat invariant out vec4 dataOUT;\n" "void main() {\n" "gl_Position = positionIN;\n" "dataOUT = 0.5 * dataOUT + vec4(0.5);\n" "}\n"; if (compile(shaderString, GL_VERTEX_SHADER, SH_GLES3_SPEC)) { FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; } } // The invariant qualifer has to be before the storage qualifiers. TEST_F(QualificationOrderShaderTest, WrongOrderInvariantNotFirst) { const std::string &shaderString = "#version 300 es\n" "precision mediump float;\n" "in vec4 positionIN;\n" "centroid out invariant vec4 dataOUT;\n" "void main() {\n" "gl_Position = positionIN;\n" "dataOUT = 0.5 * dataOUT + vec4(0.5);\n" "}\n"; if (compile(shaderString, GL_VERTEX_SHADER, SH_GLES3_SPEC)) { FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; } } // The precision qualifier is after the storage qualifiers. TEST_F(QualificationOrderShaderTest, WrongOrderPrecision) { const std::string &shaderString = "#version 300 es\n" "precision mediump float;\n" "in vec4 positionIN;\n" "highp centroid out vec4 dataOUT;\n" "void main() {\n" "gl_Position = positionIN;\n" "dataOUT = 0.5 * dataOUT + vec4(0.5);\n" "}\n"; if (compile(shaderString, GL_VERTEX_SHADER, SH_GLES3_SPEC)) { FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; } } // A variable cannot have multiple declarations of the 'in' storage qualifier. TEST_F(QualificationOrderShaderTest, RepeatingInQualifier) { const std::string &shaderString = "#version 300 es\n" "precision mediump float;\n" "in in vec4 positionIN;\n" "void main() {\n" "gl_Position = positionIN;\n" "}\n"; if (compile(shaderString, GL_VERTEX_SHADER, SH_GLES3_SPEC)) { FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; } } // A variable cannot have multiple declarations of the 'attribute' storage qualifier. TEST_F(QualificationOrderShaderTest, RepeatingAttributeQualifier) { const std::string &shaderString = "precision mediump float;\n" "attribute attribute vec4 positionIN;\n" "void main() {\n" "gl_Position = positionIN;\n" "}\n"; if (compile(shaderString, GL_VERTEX_SHADER, SH_GLES3_SPEC)) { FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; } } // Vertex input cannot be qualified with invariant. TEST_F(QualificationOrderShaderTest, InvariantVertexInput) { const std::string &shaderString = "precision mediump float;\n" "invariant attribute vec4 positionIN;\n" "void main() {\n" "gl_Position = positionIN;\n" "}\n"; if (compile(shaderString, GL_VERTEX_SHADER, SH_GLES3_SPEC)) { FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; } } // Cannot have a function parameter with the invariant qualifier. TEST_F(QualificationOrderShaderTest, InvalidFunctionParametersInvariant) { const std::string &shaderString = "precision lowp float;\n" "varying float value;\n" "float foo0 (invariant in float x) {\n" " return 2.0*x;\n" "}\n" "void main()\n" "{\n" " gl_FragColor = vec4(foo0(value));\n" "}\n"; if (compile(shaderString, GL_FRAGMENT_SHADER, SH_GLES3_SPEC)) { FAIL() << "Shader compilation succeeded, expecting failure" << mInfoLog; } } // Cannot have a function parameter with the attribute qualifier. TEST_F(QualificationOrderShaderTest, InvalidFunctionParametersAttribute) { const std::string &shaderString = "precision lowp float;\n" "varying float value;\n" "float foo0 (attribute float x) {\n" " return 2.0*x;\n" "}\n" "void main()\n" "{\n" " gl_FragColor = vec4(foo0(value));\n" "}\n"; if (compile(shaderString, GL_FRAGMENT_SHADER, SH_GLES3_SPEC)) { FAIL() << "Shader compilation succeeded, expecting failure" << mInfoLog; } } // Cannot have a function parameter with the varying qualifier. TEST_F(QualificationOrderShaderTest, InvalidFunctionParametersVarying) { const std::string &shaderString = "precision lowp float;\n" "varying float value;\n" "float foo0 (varying float x) {\n" " return 2.0*x;\n" "}\n" "void main()\n" "{\n" " gl_FragColor = vec4(foo0(value));\n" "}\n"; if (compile(shaderString, GL_FRAGMENT_SHADER, SH_GLES3_SPEC)) { FAIL() << "Shader compilation succeeded, expecting failure" << mInfoLog; } } // Cannot have a function parameter with the layout qualifier TEST_F(QualificationOrderShaderTest, InvalidFunctionParametersLayout) { const std::string &shaderString = "#version 300 es\n" "precision lowp float;\n" "in float value;\n" "float foo0 (layout(location = 3) in float x) {\n" " return 2.0*x;\n" "}\n" "out vec4 colorOUT;\n" "void main()\n" "{\n" " colorOUT = vec4(foo0(value));\n" "}\n"; if (compile(shaderString, GL_FRAGMENT_SHADER, SH_GLES3_SPEC)) { FAIL() << "Shader compilation succeeded, expecting failure" << mInfoLog; } } // Cannot have a function parameter with the centroid qualifier TEST_F(QualificationOrderShaderTest, InvalidFunctionParametersCentroidIn) { const std::string &shaderString = "#version 300 es\n" "precision lowp float;\n" "in float value;\n" "float foo0 (centroid in float x) {\n" " return 2.0*x;\n" "}\n" "out vec4 colorOUT;\n" "void main()\n" "{\n" " colorOUT = vec4(foo0(value));\n" "}\n"; if (compile(shaderString, GL_FRAGMENT_SHADER, SH_GLES3_SPEC)) { FAIL() << "Shader compilation succeeded, expecting failure" << mInfoLog; } } // Cannot have a function parameter with the flat qualifier TEST_F(QualificationOrderShaderTest, InvalidFunctionParametersFlatIn) { const std::string &shaderString = "#version 300 es\n" "precision lowp float;\n" "in float value;\n" "float foo0 (flat in float x) {\n" " return 2.0*x;\n" "}\n" "out vec4 colorOUT;\n" "void main()\n" "{\n" " colorOUT = vec4(foo0(value));\n" "}\n"; if (compile(shaderString, GL_FRAGMENT_SHADER, SH_GLES3_SPEC)) { FAIL() << "Shader compilation succeeded, expecting failure" << mInfoLog; } } // Output layout location qualifier can't appear more than once within a declaration. // GLSL ES 3.00.6 section 4.3.8.2 Output Layout Qualifiers. TEST_F(QualificationOrderShaderTest, TwoOutputLocations) { const std::string &shaderString = "#version 300 es\n" "precision mediump float;\n" "layout(location=1, location=2) out vec4 myColor;\n" "void main() {\n" "}\n"; if (compile(shaderString, GL_FRAGMENT_SHADER, SH_GLES3_SPEC)) { FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; } }