Commit e4e2a016 by Charlie Lao Committed by Commit Bot

Vulkan: Use color mask to handle draw buffer disabled case

When draw buffers set to GL_NONE, instead of remove the attachment from renderpass which breaks renderpass, we force vulkan's per buffer color mask to false while keep the disabled draw buffer attached. This CL also always create FrameBuffer with all color attachments regardless it is enabled or not. Bug: b/167301719 Change-Id: Ice9fca9aacf774a47d13b749f822b222cc050174 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2389007Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Commit-Queue: Charlie Lao <cclao@google.com>
parent 821aabb3
......@@ -2624,10 +2624,10 @@ void ContextVk::updateColorMask(const gl::BlendState &blendState)
mClearColorMask =
gl_vk::GetColorComponentFlags(blendState.colorMaskRed, blendState.colorMaskGreen,
blendState.colorMaskBlue, blendState.colorMaskAlpha);
FramebufferVk *framebufferVk = vk::GetImpl(mState.getDrawFramebuffer());
mGraphicsPipelineDesc->updateColorWriteMask(&mGraphicsPipelineTransition, mClearColorMask,
framebufferVk->getEmulatedAlphaAttachmentMask());
framebufferVk->getEmulatedAlphaAttachmentMask(),
framebufferVk->getState().getEnabledDrawBuffers());
}
void ContextVk::updateSampleMask(const gl::State &glState)
......
......@@ -1477,9 +1477,10 @@ angle::Result FramebufferVk::invalidateImpl(ContextVk *contextVk,
{
// Set the appropriate storeOp for attachments.
size_t attachmentIndexVk = 0;
for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
for (size_t colorIndexGL : mAttachedColorBufferMask)
{
if (invalidateColorBuffers.test(colorIndexGL))
if (mState.getEnabledDrawBuffers()[colorIndexGL] &&
invalidateColorBuffers.test(colorIndexGL))
{
contextVk->getStartedRenderPassCommands().invalidateRenderPassColorAttachment(
attachmentIndexVk);
......@@ -1576,16 +1577,19 @@ angle::Result FramebufferVk::updateColorAttachment(const gl::Context *context,
updateActiveColorMasks(colorIndexGL, false, false, false, false);
}
const bool enabledColor = renderTarget && mState.getEnabledDrawBuffers()[colorIndexGL];
const bool enabledColor =
renderTarget && mState.getColorAttachments()[colorIndexGL].isAttached();
const bool enabledResolve = enabledColor && renderTarget->hasResolveAttachment();
if (enabledColor)
{
mCurrentFramebufferDesc.updateColor(colorIndexGL, renderTarget->getDrawSubresourceSerial());
mAttachedColorBufferMask.set(colorIndexGL);
}
else
{
mCurrentFramebufferDesc.updateColor(colorIndexGL, vk::kInvalidImageViewSubresourceSerial);
mAttachedColorBufferMask.reset(colorIndexGL);
}
if (enabledResolve)
......@@ -1662,6 +1666,7 @@ angle::Result FramebufferVk::syncState(const gl::Context *context,
// If we are notified that any attachment is dirty, but we have deferred clears for them, a
// flushDeferredClears() call is missing somewhere. ASSERT this to catch these bugs.
vk::ClearValuesArray previousDeferredClears = mDeferredClears;
bool shouldUpdateColorMask = false;
// For any updated attachments we'll update their Serials below
ASSERT(dirtyBits.any());
......@@ -1681,22 +1686,7 @@ angle::Result FramebufferVk::syncState(const gl::Context *context,
ANGLE_TRY(mRenderTargetCache.update(context, mState, dirtyBits));
break;
case gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
// Force update of serial for enabled draw buffers
mCurrentFramebufferDesc.reset();
for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
{
uint32_t colorIndex32 = static_cast<uint32_t>(colorIndexGL);
RenderTargetVk *renderTarget = mRenderTargetCache.getColors()[colorIndexGL];
mCurrentFramebufferDesc.updateColor(colorIndex32,
renderTarget->getDrawSubresourceSerial());
if (renderTarget->hasResolveAttachment())
{
mCurrentFramebufferDesc.updateColorResolve(
colorIndex32, renderTarget->getResolveSubresourceSerial());
}
}
updateDepthStencilAttachmentSerial(contextVk);
shouldUpdateColorMask = true;
break;
case gl::Framebuffer::DIRTY_BIT_DEFAULT_WIDTH:
case gl::Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT:
......@@ -1724,13 +1714,18 @@ angle::Result FramebufferVk::syncState(const gl::Context *context,
}
ASSERT(!previousDeferredClears.test(colorIndexGL));
ANGLE_TRY(updateColorAttachment(context, deferClears, colorIndexGL));
shouldUpdateColorMask = true;
break;
}
}
}
if (shouldUpdateColorMask)
{
contextVk->updateColorMask(context->getState().getBlendState());
}
// In some cases we'll need to force a flush of deferred clears. When we're syncing the read
// framebuffer we might not get a RenderPass. Also when there are masked out cleared color
// channels.
......@@ -1802,11 +1797,10 @@ void FramebufferVk::updateRenderPassDesc()
mRenderPassDesc.setSamples(getSamples());
// Color attachments.
const auto &colorRenderTargets = mRenderTargetCache.getColors();
const gl::DrawBufferMask enabledDrawBuffers = mState.getEnabledDrawBuffers();
for (size_t colorIndexGL = 0; colorIndexGL < enabledDrawBuffers.size(); ++colorIndexGL)
const auto &colorRenderTargets = mRenderTargetCache.getColors();
for (size_t colorIndexGL = 0; colorIndexGL < mAttachedColorBufferMask.size(); ++colorIndexGL)
{
if (enabledDrawBuffers[colorIndexGL])
if (mAttachedColorBufferMask[colorIndexGL])
{
RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
ASSERT(colorRenderTarget);
......@@ -1880,7 +1874,7 @@ angle::Result FramebufferVk::getFramebuffer(ContextVk *contextVk,
// Color attachments.
const auto &colorRenderTargets = mRenderTargetCache.getColors();
for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
for (size_t colorIndexGL : mAttachedColorBufferMask)
{
RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
ASSERT(colorRenderTarget);
......@@ -1920,7 +1914,7 @@ angle::Result FramebufferVk::getFramebuffer(ContextVk *contextVk,
else
{
// This Framebuffer owns all of the ImageViews, including its own resolve ImageViews.
for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
for (size_t colorIndexGL : mAttachedColorBufferMask)
{
RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
ASSERT(colorRenderTarget);
......@@ -2124,18 +2118,16 @@ void FramebufferVk::clearWithLoadOp(ContextVk *contextVk,
ASSERT(commands.getCommandBuffer().empty());
// The clear colors are packed with no gaps. The draw buffers mask is unpacked
// and can have gaps. Thus we need to count the packed index explicitly in this loop.
size_t colorCount = 0;
for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
uint32_t colorIndexVk = 0;
for (size_t colorIndexGL : mAttachedColorBufferMask)
{
if (clearColorBuffers[colorIndexGL])
if (mState.getEnabledDrawBuffers()[colorIndexGL] && clearColorBuffers[colorIndexGL])
{
VkClearValue clearValue =
getCorrectedColorClearValue(colorIndexGL, clearColorValue);
commands.updateRenderPassColorClear(colorCount, clearValue);
commands.updateRenderPassColorClear(colorIndexVk, clearValue);
}
colorCount++;
++colorIndexVk;
}
if (dsAspectFlags)
......@@ -2242,7 +2234,7 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
// Color attachments.
const auto &colorRenderTargets = mRenderTargetCache.getColors();
uint32_t colorAttachmentCount = 0;
for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
for (size_t colorIndexGL : mAttachedColorBufferMask)
{
RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
ASSERT(colorRenderTarget);
......@@ -2386,7 +2378,7 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
// Transition the images to the correct layout (through onColorDraw) after the
// resolve-to-multisampled copies are done.
for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
for (size_t colorIndexGL : mAttachedColorBufferMask)
{
RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
colorRenderTarget->onColorDraw(contextVk);
......
......@@ -124,13 +124,6 @@ class FramebufferVk : public FramebufferImpl
const vk::RenderPassDesc &getRenderPassDesc() const { return mRenderPassDesc; }
// We only support depth/stencil packed format and depthstencil attachment always follow all
// color attachments
size_t getDepthStencilAttachmentIndexVk() const
{
return getState().getEnabledDrawBuffers().count();
}
angle::Result getFramebuffer(ContextVk *contextVk,
vk::Framebuffer **framebufferOut,
const vk::ImageView *resolveImageViewIn);
......@@ -257,6 +250,8 @@ class FramebufferVk : public FramebufferImpl
vk::FramebufferDesc mCurrentFramebufferDesc;
std::unordered_map<vk::FramebufferDesc, vk::FramebufferHelper> mFramebufferCache;
// Tracks all the color buffers attached to this FramebufferDesc
gl::DrawBufferMask mAttachedColorBufferMask;
vk::ClearValuesArray mDeferredClears;
};
......
......@@ -1162,7 +1162,7 @@ angle::Result UtilsVk::clearFramebuffer(ContextVk *contextVk,
vk::GraphicsPipelineDesc pipelineDesc;
pipelineDesc.initDefaults();
pipelineDesc.setCullMode(VK_CULL_MODE_NONE);
pipelineDesc.setColorWriteMask(0, gl::DrawBufferMask());
pipelineDesc.setColorWriteMask(0, gl::DrawBufferMask(), gl::DrawBufferMask());
pipelineDesc.setSingleColorWriteMask(params.colorAttachmentIndexGL, params.colorMaskFlags);
pipelineDesc.setRasterizationSamples(framebuffer->getSamples());
pipelineDesc.setRenderPassDesc(framebuffer->getRenderPassDesc());
......@@ -1374,11 +1374,12 @@ angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk,
if (blitColor)
{
pipelineDesc.setColorWriteMask(kAllColorComponents,
framebuffer->getEmulatedAlphaAttachmentMask());
framebuffer->getEmulatedAlphaAttachmentMask(),
~gl::DrawBufferMask());
}
else
{
pipelineDesc.setColorWriteMask(0, gl::DrawBufferMask());
pipelineDesc.setColorWriteMask(0, gl::DrawBufferMask(), gl::DrawBufferMask());
}
pipelineDesc.setCullMode(VK_CULL_MODE_NONE);
pipelineDesc.setRenderPassDesc(framebuffer->getRenderPassDesc());
......
......@@ -1246,7 +1246,8 @@ void GraphicsPipelineDesc::updateBlendFuncs(GraphicsPipelineTransitionBits *tran
}
void GraphicsPipelineDesc::setColorWriteMask(VkColorComponentFlags colorComponentFlags,
const gl::DrawBufferMask &alphaMask)
const gl::DrawBufferMask &alphaMask,
const gl::DrawBufferMask &enabledDrawBuffers)
{
PackedInputAssemblyAndColorBlendStateInfo &inputAndBlend = mInputAssemblyAndColorBlendStateInfo;
uint8_t colorMask = static_cast<uint8_t>(colorComponentFlags);
......@@ -1254,8 +1255,11 @@ void GraphicsPipelineDesc::setColorWriteMask(VkColorComponentFlags colorComponen
for (uint32_t colorIndexGL = 0; colorIndexGL < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS;
colorIndexGL++)
{
uint8_t mask =
alphaMask[colorIndexGL] ? (colorMask & ~VK_COLOR_COMPONENT_A_BIT) : colorMask;
uint8_t mask = 0;
if (enabledDrawBuffers.test(colorIndexGL))
{
mask = alphaMask[colorIndexGL] ? (colorMask & ~VK_COLOR_COMPONENT_A_BIT) : colorMask;
}
Int4Array_Set(inputAndBlend.colorWriteMaskBits, colorIndexGL, mask);
}
}
......@@ -1270,9 +1274,10 @@ void GraphicsPipelineDesc::setSingleColorWriteMask(uint32_t colorIndexGL,
void GraphicsPipelineDesc::updateColorWriteMask(GraphicsPipelineTransitionBits *transition,
VkColorComponentFlags colorComponentFlags,
const gl::DrawBufferMask &alphaMask)
const gl::DrawBufferMask &alphaMask,
const gl::DrawBufferMask &enabledDrawBuffers)
{
setColorWriteMask(colorComponentFlags, alphaMask);
setColorWriteMask(colorComponentFlags, alphaMask, enabledDrawBuffers);
for (size_t colorIndexGL = 0; colorIndexGL < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS;
colorIndexGL++)
......
......@@ -523,11 +523,13 @@ class GraphicsPipelineDesc final
void updateBlendEquations(GraphicsPipelineTransitionBits *transition,
const gl::BlendState &blendState);
void setColorWriteMask(VkColorComponentFlags colorComponentFlags,
const gl::DrawBufferMask &alphaMask);
const gl::DrawBufferMask &alphaMask,
const gl::DrawBufferMask &enabledDrawBuffers);
void setSingleColorWriteMask(uint32_t colorIndexGL, VkColorComponentFlags colorComponentFlags);
void updateColorWriteMask(GraphicsPipelineTransitionBits *transition,
VkColorComponentFlags colorComponentFlags,
const gl::DrawBufferMask &alphaMask);
const gl::DrawBufferMask &alphaMask,
const gl::DrawBufferMask &enabledDrawBuffers);
// Depth/stencil states.
void setDepthTestEnabled(bool enabled);
......
......@@ -1183,6 +1183,65 @@ TEST_P(VulkanPerformanceCounterTest, MaskedClearDoesNotBreakRenderPass)
EXPECT_PIXEL_NEAR(0, 0, 63, 127, 255, 191, 1);
}
// Tests that draw buffer change with all color channel mask off should not break renderpass
TEST_P(VulkanPerformanceCounterTest, DrawbufferChangeWithAllColorMaskDisabled)
{
const rx::vk::PerfCounters &counters = hackANGLE();
ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::UniformColor());
glUseProgram(program);
GLint colorUniformLocation =
glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
ASSERT_NE(-1, colorUniformLocation);
ASSERT_GL_NO_ERROR();
GLTexture textureRGBA;
glBindTexture(GL_TEXTURE_2D, textureRGBA);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
GLTexture textureDepth;
glBindTexture(GL_TEXTURE_2D, textureDepth);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 64, 64, 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);
GLFramebuffer framebuffer;
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureRGBA, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, textureDepth, 0);
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
ASSERT_GL_NO_ERROR();
uint32_t expectedRenderPassCount = counters.renderPasses + 1;
// Draw into FBO
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glClearColor(0.0f, 1.0f, 0.0f, 1.0f); // clear to green
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, 256, 256);
glUniform4fv(colorUniformLocation, 1, GLColor::blue.toNormalizedVector().data());
GLenum glDrawBuffers_bufs_1[] = {GL_COLOR_ATTACHMENT0};
glDrawBuffers(1, glDrawBuffers_bufs_1);
glEnable(GL_DEPTH_TEST);
drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
// Change draw buffer state and color mask
GLenum glDrawBuffers_bufs_0[] = {GL_NONE};
glDrawBuffers(1, glDrawBuffers_bufs_0);
glColorMask(false, false, false, false);
drawQuad(program, essl1_shaders::PositionAttrib(), 0.6f);
// Change back draw buffer state and color mask
glDrawBuffers(1, glDrawBuffers_bufs_1);
glColorMask(true, true, true, true);
glUniform4fv(colorUniformLocation, 1, GLColor::red.toNormalizedVector().data());
drawQuad(program, essl1_shaders::PositionAttrib(), 0.7f);
uint32_t actualRenderPassCount = counters.renderPasses;
EXPECT_EQ(expectedRenderPassCount, actualRenderPassCount);
}
ANGLE_INSTANTIATE_TEST(VulkanPerformanceCounterTest, ES3_VULKAN());
ANGLE_INSTANTIATE_TEST(VulkanPerformanceCounterTest_ES31, ES31_VULKAN());
......
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