| // |
| // 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 "tests/test_utils/ShaderCompileTreeTest.h" |
| |
| using namespace sh; |
| |
| class QualificationOrderFragmentShaderTest : public ShaderCompileTreeTest |
| { |
| public: |
| QualificationOrderFragmentShaderTest() {} |
| |
| protected: |
| void initResources(ShBuiltInResources *resources) override |
| { |
| resources->MaxDrawBuffers = (getShaderSpec() == SH_GLES2_SPEC) ? 1 : 8; |
| } |
| |
| ::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; } |
| |
| ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; } |
| }; |
| |
| class QualificationOrderVertexShaderTest : public QualificationOrderFragmentShaderTest |
| { |
| public: |
| QualificationOrderVertexShaderTest() {} |
| |
| protected: |
| ::GLenum getShaderType() const override { return GL_VERTEX_SHADER; } |
| }; |
| |
| // Repeating centroid qualifier is invalid. |
| TEST_F(QualificationOrderFragmentShaderTest, 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)) |
| { |
| FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; |
| } |
| } |
| |
| // Repeating uniform storage qualifiers is invalid. |
| TEST_F(QualificationOrderFragmentShaderTest, 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)) |
| { |
| FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; |
| } |
| } |
| |
| // Repeating varying storage qualifiers is invalid. |
| TEST_F(QualificationOrderFragmentShaderTest, RepeatingVaryings) |
| { |
| const std::string &shaderString = |
| "precision mediump float;\n" |
| "varying varying vec4 myColor;\n" |
| "void main() {\n" |
| "}\n"; |
| |
| if (compile(shaderString)) |
| { |
| FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; |
| } |
| } |
| |
| // Layout qualifier should be before the storage qualifiers. |
| TEST_F(QualificationOrderFragmentShaderTest, 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)) |
| { |
| FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; |
| } |
| } |
| |
| // Centroid out is the correct order. Out centroid is incorrect. |
| TEST_F(QualificationOrderVertexShaderTest, 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)) |
| { |
| FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; |
| } |
| } |
| |
| // Centroid in is the correct order. In centroid is incorrect. |
| TEST_F(QualificationOrderFragmentShaderTest, 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)) |
| { |
| FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; |
| } |
| } |
| |
| // Type cannot be before the storage qualifier. |
| TEST_F(QualificationOrderFragmentShaderTest, 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)) |
| { |
| FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; |
| } |
| } |
| |
| // A variable cannot have two conflicting storage qualifiers. |
| TEST_F(QualificationOrderFragmentShaderTest, 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)) |
| { |
| FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; |
| } |
| } |
| |
| // A variable cannot have two different layout qualifiers. |
| TEST_F(QualificationOrderFragmentShaderTest, 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)) |
| { |
| FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; |
| } |
| } |
| |
| // A variable cannot have repeating invariant qualifiers. |
| TEST_F(QualificationOrderFragmentShaderTest, 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)) |
| { |
| FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; |
| } |
| } |
| |
| // A variable cannot have repeating storage qualifiers. |
| TEST_F(QualificationOrderVertexShaderTest, 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)) |
| { |
| FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; |
| } |
| } |
| |
| // Wrong order for invariant varying. It should be 'invariant varying', not 'varying invariant'. |
| TEST_F(QualificationOrderVertexShaderTest, 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)) |
| { |
| FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; |
| } |
| } |
| |
| // A variable cannot have repeating storage qualifiers. |
| TEST_F(QualificationOrderVertexShaderTest, AttributeVaryingMix) |
| { |
| const std::string &shaderString = |
| "precision mediump float;\n" |
| "attribute varying vec4 positionIN;\n" |
| "void main() {\n" |
| "gl_Position = positionIN;\n" |
| "}\n"; |
| |
| if (compile(shaderString)) |
| { |
| FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; |
| } |
| } |
| |
| // A variable cannot have repeating storage qualifiers. |
| TEST_F(QualificationOrderVertexShaderTest, VaryingAttributeMix) |
| { |
| const std::string &shaderString = |
| "precision mediump float;\n" |
| "varying attribute vec4 positionIN;\n" |
| "void main() {\n" |
| "gl_Position = positionIN;\n" |
| "}\n"; |
| if (compile(shaderString)) |
| { |
| FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; |
| } |
| } |
| |
| // A variable cannot have repeating interpolation qualifiers. |
| TEST_F(QualificationOrderVertexShaderTest, 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)) |
| { |
| 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(QualificationOrderVertexShaderTest, 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)) |
| { |
| FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; |
| } |
| } |
| |
| // The correct order is invariant, interpolation, storage. |
| TEST_F(QualificationOrderVertexShaderTest, 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)) |
| { |
| FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; |
| } |
| } |
| |
| // The invariant qualifer has to be before the storage qualifiers. |
| TEST_F(QualificationOrderVertexShaderTest, 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)) |
| { |
| FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; |
| } |
| } |
| |
| // The precision qualifier is after the storage qualifiers. |
| TEST_F(QualificationOrderVertexShaderTest, 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)) |
| { |
| FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; |
| } |
| } |
| |
| // A variable cannot have multiple declarations of the 'in' storage qualifier. |
| TEST_F(QualificationOrderVertexShaderTest, 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)) |
| { |
| FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; |
| } |
| } |
| |
| // A variable cannot have multiple declarations of the 'attribute' storage qualifier. |
| TEST_F(QualificationOrderVertexShaderTest, 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)) |
| { |
| FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; |
| } |
| } |
| |
| // Vertex input cannot be qualified with invariant. |
| TEST_F(QualificationOrderVertexShaderTest, 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)) |
| { |
| FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; |
| } |
| } |
| |
| // Cannot have a function parameter with the invariant qualifier. |
| TEST_F(QualificationOrderFragmentShaderTest, 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)) |
| { |
| FAIL() << "Shader compilation succeeded, expecting failure" << mInfoLog; |
| } |
| } |
| |
| // Cannot have a function parameter with the attribute qualifier. |
| TEST_F(QualificationOrderFragmentShaderTest, 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)) |
| { |
| FAIL() << "Shader compilation succeeded, expecting failure" << mInfoLog; |
| } |
| } |
| |
| // Cannot have a function parameter with the varying qualifier. |
| TEST_F(QualificationOrderFragmentShaderTest, 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)) |
| { |
| FAIL() << "Shader compilation succeeded, expecting failure" << mInfoLog; |
| } |
| } |
| |
| // Cannot have a function parameter with the layout qualifier |
| TEST_F(QualificationOrderFragmentShaderTest, 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)) |
| { |
| FAIL() << "Shader compilation succeeded, expecting failure" << mInfoLog; |
| } |
| } |
| |
| // Cannot have a function parameter with the centroid qualifier |
| TEST_F(QualificationOrderFragmentShaderTest, 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)) |
| { |
| FAIL() << "Shader compilation succeeded, expecting failure" << mInfoLog; |
| } |
| } |
| |
| // Cannot have a function parameter with the flat qualifier |
| TEST_F(QualificationOrderFragmentShaderTest, 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)) |
| { |
| 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(QualificationOrderFragmentShaderTest, 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)) |
| { |
| FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; |
| } |
| } |