Commit a1f6dc95 by Yuly Novikov Committed by Commit Bot

Varying invariance must match between shaders in ESSL 1.00

While in ESSL 3.00 invariant is allowed only for out varyings. Verify that, and update test expectations. BUG=angleproject:1293 TEST=GLSLTest*.Invariant* Change-Id: I5cab6c68f2b94ea2179719119668d905fe7a9b3d Reviewed-on: https://chromium-review.googlesource.com/352743Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Yuly Novikov <ynovikov@chromium.org>
parent cfa48d37
...@@ -1628,6 +1628,8 @@ bool Program::linkVaryings(InfoLog &infoLog, ...@@ -1628,6 +1628,8 @@ bool Program::linkVaryings(InfoLog &infoLog,
const Shader *vertexShader, const Shader *vertexShader,
const Shader *fragmentShader) const Shader *fragmentShader)
{ {
ASSERT(vertexShader->getShaderVersion() == fragmentShader->getShaderVersion());
const std::vector<sh::Varying> &vertexVaryings = vertexShader->getVaryings(); const std::vector<sh::Varying> &vertexVaryings = vertexShader->getVaryings();
const std::vector<sh::Varying> &fragmentVaryings = fragmentShader->getVaryings(); const std::vector<sh::Varying> &fragmentVaryings = fragmentShader->getVaryings();
...@@ -1646,7 +1648,8 @@ bool Program::linkVaryings(InfoLog &infoLog, ...@@ -1646,7 +1648,8 @@ bool Program::linkVaryings(InfoLog &infoLog,
if (output.name == input.name) if (output.name == input.name)
{ {
ASSERT(!input.isBuiltIn()); ASSERT(!input.isBuiltIn());
if (!linkValidateVaryings(infoLog, output.name, input, output)) if (!linkValidateVaryings(infoLog, output.name, input, output,
vertexShader->getShaderVersion()))
{ {
return false; return false;
} }
...@@ -2103,7 +2106,11 @@ bool Program::linkValidateUniforms(InfoLog &infoLog, const std::string &uniformN ...@@ -2103,7 +2106,11 @@ bool Program::linkValidateUniforms(InfoLog &infoLog, const std::string &uniformN
return true; return true;
} }
bool Program::linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying) bool Program::linkValidateVaryings(InfoLog &infoLog,
const std::string &varyingName,
const sh::Varying &vertexVarying,
const sh::Varying &fragmentVarying,
int shaderVersion)
{ {
if (!linkValidateVariablesBase(infoLog, varyingName, vertexVarying, fragmentVarying, false)) if (!linkValidateVariablesBase(infoLog, varyingName, vertexVarying, fragmentVarying, false))
{ {
...@@ -2112,7 +2119,15 @@ bool Program::linkValidateVaryings(InfoLog &infoLog, const std::string &varyingN ...@@ -2112,7 +2119,15 @@ bool Program::linkValidateVaryings(InfoLog &infoLog, const std::string &varyingN
if (!sh::InterpolationTypesMatch(vertexVarying.interpolation, fragmentVarying.interpolation)) if (!sh::InterpolationTypesMatch(vertexVarying.interpolation, fragmentVarying.interpolation))
{ {
infoLog << "Interpolation types for " << varyingName << " differ between vertex and fragment shaders"; infoLog << "Interpolation types for " << varyingName
<< " differ between vertex and fragment shaders.";
return false;
}
if (shaderVersion == 100 && vertexVarying.isInvariant != fragmentVarying.isInvariant)
{
infoLog << "Invariance for " << varyingName
<< " differs between vertex and fragment shaders.";
return false; return false;
} }
......
...@@ -366,7 +366,11 @@ class Program final : angle::NonCopyable, public LabeledObject ...@@ -366,7 +366,11 @@ class Program final : angle::NonCopyable, public LabeledObject
const sh::ShaderVariable &fragmentVariable, const sh::ShaderVariable &fragmentVariable,
bool validatePrecision); bool validatePrecision);
static bool linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying); static bool linkValidateVaryings(InfoLog &infoLog,
const std::string &varyingName,
const sh::Varying &vertexVarying,
const sh::Varying &fragmentVarying,
int shaderVersion);
bool linkValidateTransformFeedback(InfoLog &infoLog, bool linkValidateTransformFeedback(InfoLog &infoLog,
const std::vector<const sh::Varying *> &linkedVaryings, const std::vector<const sh::Varying *> &linkedVaryings,
const Caps &caps) const; const Caps &caps) const;
......
...@@ -624,6 +624,57 @@ TEST_P(GLSLTest, TwoElseIfRewriting) ...@@ -624,6 +624,57 @@ TEST_P(GLSLTest, TwoElseIfRewriting)
EXPECT_NE(0u, program); EXPECT_NE(0u, program);
} }
TEST_P(GLSLTest, FrontFacingAndVarying)
{
EGLPlatformParameters platform = GetParam().eglParameters;
const std::string vertexShaderSource = SHADER_SOURCE
(
attribute vec4 a_position;
varying float v_varying;
void main()
{
v_varying = a_position.x;
gl_Position = a_position;
}
);
const std::string fragmentShaderSource = SHADER_SOURCE
(
precision mediump float;
varying float v_varying;
void main()
{
vec4 c;
if (gl_FrontFacing)
{
c = vec4(v_varying, 0, 0, 1.0);
}
else
{
c = vec4(0, v_varying, 0, 1.0);
}
gl_FragColor = c;
}
);
GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
// Compilation should fail on D3D11 feature level 9_3, since gl_FrontFacing isn't supported.
if (platform.renderer == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
{
if (platform.majorVersion == 9 && platform.minorVersion == 3)
{
EXPECT_EQ(0u, program);
return;
}
}
// Otherwise, compilation should succeed
EXPECT_NE(0u, program);
}
// Verify that linking shaders declaring different shading language versions fails. // Verify that linking shaders declaring different shading language versions fails.
TEST_P(GLSLTest_ES3, VersionMismatch) TEST_P(GLSLTest_ES3, VersionMismatch)
{ {
...@@ -657,175 +708,295 @@ TEST_P(GLSLTest_ES3, VersionMismatch) ...@@ -657,175 +708,295 @@ TEST_P(GLSLTest_ES3, VersionMismatch)
EXPECT_EQ(0u, program); EXPECT_EQ(0u, program);
} }
// Verify that declaring varying as invariant only in vertex shader fails in ESSL 1.00.
TEST_P(GLSLTest, InvariantVaryingOut) TEST_P(GLSLTest, InvariantVaryingOut)
{ {
// TODO(geofflang): Some OpenGL drivers have compile errors when varyings do not have matching const std::string fragmentShaderSource =
// invariant attributes (http://anglebug.com/1293) "precision mediump float;\n"
if (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE) "varying float v_varying;\n"
"void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
const std::string vertexShaderSource =
"attribute vec4 a_position;\n"
"invariant varying float v_varying;\n"
"void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
EXPECT_EQ(0u, program);
}
// Verify that declaring varying as invariant only in vertex shader succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3, InvariantVaryingOut)
{
// TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
// for varyings which are invariant in vertex shader (http://anglebug.com/1293)
if (isOpenGL())
{ {
std::cout << "Test disabled on OpenGL." << std::endl; std::cout << "Test disabled on OpenGL." << std::endl;
return; return;
} }
const std::string fragmentShaderSource = SHADER_SOURCE const std::string fragmentShaderSource =
( "#version 300 es\n"
precision mediump float; "precision mediump float;\n"
varying float v_varying; "in float v_varying;\n"
void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); } "out vec4 my_FragColor;\n"
); "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
const std::string vertexShaderSource = SHADER_SOURCE const std::string vertexShaderSource =
( "#version 300 es\n"
attribute vec4 a_position; "in vec4 a_position;\n"
invariant varying float v_varying; "invariant out float v_varying;\n"
void main() { v_varying = a_position.x; gl_Position = a_position; } "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
);
GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource); GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
EXPECT_NE(0u, program); EXPECT_NE(0u, program);
} }
TEST_P(GLSLTest, FrontFacingAndVarying) // Verify that declaring varying as invariant only in fragment shader fails in ESSL 1.00.
TEST_P(GLSLTest, InvariantVaryingIn)
{ {
EGLPlatformParameters platform = GetParam().eglParameters; const std::string fragmentShaderSource =
"precision mediump float;\n"
"invariant varying float v_varying;\n"
"void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
const std::string vertexShaderSource = SHADER_SOURCE const std::string vertexShaderSource =
( "attribute vec4 a_position;\n"
attribute vec4 a_position; "varying float v_varying;\n"
varying float v_varying; "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
void main()
{
v_varying = a_position.x;
gl_Position = a_position;
}
);
const std::string fragmentShaderSource = SHADER_SOURCE GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
( EXPECT_EQ(0u, program);
precision mediump float; }
varying float v_varying;
void main()
{
vec4 c;
if (gl_FrontFacing) // Verify that declaring varying as invariant only in fragment shader fails in ESSL 3.00.
{ TEST_P(GLSLTest_ES3, InvariantVaryingIn)
c = vec4(v_varying, 0, 0, 1.0); {
} const std::string fragmentShaderSource =
else "#version 300 es\n"
{ "precision mediump float;\n"
c = vec4(0, v_varying, 0, 1.0); "invariant in float v_varying;\n"
} "out vec4 my_FragColor;\n"
gl_FragColor = c; "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
}
); const std::string vertexShaderSource =
"#version 300 es\n"
"in vec4 a_position;\n"
"out float v_varying;\n"
"void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource); GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
EXPECT_EQ(0u, program);
}
// Compilation should fail on D3D11 feature level 9_3, since gl_FrontFacing isn't supported. // Verify that declaring varying as invariant in both shaders succeeds in ESSL 1.00.
if (platform.renderer == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE) TEST_P(GLSLTest, InvariantVaryingBoth)
{ {
if (platform.majorVersion == 9 && platform.minorVersion == 3) const std::string fragmentShaderSource =
{ "precision mediump float;\n"
"invariant varying float v_varying;\n"
"void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
const std::string vertexShaderSource =
"attribute vec4 a_position;\n"
"invariant varying float v_varying;\n"
"void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
EXPECT_NE(0u, program);
}
// Verify that declaring varying as invariant in both shaders fails in ESSL 3.00.
TEST_P(GLSLTest_ES3, InvariantVaryingBoth)
{
const std::string fragmentShaderSource =
"#version 300 es\n"
"precision mediump float;\n"
"invariant in float v_varying;\n"
"out vec4 my_FragColor;\n"
"void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
const std::string vertexShaderSource =
"#version 300 es\n"
"in vec4 a_position;\n"
"invariant out float v_varying;\n"
"void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
EXPECT_EQ(0u, program); EXPECT_EQ(0u, program);
return; }
}
}
// Otherwise, compilation should succeed // Verify that declaring gl_Position as invariant succeeds in ESSL 1.00.
TEST_P(GLSLTest, InvariantGLPosition)
{
const std::string fragmentShaderSource =
"precision mediump float;\n"
"varying float v_varying;\n"
"void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
const std::string vertexShaderSource =
"attribute vec4 a_position;\n"
"invariant gl_Position;\n"
"varying float v_varying;\n"
"void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
EXPECT_NE(0u, program); EXPECT_NE(0u, program);
} }
TEST_P(GLSLTest, InvariantVaryingIn) // Verify that declaring gl_Position as invariant succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3, InvariantGLPosition)
{ {
// TODO(geofflang): Some OpenGL drivers have compile errors when varyings do not have matching const std::string fragmentShaderSource =
// invariant attributes (http://anglebug.com/1293) "#version 300 es\n"
if (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE) "precision mediump float;\n"
"in float v_varying;\n"
"out vec4 my_FragColor;\n"
"void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
const std::string vertexShaderSource =
"#version 300 es\n"
"in vec4 a_position;\n"
"invariant gl_Position;\n"
"out float v_varying;\n"
"void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
EXPECT_NE(0u, program);
}
// Verify that using invariant(all) in both shaders succeeds in ESSL 1.00.
TEST_P(GLSLTest, InvariantAllBoth)
{
// TODO: ESSL 1.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
// for varyings which are invariant in vertex shader individually,
// and remove invariant(all) from fragment shader (http://anglebug.com/1293)
if (isOpenGL())
{ {
std::cout << "Test disabled on OpenGL." << std::endl; std::cout << "Test disabled on OpenGL." << std::endl;
return; return;
} }
const std::string fragmentShaderSource = SHADER_SOURCE const std::string fragmentShaderSource =
( "#pragma STDGL invariant(all)\n"
precision mediump float; "precision mediump float;\n"
invariant varying float v_varying; "varying float v_varying;\n"
void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); } "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
);
const std::string vertexShaderSource = SHADER_SOURCE const std::string vertexShaderSource =
( "#pragma STDGL invariant(all)\n"
attribute vec4 a_position; "attribute vec4 a_position;\n"
varying float v_varying; "varying float v_varying;\n"
void main() { v_varying = a_position.x; gl_Position = a_position; } "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
);
GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource); GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
EXPECT_NE(0u, program); EXPECT_NE(0u, program);
} }
TEST_P(GLSLTest, InvariantVaryingBoth) // Verify that using invariant(all) in both shaders fails in ESSL 3.00.
TEST_P(GLSLTest_ES3, InvariantAllBoth)
{ {
const std::string fragmentShaderSource = SHADER_SOURCE const std::string fragmentShaderSource =
( "#version 300 es\n"
precision mediump float; "#pragma STDGL invariant(all)\n"
invariant varying float v_varying; "precision mediump float;\n"
void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); } "in float v_varying;\n"
); "out vec4 my_FragColor;\n"
"void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
const std::string vertexShaderSource = SHADER_SOURCE const std::string vertexShaderSource =
( "#version 300 es\n"
attribute vec4 a_position; "#pragma STDGL invariant(all)\n"
invariant varying float v_varying; "in vec4 a_position;\n"
void main() { v_varying = a_position.x; gl_Position = a_position; } "out float v_varying;\n"
); "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource); GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
EXPECT_NE(0u, program); EXPECT_EQ(0u, program);
} }
TEST_P(GLSLTest, InvariantGLPosition) // Verify that using invariant(all) only in fragment shader fails in ESSL 1.00.
TEST_P(GLSLTest, InvariantAllIn)
{ {
const std::string fragmentShaderSource = SHADER_SOURCE const std::string fragmentShaderSource =
( "#pragma STDGL invariant(all)\n"
precision mediump float; "precision mediump float;\n"
varying float v_varying; "varying float v_varying;\n"
void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); } "void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
);
const std::string vertexShaderSource = SHADER_SOURCE const std::string vertexShaderSource =
( "attribute vec4 a_position;\n"
attribute vec4 a_position; "varying float v_varying;\n"
invariant gl_Position; "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
varying float v_varying;
void main() { v_varying = a_position.x; gl_Position = a_position; }
);
GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource); GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
EXPECT_NE(0u, program); EXPECT_EQ(0u, program);
} }
TEST_P(GLSLTest, InvariantAll) // Verify that using invariant(all) only in fragment shader fails in ESSL 3.00.
TEST_P(GLSLTest_ES3, InvariantAllIn)
{ {
// TODO(geofflang): Some OpenGL drivers have compile errors when varyings do not have matching const std::string fragmentShaderSource =
// invariant attributes (http://anglebug.com/1293) "#version 300 es\n"
if (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE) "#pragma STDGL invariant(all)\n"
"precision mediump float;\n"
"in float v_varying;\n"
"out vec4 my_FragColor;\n"
"void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
const std::string vertexShaderSource =
"#version 300 es\n"
"in vec4 a_position;\n"
"out float v_varying;\n"
"void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
EXPECT_EQ(0u, program);
}
// Verify that using invariant(all) only in vertex shader fails in ESSL 1.00.
TEST_P(GLSLTest, InvariantAllOut)
{
const std::string fragmentShaderSource =
"precision mediump float;\n"
"varying float v_varying;\n"
"void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
const std::string vertexShaderSource =
"#pragma STDGL invariant(all)\n"
"attribute vec4 a_position;\n"
"varying float v_varying;\n"
"void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
EXPECT_EQ(0u, program);
}
// Verify that using invariant(all) only in vertex shader succeeds in ESSL 3.00.
TEST_P(GLSLTest_ES3, InvariantAllOut)
{
// TODO: ESSL 3.00 -> GLSL 1.20 translation should add "invariant" in fragment shader
// for varyings which are invariant in vertex shader,
// because of invariant(all) being used in vertex shader (http://anglebug.com/1293)
if (isOpenGL())
{ {
std::cout << "Test disabled on OpenGL." << std::endl; std::cout << "Test disabled on OpenGL." << std::endl;
return; return;
} }
const std::string fragmentShaderSource = SHADER_SOURCE const std::string fragmentShaderSource =
( "#version 300 es\n"
precision mediump float; "precision mediump float;\n"
varying float v_varying; "in float v_varying;\n"
void main() { gl_FragColor = vec4(v_varying, 0, 0, 1.0); } "out vec4 my_FragColor;\n"
); "void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); }\n";
const std::string vertexShaderSource = const std::string vertexShaderSource =
"#version 300 es\n"
"#pragma STDGL invariant(all)\n" "#pragma STDGL invariant(all)\n"
"attribute vec4 a_position;\n" "in vec4 a_position;\n"
"varying float v_varying;\n" "out float v_varying;\n"
"void main() { v_varying = a_position.x; gl_Position = a_position; }\n"; "void main() { v_varying = a_position.x; gl_Position = a_position; }\n";
GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource); GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment