Edit

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

Branch :

  • Show log

    Commit

  • Author : Jiajia Qin
    Date : 2017-06-23 15:42:17
    Hash : bc58515e
    Message : ES31: Add 'buffer' qualifier support in shader This change added 'buffer' qualifier support in shader which corresponds to ESSL 3.1 spec, session 4.3.7 'Buffer Variables'. BUG=angleproject:1951 TEST=angle_unittests:BufferVariablesTest Change-Id: I2ecb5317d5ea9d378a60b03f86bdae04dbd89e9f Reviewed-on: https://chromium-review.googlesource.com/534960 Reviewed-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Geoff Lang <geofflang@chromium.org>

  • src/tests/compiler_tests/BufferVariables_test.cpp
  • //
    // Copyright (c) 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 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"
            "    float test = 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;
        }
    }