Commit 5fd3693e by Luc Ferron Committed by Commit Bot

Vulkan: Mask the alpha channel for draw when needed

When the angleFormat we have has no alpha channel, but the actual texture underneath has one, we shouldn't be drawing over the alpha channel, so we apply a mask on it when we're in this situation. Bug: angleproject:2597 Change-Id: Ia7110709e6ee32bb61988d08f5049e4e80e7e24e Reviewed-on: https://chromium-review.googlesource.com/1106759 Commit-Queue: Luc Ferron <lucferron@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 1a3bbaa8
...@@ -362,6 +362,17 @@ void ContextVk::popDebugGroup() ...@@ -362,6 +362,17 @@ void ContextVk::popDebugGroup()
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
void ContextVk::updateClearColorMask(const gl::BlendState &blendState)
{
mClearColorMask =
gl_vk::GetColorComponentFlags(blendState.colorMaskRed, blendState.colorMaskGreen,
blendState.colorMaskBlue, blendState.colorMaskAlpha);
FramebufferVk *framebufferVk = vk::GetImpl(mState.getState().getDrawFramebuffer());
mPipelineDesc->updateColorWriteMask(mClearColorMask,
framebufferVk->getEmulatedAlphaAttachmentMask());
}
void ContextVk::updateScissor(const gl::State &glState) void ContextVk::updateScissor(const gl::State &glState)
{ {
if (glState.isScissorTestEnabled()) if (glState.isScissorTestEnabled())
...@@ -417,14 +428,8 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits ...@@ -417,14 +428,8 @@ 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());
const gl::BlendState &blendState = glState.getBlendState();
mClearColorMask = gl_vk::GetColorComponentFlags(
blendState.colorMaskRed, blendState.colorMaskGreen, blendState.colorMaskBlue,
blendState.colorMaskAlpha);
mPipelineDesc->updateColorWriteMask(mClearColorMask);
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";
break; break;
...@@ -534,7 +539,7 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits ...@@ -534,7 +539,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:
WARN() << "DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING unimplemented"; updateClearColorMask(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";
......
...@@ -171,6 +171,7 @@ class ContextVk : public ContextImpl ...@@ -171,6 +171,7 @@ 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;
......
...@@ -203,11 +203,21 @@ gl::Error FramebufferVk::clear(const gl::Context *context, GLbitfield mask) ...@@ -203,11 +203,21 @@ gl::Error FramebufferVk::clear(const gl::Context *context, GLbitfield mask)
const VkClearColorValue &clearColorValue = contextVk->getClearColorValue().color; const VkClearColorValue &clearColorValue = contextVk->getClearColorValue().color;
for (size_t colorIndex : mState.getEnabledDrawBuffers()) for (size_t colorIndex : mState.getEnabledDrawBuffers())
{ {
VkClearColorValue modifiedClearColorValue = clearColorValue;
RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndex]; RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndex];
// Its possible we're clearing a render target that has no alpha channel but we represent it
// with a texture that has one. We must not affect its alpha channel no matter what the
// clear value is in that case.
if (mEmulatedAlphaAttachmentMask[colorIndex])
{
modifiedClearColorValue.float32[3] = 1.0;
}
ASSERT(colorRenderTarget); ASSERT(colorRenderTarget);
vk::ImageHelper *image = colorRenderTarget->getImageForWrite(currentSerial, this); vk::ImageHelper *image = colorRenderTarget->getImageForWrite(currentSerial, this);
GLint mipLevelToClear = (attachment->type() == GL_TEXTURE) ? attachment->mipLevel() : 0; GLint mipLevelToClear = (attachment->type() == GL_TEXTURE) ? attachment->mipLevel() : 0;
image->clearColor(clearColorValue, mipLevelToClear, 1, commandBuffer); image->clearColor(modifiedClearColorValue, mipLevelToClear, 1, commandBuffer);
} }
return gl::NoError(); return gl::NoError();
...@@ -369,9 +379,19 @@ gl::Error FramebufferVk::syncState(const gl::Context *context, ...@@ -369,9 +379,19 @@ gl::Error FramebufferVk::syncState(const gl::Context *context,
RenderTargetVk *renderTarget = mRenderTargetCache.getColors()[colorIndex]; RenderTargetVk *renderTarget = mRenderTargetCache.getColors()[colorIndex];
if (renderTarget) if (renderTarget)
{ {
const angle::Format &format = renderTarget->getImageFormat().textureFormat(); const angle::Format &emulatedFormat =
updateActiveColorMasks(colorIndex, format.redBits > 0, format.greenBits > 0, renderTarget->getImageFormat().textureFormat();
format.blueBits > 0, format.alphaBits > 0); updateActiveColorMasks(
colorIndex, emulatedFormat.redBits > 0, emulatedFormat.greenBits > 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 =
renderTarget->getImageFormat().angleFormat();
mEmulatedAlphaAttachmentMask.set(
colorIndex, sourceFormat.alphaBits == 0 && emulatedFormat.alphaBits > 0);
} }
else else
{ {
...@@ -383,8 +403,8 @@ gl::Error FramebufferVk::syncState(const gl::Context *context, ...@@ -383,8 +403,8 @@ gl::Error FramebufferVk::syncState(const gl::Context *context,
} }
mActiveColorComponents = gl_vk::GetColorComponentFlags( mActiveColorComponents = gl_vk::GetColorComponentFlags(
mActiveColorComponentMasks[0].any(), mActiveColorComponentMasks[1].any(), mActiveColorComponentMasksForClear[0].any(), mActiveColorComponentMasksForClear[1].any(),
mActiveColorComponentMasks[2].any(), mActiveColorComponentMasks[3].any()); mActiveColorComponentMasksForClear[2].any(), mActiveColorComponentMasksForClear[3].any());
mRenderPassDesc.reset(); mRenderPassDesc.reset();
renderer->releaseObject(getStoredQueueSerial(), &mFramebuffer); renderer->releaseObject(getStoredQueueSerial(), &mFramebuffer);
...@@ -626,7 +646,7 @@ gl::Error FramebufferVk::clearWithDraw(const gl::Context *context, ...@@ -626,7 +646,7 @@ gl::Error FramebufferVk::clearWithDraw(const gl::Context *context,
// This pipeline desc could be cached. // This pipeline desc could be cached.
vk::PipelineDesc pipelineDesc; vk::PipelineDesc pipelineDesc;
pipelineDesc.initDefaults(); pipelineDesc.initDefaults();
pipelineDesc.updateColorWriteMask(colorMaskFlags); pipelineDesc.updateColorWriteMask(colorMaskFlags, getEmulatedAlphaAttachmentMask());
pipelineDesc.updateRenderPassDesc(getRenderPassDesc()); pipelineDesc.updateRenderPassDesc(getRenderPassDesc());
pipelineDesc.updateShaders(fullScreenQuad->queueSerial(), pushConstantColor->queueSerial()); pipelineDesc.updateShaders(fullScreenQuad->queueSerial(), pushConstantColor->queueSerial());
pipelineDesc.updateViewport(renderArea, 0.0f, 1.0f); pipelineDesc.updateViewport(renderArea, 0.0f, 1.0f);
...@@ -740,10 +760,15 @@ gl::Error FramebufferVk::getCommandBufferForDraw(ContextVk *contextVk, ...@@ -740,10 +760,15 @@ gl::Error FramebufferVk::getCommandBufferForDraw(ContextVk *contextVk,
void FramebufferVk::updateActiveColorMasks(size_t colorIndex, bool r, bool g, bool b, bool a) void FramebufferVk::updateActiveColorMasks(size_t colorIndex, bool r, bool g, bool b, bool a)
{ {
mActiveColorComponentMasks[0].set(colorIndex, r); mActiveColorComponentMasksForClear[0].set(colorIndex, r);
mActiveColorComponentMasks[1].set(colorIndex, g); mActiveColorComponentMasksForClear[1].set(colorIndex, g);
mActiveColorComponentMasks[2].set(colorIndex, b); mActiveColorComponentMasksForClear[2].set(colorIndex, b);
mActiveColorComponentMasks[3].set(colorIndex, a); mActiveColorComponentMasksForClear[3].set(colorIndex, a);
}
gl::DrawBufferMask FramebufferVk::getEmulatedAlphaAttachmentMask()
{
return mEmulatedAlphaAttachmentMask;
} }
gl::Error FramebufferVk::readPixelsImpl(const gl::Context *context, gl::Error FramebufferVk::readPixelsImpl(const gl::Context *context,
......
...@@ -100,6 +100,8 @@ class FramebufferVk : public FramebufferImpl, public vk::CommandGraphResource ...@@ -100,6 +100,8 @@ class FramebufferVk : public FramebufferImpl, public vk::CommandGraphResource
const gl::Extents &getReadImageExtents() const; const gl::Extents &getReadImageExtents() const;
gl::DrawBufferMask getEmulatedAlphaAttachmentMask();
private: private:
FramebufferVk(const gl::FramebufferState &state); FramebufferVk(const gl::FramebufferState &state);
FramebufferVk(const gl::FramebufferState &state, WindowSurfaceVk *backbuffer); FramebufferVk(const gl::FramebufferState &state, WindowSurfaceVk *backbuffer);
...@@ -124,9 +126,13 @@ class FramebufferVk : public FramebufferImpl, public vk::CommandGraphResource ...@@ -124,9 +126,13 @@ class FramebufferVk : public FramebufferImpl, public vk::CommandGraphResource
// channel is masked out, we check against the Framebuffer Attachments (RenderTargets) to see // channel is masked out, we check against the Framebuffer Attachments (RenderTargets) to see
// if the masked out channel is present in any of the attachments. // if the masked out channel is present in any of the attachments.
VkColorComponentFlags mActiveColorComponents; VkColorComponentFlags mActiveColorComponents;
gl::DrawBufferMask mActiveColorComponentMasks[4]; gl::DrawBufferMask mActiveColorComponentMasksForClear[4];
vk::DynamicBuffer mReadPixelsBuffer; vk::DynamicBuffer mReadPixelsBuffer;
// When we draw to the framebuffer, and the real format has an alpha channel but the format of
// the framebuffer does not, we need to mask out the alpha channel. This DrawBufferMask will
// contain the mask to apply to the alpha channel when drawing.
gl::DrawBufferMask mEmulatedAlphaAttachmentMask;
}; };
} // namespace rx } // namespace rx
......
...@@ -723,13 +723,15 @@ void PipelineDesc::updateBlendFuncs(const gl::BlendState &blendState) ...@@ -723,13 +723,15 @@ void PipelineDesc::updateBlendFuncs(const gl::BlendState &blendState)
} }
} }
void PipelineDesc::updateColorWriteMask(VkColorComponentFlags colorComponentFlags) void PipelineDesc::updateColorWriteMask(VkColorComponentFlags colorComponentFlags,
const gl::DrawBufferMask &alphaMask)
{ {
uint8_t colorMask = static_cast<uint8_t>(colorComponentFlags); uint8_t colorMask = static_cast<uint8_t>(colorComponentFlags);
for (PackedColorBlendAttachmentState &blendAttachmentState : mColorBlendStateInfo.attachments) for (size_t colorIndex = 0; colorIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorIndex++)
{ {
blendAttachmentState.colorWriteMask = colorMask; mColorBlendStateInfo.attachments[colorIndex].colorWriteMask =
alphaMask[colorIndex] ? (colorMask & ~VK_COLOR_COMPONENT_A_BIT) : colorMask;
} }
} }
......
...@@ -382,7 +382,8 @@ class PipelineDesc final ...@@ -382,7 +382,8 @@ class PipelineDesc final
void updateBlendColor(const gl::ColorF &color); void updateBlendColor(const gl::ColorF &color);
void updateBlendFuncs(const gl::BlendState &blendState); void updateBlendFuncs(const gl::BlendState &blendState);
void updateBlendEquations(const gl::BlendState &blendState); void updateBlendEquations(const gl::BlendState &blendState);
void updateColorWriteMask(VkColorComponentFlags colorComponentFlags); void updateColorWriteMask(VkColorComponentFlags colorComponentFlags,
const gl::DrawBufferMask &alphaMask);
// Depth/stencil states. // Depth/stencil states.
void updateDepthTestEnabled(const gl::DepthStencilState &depthStencilState); void updateDepthTestEnabled(const gl::DepthStencilState &depthStencilState);
......
...@@ -231,7 +231,6 @@ ...@@ -231,7 +231,6 @@
2592 VULKAN : dEQP-GLES2.functional.shaders.builtin_variable.depth_range* = SKIP 2592 VULKAN : dEQP-GLES2.functional.shaders.builtin_variable.depth_range* = SKIP
2595 VULKAN : dEQP-GLES2.functional.shaders.random.all_features.fragment* = SKIP 2595 VULKAN : dEQP-GLES2.functional.shaders.random.all_features.fragment* = SKIP
2597 VULKAN : dEQP-GLES2.functional.fbo.render.recreate_stencilbuffer.no_rebind_rbo_rgb* = SKIP 2597 VULKAN : dEQP-GLES2.functional.fbo.render.recreate_stencilbuffer.no_rebind_rbo_rgb* = SKIP
2597 VULKAN : dEQP-GLES2.functional.fbo.render.stencil_clear.tex2d_rgb_stencil_index8 = SKIP
2161 VULKAN : dEQP-GLES2.functional.vertex_arrays.* = SKIP 2161 VULKAN : dEQP-GLES2.functional.vertex_arrays.* = SKIP
2598 VULKAN : dEQP-GLES2.functional.rasterization.primitives.line* = SKIP 2598 VULKAN : dEQP-GLES2.functional.rasterization.primitives.line* = SKIP
2599 VULKAN : dEQP-GLES2.functional.rasterization.limits.points = SKIP 2599 VULKAN : dEQP-GLES2.functional.rasterization.limits.points = SKIP
......
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