Commit 0bb940a8 by Luc Ferron Committed by Commit Bot

Vulkan: Edge case test and fix for alpha channel masks

The contextVk color mask needed to be updated when we were syncing the state of the framebufferVk to make sure the right mask gets applied in the test described in ClearTest.cpp Bug: angleproject:2685 Bug: angleproject:2597 Change-Id: I575028aad4cd495bf4ec1484cc870940dcde92d5 Reviewed-on: https://chromium-review.googlesource.com/1112038 Commit-Queue: Luc Ferron <lucferron@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent af7dc01c
...@@ -378,7 +378,7 @@ void ContextVk::popDebugGroup() ...@@ -378,7 +378,7 @@ void ContextVk::popDebugGroup()
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
void ContextVk::updateClearColorMask(const gl::BlendState &blendState) void ContextVk::updateColorMask(const gl::BlendState &blendState)
{ {
mClearColorMask = mClearColorMask =
gl_vk::GetColorComponentFlags(blendState.colorMaskRed, blendState.colorMaskGreen, gl_vk::GetColorComponentFlags(blendState.colorMaskRed, blendState.colorMaskGreen,
...@@ -444,7 +444,7 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits ...@@ -444,7 +444,7 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits
mPipelineDesc->updateBlendEquations(glState.getBlendState()); mPipelineDesc->updateBlendEquations(glState.getBlendState());
break; break;
case gl::State::DIRTY_BIT_COLOR_MASK: case gl::State::DIRTY_BIT_COLOR_MASK:
updateClearColorMask(glState.getBlendState()); updateColorMask(glState.getBlendState());
break; break;
case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED: case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
WARN() << "DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED unimplemented"; WARN() << "DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED unimplemented";
...@@ -555,7 +555,7 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits ...@@ -555,7 +555,7 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits
WARN() << "DIRTY_BIT_READ_FRAMEBUFFER_BINDING unimplemented"; WARN() << "DIRTY_BIT_READ_FRAMEBUFFER_BINDING unimplemented";
break; break;
case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING: case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING:
updateClearColorMask(glState.getBlendState()); updateColorMask(glState.getBlendState());
break; break;
case gl::State::DIRTY_BIT_RENDERBUFFER_BINDING: case gl::State::DIRTY_BIT_RENDERBUFFER_BINDING:
WARN() << "DIRTY_BIT_RENDERBUFFER_BINDING unimplemented"; WARN() << "DIRTY_BIT_RENDERBUFFER_BINDING unimplemented";
......
...@@ -163,6 +163,7 @@ class ContextVk : public ContextImpl ...@@ -163,6 +163,7 @@ class ContextVk : public ContextImpl
gl::Error getIncompleteTexture(const gl::Context *context, gl::Error getIncompleteTexture(const gl::Context *context,
gl::TextureType type, gl::TextureType type,
gl::Texture **textureOut); gl::Texture **textureOut);
void updateColorMask(const gl::BlendState &blendState);
private: private:
gl::Error initPipeline(); gl::Error initPipeline();
...@@ -171,7 +172,6 @@ class ContextVk : public ContextImpl ...@@ -171,7 +172,6 @@ class ContextVk : public ContextImpl
vk::CommandBuffer **commandBufferOut, vk::CommandBuffer **commandBufferOut,
bool *shouldApplyVertexArrayOut); bool *shouldApplyVertexArrayOut);
void updateClearColorMask(const gl::BlendState &blendState);
void updateScissor(const gl::State &glState); void updateScissor(const gl::State &glState);
RendererVk *mRenderer; RendererVk *mRenderer;
......
...@@ -390,13 +390,12 @@ gl::Error FramebufferVk::syncState(const gl::Context *context, ...@@ -390,13 +390,12 @@ gl::Error FramebufferVk::syncState(const gl::Context *context,
colorIndex, emulatedFormat.redBits > 0, emulatedFormat.greenBits > 0, colorIndex, emulatedFormat.redBits > 0, emulatedFormat.greenBits > 0,
emulatedFormat.blueBits > 0, emulatedFormat.alphaBits > 0); emulatedFormat.blueBits > 0, emulatedFormat.alphaBits > 0);
// TODO(lucferron): Add a test to trigger edge case where the framebuffer
// attachment would change but not the binding.
// http://anglebug.com/2597
const angle::Format &sourceFormat = const angle::Format &sourceFormat =
renderTarget->getImageFormat().angleFormat(); renderTarget->getImageFormat().angleFormat();
mEmulatedAlphaAttachmentMask.set( mEmulatedAlphaAttachmentMask.set(
colorIndex, sourceFormat.alphaBits == 0 && emulatedFormat.alphaBits > 0); colorIndex, sourceFormat.alphaBits == 0 && emulatedFormat.alphaBits > 0);
contextVk->updateColorMask(context->getGLState().getBlendState());
} }
else else
{ {
......
...@@ -106,6 +106,61 @@ TEST_P(ClearTest, RGBA8Framebuffer) ...@@ -106,6 +106,61 @@ TEST_P(ClearTest, RGBA8Framebuffer)
EXPECT_PIXEL_NEAR(0, 0, 128, 128, 128, 128, 1.0); EXPECT_PIXEL_NEAR(0, 0, 128, 128, 128, 128, 1.0);
} }
// Test to validate that we can go from an RGBA framebuffer attachment, to an RGB one and still
// have a correct behavior after.
TEST_P(ClearTest, ChangeFramebufferAttachmentFromRGBAtoRGB)
{
// TODO(lucferron): Diagnose and fix this on D3D9 and 11.
// http://anglebug.com/2685
ANGLE_SKIP_TEST_IF(IsD3D9() || IsD3D11());
ANGLE_GL_PROGRAM(program, angle::essl1_shaders::vs::Simple(),
angle::essl1_shaders::fs::UniformColor());
setupQuadVertexBuffer(0.5f, 1.0f);
glUseProgram(program);
GLint positionLocation = glGetAttribLocation(program, angle::essl1_shaders::PositionAttrib());
ASSERT_NE(positionLocation, -1);
glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(positionLocation);
GLint colorUniformLocation =
glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
ASSERT_NE(colorUniformLocation, -1);
glUniform4f(colorUniformLocation, 1.0f, 1.0f, 1.0f, 0.5f);
glBindFramebuffer(GL_FRAMEBUFFER, mFBOs[0]);
GLTexture texture;
glColorMask(GL_TRUE, GL_FALSE, GL_TRUE, GL_TRUE);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
GL_UNSIGNED_BYTE, nullptr);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
glClearColor(0.5f, 0.5f, 0.5f, 0.5f);
glClear(GL_COLOR_BUFFER_BIT);
ASSERT_GL_NO_ERROR();
// So far so good, we have an RGBA framebuffer that we've cleared to 0.5 everywhere.
EXPECT_PIXEL_NEAR(0, 0, 128, 0, 128, 128, 1.0);
// In the Vulkan backend, RGB textures are emulated with an RGBA texture format
// underneath and we keep a special mask to know that we shouldn't touch the alpha
// channel when we have that emulated texture. This test exists to validate that
// this mask gets updated correctly when the framebuffer attachment changes.
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB,
GL_UNSIGNED_BYTE, nullptr);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
ASSERT_GL_NO_ERROR();
glDrawArrays(GL_TRIANGLES, 0, 6);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::magenta);
}
// Test clearing a RGB8 Framebuffer with a color mask. // Test clearing a RGB8 Framebuffer with a color mask.
TEST_P(ClearTest, RGB8WithMaskFramebuffer) TEST_P(ClearTest, RGB8WithMaskFramebuffer)
{ {
......
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