Commit e5d52ac3 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Restore at the end of RP if write-after-invalidate

If a depth/stencil attachment is invalidated, but subsequently drawn to in the same render pass, undo the invalidate when the render pass is closed. Adapted from https://chromium-review.googlesource.com/c/angle/angle/+/2386478. Bug: b/167275320 Bug: angleproject:4836 Change-Id: I17a35bfd692ddc403ceaa6ec44b5c4f16ff9eed6 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2461464 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarIan Elliott <ianelliott@google.com>
parent f8070feb
...@@ -5129,16 +5129,8 @@ angle::Result ContextVk::updateRenderPassDepthStencilAccess() ...@@ -5129,16 +5129,8 @@ angle::Result ContextVk::updateRenderPassDepthStencilAccess()
} }
else else
{ {
if (mRenderPassCommands->onDepthAccess(depthAccess)) mRenderPassCommands->onDepthAccess(depthAccess);
{ mRenderPassCommands->onStencilAccess(stencilAccess);
// The attachment is no longer invalidated, so set mContentDefined to true
mDrawFramebuffer->restoreDepthDefinedContents();
}
if (mRenderPassCommands->onStencilAccess(stencilAccess))
{
// The attachment is no longer invalidated, so set mContentDefined to true
mDrawFramebuffer->restoreStencilDefinedContents();
}
mDrawFramebuffer->updateRenderPassReadOnlyDepthMode(this, mRenderPassCommands); mDrawFramebuffer->updateRenderPassReadOnlyDepthMode(this, mRenderPassCommands);
} }
......
...@@ -2216,11 +2216,7 @@ angle::Result FramebufferVk::clearWithCommand( ...@@ -2216,11 +2216,7 @@ angle::Result FramebufferVk::clearWithCommand(
dsAspectFlags |= VK_IMAGE_ASPECT_DEPTH_BIT; dsAspectFlags |= VK_IMAGE_ASPECT_DEPTH_BIT;
dsClearValue.depthStencil = clearDepthStencilValue; dsClearValue.depthStencil = clearDepthStencilValue;
// Explicitly mark a depth write because we are clearing the depth buffer. // Explicitly mark a depth write because we are clearing the depth buffer.
if (renderpassCommands->onDepthAccess(vk::ResourceAccess::Write)) renderpassCommands->onDepthAccess(vk::ResourceAccess::Write);
{
// The attachment is no longer invalidated, so set mContentDefined to true
restoreDepthDefinedContents();
}
} }
if (clearStencil) if (clearStencil)
...@@ -2228,11 +2224,7 @@ angle::Result FramebufferVk::clearWithCommand( ...@@ -2228,11 +2224,7 @@ angle::Result FramebufferVk::clearWithCommand(
dsAspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT; dsAspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
dsClearValue.depthStencil = clearDepthStencilValue; dsClearValue.depthStencil = clearDepthStencilValue;
// Explicitly mark a stencil write because we are clearing the stencil buffer. // Explicitly mark a stencil write because we are clearing the stencil buffer.
if (renderpassCommands->onStencilAccess(vk::ResourceAccess::Write)) renderpassCommands->onStencilAccess(vk::ResourceAccess::Write);
{
// The attachment is no longer invalidated, so set mContentDefined to true
restoreStencilDefinedContents();
}
} }
if (dsAspectFlags != 0) if (dsAspectFlags != 0)
...@@ -2535,28 +2527,6 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk, ...@@ -2535,28 +2527,6 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
return angle::Result::Continue; return angle::Result::Continue;
} }
void FramebufferVk::restoreDepthDefinedContents()
{
// If the depthStencilRenderTarget does not have "defined content" (i.e. meaning that a future
// render pass should use a loadOp of DONT_CARE), we should restore it (i.e. so that a future
// render pass uses a loadOp of LOAD).
RenderTargetVk *depthStencilRenderTarget = mRenderTargetCache.getDepthStencil();
if (depthStencilRenderTarget)
{
depthStencilRenderTarget->restoreEntireContent();
}
}
void FramebufferVk::restoreStencilDefinedContents()
{
// Similar to restoreDepthDefinedContents, but for the stencil aspect.
RenderTargetVk *depthStencilRenderTarget = mRenderTargetCache.getDepthStencil();
if (depthStencilRenderTarget)
{
depthStencilRenderTarget->restoreEntireStencilContent();
}
}
void FramebufferVk::updateActiveColorMasks(size_t colorIndexGL, bool r, bool g, bool b, bool a) void FramebufferVk::updateActiveColorMasks(size_t colorIndexGL, bool r, bool g, bool b, bool a)
{ {
gl::BlendStateExt::ColorMaskStorage::SetValueIndexed( gl::BlendStateExt::ColorMaskStorage::SetValueIndexed(
......
...@@ -118,8 +118,6 @@ class FramebufferVk : public FramebufferImpl ...@@ -118,8 +118,6 @@ class FramebufferVk : public FramebufferImpl
angle::Result startNewRenderPass(ContextVk *contextVk, angle::Result startNewRenderPass(ContextVk *contextVk,
const gl::Rectangle &renderArea, const gl::Rectangle &renderArea,
vk::CommandBuffer **commandBufferOut); vk::CommandBuffer **commandBufferOut);
void restoreDepthDefinedContents();
void restoreStencilDefinedContents();
RenderTargetVk *getFirstRenderTarget() const; RenderTargetVk *getFirstRenderTarget() const;
GLint getSamples() const; GLint getSamples() const;
......
...@@ -648,7 +648,9 @@ CommandBufferHelper::CommandBufferHelper() ...@@ -648,7 +648,9 @@ CommandBufferHelper::CommandBufferHelper()
mStencilCmdSizeDisabled(kInfiniteCmdSize), mStencilCmdSizeDisabled(kInfiniteCmdSize),
mDepthStencilAttachmentIndex(kAttachmentIndexInvalid), mDepthStencilAttachmentIndex(kAttachmentIndexInvalid),
mDepthStencilImage(nullptr), mDepthStencilImage(nullptr),
mDepthStencilResolveImage(nullptr) mDepthStencilResolveImage(nullptr),
mDepthStencilLevelIndex(0),
mDepthStencilLayerIndex(0)
{} {}
CommandBufferHelper::~CommandBufferHelper() CommandBufferHelper::~CommandBufferHelper()
...@@ -806,10 +808,15 @@ void CommandBufferHelper::depthStencilImagesDraw(ResourceUseList *resourceUseLis ...@@ -806,10 +808,15 @@ void CommandBufferHelper::depthStencilImagesDraw(ResourceUseList *resourceUseLis
image->retain(resourceUseList); image->retain(resourceUseList);
image->onWrite(level, 1, layer, 1, kDepthStencilAspects); image->onWrite(level, 1, layer, 1, kDepthStencilAspects);
mRenderPassUsedImages.insert(image->getImageSerial().getValue()); mRenderPassUsedImages.insert(image->getImageSerial().getValue());
mDepthStencilImage = image; mDepthStencilImage = image;
mDepthStencilLevelIndex = level;
mDepthStencilLayerIndex = layer;
if (resolveImage) if (resolveImage)
{ {
// Note that the resolve depth/stencil image has the same level/layer index as the
// depth/stencil image as currently it can only ever come from
// multisampled-render-to-texture renderbuffers.
resolveImage->retain(resourceUseList); resolveImage->retain(resourceUseList);
resolveImage->onWrite(level, 1, layer, 1, kDepthStencilAspects); resolveImage->onWrite(level, 1, layer, 1, kDepthStencilAspects);
mRenderPassUsedImages.insert(resolveImage->getImageSerial().getValue()); mRenderPassUsedImages.insert(resolveImage->getImageSerial().getValue());
...@@ -817,22 +824,30 @@ void CommandBufferHelper::depthStencilImagesDraw(ResourceUseList *resourceUseLis ...@@ -817,22 +824,30 @@ void CommandBufferHelper::depthStencilImagesDraw(ResourceUseList *resourceUseLis
} }
} }
bool CommandBufferHelper::onDepthAccess(ResourceAccess access) void CommandBufferHelper::onDepthAccess(ResourceAccess access)
{ {
// Update the access for optimizing this render pass's loadOp // Update the access for optimizing this render pass's loadOp
UpdateAccess(&mDepthAccess, access); UpdateAccess(&mDepthAccess, access);
// Update the invalidate state for optimizing this render pass's storeOp // Update the invalidate state for optimizing this render pass's storeOp
return onDepthStencilAccess(access, &mDepthCmdSizeInvalidated, &mDepthCmdSizeDisabled); if (onDepthStencilAccess(access, &mDepthCmdSizeInvalidated, &mDepthCmdSizeDisabled))
{
// The attachment is no longer invalid, so restore its content.
restoreDepthContent();
}
} }
bool CommandBufferHelper::onStencilAccess(ResourceAccess access) void CommandBufferHelper::onStencilAccess(ResourceAccess access)
{ {
// Update the access for optimizing this render pass's loadOp // Update the access for optimizing this render pass's loadOp
UpdateAccess(&mStencilAccess, access); UpdateAccess(&mStencilAccess, access);
// Update the invalidate state for optimizing this render pass's stencilStoreOp // Update the invalidate state for optimizing this render pass's stencilStoreOp
return onDepthStencilAccess(access, &mStencilCmdSizeInvalidated, &mStencilCmdSizeDisabled); if (onDepthStencilAccess(access, &mStencilCmdSizeInvalidated, &mStencilCmdSizeDisabled))
{
// The attachment is no longer invalid, so restore its content.
restoreStencilContent();
}
} }
bool CommandBufferHelper::onDepthStencilAccess(ResourceAccess access, bool CommandBufferHelper::onDepthStencilAccess(ResourceAccess access,
...@@ -878,6 +893,28 @@ bool CommandBufferHelper::onDepthStencilAccess(ResourceAccess access, ...@@ -878,6 +893,28 @@ bool CommandBufferHelper::onDepthStencilAccess(ResourceAccess access,
} }
} }
void CommandBufferHelper::restoreDepthContent()
{
// Note that the image may have been deleted since the render pass has started.
if (mDepthStencilImage)
{
ASSERT(mDepthStencilImage->valid());
mDepthStencilImage->restoreSubresourceContent(mDepthStencilLevelIndex,
mDepthStencilLayerIndex);
}
}
void CommandBufferHelper::restoreStencilContent()
{
// Note that the image may have been deleted since the render pass has started.
if (mDepthStencilImage)
{
ASSERT(mDepthStencilImage->valid());
mDepthStencilImage->restoreSubresourceStencilContent(mDepthStencilLevelIndex,
mDepthStencilLayerIndex);
}
}
void CommandBufferHelper::executeBarriers(ContextVk *contextVk, PrimaryCommandBuffer *primary) void CommandBufferHelper::executeBarriers(ContextVk *contextVk, PrimaryCommandBuffer *primary)
{ {
// make a local copy for faster access // make a local copy for faster access
...@@ -1035,11 +1072,23 @@ void CommandBufferHelper::endRenderPass(ContextVk *contextVk) ...@@ -1035,11 +1072,23 @@ void CommandBufferHelper::endRenderPass(ContextVk *contextVk)
dsOps.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; dsOps.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
dsOps.isInvalidated = true; dsOps.isInvalidated = true;
} }
else if (hasWriteAfterInvalidate(mDepthCmdSizeInvalidated, mDepthCmdSizeDisabled))
{
// The depth attachment was invalidated, but is now valid. Let the image know the contents
// are now defined so a future render pass would use loadOp=LOAD.
restoreDepthContent();
}
if (isInvalidated(mStencilCmdSizeInvalidated, mStencilCmdSizeDisabled)) if (isInvalidated(mStencilCmdSizeInvalidated, mStencilCmdSizeDisabled))
{ {
dsOps.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; dsOps.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
dsOps.isStencilInvalidated = true; dsOps.isStencilInvalidated = true;
} }
else if (hasWriteAfterInvalidate(mStencilCmdSizeInvalidated, mStencilCmdSizeDisabled))
{
// The stencil attachment was invalidated, but is now valid. Let the image know the
// contents are now defined so a future render pass would use loadOp=LOAD.
restoreStencilContent();
}
// Second, if we are loading or clearing the attachment, but the attachment has not been used, // Second, if we are loading or clearing the attachment, but the attachment has not been used,
// and the data has also not been stored back into attachment, then just skip the load/clear op. // and the data has also not been stored back into attachment, then just skip the load/clear op.
......
...@@ -1108,8 +1108,8 @@ class CommandBufferHelper : angle::NonCopyable ...@@ -1108,8 +1108,8 @@ class CommandBufferHelper : angle::NonCopyable
// Dumping the command stream is disabled by default. // Dumping the command stream is disabled by default.
static constexpr bool kEnableCommandStreamDiagnostics = false; static constexpr bool kEnableCommandStreamDiagnostics = false;
bool onDepthAccess(ResourceAccess access); void onDepthAccess(ResourceAccess access);
bool onStencilAccess(ResourceAccess access); void onStencilAccess(ResourceAccess access);
void updateRenderPassForResolve(vk::Framebuffer *newFramebuffer, void updateRenderPassForResolve(vk::Framebuffer *newFramebuffer,
const vk::RenderPassDesc &renderPassDesc); const vk::RenderPassDesc &renderPassDesc);
...@@ -1130,6 +1130,8 @@ class CommandBufferHelper : angle::NonCopyable ...@@ -1130,6 +1130,8 @@ class CommandBufferHelper : angle::NonCopyable
bool onDepthStencilAccess(ResourceAccess access, bool onDepthStencilAccess(ResourceAccess access,
uint32_t *cmdCountInvalidated, uint32_t *cmdCountInvalidated,
uint32_t *cmdCountDisabled); uint32_t *cmdCountDisabled);
void restoreDepthContent();
void restoreStencilContent();
void finalizeDepthStencilImageLayout(); void finalizeDepthStencilImageLayout();
void finalizeDepthStencilResolveImageLayout(); void finalizeDepthStencilResolveImageLayout();
...@@ -1186,6 +1188,8 @@ class CommandBufferHelper : angle::NonCopyable ...@@ -1186,6 +1188,8 @@ class CommandBufferHelper : angle::NonCopyable
ImageHelper *mDepthStencilImage; ImageHelper *mDepthStencilImage;
ImageHelper *mDepthStencilResolveImage; ImageHelper *mDepthStencilResolveImage;
gl::LevelIndex mDepthStencilLevelIndex;
uint32_t mDepthStencilLayerIndex;
}; };
// Imagine an image going through a few layout transitions: // Imagine an image going through a few layout transitions:
......
...@@ -756,10 +756,6 @@ TEST_P(VulkanPerformanceCounterTest, InvalidateDraw) ...@@ -756,10 +756,6 @@ TEST_P(VulkanPerformanceCounterTest, InvalidateDraw)
// Draw (since enabled, should result: in storeOp = STORE; mContentDefined = true) // Draw (since enabled, should result: in storeOp = STORE; mContentDefined = true)
drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
// TODO: Fix ANGLE to correct set mContentDefined for this scenario. At this point,
// mContentDefined will remain false since we don't do record anything at draw-time, and since
// we don't set mContentDefined at endRP().
// https://issuetracker.google.com/issues/167275320
// Ensure that the render pass wasn't broken // Ensure that the render pass wasn't broken
EXPECT_EQ(expected.renderPasses, counters.renderPasses); EXPECT_EQ(expected.renderPasses, counters.renderPasses);
...@@ -773,8 +769,7 @@ TEST_P(VulkanPerformanceCounterTest, InvalidateDraw) ...@@ -773,8 +769,7 @@ TEST_P(VulkanPerformanceCounterTest, InvalidateDraw)
drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
swapBuffers(); swapBuffers();
// TODO: After fixing ANGLE per https://issuetracker.google.com/issues/167275320, uncomment: compareLoadCountersForInvalidateTest(counters, expected);
// compareLoadCountersForInvalidateTest(counters, expected);
} }
// Tests that another case does not break render pass, and that counts are correct: // Tests that another case does not break render pass, and that counts are correct:
...@@ -1198,8 +1193,8 @@ TEST_P(VulkanPerformanceCounterTest, InvalidateAndClear) ...@@ -1198,8 +1193,8 @@ TEST_P(VulkanPerformanceCounterTest, InvalidateAndClear)
swapBuffers(); swapBuffers();
compareDepthStencilCountersForInvalidateTest(counters, expected); compareDepthStencilCountersForInvalidateTest(counters, expected);
// Expect rpCount+1, depth(Clears+0, Loads+1, Stores+1), stencil(Clears+0, Load+0, Stores+1) // Expect rpCount+1, depth(Clears+0, Loads+1, Stores+1), stencil(Clears+0, Load+1, Stores+1)
setExpectedCountersForInvalidateTest(counters, 0, 0, 1, 1, 0, 0, 1, &expected); setExpectedCountersForInvalidateTest(counters, 0, 0, 1, 1, 0, 1, 1, &expected);
// Bind FBO again and try to use the depth buffer without clear. This should result in // Bind FBO again and try to use the depth buffer without clear. This should result in
// loadOp=LOAD and StoreOP=STORE // loadOp=LOAD and StoreOP=STORE
...@@ -1271,8 +1266,7 @@ TEST_P(VulkanPerformanceCounterTest, InvalidateAndMaskedClear) ...@@ -1271,8 +1266,7 @@ TEST_P(VulkanPerformanceCounterTest, InvalidateAndMaskedClear)
ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue()); ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.95f); drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.95f);
EXPECT_PIXEL_COLOR_EQ(kInvalidateTestSize / 2, kInvalidateTestSize / 2, GLColor::blue); EXPECT_PIXEL_COLOR_EQ(kInvalidateTestSize / 2, kInvalidateTestSize / 2, GLColor::blue);
// TODO: After fixing ANGLE per https://issuetracker.google.com/issues/167275320, uncomment: compareDepthStencilCountersForInvalidateTest(counters, expected);
// compareDepthStencilCountersForInvalidateTest(counters, expected);
} }
// Tests whether depth-stencil ContentDefined will be correct when: // Tests whether depth-stencil ContentDefined will be correct when:
......
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