Edit

kc3-lang/angle/src/tests/compiler_tests/BufferVariables_test.cpp

Branch :

  • Show log

    Commit

  • Author : Stuart Morgan
    Date : 2019-08-14 12:25:12
    Hash : 9d737966
    Message : Standardize copyright notices to project style For all "ANGLE Project" copyrights, standardize to the format specified by the style guide. Changes: - "Copyright (c)" and "Copyright(c)" changed to just "Copyright". - Removed the second half of date ranges ("Y1Y1-Y2Y2"->"Y1Y1"). - Fixed a small number of files that had no copyright date using the initial commit year from the version control history. - Fixed one instance of copyright being "The ANGLE Project" rather than "The ANGLE Project Authors" These changes are applied both to the copyright of source file, and where applicable to copyright statements that are generated by templates. BUG=angleproject:3811 Change-Id: I973dd65e4ef9deeba232d5be74c768256a0eb2e5 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1754397 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: Jamie Madill <jmadill@chromium.org>

  • src/tests/compiler_tests/BufferVariables_test.cpp
  • //
    // Copyright 2017 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.
    //
    // BufferVariables_test.cpp:
    //   Tests for buffer variables in GLSL ES 3.10 section 4.3.7.
    //
    
    #include "gtest/gtest.h"
    
    #include "GLSLANG/ShaderLang.h"
    #include "angle_gl.h"
    #include "gtest/gtest.h"
    #include "tests/test_utils/ShaderCompileTreeTest.h"
    
    using namespace sh;
    
    class BufferVariablesTest : public ShaderCompileTreeTest
    {
      public:
        BufferVariablesTest() {}
    
      protected:
        ::GLenum getShaderType() const override { return GL_VERTEX_SHADER; }
        ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; }
        void initResources(ShBuiltInResources *resources) override
        {
            resources->MaxShaderStorageBufferBindings = 8;
        }
    };
    
    // Test that the buffer qualifier described in GLSL ES 3.10 section 4.3.7 can be successfully
    // compiled.
    TEST_F(BufferVariablesTest, BasicShaderStorageBlockDeclaration)
    {
        const std::string &source =
            "#version 310 es\n"
            "layout(binding = 3) buffer buf {\n"
            "    int b1;\n"
            "    buffer int b2;\n"
            "};\n"
            "void main()\n"
            "{\n"
            "}\n";
        if (!compile(source))
        {
            FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
        }
    }
    
    // Test that shader storage block layout qualifiers can be declared for global scope.
    TEST_F(BufferVariablesTest, LayoutQualifiersDeclaredInGlobal)
    {
        const std::string &source =
            "#version 310 es\n"
            "layout(shared, column_major) buffer;\n"
            "void main()\n"
            "{\n"
            "}\n";
        if (!compile(source))
        {
            FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
        }
    }
    
    // Test that shader storage block can be used with one or more memory qualifiers.
    TEST_F(BufferVariablesTest, ShaderStorageBlockWithMemoryQualifier)
    {
        const std::string &source =
            "#version 310 es\n"
            "layout(binding = 3) writeonly buffer buf {\n"
            "    int b1;\n"
            "    buffer int b2;\n"
            "};\n"
            "void main()\n"
            "{\n"
            "}\n";
        if (!compile(source))
        {
            FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
        }
    }
    
    // Test that buffer variables can be used with one or more memory qualifiers.
    TEST_F(BufferVariablesTest, BufferVariablesWithMemoryQualifier)
    {
        const std::string &source =
            "#version 310 es\n"
            "layout(binding = 3) buffer buf {\n"
            "    writeonly int b1;\n"
            "    writeonly buffer int b2;\n"
            "};\n"
            "void main()\n"
            "{\n"
            "}\n";
        if (!compile(source))
        {
            FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
        }
    }
    
    // Test that it is a compile-time error to declare buffer variables at global scope (outside a
    // block).
    TEST_F(BufferVariablesTest, DeclareBufferVariableAtGlobal)
    {
        const std::string &source =
            "#version 310 es\n"
            "layout(binding = 3) buffer int a;\n"
            "void main()\n"
            "{\n"
            "}\n";
        if (compile(source))
        {
            FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
        }
    }
    
    // Test that the buffer variable can't be opaque type.
    TEST_F(BufferVariablesTest, BufferVariableWithOpaqueType)
    {
        const std::string &source =
            "#version 310 es\n"
            "layout(binding = 3) buffer buf {\n"
            "    int b1;\n"
            "    atomic_uint b2;\n"
            "};\n"
            "void main()\n"
            "{\n"
            "}\n";
        if (compile(source))
        {
            FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
        }
    }
    
    // Test that the uniform variable can't be in shader storage block.
    TEST_F(BufferVariablesTest, UniformVariableInShaderStorageBlock)
    {
        const std::string &source =
            "#version 310 es\n"
            "layout(binding = 3) buffer buf {\n"
            "    uniform int a;\n"
            "};\n"
            "void main()\n"
            "{\n"
            "}\n";
        if (compile(source))
        {
            FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
        }
    }
    
    // Test that buffer qualifier is not supported in verson lower than GLSL ES 3.10.
    TEST_F(BufferVariablesTest, BufferQualifierInESSL3)
    {
        const std::string &source =
            "#version 300 es\n"
            "layout(binding = 3) buffer buf {\n"
            "    int b1;\n"
            "    buffer int b2;\n"
            "};\n"
            "void main()\n"
            "{\n"
            "}\n";
        if (compile(source))
        {
            FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
        }
    }
    
    // Test that can't assign to a readonly buffer variable.
    TEST_F(BufferVariablesTest, AssignToReadonlyBufferVariable)
    {
        const std::string &source =
            "#version 310 es\n"
            "layout(binding = 3) buffer buf {\n"
            "    readonly int b1;\n"
            "};\n"
            "void main()\n"
            "{\n"
            "    b1 = 5;\n"
            "}\n";
        if (compile(source))
        {
            FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
        }
    }
    
    // Test that can't assign to a buffer variable declared within shader storage block with readonly.
    TEST_F(BufferVariablesTest, AssignToBufferVariableWithinReadonlyBlock)
    {
        const std::string &source =
            "#version 310 es\n"
            "layout(binding = 3) readonly buffer buf {\n"
            "    int b1;\n"
            "};\n"
            "void main()\n"
            "{\n"
            "    b1 = 5;\n"
            "}\n";
        if (compile(source))
        {
            FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
        }
    }
    
    // Test that can't assign to a readonly buffer variable through an instance name.
    TEST_F(BufferVariablesTest, AssignToReadonlyBufferVariableByInstanceName)
    {
        const std::string &source =
            R"(#version 310 es
            layout(binding = 3) buffer buf {
                readonly float f;
            } instanceBuffer;
            void main()
            {
                instanceBuffer.f += 0.2;
            })";
        if (compile(source))
        {
            FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
        }
    }
    
    // Test that can't assign to a readonly struct buffer variable.
    TEST_F(BufferVariablesTest, AssignToReadonlyStructBufferVariable)
    {
        const std::string &source =
            R"(#version 310 es
            struct S {
                float f;
            };
            layout(binding = 3) buffer buf {
                readonly S s;
            };
            void main()
            {
                s.f += 0.2;
            })";
        if (compile(source))
        {
            FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
        }
    }
    
    // Test that can't assign to a readonly struct buffer variable through an instance name.
    TEST_F(BufferVariablesTest, AssignToReadonlyStructBufferVariableByInstanceName)
    {
        const std::string &source =
            R"(#version 310 es
            struct S {
                float f;
            };
            layout(binding = 3) buffer buf {
                readonly S s;
            } instanceBuffer;
            void main()
            {
                instanceBuffer.s.f += 0.2;
            })";
        if (compile(source))
        {
            FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
        }
    }
    
    // Test that a readonly and writeonly buffer variable should neither read or write.
    TEST_F(BufferVariablesTest, AccessReadonlyWriteonlyBufferVariable)
    {
        const std::string &source =
            "#version 310 es\n"
            "layout(binding = 3) buffer buf {\n"
            "    readonly writeonly int b1;\n"
            "};\n"
            "void main()\n"
            "{\n"
            "    b1 = 5;\n"
            "    int test = b1;\n"
            "}\n";
        if (compile(source))
        {
            FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
        }
    }
    
    // Test that accessing a writeonly buffer variable should be error.
    TEST_F(BufferVariablesTest, AccessWriteonlyBufferVariable)
    {
        const std::string &source =
            "#version 310 es\n"
            "layout(binding = 3) buffer buf {\n"
            "    writeonly int b1;\n"
            "};\n"
            "void main()\n"
            "{\n"
            "    int test = b1;\n"
            "}\n";
        if (compile(source))
        {
            FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
        }
    }
    
    // Test that accessing a buffer variable through an instance name is ok.
    TEST_F(BufferVariablesTest, AccessReadonlyBufferVariableByInstanceName)
    {
        const std::string &source =
            "#version 310 es\n"
            "layout(binding = 3) buffer buf {\n"
            "    readonly float f;\n"
            "} instanceBuffer;\n"
            "void main()\n"
            "{\n"
            "    gl_Position.x = instanceBuffer.f;\n"
            "}\n";
        if (!compile(source))
        {
            FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
        }
    }
    
    // Test that accessing a buffer variable through an instance name inherits the writeonly qualifier
    // and generates errors.
    TEST_F(BufferVariablesTest, AccessWriteonlyBufferVariableByInstanceName)
    {
        const std::string &source =
            "#version 310 es\n"
            "layout(binding = 3) writeonly buffer buf {\n"
            "    float f;\n"
            "} instanceBuffer;\n"
            "void main()\n"
            "{\n"
            "    float test = instanceBuffer.f;\n"
            "}\n";
        if (compile(source))
        {
            FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
        }
    }
    
    // Test that writeonly buffer variable as the argument of a unary operator should be error.
    TEST_F(BufferVariablesTest, UnaryOperatorWithWriteonlyBufferVariable)
    {
        const std::string &source =
            "#version 310 es\n"
            "layout(binding = 3) buffer buf {\n"
            "    writeonly int b1;\n"
            "};\n"
            "void main()\n"
            "{\n"
            "    ++b1;\n"
            "}\n";
        if (compile(source))
        {
            FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
        }
    }
    
    // Test that writeonly buffer variable on the left-hand side of compound assignment should be error.
    TEST_F(BufferVariablesTest, CompoundAssignmentToWriteonlyBufferVariable)
    {
        const std::string &source =
            "#version 310 es\n"
            "layout(binding = 3) buffer buf {\n"
            "    writeonly int b1;\n"
            "};\n"
            "void main()\n"
            "{\n"
            "    b1 += 5;\n"
            "}\n";
        if (compile(source))
        {
            FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
        }
    }
    
    // Test that writeonly buffer variable as ternary op argument should be error.
    TEST_F(BufferVariablesTest, TernarySelectionWithWriteonlyBufferVariable)
    {
        const std::string &source =
            "#version 310 es\n"
            "layout(binding = 3) buffer buf {\n"
            "    writeonly bool b1;\n"
            "};\n"
            "void main()\n"
            "{\n"
            "    int test = b1 ? 1 : 0;\n"
            "}\n";
        if (compile(source))
        {
            FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
        }
    }
    
    // Test that writeonly buffer variable as array constructor argument should be error.
    TEST_F(BufferVariablesTest, ArrayConstructorWithWriteonlyBufferVariable)
    {
        const std::string &source =
            "#version 310 es\n"
            "layout(binding = 3) buffer buf {\n"
            "    writeonly float f;\n"
            "};\n"
            "void main()\n"
            "{\n"
            "    float a[3] = float[3](f, f, f);\n"
            "}\n";
        if (compile(source))
        {
            FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
        }
    }
    
    // Test that writeonly buffer variable as structure constructor argument should be error.
    TEST_F(BufferVariablesTest, StructureConstructorWithWriteonlyBufferVariable)
    {
        const std::string &source =
            "#version 310 es\n"
            "struct S {\n"
            "    int a;\n"
            "};\n"
            "struct T {\n"
            "    S b;\n"
            "};\n"
            "layout(binding = 3) buffer buf {\n"
            "    writeonly S c;\n"
            "};\n"
            "void main()\n"
            "{\n"
            "    T t = T(c);\n"
            "}\n";
        if (compile(source))
        {
            FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
        }
    }
    
    // Test that writeonly buffer variable as built-in function argument should be error.
    TEST_F(BufferVariablesTest, BuildInFunctionWithWriteonlyBufferVariable)
    {
        const std::string &source =
            "#version 310 es\n"
            "layout(binding = 3) buffer buf {\n"
            "    writeonly int a;\n"
            "};\n"
            "void main()\n"
            "{\n"
            "    int test = min(a, 1);\n"
            "}\n";
        if (compile(source))
        {
            FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
        }
    }
    
    // Test that readonly buffer variable as user-defined function in argument should be ok.
    TEST_F(BufferVariablesTest, UserDefinedFunctionWithReadonlyBufferVariableInArgument)
    {
        const std::string &source =
            "#version 310 es\n"
            "layout(binding = 3) buffer buf {\n"
            "    readonly float f;\n"
            "};\n"
            "void foo(float a) {}\n"
            "void main()\n"
            "{\n"
            "    foo(f);\n"
            "}\n";
        if (!compile(source))
        {
            FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
        }
    }
    
    // Test that writeonly buffer variable as user-defined function in argument should be error.
    TEST_F(BufferVariablesTest, UserDefinedFunctionWithWriteonlyBufferVariableInArgument)
    {
        const std::string &source =
            "#version 310 es\n"
            "layout(binding = 3) buffer buf {\n"
            "    writeonly float f;\n"
            "};\n"
            "void foo(float a) {}\n"
            "void main()\n"
            "{\n"
            "    foo(f);\n"
            "}\n";
        if (compile(source))
        {
            FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
        }
    }
    
    // Test that writeonly buffer variable as user-defined function out argument should be ok.
    TEST_F(BufferVariablesTest, UserDefinedFunctionWithWriteonlyBufferVariableOutArgument)
    {
        const std::string &source =
            "#version 310 es\n"
            "layout(binding = 3) buffer buf {\n"
            "    writeonly float f;\n"
            "};\n"
            "void foo(out float a) {}\n"
            "void main()\n"
            "{\n"
            "    foo(f);\n"
            "}\n";
        if (!compile(source))
        {
            FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
        }
    }
    
    // Test that readonly buffer variable as user-defined function out argument should be error.
    TEST_F(BufferVariablesTest, UserDefinedFunctionWithReadonlyBufferVariableOutArgument)
    {
        const std::string &source =
            "#version 310 es\n"
            "layout(binding = 3) buffer buf {\n"
            "    readonly float f;\n"
            "};\n"
            "void foo(out float a) {}\n"
            "void main()\n"
            "{\n"
            "    foo(f);\n"
            "}\n";
        if (compile(source))
        {
            FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
        }
    }
    
    // Test that buffer qualifier can't modify a function parameter.
    TEST_F(BufferVariablesTest, BufferQualifierOnFunctionParameter)
    {
        const std::string &source =
            "#version 310 es\n"
            "void foo(buffer float a) {}\n"
            "void main()\n"
            "{\n"
            "}\n";
        if (compile(source))
        {
            FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
        }
    }
    
    // Test that std430 qualifier is supported for shader storage blocks.
    TEST_F(BufferVariablesTest, ShaderStorageBlockWithStd430)
    {
        const std::string &source =
            "#version 310 es\n"
            "layout(std430) buffer buf {\n"
            "    int b1;\n"
            "    int b2;\n"
            "};\n"
            "void main()\n"
            "{\n"
            "}\n";
        if (!compile(source))
        {
            FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
        }
    }
    
    // Test that using std430 qualifier on a uniform block will fail to compile.
    TEST_F(BufferVariablesTest, UniformBlockWithStd430)
    {
        const std::string &source =
            "#version 310 es\n"
            "layout(std430) uniform buf {\n"
            "    int b1;\n"
            "    int b2;\n"
            "};\n"
            "void main()\n"
            "{\n"
            "}\n";
        if (compile(source))
        {
            FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
        }
    }
    
    // Test that indexing a runtime-sized array with a positive index compiles.
    TEST_F(BufferVariablesTest, IndexRuntimeSizedArray)
    {
        const std::string &source =
            R"(#version 310 es
    
            layout(std430) buffer buf
            {
                int arr[];
            };
    
            void main()
            {
                arr[100];
            })";
        if (!compile(source))
        {
            FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
        }
    }
    
    // Test that indexing a runtime-sized array with a negative constant index does not compile.
    TEST_F(BufferVariablesTest, IndexRuntimeSizedArrayWithNegativeIndex)
    {
        const std::string &source =
            R"(#version 310 es
    
            layout(std430) buffer buf
            {
                int arr[];
            };
    
            void main()
            {
                arr[-1];
            })";
        if (compile(source))
        {
            FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
        }
    }
    
    // Test that only the last member of a buffer can be runtime-sized.
    TEST_F(BufferVariablesTest, RuntimeSizedVariableInNotLastInBuffer)
    {
        const std::string &source =
            R"(#version 310 es
    
            layout(std430) buffer buf
            {
                int arr[];
                int i;
            };
    
            void main()
            {
            })";
        if (compile(source))
        {
            FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
        }
    }