Commit 77e3d0ae by Charlie Lao Committed by Commit Bot

Vulkan: Defer the depthStencil buffer layout change to endRenderPass

Depth stencil layout may change while we build the render pass, depending on the read/write access been made. Right now we are always inserting a layout change barrier at the start of render pass. Later on when the read/write property changes, we insert another layout change barrier. Similarly, we maintain the attachmentOps and RenderPassDesc::mPackedColorAttachmentRangeAndDSAccess as we changes read/write access. This makes code quite commplicated. This CL moves mReadOnlyDepthStencilMode from FramebufferVK to CommandBufferHelper object and we only maintain that boolean while we updating the read/write access. Then at the end of render pass or when depthStencil image is deleted, we update attachmentOps and mRenderPassDesc and layout transition all at once and only done once. This simplifies the read only depth stencil mode implementation a lot. Bug: b/168953278 Change-Id: Ie263b4526c82a9858e5d1f141ea58f499187a3ca Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2432075 Commit-Queue: Charlie Lao <cclao@google.com> Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent f074d61a
...@@ -4042,7 +4042,7 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context) ...@@ -4042,7 +4042,7 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context)
if (hasStartedRenderPass()) if (hasStartedRenderPass())
{ {
if (!mDrawFramebuffer->isReadOnlyDepthMode()) if (!mRenderPassCommands->isReadOnlyDepthMode())
{ {
// To enter depth feedback loop, we must flush and start a new renderpass. // To enter depth feedback loop, we must flush and start a new renderpass.
// Otherwise it will stick with writable layout and cause validation error. // Otherwise it will stick with writable layout and cause validation error.
...@@ -4050,8 +4050,7 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context) ...@@ -4050,8 +4050,7 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context)
} }
else else
{ {
ANGLE_TRY(mDrawFramebuffer->updateRenderPassReadOnlyDepthMode( mDrawFramebuffer->updateRenderPassReadOnlyDepthMode(this, mRenderPassCommands);
this, mRenderPassCommands));
} }
} }
...@@ -4573,13 +4572,6 @@ angle::Result ContextVk::onImageRead(VkImageAspectFlags aspectFlags, ...@@ -4573,13 +4572,6 @@ angle::Result ContextVk::onImageRead(VkImageAspectFlags aspectFlags,
ASSERT(!image->isReleasedToExternal()); ASSERT(!image->isReleasedToExternal());
ASSERT(image->getImageSerial().valid()); ASSERT(image->getImageSerial().valid());
// Layout transitions for images used in the render pass are handled especially. This function
// is only called when the image is used outside the render pass. As such, if the image is used
// inside the render pass, its layout is necessarily different from imageLayout, and thus a
// layout transition is necessary (and the render pass has to break).
ASSERT(image->isReadBarrierNecessary(imageLayout) ||
!(mRenderPassCommands->started() && mRenderPassCommands->usesImageInRenderPass(*image)));
// Note that different read methods are not compatible. A shader read uses a different layout // Note that different read methods are not compatible. A shader read uses a different layout
// than a transfer read. So we cannot support simultaneous read usage as easily as for Buffers. // than a transfer read. So we cannot support simultaneous read usage as easily as for Buffers.
// TODO: Don't close the render pass if the image was only used read-only in the render pass. // TODO: Don't close the render pass if the image was only used read-only in the render pass.
...@@ -4636,22 +4628,18 @@ angle::Result ContextVk::startRenderPass(gl::Rectangle renderArea, ...@@ -4636,22 +4628,18 @@ angle::Result ContextVk::startRenderPass(gl::Rectangle renderArea,
{ {
mGraphicsDirtyBits |= mNewGraphicsCommandBufferDirtyBits; mGraphicsDirtyBits |= mNewGraphicsCommandBufferDirtyBits;
// We always start renderpass with proper depth stencil read only mode based on the current ANGLE_TRY(mDrawFramebuffer->startNewRenderPass(this, renderArea, &mRenderPassCommandBuffer));
// depth stencil state.
const gl::DepthStencilState &dsState = mState.getDepthStencilState();
vk::ResourceAccess depthAccess = GetDepthAccess(dsState);
vk::ResourceAccess stencilAccess = GetStencilAccess(dsState);
bool readOnlyDepthMode =
depthAccess != vk::ResourceAccess::Write && stencilAccess != vk::ResourceAccess::Write;
ANGLE_TRY(mDrawFramebuffer->startNewRenderPass(this, readOnlyDepthMode, renderArea,
&mRenderPassCommandBuffer));
ANGLE_TRY(resumeOcclusionQueryIfActive()); ANGLE_TRY(resumeOcclusionQueryIfActive());
const gl::DepthStencilState &dsState = mState.getDepthStencilState();
vk::ResourceAccess depthAccess = GetDepthAccess(dsState);
vk::ResourceAccess stencilAccess = GetStencilAccess(dsState);
mRenderPassCommands->onDepthAccess(depthAccess); mRenderPassCommands->onDepthAccess(depthAccess);
mRenderPassCommands->onStencilAccess(stencilAccess); mRenderPassCommands->onStencilAccess(stencilAccess);
mDrawFramebuffer->updateRenderPassReadOnlyDepthMode(this, mRenderPassCommands);
if (commandBufferOut) if (commandBufferOut)
{ {
*commandBufferOut = mRenderPassCommandBuffer; *commandBufferOut = mRenderPassCommandBuffer;
...@@ -5088,8 +5076,7 @@ angle::Result ContextVk::updateRenderPassDepthStencilAccess() ...@@ -5088,8 +5076,7 @@ angle::Result ContextVk::updateRenderPassDepthStencilAccess()
mDrawFramebuffer->restoreDepthStencilDefinedContents(); mDrawFramebuffer->restoreDepthStencilDefinedContents();
} }
ANGLE_TRY( mDrawFramebuffer->updateRenderPassReadOnlyDepthMode(this, mRenderPassCommands);
mDrawFramebuffer->updateRenderPassReadOnlyDepthMode(this, mRenderPassCommands));
} }
} }
......
...@@ -553,6 +553,12 @@ class ContextVk : public ContextImpl, public vk::Context ...@@ -553,6 +553,12 @@ class ContextVk : public ContextImpl, public vk::Context
vk::AliasingMode::Allowed, image); vk::AliasingMode::Allowed, image);
} }
void onDepthStencilDraw(vk::ImageHelper *image, vk::ImageHelper *resolveImage)
{
ASSERT(mRenderPassCommands->started());
mRenderPassCommands->depthStencilImagesDraw(&mResourceUseList, image, resolveImage);
}
void onImageHelperRelease(const vk::ImageHelper *image) void onImageHelperRelease(const vk::ImageHelper *image)
{ {
if (mRenderPassCommands->started()) if (mRenderPassCommands->started())
......
...@@ -309,7 +309,6 @@ FramebufferVk::FramebufferVk(RendererVk *renderer, ...@@ -309,7 +309,6 @@ FramebufferVk::FramebufferVk(RendererVk *renderer,
mBackbuffer(backbuffer), mBackbuffer(backbuffer),
mFramebuffer(nullptr), mFramebuffer(nullptr),
mActiveColorComponents(0), mActiveColorComponents(0),
mReadOnlyDepthStencilMode(false),
mReadOnlyDepthFeedbackLoopMode(false) mReadOnlyDepthFeedbackLoopMode(false)
{ {
mReadPixelBuffer.init(renderer, VK_BUFFER_USAGE_TRANSFER_DST_BIT, kReadPixelsBufferAlignment, mReadPixelBuffer.init(renderer, VK_BUFFER_USAGE_TRANSFER_DST_BIT, kReadPixelsBufferAlignment,
...@@ -1749,9 +1748,6 @@ angle::Result FramebufferVk::syncState(const gl::Context *context, ...@@ -1749,9 +1748,6 @@ angle::Result FramebufferVk::syncState(const gl::Context *context,
return angle::Result::Continue; return angle::Result::Continue;
} }
// Default to writable depth on any Framebuffer change.
mReadOnlyDepthStencilMode = false;
// The FBO's new attachment may have changed the renderable area // The FBO's new attachment may have changed the renderable area
const gl::State &glState = context->getState(); const gl::State &glState = context->getState();
ANGLE_TRY(contextVk->updateScissor(glState)); ANGLE_TRY(contextVk->updateScissor(glState));
...@@ -1819,12 +1815,9 @@ void FramebufferVk::updateRenderPassDesc() ...@@ -1819,12 +1815,9 @@ void FramebufferVk::updateRenderPassDesc()
RenderTargetVk *depthStencilRenderTarget = getDepthStencilRenderTarget(); RenderTargetVk *depthStencilRenderTarget = getDepthStencilRenderTarget();
if (depthStencilRenderTarget) if (depthStencilRenderTarget)
{ {
vk::ResourceAccess dsAccess =
mReadOnlyDepthStencilMode ? vk::ResourceAccess::ReadOnly : vk::ResourceAccess::Write;
mRenderPassDesc.packDepthStencilAttachment( mRenderPassDesc.packDepthStencilAttachment(
depthStencilRenderTarget->getImageForRenderPass().getFormat().intendedFormatID, depthStencilRenderTarget->getImageForRenderPass().getFormat().intendedFormatID,
dsAccess); vk::ResourceAccess::Write);
// Add the resolve attachment, if any. // Add the resolve attachment, if any.
if (depthStencilRenderTarget->hasResolveAttachment()) if (depthStencilRenderTarget->hasResolveAttachment())
...@@ -2154,7 +2147,7 @@ angle::Result FramebufferVk::clearWithLoadOp(ContextVk *contextVk, ...@@ -2154,7 +2147,7 @@ angle::Result FramebufferVk::clearWithLoadOp(ContextVk *contextVk,
clearValue.depthStencil = clearDepthStencilValue; clearValue.depthStencil = clearDepthStencilValue;
commands.updateRenderPassDepthStencilClear(dsAspectFlags, clearValue); commands.updateRenderPassDepthStencilClear(dsAspectFlags, clearValue);
// If we were in depth read only mode, we must change to write mode // If we were in depth read only mode, we must change to write mode
ANGLE_TRY(updateRenderPassReadOnlyDepthMode(contextVk, &commands)); updateRenderPassReadOnlyDepthMode(contextVk, &commands);
} }
} }
else else
...@@ -2237,7 +2230,7 @@ angle::Result FramebufferVk::clearWithCommand( ...@@ -2237,7 +2230,7 @@ angle::Result FramebufferVk::clearWithCommand(
attachments.emplace_back(VkClearAttachment{dsAspectFlags, 0, dsClearValue}); attachments.emplace_back(VkClearAttachment{dsAspectFlags, 0, dsClearValue});
// Because we may have changed the depth stencil access mode, update read only depth mode // Because we may have changed the depth stencil access mode, update read only depth mode
// now. // now.
ANGLE_TRY(updateRenderPassReadOnlyDepthMode(contextVk, renderpassCommands)); updateRenderPassReadOnlyDepthMode(contextVk, renderpassCommands);
} }
VkClearRect rect = {}; VkClearRect rect = {};
...@@ -2260,7 +2253,6 @@ angle::Result FramebufferVk::getSamplePosition(const gl::Context *context, ...@@ -2260,7 +2253,6 @@ angle::Result FramebufferVk::getSamplePosition(const gl::Context *context,
} }
angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk, angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
bool readOnlyDepthMode,
const gl::Rectangle &renderArea, const gl::Rectangle &renderArea,
vk::CommandBuffer **commandBufferOut) vk::CommandBuffer **commandBufferOut)
{ {
...@@ -2466,22 +2458,6 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk, ...@@ -2466,22 +2458,6 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
renderPassAttachmentOps.setOps(depthStencilAttachmentIndex, depthLoadOp, depthStoreOp); renderPassAttachmentOps.setOps(depthStencilAttachmentIndex, depthLoadOp, depthStoreOp);
renderPassAttachmentOps.setStencilOps(depthStencilAttachmentIndex, stencilLoadOp, renderPassAttachmentOps.setStencilOps(depthStencilAttachmentIndex, stencilLoadOp,
stencilStoreOp); stencilStoreOp);
// We can only start the renderpass in read only mode if it is requested to be read only and
// we are not doing clear.
bool depthStencilReadOnly =
readOnlyDepthMode && !depthStencilRenderTarget->hasResolveAttachment() &&
renderPassAttachmentOps[depthStencilAttachmentIndex].loadOp !=
VK_ATTACHMENT_LOAD_OP_CLEAR &&
renderPassAttachmentOps[depthStencilAttachmentIndex].stencilLoadOp !=
VK_ATTACHMENT_LOAD_OP_CLEAR;
setReadOnlyDepthMode(depthStencilReadOnly);
vk::ImageLayout dsLayout = mReadOnlyDepthStencilMode
? vk::ImageLayout::DepthStencilReadOnly
: vk::ImageLayout::DepthStencilAttachment;
renderPassAttachmentOps.setLayouts(depthStencilAttachmentIndex, dsLayout, dsLayout);
} }
// If render pass description is changed, the previous render pass desc is no longer compatible. // If render pass description is changed, the previous render pass desc is no longer compatible.
...@@ -2524,7 +2500,8 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk, ...@@ -2524,7 +2500,8 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
// tracking content valid very loosely here that as long as it is attached, it assumes will // tracking content valid very loosely here that as long as it is attached, it assumes will
// have valid content. The only time it has undefined content is between swap and // have valid content. The only time it has undefined content is between swap and
// startNewRenderPass // startNewRenderPass
depthStencilRenderTarget->onDepthStencilDraw(contextVk, mReadOnlyDepthStencilMode); // The actual layout determination will be deferred until endRenderPass time
depthStencilRenderTarget->onDepthStencilDraw(contextVk);
} }
if (unresolveColorMask.any() || unresolveDepth || unresolveStencil) if (unresolveColorMask.any() || unresolveDepth || unresolveStencil)
...@@ -2663,50 +2640,19 @@ angle::Result FramebufferVk::flushDeferredClears(ContextVk *contextVk, ...@@ -2663,50 +2640,19 @@ angle::Result FramebufferVk::flushDeferredClears(ContextVk *contextVk,
return contextVk->startRenderPass(renderArea, nullptr); return contextVk->startRenderPass(renderArea, nullptr);
} }
void FramebufferVk::setReadOnlyDepthMode(bool readOnlyDepthEnabled) void FramebufferVk::updateRenderPassReadOnlyDepthMode(ContextVk *contextVk,
{ vk::CommandBufferHelper *renderPass)
if (mReadOnlyDepthStencilMode != readOnlyDepthEnabled)
{
mReadOnlyDepthStencilMode = readOnlyDepthEnabled;
ASSERT(getDepthStencilRenderTarget());
vk::ResourceAccess dsAccess =
isReadOnlyDepthMode() ? vk::ResourceAccess::ReadOnly : vk::ResourceAccess::Write;
ASSERT(mRenderPassDesc.hasDepthStencilAttachment());
mRenderPassDesc.updateDepthStencilAccess(dsAccess);
}
}
angle::Result FramebufferVk::updateRenderPassReadOnlyDepthMode(ContextVk *contextVk,
vk::CommandBufferHelper *renderPass)
{ {
ASSERT(getDepthStencilRenderTarget()); bool readOnlyDepthStencilMode =
getDepthStencilRenderTarget() && !getDepthStencilRenderTarget()->hasResolveAttachment() &&
bool readOnlyDepthStencil =
!getDepthStencilRenderTarget()->hasResolveAttachment() &&
(mReadOnlyDepthFeedbackLoopMode || !renderPass->hasDepthStencilWriteOrClear()); (mReadOnlyDepthFeedbackLoopMode || !renderPass->hasDepthStencilWriteOrClear());
if (readOnlyDepthStencil == mReadOnlyDepthStencilMode)
{
return angle::Result::Continue;
}
// If readOnlyDepthStencil is false, we are switching out of read only mode due to depth write. // If readOnlyDepthStencil is false, we are switching out of read only mode due to depth write.
// We must not be in the read only feedback loop mode because the logic in // We must not be in the read only feedback loop mode because the logic in
// ContextVk::updateRenderPassDepthStencilAccess() should ensure we end the previous renderpass // ContextVk::updateRenderPassDepthStencilAccess() should ensure we end the previous renderpass
// and a new renderpass will start with feedback loop disabled. // and a new renderpass will start with feedback loop disabled.
ASSERT(readOnlyDepthStencil || !mReadOnlyDepthFeedbackLoopMode); ASSERT(readOnlyDepthStencilMode || !mReadOnlyDepthFeedbackLoopMode);
setReadOnlyDepthMode(readOnlyDepthStencil);
// When we toggle read/write mode, we must insert a layout transition.
getDepthStencilRenderTarget()->onDepthStencilDraw(contextVk, readOnlyDepthStencil);
vk::Framebuffer *currentFramebuffer = nullptr; renderPass->updateStartedRenderPassWithDepthMode(readOnlyDepthStencilMode);
ANGLE_TRY(getFramebuffer(contextVk, &currentFramebuffer, nullptr));
renderPass->updateStartedRenderPassWithDepthMode(*currentFramebuffer, mRenderPassDesc,
readOnlyDepthStencil);
return angle::Result::Continue;
} }
} // namespace rx } // namespace rx
...@@ -116,7 +116,6 @@ class FramebufferVk : public FramebufferImpl ...@@ -116,7 +116,6 @@ class FramebufferVk : public FramebufferImpl
RenderTargetVk *getColorReadRenderTarget() const; RenderTargetVk *getColorReadRenderTarget() const;
angle::Result startNewRenderPass(ContextVk *contextVk, angle::Result startNewRenderPass(ContextVk *contextVk,
bool readOnlyDepthMode,
const gl::Rectangle &renderArea, const gl::Rectangle &renderArea,
vk::CommandBuffer **commandBufferOut); vk::CommandBuffer **commandBufferOut);
void restoreDepthStencilDefinedContents(); void restoreDepthStencilDefinedContents();
...@@ -130,8 +129,6 @@ class FramebufferVk : public FramebufferImpl ...@@ -130,8 +129,6 @@ class FramebufferVk : public FramebufferImpl
vk::Framebuffer **framebufferOut, vk::Framebuffer **framebufferOut,
const vk::ImageView *resolveImageViewIn); const vk::ImageView *resolveImageViewIn);
bool isReadOnlyDepthMode() const { return mReadOnlyDepthStencilMode; }
bool hasDeferredClears() const { return !mDeferredClears.empty(); } bool hasDeferredClears() const { return !mDeferredClears.empty(); }
angle::Result flushDeferredClears(ContextVk *contextVk, const gl::Rectangle &renderArea); angle::Result flushDeferredClears(ContextVk *contextVk, const gl::Rectangle &renderArea);
void setReadOnlyDepthFeedbackLoopMode(bool readOnlyDepthFeedbackModeEnabled) void setReadOnlyDepthFeedbackLoopMode(bool readOnlyDepthFeedbackModeEnabled)
...@@ -139,8 +136,8 @@ class FramebufferVk : public FramebufferImpl ...@@ -139,8 +136,8 @@ class FramebufferVk : public FramebufferImpl
mReadOnlyDepthFeedbackLoopMode = readOnlyDepthFeedbackModeEnabled; mReadOnlyDepthFeedbackLoopMode = readOnlyDepthFeedbackModeEnabled;
} }
bool isReadOnlyDepthFeedbackLoopMode() const { return mReadOnlyDepthFeedbackLoopMode; } bool isReadOnlyDepthFeedbackLoopMode() const { return mReadOnlyDepthFeedbackLoopMode; }
angle::Result updateRenderPassReadOnlyDepthMode(ContextVk *contextVk, void updateRenderPassReadOnlyDepthMode(ContextVk *contextVk,
vk::CommandBufferHelper *renderPass); vk::CommandBufferHelper *renderPass);
private: private:
FramebufferVk(RendererVk *renderer, FramebufferVk(RendererVk *renderer,
...@@ -232,8 +229,6 @@ class FramebufferVk : public FramebufferImpl ...@@ -232,8 +229,6 @@ class FramebufferVk : public FramebufferImpl
vk::ImageViewSubresourceSerial resolveImageViewSerial); vk::ImageViewSubresourceSerial resolveImageViewSerial);
void removeColorResolveAttachment(uint32_t colorIndexGL); void removeColorResolveAttachment(uint32_t colorIndexGL);
void setReadOnlyDepthMode(bool readOnlyDepthEnabled);
WindowSurfaceVk *mBackbuffer; WindowSurfaceVk *mBackbuffer;
vk::RenderPassDesc mRenderPassDesc; vk::RenderPassDesc mRenderPassDesc;
...@@ -257,8 +252,6 @@ class FramebufferVk : public FramebufferImpl ...@@ -257,8 +252,6 @@ class FramebufferVk : public FramebufferImpl
vk::ClearValuesArray mDeferredClears; vk::ClearValuesArray mDeferredClears;
// True if depth stencil buffer is read only.
bool mReadOnlyDepthStencilMode;
// Tracks if we are in depth feedback loop. Depth read only feedback loop is a special kind of // Tracks if we are in depth feedback loop. Depth read only feedback loop is a special kind of
// depth stencil read only mode. When we are in feedback loop, we must flush renderpass to exit // depth stencil read only mode. When we are in feedback loop, we must flush renderpass to exit
// the loop instead of update the layout. // the loop instead of update the layout.
......
...@@ -107,29 +107,12 @@ void RenderTargetVk::onColorDraw(ContextVk *contextVk) ...@@ -107,29 +107,12 @@ void RenderTargetVk::onColorDraw(ContextVk *contextVk)
mContentDefined = true; mContentDefined = true;
} }
void RenderTargetVk::onDepthStencilDraw(ContextVk *contextVk, bool isReadOnly) void RenderTargetVk::onDepthStencilDraw(ContextVk *contextVk)
{ {
const angle::Format &format = mImage->getFormat().actualImageFormat(); const angle::Format &format = mImage->getFormat().actualImageFormat();
ASSERT(format.hasDepthOrStencilBits()); ASSERT(format.hasDepthOrStencilBits());
VkImageAspectFlags aspectFlags = vk::GetDepthStencilAspectFlags(format);
if (isReadOnly)
{
ASSERT(!mResolveImage);
contextVk->onImageRenderPassRead(aspectFlags, vk::ImageLayout::DepthStencilReadOnly,
mImage);
}
else
{
contextVk->onImageRenderPassWrite(aspectFlags, vk::ImageLayout::DepthStencilAttachment,
mImage);
if (mResolveImage)
{
contextVk->onImageRenderPassWrite(
aspectFlags, vk::ImageLayout::DepthStencilResolveAttachment, mResolveImage);
}
}
contextVk->onDepthStencilDraw(mImage, mResolveImage);
retainImageViews(contextVk); retainImageViews(contextVk);
mContentDefined = true; mContentDefined = true;
......
...@@ -67,7 +67,7 @@ class RenderTargetVk final : public FramebufferAttachmentRenderTarget ...@@ -67,7 +67,7 @@ class RenderTargetVk final : public FramebufferAttachmentRenderTarget
// Note: RenderTargets should be called in order, with the depth/stencil onRender last. // Note: RenderTargets should be called in order, with the depth/stencil onRender last.
void onColorDraw(ContextVk *contextVk); void onColorDraw(ContextVk *contextVk);
void onDepthStencilDraw(ContextVk *contextVk, bool isReadOnly); void onDepthStencilDraw(ContextVk *contextVk);
vk::ImageHelper &getImageForRenderPass(); vk::ImageHelper &getImageForRenderPass();
const vk::ImageHelper &getImageForRenderPass() const; const vk::ImageHelper &getImageForRenderPass() const;
......
...@@ -1413,7 +1413,7 @@ angle::Result UtilsVk::clearFramebuffer(ContextVk *contextVk, ...@@ -1413,7 +1413,7 @@ angle::Result UtilsVk::clearFramebuffer(ContextVk *contextVk,
// We may have changed depth stencil access mode, so update read only depth stencil mode // We may have changed depth stencil access mode, so update read only depth stencil mode
// here. // here.
ANGLE_TRY(framebuffer->updateRenderPassReadOnlyDepthMode(contextVk, renderpassCommands)); framebuffer->updateRenderPassReadOnlyDepthMode(contextVk, renderpassCommands);
} }
ImageClearShaderParams shaderParams; ImageClearShaderParams shaderParams;
...@@ -1666,7 +1666,7 @@ angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk, ...@@ -1666,7 +1666,7 @@ angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk,
pipelineDesc.setScissor(gl_vk::GetRect(params.blitArea)); pipelineDesc.setScissor(gl_vk::GetRect(params.blitArea));
vk::CommandBuffer *commandBuffer; vk::CommandBuffer *commandBuffer;
ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, false, params.blitArea, &commandBuffer)); ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, params.blitArea, &commandBuffer));
contextVk->onImageRenderPassRead(src->getAspectFlags(), vk::ImageLayout::FragmentShaderReadOnly, contextVk->onImageRenderPassRead(src->getAspectFlags(), vk::ImageLayout::FragmentShaderReadOnly,
src); src);
......
...@@ -618,18 +618,20 @@ CommandBufferHelper::CommandBufferHelper() ...@@ -618,18 +618,20 @@ CommandBufferHelper::CommandBufferHelper()
mCounter(0), mCounter(0),
mClearValues{}, mClearValues{},
mRenderPassStarted(false), mRenderPassStarted(false),
mForceIndividualBarriers(false),
mTransformFeedbackCounterBuffers{}, mTransformFeedbackCounterBuffers{},
mValidTransformFeedbackBufferCount(0), mValidTransformFeedbackBufferCount(0),
mRebindTransformFeedbackBuffers(false), mRebindTransformFeedbackBuffers(false),
mIsRenderPassCommandBuffer(false), mIsRenderPassCommandBuffer(false),
mReadOnlyDepthStencilMode(false),
mDepthAccess(ResourceAccess::Unused), mDepthAccess(ResourceAccess::Unused),
mStencilAccess(ResourceAccess::Unused), mStencilAccess(ResourceAccess::Unused),
mDepthCmdSizeInvalidated(kInfiniteCmdSize), mDepthCmdSizeInvalidated(kInfiniteCmdSize),
mDepthCmdSizeDisabled(kInfiniteCmdSize), mDepthCmdSizeDisabled(kInfiniteCmdSize),
mStencilCmdSizeInvalidated(kInfiniteCmdSize), mStencilCmdSizeInvalidated(kInfiniteCmdSize),
mStencilCmdSizeDisabled(kInfiniteCmdSize), mStencilCmdSizeDisabled(kInfiniteCmdSize),
mDepthStencilAttachmentIndex(kAttachmentIndexInvalid) mDepthStencilAttachmentIndex(kAttachmentIndexInvalid),
mDepthStencilImage(nullptr),
mDepthStencilResolveImage(nullptr)
{} {}
CommandBufferHelper::~CommandBufferHelper() CommandBufferHelper::~CommandBufferHelper()
...@@ -768,6 +770,31 @@ void CommandBufferHelper::imageWrite(ResourceUseList *resourceUseList, ...@@ -768,6 +770,31 @@ void CommandBufferHelper::imageWrite(ResourceUseList *resourceUseList,
} }
} }
void CommandBufferHelper::depthStencilImagesDraw(ResourceUseList *resourceUseList,
ImageHelper *image,
ImageHelper *resolveImage)
{
ASSERT(mIsRenderPassCommandBuffer);
ASSERT(!usesImageInRenderPass(*image));
ASSERT(!resolveImage || !usesImageInRenderPass(*resolveImage));
// Because depthStencil buffer's read/write property can change while we build renderpass, we
// defer the image layout changes until endRenderPass time or when images going away so that we
// only insert layout change barrier once.
image->retain(resourceUseList);
image->onWrite();
mRenderPassUsedImages.insert(image->getImageSerial().getValue());
mDepthStencilImage = image;
if (resolveImage)
{
resolveImage->retain(resourceUseList);
resolveImage->onWrite();
mRenderPassUsedImages.insert(resolveImage->getImageSerial().getValue());
mDepthStencilResolveImage = resolveImage;
}
}
bool CommandBufferHelper::onDepthAccess(ResourceAccess access) bool CommandBufferHelper::onDepthAccess(ResourceAccess access)
{ {
// Update the access for optimizing this render pass's loadOp // Update the access for optimizing this render pass's loadOp
...@@ -838,20 +865,7 @@ void CommandBufferHelper::executeBarriers(ContextVk *contextVk, PrimaryCommandBu ...@@ -838,20 +865,7 @@ void CommandBufferHelper::executeBarriers(ContextVk *contextVk, PrimaryCommandBu
return; return;
} }
if (mForceIndividualBarriers) if (contextVk->getFeatures().preferAggregateBarrierCalls.enabled)
{
// Note: ideally we could merge double barriers into a single barrier (or even completely
// eliminate them in some cases). This is a bit trickier to manage than splitting barriers
// into single calls. It should only affect Framebuffer transitions.
// TODO: Investigate merging barriers. http://anglebug.com/4976
for (PipelineStage pipelineStage : mask)
{
PipelineBarrier &barrier = mPipelineBarriers[pipelineStage];
barrier.executeIndividually(primary);
}
mForceIndividualBarriers = false;
}
else if (contextVk->getFeatures().preferAggregateBarrierCalls.enabled)
{ {
PipelineStagesMask::Iterator iter = mask.begin(); PipelineStagesMask::Iterator iter = mask.begin();
PipelineBarrier &barrier = mPipelineBarriers[*iter]; PipelineBarrier &barrier = mPipelineBarriers[*iter];
...@@ -872,11 +886,84 @@ void CommandBufferHelper::executeBarriers(ContextVk *contextVk, PrimaryCommandBu ...@@ -872,11 +886,84 @@ void CommandBufferHelper::executeBarriers(ContextVk *contextVk, PrimaryCommandBu
mPipelineBarrierMask.reset(); mPipelineBarrierMask.reset();
} }
void CommandBufferHelper::finalizeDepthStencilImageLayout()
{
ASSERT(mIsRenderPassCommandBuffer);
ASSERT(mDepthStencilImage);
// Do depth stencil layout change.
ImageLayout imageLayout;
bool barrierRequired;
if (mReadOnlyDepthStencilMode)
{
imageLayout = ImageLayout::DepthStencilReadOnly;
mRenderPassDesc.updateDepthStencilAccess(ResourceAccess::ReadOnly);
barrierRequired = mDepthStencilImage->isReadBarrierNecessary(imageLayout);
}
else
{
// Write always requires a barrier
imageLayout = ImageLayout::DepthStencilAttachment;
mRenderPassDesc.updateDepthStencilAccess(ResourceAccess::Write);
barrierRequired = true;
}
mAttachmentOps.setLayouts(mDepthStencilAttachmentIndex, imageLayout, imageLayout);
if (barrierRequired)
{
const angle::Format &format = mDepthStencilImage->getFormat().actualImageFormat();
ASSERT(format.hasDepthOrStencilBits());
VkImageAspectFlags aspectFlags = GetDepthStencilAspectFlags(format);
PipelineStage barrierIndex = kImageMemoryBarrierData[imageLayout].barrierIndex;
ASSERT(barrierIndex != PipelineStage::InvalidEnum);
PipelineBarrier *barrier = &mPipelineBarriers[barrierIndex];
if (mDepthStencilImage->updateLayoutAndBarrier(aspectFlags, imageLayout, barrier))
{
mPipelineBarrierMask.set(barrierIndex);
}
}
}
void CommandBufferHelper::finalizeDepthStencilResolveImageLayout()
{
ASSERT(mIsRenderPassCommandBuffer);
ASSERT(mDepthStencilImage);
ASSERT(!mReadOnlyDepthStencilMode);
ImageLayout imageLayout = ImageLayout::DepthStencilResolveAttachment;
const angle::Format &format = mDepthStencilResolveImage->getFormat().actualImageFormat();
ASSERT(format.hasDepthOrStencilBits());
VkImageAspectFlags aspectFlags = GetDepthStencilAspectFlags(format);
PipelineStage barrierIndex = kImageMemoryBarrierData[imageLayout].barrierIndex;
ASSERT(barrierIndex != PipelineStage::InvalidEnum);
PipelineBarrier *barrier = &mPipelineBarriers[barrierIndex];
if (mDepthStencilResolveImage->updateLayoutAndBarrier(aspectFlags, imageLayout, barrier))
{
mPipelineBarrierMask.set(barrierIndex);
}
}
void CommandBufferHelper::onImageHelperRelease(const vk::ImageHelper *image) void CommandBufferHelper::onImageHelperRelease(const vk::ImageHelper *image)
{ {
ASSERT(mIsRenderPassCommandBuffer); ASSERT(mIsRenderPassCommandBuffer);
// TODO: https://issuetracker.google.com/168953278 We will use this to finalize image layout
// transition if (mDepthStencilImage == image)
{
finalizeDepthStencilImageLayout();
mDepthStencilImage = nullptr;
}
if (mDepthStencilResolveImage == image)
{
finalizeDepthStencilResolveImageLayout();
mDepthStencilResolveImage = nullptr;
}
} }
void CommandBufferHelper::beginRenderPass(const Framebuffer &framebuffer, void CommandBufferHelper::beginRenderPass(const Framebuffer &framebuffer,
...@@ -894,32 +981,14 @@ void CommandBufferHelper::beginRenderPass(const Framebuffer &framebuffer, ...@@ -894,32 +981,14 @@ void CommandBufferHelper::beginRenderPass(const Framebuffer &framebuffer,
mAttachmentOps = renderPassAttachmentOps; mAttachmentOps = renderPassAttachmentOps;
mDepthStencilAttachmentIndex = depthStencilAttachmentIndex; mDepthStencilAttachmentIndex = depthStencilAttachmentIndex;
mFramebuffer.setHandle(framebuffer.getHandle()); mFramebuffer.setHandle(framebuffer.getHandle());
mRenderArea = renderArea; mRenderArea = renderArea;
mClearValues = clearValues; mClearValues = clearValues;
*commandBufferOut = &mCommandBuffer; *commandBufferOut = &mCommandBuffer;
mForceIndividualBarriers = false;
mRenderPassStarted = true; mRenderPassStarted = true;
mCounter++; mCounter++;
} }
void CommandBufferHelper::updateStartedRenderPassWithDepthMode(const Framebuffer &framebuffer,
const RenderPassDesc &renderPassDesc,
bool readOnlyDepth)
{
ASSERT(mIsRenderPassCommandBuffer);
ASSERT(mRenderPassStarted);
mRenderPassDesc = renderPassDesc;
ImageLayout depthStencilLayout =
readOnlyDepth ? ImageLayout::DepthStencilReadOnly : ImageLayout::DepthStencilAttachment;
mAttachmentOps.setLayouts(mDepthStencilAttachmentIndex, depthStencilLayout, depthStencilLayout);
mFramebuffer.setHandle(framebuffer.getHandle());
// Barrier aggregation messes up with RenderPass restarting.
mForceIndividualBarriers = true;
}
void CommandBufferHelper::endRenderPass(ContextVk *contextVk) void CommandBufferHelper::endRenderPass(ContextVk *contextVk)
{ {
if (mDepthStencilAttachmentIndex == kAttachmentIndexInvalid) if (mDepthStencilAttachmentIndex == kAttachmentIndexInvalid)
...@@ -927,8 +996,17 @@ void CommandBufferHelper::endRenderPass(ContextVk *contextVk) ...@@ -927,8 +996,17 @@ void CommandBufferHelper::endRenderPass(ContextVk *contextVk)
return; return;
} }
PackedAttachmentOpsDesc &dsOps = mAttachmentOps[mDepthStencilAttachmentIndex]; // Do depth stencil layout change.
if (mDepthStencilImage)
{
finalizeDepthStencilImageLayout();
}
if (mDepthStencilResolveImage)
{
finalizeDepthStencilResolveImageLayout();
}
PackedAttachmentOpsDesc &dsOps = mAttachmentOps[mDepthStencilAttachmentIndex];
// Depth/Stencil buffer optimizations: // Depth/Stencil buffer optimizations:
// //
// First, if the attachment is invalidated, skip the store op. // First, if the attachment is invalidated, skip the store op.
...@@ -1171,6 +1249,9 @@ void CommandBufferHelper::reset() ...@@ -1171,6 +1249,9 @@ void CommandBufferHelper::reset()
mStencilCmdSizeDisabled = kInfiniteCmdSize; mStencilCmdSizeDisabled = kInfiniteCmdSize;
mDepthStencilAttachmentIndex = kAttachmentIndexInvalid; mDepthStencilAttachmentIndex = kAttachmentIndexInvalid;
mRenderPassUsedImages.clear(); mRenderPassUsedImages.clear();
mDepthStencilImage = nullptr;
mDepthStencilResolveImage = nullptr;
mReadOnlyDepthStencilMode = false;
} }
// This state should never change for non-renderPass command buffer // This state should never change for non-renderPass command buffer
ASSERT(mRenderPassStarted == false); ASSERT(mRenderPassStarted == false);
......
...@@ -950,6 +950,10 @@ class CommandBufferHelper : angle::NonCopyable ...@@ -950,6 +950,10 @@ class CommandBufferHelper : angle::NonCopyable
AliasingMode aliasingMode, AliasingMode aliasingMode,
ImageHelper *image); ImageHelper *image);
void depthStencilImagesDraw(ResourceUseList *resourceUseList,
ImageHelper *image,
ImageHelper *resolveImage);
CommandBuffer &getCommandBuffer() { return mCommandBuffer; } CommandBuffer &getCommandBuffer() { return mCommandBuffer; }
angle::Result flushToPrimary(ContextVk *contextVk, PrimaryCommandBuffer *primary); angle::Result flushToPrimary(ContextVk *contextVk, PrimaryCommandBuffer *primary);
...@@ -999,9 +1003,12 @@ class CommandBufferHelper : angle::NonCopyable ...@@ -999,9 +1003,12 @@ class CommandBufferHelper : angle::NonCopyable
void endRenderPass(ContextVk *contextVk); void endRenderPass(ContextVk *contextVk);
void updateStartedRenderPassWithDepthMode(const Framebuffer &framebuffer, void updateStartedRenderPassWithDepthMode(bool readOnlyDepthStencilMode)
const RenderPassDesc &renderPassDesc, {
bool readOnlyDepth); ASSERT(mIsRenderPassCommandBuffer);
ASSERT(mRenderPassStarted);
mReadOnlyDepthStencilMode = readOnlyDepthStencilMode;
}
void beginTransformFeedback(size_t validBufferCount, void beginTransformFeedback(size_t validBufferCount,
const VkBuffer *counterBuffers, const VkBuffer *counterBuffers,
...@@ -1109,6 +1116,8 @@ class CommandBufferHelper : angle::NonCopyable ...@@ -1109,6 +1116,8 @@ class CommandBufferHelper : angle::NonCopyable
VK_ATTACHMENT_LOAD_OP_CLEAR; VK_ATTACHMENT_LOAD_OP_CLEAR;
} }
bool isReadOnlyDepthMode() const { return mReadOnlyDepthStencilMode; }
private: private:
void addCommandDiagnostics(ContextVk *contextVk); void addCommandDiagnostics(ContextVk *contextVk);
...@@ -1116,6 +1125,9 @@ class CommandBufferHelper : angle::NonCopyable ...@@ -1116,6 +1125,9 @@ class CommandBufferHelper : angle::NonCopyable
uint32_t *cmdCountInvalidated, uint32_t *cmdCountInvalidated,
uint32_t *cmdCountDisabled); uint32_t *cmdCountDisabled);
void finalizeDepthStencilImageLayout();
void finalizeDepthStencilResolveImageLayout();
// Allocator used by this class. Using a pool allocator per CBH to avoid threading issues // Allocator used by this class. Using a pool allocator per CBH to avoid threading issues
// that occur w/ shared allocator between multiple CBHs. // that occur w/ shared allocator between multiple CBHs.
angle::PoolAllocator mAllocator; angle::PoolAllocator mAllocator;
...@@ -1133,7 +1145,6 @@ class CommandBufferHelper : angle::NonCopyable ...@@ -1133,7 +1145,6 @@ class CommandBufferHelper : angle::NonCopyable
gl::Rectangle mRenderArea; gl::Rectangle mRenderArea;
PackedClearValuesArray mClearValues; PackedClearValuesArray mClearValues;
bool mRenderPassStarted; bool mRenderPassStarted;
bool mForceIndividualBarriers;
// Transform feedback state // Transform feedback state
gl::TransformFeedbackBuffersArray<VkBuffer> mTransformFeedbackCounterBuffers; gl::TransformFeedbackBuffersArray<VkBuffer> mTransformFeedbackCounterBuffers;
...@@ -1141,6 +1152,7 @@ class CommandBufferHelper : angle::NonCopyable ...@@ -1141,6 +1152,7 @@ class CommandBufferHelper : angle::NonCopyable
bool mRebindTransformFeedbackBuffers; bool mRebindTransformFeedbackBuffers;
bool mIsRenderPassCommandBuffer; bool mIsRenderPassCommandBuffer;
bool mReadOnlyDepthStencilMode;
// State tracking for the maximum (Write been the highest) depth access during the entire // State tracking for the maximum (Write been the highest) depth access during the entire
// renderpass. Note that this does not include VK_ATTACHMENT_LOAD_OP_CLEAR which is tracked // renderpass. Note that this does not include VK_ATTACHMENT_LOAD_OP_CLEAR which is tracked
...@@ -1165,6 +1177,9 @@ class CommandBufferHelper : angle::NonCopyable ...@@ -1165,6 +1177,9 @@ class CommandBufferHelper : angle::NonCopyable
// Images have unique layouts unlike buffers therefore we don't support multi-read. // Images have unique layouts unlike buffers therefore we don't support multi-read.
angle::FastIntegerMap<BufferAccess> mUsedBuffers; angle::FastIntegerMap<BufferAccess> mUsedBuffers;
angle::FastIntegerSet mRenderPassUsedImages; angle::FastIntegerSet mRenderPassUsedImages;
ImageHelper *mDepthStencilImage;
ImageHelper *mDepthStencilResolveImage;
}; };
// Imagine an image going through a few layout transitions: // Imagine an image going through a few layout transitions:
......
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