Commit 73bf99b7 by Alexis Hetu Committed by Commit Bot

Fix clearing the program's validation-related cache too early

When attempting to link a new program, the program must be marked as unlinked, but the validation-related caching should not be cleared yet, since we can still use the previously linked program if linking fails at this point. Added an angle end2end test which fails without this fix and passes with this fix. Fixes the following WebGL 1.0.4 test with SwANGLE: conformance/programs/program-test.html Bug: angleproject:3557 Change-Id: Ib6722ba88803979e8f292c9b7b81f85cc0304662 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2173538Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Alexis Hétu <sugoi@chromium.org>
parent 4271443d
......@@ -1419,7 +1419,10 @@ angle::Result Program::link(const Context *context)
auto *platform = ANGLEPlatformCurrent();
double startTime = platform->currentTime(platform);
unlink();
// Unlink the program, but do not clear the validation-related caching yet, since we can still
// use the previously linked program if linking the shaders fails
mLinked = false;
infoLog.reset();
// Validate we have properly attached shaders before checking the cache.
......
......@@ -5991,6 +5991,71 @@ void main()
ASSERT_GL_NO_ERROR();
}
// Verify that a valid program still draws correctly after a shader link error
TEST_P(GLSLTest, DrawAfterShaderLinkError)
{
constexpr char kVS[] = R"(attribute vec4 position;
varying vec4 vColor;
void main()
{
vColor = vec4(0.0, 1.0, 0.0, 1.0);
gl_Position = position;
})";
constexpr char kFS[] = R"(precision mediump float;
varying vec4 vColor;
void main()
{
gl_FragColor = vColor;
})";
constexpr char kBadFS[] = R"(WILL NOT COMPILE;)";
GLuint fsBad = glCreateShader(GL_FRAGMENT_SHADER);
// Create bad fragment shader
{
const char *sourceArray[1] = {kBadFS};
glShaderSource(fsBad, 1, sourceArray, nullptr);
glCompileShader(fsBad);
GLint compileResult;
glGetShaderiv(fsBad, GL_COMPILE_STATUS, &compileResult);
ASSERT_FALSE(compileResult);
}
ANGLE_GL_PROGRAM(program, kVS, kFS);
GLuint fs = GetProgramShader(program.get(), GL_FRAGMENT_SHADER);
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
glUseProgram(program.get());
GLint positionLocation = glGetAttribLocation(program.get(), "position");
std::array<Vector3, 6> quadVertices = GetQuadVertices();
for (Vector3 &vertex : quadVertices)
{
vertex.z() = 0.5f;
}
glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
glEnableVertexAttribArray(positionLocation);
glDrawArrays(GL_TRIANGLES, 0, 6);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
glDetachShader(program.get(), fs);
glAttachShader(program.get(), fsBad);
glLinkProgram(program.get());
GLint linkStatus = GL_TRUE;
glGetProgramiv(program.get(), GL_LINK_STATUS, &linkStatus);
ASSERT_FALSE(linkStatus);
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
glDrawArrays(GL_TRIANGLES, 0, 6);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
}
// Validate error messages when the link mismatch occurs on the type of a non-struct varying.
TEST_P(GLSLTest, ErrorMessageOfVaryingMismatch)
{
......
......@@ -164,6 +164,25 @@ GLuint CheckLinkStatusAndReturnProgram(GLuint program, bool outputErrorMessages)
return program;
}
GLuint GetProgramShader(GLuint program, GLint requestedType)
{
static constexpr GLsizei kMaxShaderCount = 16;
GLuint attachedShaders[kMaxShaderCount] = {0u};
GLsizei count = 0;
glGetAttachedShaders(program, kMaxShaderCount, &count, attachedShaders);
for (int i = 0; i < count; ++i)
{
GLint type = 0;
glGetShaderiv(attachedShaders[i], GL_SHADER_TYPE, &type);
if (type == requestedType)
{
return attachedShaders[i];
}
}
return 0;
}
GLuint CompileProgramWithTransformFeedback(
const char *vsSource,
const char *fsSource,
......
......@@ -15,6 +15,7 @@
#include "util/util_gl.h"
ANGLE_UTIL_EXPORT GLuint CheckLinkStatusAndReturnProgram(GLuint program, bool outputErrorMessages);
ANGLE_UTIL_EXPORT GLuint GetProgramShader(GLuint program, GLint requestedType);
ANGLE_UTIL_EXPORT GLuint CompileShader(GLenum type, const char *source);
ANGLE_UTIL_EXPORT GLuint CompileShaderFromFile(GLenum type, const std::string &sourcePath);
......
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