Commit 6af0c03f by Ian Elliott Committed by Commit Bot

Vulkan: Always write to swapchain alpha channel

This fixes an issue with the "Ragnarok M: Eternal Love" game, which uses a GL_RGB8 format for its window, which is actually backed by a GL_RGBA8 format (a.k.a. "emulated alpha"). The game does no explicit clear per frame. Therefore, ANGLE selects a render pass loadOp=DONT_CARE, which leaves the alpha channel undefined (0.0 on a Pixel 4 XL). That causes SurfaceFlinger to show (blend or alternate vsyncs) what should have been covered up by the game (e.g. the Android launcher and live wallpaper). The solution is to prevent loadOp=DONT_CARE for emulated alpha. Test: ClearTest.ChangeFramebufferAttachmentFromRGBAtoRGB Test: dEQP-GLES2.functional.fbo.render.stencil_clear.tex2d_rgb_stencil_index8 Bug: b/180139027 Change-Id: Ied97b57c93d41326cb3294ff246691e09f316791 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2704949Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Commit-Queue: Ian Elliott <ianelliott@google.com>
parent 79f24110
......@@ -2382,9 +2382,24 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
? VK_ATTACHMENT_LOAD_OP_LOAD
: VK_ATTACHMENT_LOAD_OP_DONT_CARE;
renderPassAttachmentOps.setOps(colorIndexVk, loadOp, storeOp);
packedClearValues.store(colorIndexVk, VK_IMAGE_ASPECT_COLOR_BIT,
kUninitializedClearValue);
if (loadOp == VK_ATTACHMENT_LOAD_OP_DONT_CARE &&
mEmulatedAlphaAttachmentMask[colorIndexGL])
{
// This color attachment has a format with no alpha channel, but is emulated with a
// format that does have an alpha channel, which must be cleared to 1.0 in order to
// be visible.
renderPassAttachmentOps.setOps(colorIndexVk, VK_ATTACHMENT_LOAD_OP_CLEAR, storeOp);
VkClearValue emulatedAlphaClearValue =
getCorrectedColorClearValue(colorIndexGL, {});
packedClearValues.store(colorIndexVk, VK_IMAGE_ASPECT_COLOR_BIT,
emulatedAlphaClearValue);
}
else
{
renderPassAttachmentOps.setOps(colorIndexVk, loadOp, storeOp);
packedClearValues.store(colorIndexVk, VK_IMAGE_ASPECT_COLOR_BIT,
kUninitializedClearValue);
}
}
renderPassAttachmentOps.setStencilOps(colorIndexVk, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
vk::RenderPassStoreOp::DontCare);
......
......@@ -344,6 +344,33 @@ TEST_P(ClearTestRGB, DefaultFramebufferRGB)
EXPECT_PIXEL_NEAR(0, 0, 64, 128, 128, 255, 1.0);
}
// Invalidate the RGB default framebuffer and verify that the alpha channel is not cleared, and
// stays set after drawing.
TEST_P(ClearTestRGB, InvalidateDefaultFramebufferRGB)
{
ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
// Some GPUs don't support RGB format default framebuffer,
// so skip if the back buffer has alpha bits.
EGLWindow *window = getEGLWindow();
EGLDisplay display = window->getDisplay();
EGLConfig config = window->getConfig();
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());
const GLenum discards[] = {GL_COLOR};
glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discards);
EXPECT_PIXEL_NEAR(0, 0, 0, 0, 0, 255, 1.0);
// Don't explicitly clear, but draw blue (make sure alpha is not cleared)
drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.5f);
EXPECT_PIXEL_NEAR(0, 0, 0, 0, 255, 255, 1.0);
}
// Test clearing a RGBA8 Framebuffer
TEST_P(ClearTest, RGBA8Framebuffer)
{
......
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