Edit

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

Branch :

  • Show log

    Commit

  • Author : Shahbaz Youssefi
    Date : 2021-02-25 16:55:14
    Hash : 2f737c25
    Message : Translator: Rename GLSL to SPIR-V in Vulkan and Metal output Preparation for actual SPIR-V output instead of GLSL. Bug: angleproject:4889 Change-Id: Ic279b23d3a817bd5dca66a844905378207afdbac Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2721194 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Tim Van Patten <timvp@google.com>

  • src/tests/compiler_tests/EXT_shader_framebuffer_fetch_test.cpp
  • //
    // Copyright 2020 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.
    //
    // EXT_shader_framebuffer_fetch_test.cpp:
    //   Test for EXT_shader_framebuffer_fetch and EXT_shader_framebuffer_fetch_non_coherent
    //
    
    #include "tests/test_utils/ShaderExtensionTest.h"
    
    namespace
    {
    const char EXTPragma[] = "#extension GL_EXT_shader_framebuffer_fetch_non_coherent : require\n";
    
    // Redeclare gl_LastFragData with noncoherent qualifier
    const char ESSL100_LastFragDataRedeclared1[] =
        R"(
        uniform highp vec4 u_color;
        layout(noncoherent) highp vec4 gl_LastFragData[gl_MaxDrawBuffers];
    
        void main (void)
        {
            gl_FragColor = u_color + gl_LastFragData[0] + gl_LastFragData[2];
        })";
    
    // Use inout variable with noncoherent qualifier
    const char ESSL300_InOut[] =
        R"(
        layout(noncoherent, location = 0) inout highp vec4 o_color;
        uniform highp vec4 u_color;
    
        void main (void)
        {
            o_color = clamp(o_color + u_color, vec4(0.0f), vec4(1.0f));
        })";
    
    // Use inout variable with noncoherent qualifier and 3-components vector
    const char ESSL300_InOut2[] =
        R"(
        layout(noncoherent, location = 0) inout highp vec3 o_color;
        uniform highp vec3 u_color;
    
        void main (void)
        {
            o_color = clamp(o_color + u_color, vec3(0.0f), vec3(1.0f));
        })";
    
    // Use inout variable with noncoherent qualifier and integer type qualifier
    const char ESSL300_InOut3[] =
        R"(
        layout(noncoherent, location = 0) inout highp ivec4 o_color;
        uniform highp ivec4 u_color;
    
        void main (void)
        {
            o_color = clamp(o_color + u_color, ivec4(0), ivec4(1));
        })";
    
    // Use inout variable with noncoherent qualifier and unsigned integer type qualifier
    const char ESSL300_InOut4[] =
        R"(
        layout(noncoherent, location = 0) inout highp uvec4 o_color;
        uniform highp uvec4 u_color;
    
        void main (void)
        {
            o_color = clamp(o_color + u_color, uvec4(0), uvec4(1));
        })";
    
    // Use inout variable with noncoherent qualifier and inout function parameter
    const char ESSL300_InOut5[] =
        R"(
        layout(noncoherent, location = 0) inout highp vec4 o_color;
        uniform highp vec4 u_color;
    
        void getClampValue(inout highp mat4 io_color, highp vec4 i_color)
        {
            io_color[0] = clamp(io_color[0] + i_color, vec4(0.0f), vec4(1.0f));
        }
    
        void main (void)
        {
            highp mat4 o_color_mat = mat4(0);
            o_color_mat[0] = o_color;
            getClampValue(o_color_mat, u_color);
            o_color = o_color_mat[0];
        })";
    
    // Use multiple inout variables with noncoherent qualifier
    const char ESSL300_InOut6[] =
        R"(
        layout(noncoherent, location = 0) inout highp vec4 o_color0;
        layout(noncoherent, location = 1) inout highp vec4 o_color1;
        layout(noncoherent, location = 2) inout highp vec4 o_color2;
        layout(noncoherent, location = 3) inout highp vec4 o_color3;
        uniform highp vec4 u_color;
    
        void main (void)
        {
            o_color0 = clamp(o_color0 + u_color, vec4(0.0f), vec4(1.0f));
            o_color1 = clamp(o_color1 + u_color, vec4(0.0f), vec4(1.0f));
            o_color2 = clamp(o_color2 + u_color, vec4(0.0f), vec4(1.0f));
            o_color3 = clamp(o_color3 + u_color, vec4(0.0f), vec4(1.0f));
        })";
    
    // Use the array of inout variable with noncoherent qualifier
    const char ESSL300_InOut7[] =
        R"(
        layout(noncoherent, location = 0) inout highp vec4 o_color[4];
        uniform highp vec4 u_color;
    
        void main (void)
        {
            for (int i = 0 ; i < 4 ; i++)
            {
                o_color[i] = clamp(o_color[i] + u_color, vec4(0.0f), vec4(1.0f));
            }
        })";
    
    class EXTShaderFramebufferFetchNoncoherentTest : public sh::ShaderExtensionTest
    {
      public:
        void SetUp() override
        {
            std::map<ShShaderOutput, std::string> shaderOutputList = {
                {SH_GLSL_450_CORE_OUTPUT, "SH_GLSL_450_CORE_OUTPUT"},
    #if defined(ANGLE_ENABLE_VULKAN)
                {SH_SPIRV_VULKAN_OUTPUT, "SH_SPIRV_VULKAN_OUTPUT"}
    #endif
            };
    
            Initialize(shaderOutputList);
        }
    
        void TearDown() override
        {
            for (auto shaderOutputType : mShaderOutputList)
            {
                DestroyCompiler(shaderOutputType.first);
            }
        }
    
        void Initialize(std::map<ShShaderOutput, std::string> &shaderOutputList)
        {
            mShaderOutputList = std::move(shaderOutputList);
    
            for (auto shaderOutputType : mShaderOutputList)
            {
                sh::InitBuiltInResources(&mResourceList[shaderOutputType.first]);
                mCompilerList[shaderOutputType.first] = nullptr;
            }
        }
    
        void DestroyCompiler(ShShaderOutput shaderOutputType)
        {
            if (mCompilerList[shaderOutputType])
            {
                sh::Destruct(mCompilerList[shaderOutputType]);
                mCompilerList[shaderOutputType] = nullptr;
            }
        }
    
        void InitializeCompiler()
        {
            for (auto shaderOutputType : mShaderOutputList)
            {
                InitializeCompiler(shaderOutputType.first);
            }
        }
    
        void InitializeCompiler(ShShaderOutput shaderOutputType)
        {
            DestroyCompiler(shaderOutputType);
    
            mCompilerList[shaderOutputType] =
                sh::ConstructCompiler(GL_FRAGMENT_SHADER, testing::get<0>(GetParam()), shaderOutputType,
                                      &mResourceList[shaderOutputType]);
            ASSERT_TRUE(mCompilerList[shaderOutputType] != nullptr)
                << "Compiler for " << mShaderOutputList[shaderOutputType]
                << " could not be constructed.";
        }
    
        testing::AssertionResult TestShaderCompile(ShShaderOutput shaderOutputType, const char *pragma)
        {
            const char *shaderStrings[] = {testing::get<1>(GetParam()), pragma,
                                           testing::get<2>(GetParam())};
    
            bool success = sh::Compile(mCompilerList[shaderOutputType], shaderStrings, 3,
                                       SH_VARIABLES | SH_OBJECT_CODE);
            if (success)
            {
                return ::testing::AssertionSuccess()
                       << "Compilation success(" << mShaderOutputList[shaderOutputType] << ")";
            }
            return ::testing::AssertionFailure() << sh::GetInfoLog(mCompilerList[shaderOutputType]);
        }
    
        void TestShaderCompile(bool expectation, const char *pragma)
        {
            for (auto shaderOutputType : mShaderOutputList)
            {
                if (expectation)
                {
                    EXPECT_TRUE(TestShaderCompile(shaderOutputType.first, pragma));
                }
                else
                {
                    EXPECT_FALSE(TestShaderCompile(shaderOutputType.first, pragma));
                }
            }
        }
    
        void SetExtensionEnable(bool enable)
        {
            for (auto shaderOutputType : mShaderOutputList)
            {
                mResourceList[shaderOutputType.first].MaxDrawBuffers = 8;
                mResourceList[shaderOutputType.first].EXT_shader_framebuffer_fetch_non_coherent =
                    enable;
            }
        }
    
      private:
        std::map<ShShaderOutput, std::string> mShaderOutputList;
        std::map<ShShaderOutput, ShHandle> mCompilerList;
        std::map<ShShaderOutput, ShBuiltInResources> mResourceList;
    };
    
    class EXTShaderFramebufferFetchNoncoherentES100Test
        : public EXTShaderFramebufferFetchNoncoherentTest
    {};
    
    // Extension flag is required to compile properly. Expect failure when it is
    // not present.
    TEST_P(EXTShaderFramebufferFetchNoncoherentES100Test, CompileFailsWithoutExtension)
    {
        SetExtensionEnable(false);
        InitializeCompiler();
        TestShaderCompile(false, EXTPragma);
    }
    
    // Extension directive is required to compile properly. Expect failure when
    // it is not present.
    TEST_P(EXTShaderFramebufferFetchNoncoherentES100Test, CompileFailsWithExtensionWithoutPragma)
    {
        SetExtensionEnable(true);
        InitializeCompiler();
        TestShaderCompile(false, "");
    }
    
    class EXTShaderFramebufferFetchNoncoherentES300Test
        : public EXTShaderFramebufferFetchNoncoherentTest
    {};
    
    // Extension flag is required to compile properly. Expect failure when it is
    // not present.
    TEST_P(EXTShaderFramebufferFetchNoncoherentES300Test, CompileFailsWithoutExtension)
    {
        SetExtensionEnable(false);
        InitializeCompiler();
        TestShaderCompile(false, EXTPragma);
    }
    
    // Extension directive is required to compile properly. Expect failure when
    // it is not present.
    TEST_P(EXTShaderFramebufferFetchNoncoherentES300Test, CompileFailsWithExtensionWithoutPragma)
    {
        SetExtensionEnable(true);
        InitializeCompiler();
        TestShaderCompile(false, "");
    }
    
    INSTANTIATE_TEST_SUITE_P(CorrectESSL100Shaders,
                             EXTShaderFramebufferFetchNoncoherentES100Test,
                             Combine(Values(SH_GLES2_SPEC),
                                     Values(sh::ESSLVersion100),
                                     Values(ESSL100_LastFragDataRedeclared1)));
    
    INSTANTIATE_TEST_SUITE_P(CorrectESSL300Shaders,
                             EXTShaderFramebufferFetchNoncoherentES300Test,
                             Combine(Values(SH_GLES3_SPEC),
                                     Values(sh::ESSLVersion300),
                                     Values(ESSL300_InOut,
                                            ESSL300_InOut2,
                                            ESSL300_InOut3,
                                            ESSL300_InOut4,
                                            ESSL300_InOut5,
                                            ESSL300_InOut6,
                                            ESSL300_InOut7)));
    
    #if defined(ANGLE_ENABLE_VULKAN)
    
    // Use gl_LastFragData without redeclaration of gl_LastFragData with noncoherent qualifier
    const char ESSL100_LastFragDataWithoutRedeclaration[] =
        R"(
        uniform highp vec4 u_color;
    
        void main (void)
        {
            gl_FragColor = u_color + gl_LastFragData[0];
        })";
    
    // Redeclare gl_LastFragData without noncoherent qualifier
    const char ESSL100_LastFragDataRedeclaredWithoutNoncoherent[] =
        R"(
        uniform highp vec4 u_color;
        highp vec4 gl_LastFragData[gl_MaxDrawBuffers];
    
        void main (void)
        {
            gl_FragColor = u_color + gl_LastFragData[0];
        })";
    
    // Use inout variable without noncoherent qualifier
    const char ESSL300_InOutWithoutNoncoherent[] =
        R"(
        layout(location = 0) inout highp vec4 o_color;
        uniform highp vec4 u_color;
    
        void main (void)
        {
            o_color = clamp(o_color + u_color, vec4(0.0f), vec4(1.0f));
        })";
    
    class EXTShaderFramebufferFetchNoncoherentSuccessTest
        : public EXTShaderFramebufferFetchNoncoherentTest
    {
      public:
        void SetUp() override
        {
            std::map<ShShaderOutput, std::string> shaderOutputList = {
                {SH_SPIRV_VULKAN_OUTPUT, "SH_SPIRV_VULKAN_OUTPUT"}};
    
            Initialize(shaderOutputList);
        }
    };
    
    class EXTShaderFramebufferFetchNoncoherentFailureTest
        : public EXTShaderFramebufferFetchNoncoherentSuccessTest
    {};
    
    class EXTShaderFramebufferFetchNoncoherentES100SuccessTest
        : public EXTShaderFramebufferFetchNoncoherentSuccessTest
    {};
    
    class EXTShaderFramebufferFetchNoncoherentES100FailureTest
        : public EXTShaderFramebufferFetchNoncoherentFailureTest
    {};
    
    // With extension flag and extension directive, compiling succeeds.
    // Also test that the extension directive state is reset correctly.
    TEST_P(EXTShaderFramebufferFetchNoncoherentES100SuccessTest, CompileSucceedsWithExtensionAndPragma)
    {
        SetExtensionEnable(true);
        InitializeCompiler();
        TestShaderCompile(true, EXTPragma);
        // Test reset functionality.
        TestShaderCompile(false, "");
        TestShaderCompile(true, EXTPragma);
    }
    
    //
    TEST_P(EXTShaderFramebufferFetchNoncoherentES100FailureTest, CompileFailsWithoutNoncoherent)
    {
        SetExtensionEnable(true);
        InitializeCompiler();
        TestShaderCompile(false, EXTPragma);
    }
    
    class EXTShaderFramebufferFetchNoncoherentES300SuccessTest
        : public EXTShaderFramebufferFetchNoncoherentSuccessTest
    {};
    
    class EXTShaderFramebufferFetchNoncoherentES300FailureTest
        : public EXTShaderFramebufferFetchNoncoherentFailureTest
    {};
    
    // With extension flag and extension directive, compiling succeeds.
    // Also test that the extension directive state is reset correctly.
    TEST_P(EXTShaderFramebufferFetchNoncoherentES300SuccessTest, CompileSucceedsWithExtensionAndPragma)
    {
        SetExtensionEnable(true);
        InitializeCompiler();
        TestShaderCompile(true, EXTPragma);
        // Test reset functionality.
        TestShaderCompile(false, "");
        TestShaderCompile(true, EXTPragma);
    }
    
    //
    TEST_P(EXTShaderFramebufferFetchNoncoherentES300FailureTest, CompileFailsWithoutNoncoherent)
    {
        SetExtensionEnable(true);
        InitializeCompiler();
        TestShaderCompile(false, EXTPragma);
    }
    
    // The SL #version 100 shaders that are correct work similarly
    // in both GL2 and GL3, with and without the version string.
    INSTANTIATE_TEST_SUITE_P(CorrectESSL100Shaders,
                             EXTShaderFramebufferFetchNoncoherentES100SuccessTest,
                             Combine(Values(SH_GLES2_SPEC),
                                     Values(sh::ESSLVersion100),
                                     Values(ESSL100_LastFragDataRedeclared1)));
    
    INSTANTIATE_TEST_SUITE_P(IncorrectESSL100Shaders,
                             EXTShaderFramebufferFetchNoncoherentES100FailureTest,
                             Combine(Values(SH_GLES2_SPEC),
                                     Values(sh::ESSLVersion100),
                                     Values(ESSL100_LastFragDataWithoutRedeclaration,
                                            ESSL100_LastFragDataRedeclaredWithoutNoncoherent)));
    
    INSTANTIATE_TEST_SUITE_P(CorrectESSL300Shaders,
                             EXTShaderFramebufferFetchNoncoherentES300SuccessTest,
                             Combine(Values(SH_GLES3_SPEC),
                                     Values(sh::ESSLVersion300),
                                     Values(ESSL300_InOut,
                                            ESSL300_InOut2,
                                            ESSL300_InOut3,
                                            ESSL300_InOut4,
                                            ESSL300_InOut5,
                                            ESSL300_InOut6,
                                            ESSL300_InOut7)));
    
    INSTANTIATE_TEST_SUITE_P(IncorrectESSL300Shaders,
                             EXTShaderFramebufferFetchNoncoherentES300FailureTest,
                             Combine(Values(SH_GLES3_SPEC),
                                     Values(sh::ESSLVersion300),
                                     Values(ESSL300_InOutWithoutNoncoherent)));
    #endif
    
    }  // anonymous namespace