Commit 4fb3c28f by Jamie Madill Committed by Commit Bot

Vulkan: Fix Framebuffer cache depth/stencil issue.

The DrawBuffers resetting logic didn't update the depth/stencil serial. Fix this and add a regression test that would crash in this situation. Note that the Manhattan benchmark could trigger this under some cases. Bug: angleproject:4322 Bug: angleproject:4490 Change-Id: Ie4b24efeb5991ecaa85bf8f964f77476bd6f167d Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2111333 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCody Northrop <cnorthrop@google.com>
parent 1c88cf27
......@@ -981,6 +981,21 @@ angle::Result FramebufferVk::invalidateImpl(ContextVk *contextVk,
return angle::Result::Continue;
}
void FramebufferVk::updateDepthStencilAttachmentSerial(ContextVk *contextVk)
{
if (mRenderTargetCache.getDepthStencil() != nullptr)
{
mCurrentFramebufferDesc.update(
vk::kFramebufferDescDepthStencilIndex,
mRenderTargetCache.getDepthStencil()->getAssignSerial(contextVk));
}
else
{
mCurrentFramebufferDesc.update(vk::kFramebufferDescDepthStencilIndex,
vk::kZeroAttachmentSerial);
}
}
angle::Result FramebufferVk::syncState(const gl::Context *context,
const gl::Framebuffer::DirtyBits &dirtyBits)
{
......@@ -994,44 +1009,24 @@ angle::Result FramebufferVk::syncState(const gl::Context *context,
{
case gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
ANGLE_TRY(mRenderTargetCache.updateDepthStencilRenderTarget(context, mState));
if (mRenderTargetCache.getDepthStencil() != nullptr)
{
mCurrentFramebufferDesc.update(
vk::kFramebufferDescDepthIndex,
mRenderTargetCache.getDepthStencil()->getAssignSerial(contextVk));
}
else
{
mCurrentFramebufferDesc.update(vk::kFramebufferDescDepthIndex,
vk::kZeroAttachmentSerial);
}
updateDepthStencilAttachmentSerial(contextVk);
break;
case gl::Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
ANGLE_TRY(mRenderTargetCache.updateDepthStencilRenderTarget(context, mState));
if (mRenderTargetCache.getDepthStencil() != nullptr)
{
mCurrentFramebufferDesc.update(
vk::kFramebufferDescStencilIndex,
mRenderTargetCache.getDepthStencil()->getAssignSerial(contextVk));
}
else
{
mCurrentFramebufferDesc.update(vk::kFramebufferDescStencilIndex,
vk::kZeroAttachmentSerial);
}
updateDepthStencilAttachmentSerial(contextVk);
break;
case gl::Framebuffer::DIRTY_BIT_DEPTH_BUFFER_CONTENTS:
ANGLE_TRY(mRenderTargetCache.getDepthStencil()->flushStagedUpdates(contextVk));
ASSERT(mRenderTargetCache.getDepthStencil() != nullptr);
mCurrentFramebufferDesc.update(
vk::kFramebufferDescDepthIndex,
vk::kFramebufferDescDepthStencilIndex,
mRenderTargetCache.getDepthStencil()->getAssignSerial(contextVk));
break;
case gl::Framebuffer::DIRTY_BIT_STENCIL_BUFFER_CONTENTS:
ANGLE_TRY(mRenderTargetCache.getDepthStencil()->flushStagedUpdates(contextVk));
ASSERT(mRenderTargetCache.getDepthStencil() != nullptr);
mCurrentFramebufferDesc.update(
vk::kFramebufferDescStencilIndex,
vk::kFramebufferDescDepthStencilIndex,
mRenderTargetCache.getDepthStencil()->getAssignSerial(contextVk));
break;
case gl::Framebuffer::DIRTY_BIT_READ_BUFFER:
......@@ -1046,6 +1041,7 @@ angle::Result FramebufferVk::syncState(const gl::Context *context,
static_cast<uint32_t>(colorIndexGL),
mRenderTargetCache.getColors()[colorIndexGL]->getAssignSerial(contextVk));
}
updateDepthStencilAttachmentSerial(contextVk);
break;
case gl::Framebuffer::DIRTY_BIT_DEFAULT_WIDTH:
case gl::Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT:
......
......@@ -164,6 +164,7 @@ class FramebufferVk : public FramebufferImpl
angle::Result invalidateImpl(ContextVk *contextVk, size_t count, const GLenum *attachments);
// Release all FramebufferVk objects in the cache and clear cache
void clearCache(ContextVk *contextVk);
void updateDepthStencilAttachmentSerial(ContextVk *contextVk);
WindowSurfaceVk *mBackbuffer;
......
......@@ -724,10 +724,8 @@ class TextureDescriptorDesc
// This is IMPLEMENTATION_MAX_DRAW_BUFFERS + 1 for DS attachment
constexpr size_t kMaxFramebufferAttachments = gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS;
// Color serials are at index [0:gl::IMPLEMENTATION_MAX_DRAW_BUFFERS-1]
// Depth index is at gl::IMPLEMENTATION_MAX_DRAW_BUFFERS
// Stencil index is at gl::IMPLEMENTATION_MAX_DRAW_BUFFERS + 1
constexpr size_t kFramebufferDescDepthIndex = gl::IMPLEMENTATION_MAX_DRAW_BUFFERS;
constexpr size_t kFramebufferDescStencilIndex = gl::IMPLEMENTATION_MAX_DRAW_BUFFERS + 1;
// Depth/stencil index is at gl::IMPLEMENTATION_MAX_DRAW_BUFFERS
constexpr size_t kFramebufferDescDepthStencilIndex = gl::IMPLEMENTATION_MAX_DRAW_BUFFERS;
// Struct for AttachmentSerial cache signatures. Includes level/layer for imageView as
// well as a unique Serial value for the underlying image
struct AttachmentSerial
......
......@@ -1208,6 +1208,50 @@ TEST_P(AddDummyTextureNoRenderTargetTest, NoProgramOutputWorkaround)
ASSERT_GL_NO_ERROR();
}
// Covers a bug in ANGLE's Vulkan back-end framebuffer cache which ignored depth/stencil after
// calls to DrawBuffers.
TEST_P(FramebufferTest_ES3, AttachmentStateChange)
{
constexpr GLuint kSize = 2;
ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
GLTexture colorTexture;
glBindTexture(GL_TEXTURE_2D, colorTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
GLFramebuffer fbo;
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
ASSERT_GL_NO_ERROR();
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
// First draw without a depth buffer.
drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
GLRenderbuffer depthBuffer;
glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, kSize, kSize);
// Bind just a renderbuffer and draw.
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);
ASSERT_GL_NO_ERROR();
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
glDrawBuffers(0, nullptr);
drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
// Re-enable color buffer and draw one final time. This previously triggered a crash.
GLenum drawBuffs = {GL_COLOR_ATTACHMENT0};
glDrawBuffers(1, &drawBuffs);
drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
}
ANGLE_INSTANTIATE_TEST_ES2(AddDummyTextureNoRenderTargetTest);
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(FramebufferFormatsTest);
ANGLE_INSTANTIATE_TEST_ES3(FramebufferTest_ES3);
......
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