blob: 7d965d77c82313aae93bfc9df113c3202d76cd65 [file] [log] [blame]
//
// 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