Vulkan: Mask out Depth/Stencil RTs in feedback loops.
This should enable some cases of limited support for feedback loops
with depth/stencil buffers. For example with Manhattan and the Vulkan
back-end.
Increases the number of RenderPasses in Manhattan slightly. This will
regress performance slightly until we can work out a better solution
that is also conformant with the spec.
Bug: angleproject:4517
Change-Id: I2758e6b4c2a930474c09cdc0950f3b6c34541089
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2106670
Commit-Queue: 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 5f65b0e..12ec765 100644
--- a/src/tests/gl_tests/FramebufferTest.cpp
+++ b/src/tests/gl_tests/FramebufferTest.cpp
@@ -1252,6 +1252,74 @@
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
}
+// Tests that we can support a feedback loop between a depth textures and the depth buffer.
+// Does not totally mirror the case used in Manhattan. The Manhattan case seems to handle
+// "clear" specially instead of rendering to depth in the same RP.
+TEST_P(FramebufferTest_ES3, DepthFeedbackLoopSupported)
+{
+ // Feedback loops not supported on D3D11 and may not ever be.
+ ANGLE_SKIP_TEST_IF(IsD3D11());
+
+ // Also this particular test doesn't work on Android despite similar support in Manhattan.
+ ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
+
+ constexpr GLuint kSize = 2;
+ glViewport(0, 0, kSize, kSize);
+
+ constexpr char kFS[] = R"(precision mediump float;
+varying vec2 v_texCoord;
+uniform sampler2D depth;
+void main()
+{
+ if (abs(texture2D(depth, v_texCoord).x - 0.5) < 0.1)
+ {
+ gl_FragColor = vec4(0, 1, 0, 1);
+ }
+ else
+ {
+ gl_FragColor = vec4(1, 0, 0, 1);
+ }
+})";
+
+ ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
+
+ GLFramebuffer framebuffer;
+ glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+
+ GLTexture colorTexture;
+ glBindTexture(GL_TEXTURE_2D, colorTexture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 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, colorTexture, 0);
+
+ GLTexture depthTexture;
+ glBindTexture(GL_TEXTURE_2D, depthTexture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, kSize, kSize, 0, GL_DEPTH_COMPONENT,
+ GL_UNSIGNED_INT, 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_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
+
+ ASSERT_GL_NO_ERROR();
+ ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
+
+ // Clear depth to 0.5.
+ glClearDepthf(0.5f);
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ // Disable the depth mask. Although this does not remove the feedback loop as defined by the
+ // spec it mimics what gfxbench does in its rendering tests.
+ glDepthMask(false);
+
+ // Verify we can sample the depth texture and get 0.5.
+ drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
+
+ ASSERT_GL_NO_ERROR();
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
ANGLE_INSTANTIATE_TEST_ES2(AddDummyTextureNoRenderTargetTest);
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(FramebufferFormatsTest);
ANGLE_INSTANTIATE_TEST_ES3(FramebufferTest_ES3);