| // |
| // Copyright (c) 2015 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_blend_func_extended.cpp: |
| // Test for EXT_blend_func_extended_test |
| // |
| |
| #include "angle_gl.h" |
| #include "gtest/gtest.h" |
| #include "GLSLANG/ShaderLang.h" |
| |
| using testing::Combine; |
| using testing::Values; |
| using testing::make_tuple; |
| |
| namespace |
| { |
| const char ESSLVersion100[] = "#version 100\n"; |
| const char ESSLVersion300[] = "#version 300 es\n"; |
| const char ESSLVersion310[] = "#version 310 es\n"; |
| const char EXTBFEPragma[] = "#extension GL_EXT_blend_func_extended : require\n"; |
| |
| const char ESSL100_SimpleShader1[] = |
| "precision mediump float;\n" |
| "void main() { \n" |
| " gl_FragColor = vec4(1.0);\n" |
| " gl_SecondaryFragColorEXT = vec4(gl_MaxDualSourceDrawBuffersEXT / 10);\n" |
| "}\n"; |
| |
| // Shader that tests only the access to gl_MaxDualSourceDrawBuffersEXT. |
| const char ESSL100_MaxDualSourceAccessShader[] = |
| "precision mediump float;\n" |
| "void main() { gl_FragColor = vec4(gl_MaxDualSourceDrawBuffersEXT / 10); }\n"; |
| |
| // Shader that writes to SecondaryFragData. |
| const char ESSL100_FragDataShader[] = |
| "#extension GL_EXT_draw_buffers : require\n" |
| "precision mediump float;\n" |
| "void main() {\n" |
| " gl_FragData[gl_MaxDrawBuffers - 1] = vec4(1.0);\n" |
| " gl_SecondaryFragDataEXT[gl_MaxDualSourceDrawBuffersEXT - 1] = vec4(0.1);\n" |
| "}\n"; |
| |
| // Shader that writes to SecondaryFragColor and SecondaryFragData does not compile. |
| const char ESSL100_ColorAndDataWriteFailureShader1[] = |
| "precision mediump float;\n" |
| "void main() {\n" |
| " gl_SecondaryFragColorEXT = vec4(1.0);\n" |
| " gl_SecondaryFragDataEXT[gl_MaxDualSourceDrawBuffersEXT] = vec4(0.1);\n" |
| "}\n"; |
| |
| // Shader that writes to FragColor and SecondaryFragData does not compile. |
| const char ESSL100_ColorAndDataWriteFailureShader2[] = |
| "precision mediump float;\n" |
| "void main() {\n" |
| " gl_FragColor = vec4(1.0);\n" |
| " gl_SecondaryFragDataEXT[gl_MaxDualSourceDrawBuffersEXT] = vec4(0.1);\n" |
| "}\n"; |
| |
| // Shader that writes to FragData and SecondaryFragColor. |
| const char ESSL100_ColorAndDataWriteFailureShader3[] = |
| "#extension GL_EXT_draw_buffers : require\n" |
| "precision mediump float;\n" |
| "void main() {\n" |
| " gl_SecondaryFragColorEXT = vec4(1.0);\n" |
| " gl_FragData[gl_MaxDrawBuffers] = vec4(0.1);\n" |
| "}\n"; |
| |
| // In GLSL version 300 es, the gl_MaxDualSourceDrawBuffersEXT is available. |
| const char ESSL300_MaxDualSourceAccessShader[] = |
| "precision mediump float;\n" |
| "layout(location = 0) out mediump vec4 fragColor;" |
| "void main() {\n" |
| " fragColor = vec4(gl_MaxDualSourceDrawBuffersEXT / 10);\n" |
| "}\n"; |
| |
| // In GLSL version 300 es, the only way to write a correct shader is to require the extension and |
| // then leave the locations unspecified. The caller will then bind the variables with the extension |
| // binding functions. |
| const char ESSL300_LocationAndUnspecifiedOutputShader[] = |
| "precision mediump float;\n" |
| "layout(location = 0) out mediump vec4 fragColor;" |
| "out mediump vec4 secondaryFragColor;" |
| "void main() {\n" |
| " fragColor = vec4(1.0);\n" |
| " secondaryFragColor = vec4(1.0);\n" |
| "}\n"; |
| |
| const char ESSL300_TwoUnspecifiedLocationOutputsShader[] = |
| "precision mediump float;\n" |
| "out mediump vec4 fragColor;" |
| "out mediump vec4 secondaryFragColor;" |
| "void main() {\n" |
| " fragColor = vec4(1.0);\n" |
| " secondaryFragColor = vec4(1.0);\n" |
| "}\n"; |
| |
| // Shader that is correct in GLSL ES 3.10 fails when used in version 300 es. |
| const char ESSL310_LocationIndexShader[] = |
| "precision mediump float;\n" |
| "layout(location = 0) out mediump vec4 fragColor;" |
| "layout(location = 0, index = 1) out mediump vec4 secondaryFragColor;" |
| "void main() {\n" |
| " fragColor = vec4(1);\n" |
| " secondaryFragColor = vec4(1);\n" |
| "}\n"; |
| |
| // Shader that specifies index layout qualifier but not location fails to compile. Currently fails |
| // to compile due to version 310 es not being supported. |
| const char ESSL310_LocationIndexFailureShader[] = |
| "precision mediump float;\n" |
| "layout(location = 0) out mediump vec4 fragColor;" |
| "layout(index = 1) out mediump vec4 secondaryFragColor;" |
| "void main() {\n" |
| " fragColor = vec4(1.0);\n" |
| " secondaryFragColor = vec4(1.0);\n" |
| "}\n"; |
| |
| class EXTBlendFuncExtendedTest |
| : public testing::TestWithParam<testing::tuple<ShShaderSpec, const char *, const char *>> |
| { |
| protected: |
| virtual void SetUp() |
| { |
| sh::InitBuiltInResources(&mResources); |
| // EXT_draw_buffers is used in some of the shaders for test purposes. |
| mResources.EXT_draw_buffers = 1; |
| mResources.NV_draw_buffers = 2; |
| |
| mCompiler = nullptr; |
| } |
| |
| virtual void TearDown() { DestroyCompiler(); } |
| void DestroyCompiler() |
| { |
| if (mCompiler) |
| { |
| sh::Destruct(mCompiler); |
| mCompiler = nullptr; |
| } |
| } |
| |
| void InitializeCompiler() |
| { |
| DestroyCompiler(); |
| mCompiler = sh::ConstructCompiler(GL_FRAGMENT_SHADER, testing::get<0>(GetParam()), |
| SH_GLSL_COMPATIBILITY_OUTPUT, &mResources); |
| ASSERT_TRUE(mCompiler != nullptr) << "Compiler could not be constructed."; |
| } |
| |
| testing::AssertionResult TestShaderCompile(const char *pragma) |
| { |
| return TestShaderCompile(testing::get<1>(GetParam()), // Version. |
| pragma, |
| testing::get<2>(GetParam()) // Shader. |
| ); |
| } |
| |
| testing::AssertionResult TestShaderCompile(const char *version, |
| const char *pragma, |
| const char *shader) |
| { |
| const char *shaderStrings[] = {version, pragma, shader}; |
| bool success = sh::Compile(mCompiler, shaderStrings, 3, 0); |
| if (success) |
| { |
| return ::testing::AssertionSuccess() << "Compilation success"; |
| } |
| return ::testing::AssertionFailure() << sh::GetInfoLog(mCompiler); |
| } |
| |
| protected: |
| ShBuiltInResources mResources; |
| ShHandle mCompiler; |
| }; |
| |
| // Extension flag is required to compile properly. Expect failure when it is |
| // not present. |
| TEST_P(EXTBlendFuncExtendedTest, CompileFailsWithoutExtension) |
| { |
| mResources.EXT_blend_func_extended = 0; |
| InitializeCompiler(); |
| EXPECT_FALSE(TestShaderCompile(EXTBFEPragma)); |
| } |
| |
| // Extension directive is required to compile properly. Expect failure when |
| // it is not present. |
| TEST_P(EXTBlendFuncExtendedTest, CompileFailsWithExtensionWithoutPragma) |
| { |
| mResources.EXT_blend_func_extended = 1; |
| mResources.MaxDualSourceDrawBuffers = 1; |
| InitializeCompiler(); |
| EXPECT_FALSE(TestShaderCompile("")); |
| } |
| |
| // With extension flag and extension directive, compiling succeeds. |
| // Also test that the extension directive state is reset correctly. |
| TEST_P(EXTBlendFuncExtendedTest, CompileSucceedsWithExtensionAndPragma) |
| { |
| mResources.EXT_blend_func_extended = 1; |
| mResources.MaxDualSourceDrawBuffers = 1; |
| InitializeCompiler(); |
| EXPECT_TRUE(TestShaderCompile(EXTBFEPragma)); |
| // Test reset functionality. |
| EXPECT_FALSE(TestShaderCompile("")); |
| EXPECT_TRUE(TestShaderCompile(EXTBFEPragma)); |
| } |
| |
| // The SL #version 100 shaders that are correct work similarly |
| // in both GL2 and GL3, with and without the version string. |
| INSTANTIATE_TEST_CASE_P(CorrectESSL100Shaders, |
| EXTBlendFuncExtendedTest, |
| Combine(Values(SH_GLES2_SPEC, SH_GLES3_SPEC), |
| Values("", ESSLVersion100), |
| Values(ESSL100_SimpleShader1, |
| ESSL100_MaxDualSourceAccessShader, |
| ESSL100_FragDataShader))); |
| |
| INSTANTIATE_TEST_CASE_P(CorrectESSL300Shaders, |
| EXTBlendFuncExtendedTest, |
| Combine(Values(SH_GLES3_SPEC), |
| Values(ESSLVersion300), |
| Values(ESSL300_MaxDualSourceAccessShader, |
| ESSL300_LocationAndUnspecifiedOutputShader, |
| ESSL300_TwoUnspecifiedLocationOutputsShader))); |
| |
| class EXTBlendFuncExtendedCompileFailureTest : public EXTBlendFuncExtendedTest |
| { |
| }; |
| |
| TEST_P(EXTBlendFuncExtendedCompileFailureTest, CompileFails) |
| { |
| // Expect compile failure due to shader error, with shader having correct pragma. |
| mResources.EXT_blend_func_extended = 1; |
| mResources.MaxDualSourceDrawBuffers = 1; |
| InitializeCompiler(); |
| EXPECT_FALSE(TestShaderCompile(EXTBFEPragma)); |
| } |
| |
| // Incorrect #version 100 shaders fail. |
| INSTANTIATE_TEST_CASE_P(IncorrectESSL100Shaders, |
| EXTBlendFuncExtendedCompileFailureTest, |
| Combine(Values(SH_GLES2_SPEC), |
| Values(ESSLVersion100), |
| Values(ESSL100_ColorAndDataWriteFailureShader1, |
| ESSL100_ColorAndDataWriteFailureShader2, |
| ESSL100_ColorAndDataWriteFailureShader3))); |
| |
| // Correct #version 300 es shaders fail in GLES2 context, regardless of version string. |
| INSTANTIATE_TEST_CASE_P(CorrectESSL300Shaders, |
| EXTBlendFuncExtendedCompileFailureTest, |
| Combine(Values(SH_GLES2_SPEC), |
| Values("", ESSLVersion100, ESSLVersion300), |
| Values(ESSL300_LocationAndUnspecifiedOutputShader, |
| ESSL300_TwoUnspecifiedLocationOutputsShader))); |
| |
| // Correct #version 100 shaders fail when used with #version 300 es. |
| INSTANTIATE_TEST_CASE_P(CorrectESSL100Shaders, |
| EXTBlendFuncExtendedCompileFailureTest, |
| Combine(Values(SH_GLES3_SPEC), |
| Values(ESSLVersion300), |
| Values(ESSL100_SimpleShader1, ESSL100_FragDataShader))); |
| |
| // Incorrect #version 310 es always fails. |
| INSTANTIATE_TEST_CASE_P(IncorrectESSL310Shaders, |
| EXTBlendFuncExtendedCompileFailureTest, |
| Combine(Values(SH_GLES3_SPEC), |
| Values(ESSLVersion300, ESSLVersion310), |
| Values(ESSL310_LocationIndexFailureShader))); |
| |
| // Correct #version 310 es fails in #version 300 es. |
| INSTANTIATE_TEST_CASE_P( |
| CorrectESSL310ShadersInESSL300, |
| EXTBlendFuncExtendedCompileFailureTest, |
| Values(make_tuple(SH_GLES3_SPEC, &ESSLVersion300[0], &ESSL310_LocationIndexShader[0]))); |
| |
| // Correct #version 310 es fails in #version 310 es, due to 3.1 not being supported. |
| INSTANTIATE_TEST_CASE_P( |
| CorrectESSL310Shaders, |
| EXTBlendFuncExtendedCompileFailureTest, |
| Values(make_tuple(SH_GLES3_SPEC, &ESSLVersion310[0], &ESSL310_LocationIndexShader[0]))); |
| |
| } // namespace |