Create test to validate scissor size is correct
The concern is that if a user changes the framebuffer's attachment
to one with a different size, contextVk->updateScissor() may not be
called and we may render too much/little. This change creates a test to
verify that when the FBO's attachment size changes, the correct amount
of fragments are drawn.
Bug: angleproject:3754
Test: FramebufferTest_ES3
Change-Id: I47108d6fe3e671ddc8c30cf969f63c1c3ae76f84
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1842128
Commit-Queue: Courtney Goeltzenleuchter <courtneygo@google.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Courtney Goeltzenleuchter <courtneygo@google.com>
diff --git a/src/tests/gl_tests/FramebufferTest.cpp b/src/tests/gl_tests/FramebufferTest.cpp
index 247c284..ad483fd 100644
--- a/src/tests/gl_tests/FramebufferTest.cpp
+++ b/src/tests/gl_tests/FramebufferTest.cpp
@@ -366,6 +366,7 @@
// tests should be run against.
ANGLE_INSTANTIATE_TEST(FramebufferFormatsTest,
ES2_VULKAN(),
+ ES3_VULKAN(),
ES2_D3D9(),
ES2_D3D11(),
ES3_D3D11(),
@@ -380,6 +381,9 @@
// Covers invalidating an incomplete framebuffer. This should be a no-op, but should not error.
TEST_P(FramebufferTest_ES3, InvalidateIncomplete)
{
+ // TODO: anglebug.com/3971
+ ANGLE_SKIP_TEST_IF(IsVulkan());
+
GLFramebuffer framebuffer;
GLRenderbuffer renderbuffer;
@@ -645,7 +649,189 @@
EXPECT_GL_NO_ERROR();
}
-ANGLE_INSTANTIATE_TEST(FramebufferTest_ES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
+// Test that resizing the color attachment is handled correctly.
+TEST_P(FramebufferTest_ES3, ResizeColorAttachmentSmallToLarge)
+{
+ GLFramebuffer fbo;
+ GLTexture smallTexture;
+ GLTexture largeTexture;
+
+ ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
+ ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
+
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+ // Bind the small texture
+ glBindTexture(GL_TEXTURE_2D, smallTexture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, nullptr);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, smallTexture, 0);
+ ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+ // Draw to FBO backed by the small texture
+ glUseProgram(greenProgram);
+ drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
+ ASSERT_GL_NO_ERROR();
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+ EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::green);
+
+ // Change the attachment to the larger texture that fills the window
+ glBindTexture(GL_TEXTURE_2D, largeTexture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, nullptr);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, largeTexture, 0);
+ ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+ // Draw to FBO backed by the large texture
+ glUseProgram(blueProgram);
+ drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
+ ASSERT_GL_NO_ERROR();
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
+ EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::blue);
+}
+
+// Test that resizing the color attachment is handled correctly.
+TEST_P(FramebufferTest_ES3, ResizeColorAttachmentLargeToSmall)
+{
+ GLFramebuffer fbo;
+ GLTexture smallTexture;
+ GLTexture largeTexture;
+
+ ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
+ ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
+
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+ // Bind the large texture
+ glBindTexture(GL_TEXTURE_2D, largeTexture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, nullptr);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, largeTexture, 0);
+ ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+ // Draw to FBO backed by the large texture
+ glUseProgram(blueProgram);
+ drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
+ ASSERT_GL_NO_ERROR();
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
+ EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::blue);
+
+ // Change the attachment to the smaller texture
+ glBindTexture(GL_TEXTURE_2D, smallTexture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, nullptr);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, smallTexture, 0);
+ ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+ // Draw to FBO backed by the small texture
+ glUseProgram(greenProgram);
+ drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
+ ASSERT_GL_NO_ERROR();
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+ EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::green);
+}
+
+// Test that resizing the texture is handled correctly.
+TEST_P(FramebufferTest_ES3, ResizeTextureLargeToSmall)
+{
+ GLFramebuffer fbo;
+ GLTexture texture;
+
+ ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
+ ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
+
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+ // Allocate a large texture
+ glBindTexture(GL_TEXTURE_2D, texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, nullptr);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
+ ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+ // Draw to FBO backed by the large texture
+ glUseProgram(blueProgram);
+ drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
+ ASSERT_GL_NO_ERROR();
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
+ EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::blue);
+
+ // Shrink the texture
+ glBindTexture(GL_TEXTURE_2D, texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, nullptr);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
+ ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+ // Draw to FBO backed by the small texture
+ glUseProgram(greenProgram);
+ drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
+ ASSERT_GL_NO_ERROR();
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+ EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::green);
+}
+
+// Test that resizing the texture is handled correctly.
+TEST_P(FramebufferTest_ES3, ResizeTextureSmallToLarge)
+{
+ GLFramebuffer fbo;
+ GLTexture texture;
+
+ ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
+ ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
+
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+ // Allocate a small texture
+ glBindTexture(GL_TEXTURE_2D, texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, nullptr);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
+ ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+ // Draw to FBO backed by the large texture
+ glUseProgram(blueProgram);
+ drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
+ ASSERT_GL_NO_ERROR();
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
+ EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::blue);
+
+ // Grow the texture
+ glBindTexture(GL_TEXTURE_2D, texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, nullptr);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
+ ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+ // Draw to FBO backed by the small texture
+ glUseProgram(greenProgram);
+ drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
+ ASSERT_GL_NO_ERROR();
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+ EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
+}
+
+ANGLE_INSTANTIATE_TEST(FramebufferTest_ES3,
+ ES3_D3D11(),
+ ES3_OPENGL(),
+ ES3_OPENGLES(),
+ ES3_VULKAN());
class FramebufferTest_ES31 : public ANGLETest
{