Commit 30622479 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Fix crash with deferred clears and MSRTT

The following scenario was mishandled: - MSRTT draw with an unresolve operation (i.e. has two subpasses) - Deferred clear - Flush deferred clear with MSRTT framebuffer not needing unresolve (i.e. has one subpass) Bug: chromium:1178693 Change-Id: If3548e99897d698d61dfafbe9f86193723d06e5a Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2697648 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent e153063d
......@@ -3043,7 +3043,7 @@ angle::Result ContextVk::syncState(const gl::Context *context,
mGraphicsPipelineDesc->updateStencilBackWriteMask(
&mGraphicsPipelineTransition, depthStencilState, drawFramebuffer);
mGraphicsPipelineDesc->resetSubpass(&mGraphicsPipelineTransition);
onDrawFramebufferRenderPassDescChange(mDrawFramebuffer);
onDrawFramebufferRenderPassDescChange(mDrawFramebuffer, nullptr);
break;
}
case gl::State::DIRTY_BIT_RENDERBUFFER_BINDING:
......@@ -3538,17 +3538,28 @@ void ContextVk::onFramebufferChange(FramebufferVk *framebufferVk)
// Update scissor.
updateScissor(mState);
onDrawFramebufferRenderPassDescChange(framebufferVk);
invalidateCurrentGraphicsPipeline();
onDrawFramebufferRenderPassDescChange(framebufferVk, nullptr);
}
void ContextVk::onDrawFramebufferRenderPassDescChange(FramebufferVk *framebufferVk)
void ContextVk::onDrawFramebufferRenderPassDescChange(FramebufferVk *framebufferVk,
bool *renderPassDescChangedOut)
{
mGraphicsPipelineDesc->updateRenderPassDesc(&mGraphicsPipelineTransition,
framebufferVk->getRenderPassDesc());
const gl::Box &dimensions = framebufferVk->getState().getDimensions();
mGraphicsPipelineDesc->updateDrawableSize(&mGraphicsPipelineTransition, dimensions.width,
dimensions.height);
if (renderPassDescChangedOut)
{
// If render pass desc has changed while processing the dirty bits, notify the caller.
*renderPassDescChangedOut = true;
}
else
{
// Otherwise mark the pipeline as dirty.
invalidateCurrentGraphicsPipeline();
}
}
void ContextVk::invalidateCurrentTransformFeedbackBuffers()
......
......@@ -317,7 +317,8 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
void invalidateDefaultAttribute(size_t attribIndex);
void invalidateDefaultAttributes(const gl::AttributesMask &dirtyMask);
void onFramebufferChange(FramebufferVk *framebufferVk);
void onDrawFramebufferRenderPassDescChange(FramebufferVk *framebufferVk);
void onDrawFramebufferRenderPassDescChange(FramebufferVk *framebufferVk,
bool *renderPassDescChangedOut);
void onHostVisibleBufferWrite() { mIsAnyHostVisibleBufferWritten = true; }
void invalidateCurrentTransformFeedbackBuffers();
......
......@@ -2598,9 +2598,7 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
if (unresolveChanged || anyUnresolve)
{
contextVk->onDrawFramebufferRenderPassDescChange(this);
// Notify that the render pass desc has changed.
*renderPassDescChangedOut = true;
contextVk->onDrawFramebufferRenderPassDescChange(this, renderPassDescChangedOut);
}
return angle::Result::Continue;
......
......@@ -1492,9 +1492,7 @@ angle::Result UtilsVk::clearFramebuffer(ContextVk *contextVk,
}
else
{
bool renderPassDescChanged = false;
ANGLE_TRY(contextVk->startRenderPass(scissoredRenderArea, &commandBuffer,
&renderPassDescChanged));
ANGLE_TRY(contextVk->startRenderPass(scissoredRenderArea, &commandBuffer, nullptr));
}
if (params.clearStencil || params.clearDepth)
......
......@@ -3676,6 +3676,64 @@ TEST_P(MultisampledRenderToTextureES3Test, RenderbufferUnresolveColorAndDepthSte
renderbufferUnresolveColorAndDepthStencilThenTwoColors(true, true);
}
// Make sure deferred clears are flushed correctly when the framebuffer switches between
// needing unresolve and not needing it.
TEST_P(MultisampledRenderToTextureES3Test, ClearThenMaskedClearFramebufferTest)
{
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
constexpr GLsizei kSize = 16;
GLFramebuffer fboMS;
glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
// Create multisampled framebuffer to use as source.
GLRenderbuffer depthMS;
glBindRenderbuffer(GL_RENDERBUFFER, depthMS);
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT24, kSize, kSize);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthMS);
ASSERT_GL_NO_ERROR();
GLTexture textureMS;
GLRenderbuffer renderbufferMS;
createAndAttachColorAttachment(false, kSize, GL_COLOR_ATTACHMENT0, nullptr, &textureMS,
&renderbufferMS);
EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
// Clear depth to 0.5 and color to green.
glClearDepthf(0.5f);
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
ASSERT_GL_NO_ERROR();
// Break the render pass.
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
// Draw red into the multisampled color buffer. An unresolve operation is needed.
ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_EQUAL);
drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.0f);
ASSERT_GL_NO_ERROR();
// Break the render pass.
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
// Clear color to transparent blue.
glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Clear both color and depth, with color masked.
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE);
glClearDepthf(0.3f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Make sure the result is blue.
EXPECT_PIXEL_RECT_EQ(0, 0, kSize - 1, kSize - 1, GLColor::blue);
ASSERT_GL_NO_ERROR();
}
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND_ES31(MultisampledRenderToTextureTest);
ANGLE_INSTANTIATE_TEST_ES3(MultisampledRenderToTextureES3Test);
ANGLE_INSTANTIATE_TEST_ES31(MultisampledRenderToTextureES31Test);
......
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