Test RGB invalidate with user FBOs
When an RGB image is invalidated and then used as attachment, the
cleared alpha value was previously lost due to loadOp=DONT_CARE. This
was fixed by making the following render pass use loadOp=CLEAR instead.
The test for this relied on RGB backbuffers, which is not easily
testable on many platforms. This change adds a similar test using user
FBOs.
Bug: b/180139027
Bug: angleproject:6860
Change-Id: I11f408d6cd925b45bc9bcec455563cd23a226fec
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3536387
Reviewed-by: Ian Elliott <ianelliott@google.com>
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
diff --git a/src/tests/angle_end2end_tests_expectations.txt b/src/tests/angle_end2end_tests_expectations.txt
index b53f90b..520dd7f 100644
--- a/src/tests/angle_end2end_tests_expectations.txt
+++ b/src/tests/angle_end2end_tests_expectations.txt
@@ -260,6 +260,7 @@
// D3D does not support compressed textures where the base mip level is not a multiple of 4
4841 D3D9 : DXT1CompressedTextureTest.NonBlockSizesMipLevels/* = SKIP
4841 D3D11 : DXT1CompressedTextureTest.NonBlockSizesMipLevels/* = SKIP
+7109 D3D11 : ClearTestRGB_ES3.*/* = SKIP
// Android
6095 ANDROID GLES : GLSLTest_ES3.InitGlobalComplexConstant/* = SKIP
diff --git a/src/tests/gl_tests/ClearTest.cpp b/src/tests/gl_tests/ClearTest.cpp
index 45304da..a78162f 100644
--- a/src/tests/gl_tests/ClearTest.cpp
+++ b/src/tests/gl_tests/ClearTest.cpp
@@ -113,6 +113,9 @@
}
};
+class ClearTestRGB_ES3 : public ClearTestRGB
+{};
+
// Each int parameter can have three values: don't clear, clear, or masked clear. The bool
// parameter controls scissor.
using MaskedScissoredClearVariationsTestParams =
@@ -346,7 +349,7 @@
// Invalidate the RGB default framebuffer and verify that the alpha channel is not cleared, and
// stays set after drawing.
-TEST_P(ClearTestRGB, InvalidateDefaultFramebufferRGB)
+TEST_P(ClearTestRGB_ES3, InvalidateDefaultFramebufferRGB)
{
ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
@@ -358,9 +361,6 @@
EGLint backbufferAlphaBits = 0;
eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &backbufferAlphaBits);
ANGLE_SKIP_TEST_IF(backbufferAlphaBits != 0);
- // glInvalidateFramebuffer() isn't supported with GLES 2.0
- ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
- ANGLE_SKIP_TEST_IF(IsD3D11());
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
@@ -380,8 +380,40 @@
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
}
+// Invalidate an RGB user framebuffer and verify that the alpha channel is not cleared, and
+// stays set after drawing.
+TEST_P(ClearTestRGB_ES3, InvalidateUserFramebufferRGB)
+{
+ ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
+
+ GLTexture texture;
+ glBindTexture(GL_TEXTURE_2D, texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB,
+ GL_UNSIGNED_BYTE, nullptr);
+
+ GLFramebuffer fbo;
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
+ EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
+ ASSERT_GL_NO_ERROR();
+
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ // Verify that clearing alpha is ineffective on an RGB format.
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
+
+ // Invalidate the framebuffer contents.
+ const GLenum discards[] = {GL_COLOR_ATTACHMENT0};
+ glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discards);
+
+ // Without an explicit clear, draw blue and make sure alpha is unaffected. If RGB is emualted
+ // with RGBA, the previous invalidate shouldn't affect the alpha value.
+ drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.5f);
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
+}
+
// Draw with a shader that outputs alpha=0.5. Readback and ensure that alpha=1.
-TEST_P(ClearTestRGB, ShaderOutputsAlphaVerifyReadingAlphaIsOne)
+TEST_P(ClearTestRGB_ES3, ShaderOutputsAlphaVerifyReadingAlphaIsOne)
{
ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
glUseProgram(blueProgram);
@@ -394,9 +426,6 @@
EGLint backbufferAlphaBits = 0;
eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &backbufferAlphaBits);
ANGLE_SKIP_TEST_IF(backbufferAlphaBits != 0);
- // glInvalidateFramebuffer() isn't supported with GLES 2.0
- ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
- ANGLE_SKIP_TEST_IF(IsD3D11());
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
@@ -2652,4 +2681,7 @@
ES2_METAL(),
ES3_METAL());
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ClearTestRGB_ES3);
+ANGLE_INSTANTIATE_TEST(ClearTestRGB_ES3, ES3_D3D11(), ES3_VULKAN(), ES3_METAL());
+
} // anonymous namespace