Commit d2d9e682 by Charlie Lao Committed by Commit Bot

Vulkan: Use DepthStencilReadOnly when it is read only.

We are tracking depth and stencil read or write during the renderpass. We can use that to switch to DepthStencilReadOnly layout if both depth and stencil are not writing. This allows drivers to optimize out the storeOp for the renderpass. Bug: b/168953278 Change-Id: Id82e06b4bae1ae8c83d880bb5e58accfa61f8191 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2411336 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 52ee81cf
...@@ -2919,7 +2919,7 @@ angle::Result ContextVk::syncState(const gl::Context *context, ...@@ -2919,7 +2919,7 @@ angle::Result ContextVk::syncState(const gl::Context *context,
mGraphicsPipelineDesc->updateDepthTestEnabled(&mGraphicsPipelineTransition, mGraphicsPipelineDesc->updateDepthTestEnabled(&mGraphicsPipelineTransition,
glState.getDepthStencilState(), glState.getDepthStencilState(),
glState.getDrawFramebuffer()); glState.getDrawFramebuffer());
ANGLE_TRY(updateRenderPassDepthAccess()); ANGLE_TRY(updateRenderPassDepthStencilAccess());
break; break;
} }
case gl::State::DIRTY_BIT_DEPTH_FUNC: case gl::State::DIRTY_BIT_DEPTH_FUNC:
...@@ -2931,23 +2931,17 @@ angle::Result ContextVk::syncState(const gl::Context *context, ...@@ -2931,23 +2931,17 @@ angle::Result ContextVk::syncState(const gl::Context *context,
mGraphicsPipelineDesc->updateDepthWriteEnabled(&mGraphicsPipelineTransition, mGraphicsPipelineDesc->updateDepthWriteEnabled(&mGraphicsPipelineTransition,
glState.getDepthStencilState(), glState.getDepthStencilState(),
glState.getDrawFramebuffer()); glState.getDrawFramebuffer());
ANGLE_TRY(updateRenderPassDepthAccess()); ANGLE_TRY(updateRenderPassDepthStencilAccess());
break; break;
} }
case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED: case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED:
{
mGraphicsPipelineDesc->updateStencilTestEnabled(&mGraphicsPipelineTransition, mGraphicsPipelineDesc->updateStencilTestEnabled(&mGraphicsPipelineTransition,
glState.getDepthStencilState(), glState.getDepthStencilState(),
glState.getDrawFramebuffer()); glState.getDrawFramebuffer());
if (mRenderPassCommands->started()) ANGLE_TRY(updateRenderPassDepthStencilAccess());
{
vk::ResourceAccess access = GetStencilAccess(mState.getDepthStencilState());
if (mRenderPassCommands->onStencilAccess(access))
{
// The attachment is no longer invalidated, so set mContentDefined to true
mDrawFramebuffer->restoreDepthStencilDefinedContents();
}
}
break; break;
}
case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT: case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT:
mGraphicsPipelineDesc->updateStencilFrontFuncs(&mGraphicsPipelineTransition, mGraphicsPipelineDesc->updateStencilFrontFuncs(&mGraphicsPipelineTransition,
glState.getStencilRef(), glState.getStencilRef(),
...@@ -3049,7 +3043,7 @@ angle::Result ContextVk::syncState(const gl::Context *context, ...@@ -3049,7 +3043,7 @@ angle::Result ContextVk::syncState(const gl::Context *context,
gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer(); gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
mDrawFramebuffer = vk::GetImpl(drawFramebuffer); mDrawFramebuffer = vk::GetImpl(drawFramebuffer);
mDrawFramebuffer->setReadOnlyDepthMode(false); mDrawFramebuffer->setReadOnlyDepthFeedbackLoopMode(false);
updateFlipViewportDrawFramebuffer(glState); updateFlipViewportDrawFramebuffer(glState);
updateSurfaceRotationDrawFramebuffer(glState); updateSurfaceRotationDrawFramebuffer(glState);
updateViewport(mDrawFramebuffer, glState.getViewport(), glState.getNearPlane(), updateViewport(mDrawFramebuffer, glState.getViewport(), glState.getNearPlane(),
...@@ -4013,7 +4007,7 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context) ...@@ -4013,7 +4007,7 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context)
{ {
ANGLE_TRY(getIncompleteTexture(context, textureType, &texture)); ANGLE_TRY(getIncompleteTexture(context, textureType, &texture));
} }
else if (shouldSwitchToDepthReadOnlyMode(context, texture)) else if (shouldSwitchToReadOnlyDepthFeedbackLoopMode(context, texture))
{ {
// The "readOnlyDepthMode" feature enables read-only depth-stencil feedback loops. We // The "readOnlyDepthMode" feature enables read-only depth-stencil feedback loops. We
// only switch to "read-only" mode when there's loop. We track the depth-stencil access // only switch to "read-only" mode when there's loop. We track the depth-stencil access
...@@ -4032,18 +4026,20 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context) ...@@ -4032,18 +4026,20 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context)
if (hasStartedRenderPass()) if (hasStartedRenderPass())
{ {
if (mRenderPassCommands->hasDepthWriteOrClear()) if (!mDrawFramebuffer->isReadOnlyDepthMode())
{ {
// To enter depth feedback loop, we must flush and start a new renderpass.
// Otherwise it will stick with writable layout and cause validation error.
ANGLE_TRY(flushCommandsAndEndRenderPass()); ANGLE_TRY(flushCommandsAndEndRenderPass());
} }
else else
{ {
ANGLE_TRY(mDrawFramebuffer->restartRenderPassInReadOnlyDepthMode( ANGLE_TRY(mDrawFramebuffer->updateRenderPassReadOnlyDepthMode(
this, mRenderPassCommands)); this, mRenderPassCommands));
} }
} }
mDrawFramebuffer->setReadOnlyDepthMode(true); mDrawFramebuffer->setReadOnlyDepthFeedbackLoopMode(true);
} }
TextureVk *textureVk = vk::GetImpl(texture); TextureVk *textureVk = vk::GetImpl(texture);
...@@ -4623,13 +4619,22 @@ angle::Result ContextVk::startRenderPass(gl::Rectangle renderArea, ...@@ -4623,13 +4619,22 @@ angle::Result ContextVk::startRenderPass(gl::Rectangle renderArea,
vk::CommandBuffer **commandBufferOut) vk::CommandBuffer **commandBufferOut)
{ {
mGraphicsDirtyBits |= mNewGraphicsCommandBufferDirtyBits; mGraphicsDirtyBits |= mNewGraphicsCommandBufferDirtyBits;
ANGLE_TRY(mDrawFramebuffer->startNewRenderPass(this, renderArea, &mRenderPassCommandBuffer));
// We always start renderpass with proper depth stencil read only mode based on the current
// 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(); mRenderPassCommands->onDepthAccess(depthAccess);
mRenderPassCommands->onDepthAccess(GetDepthAccess(dsState)); mRenderPassCommands->onStencilAccess(stencilAccess);
mRenderPassCommands->onStencilAccess(GetStencilAccess(dsState));
if (commandBufferOut) if (commandBufferOut)
{ {
...@@ -5026,34 +5031,49 @@ void ContextVk::setDefaultUniformBlocksMinSizeForTesting(size_t minSize) ...@@ -5026,34 +5031,49 @@ void ContextVk::setDefaultUniformBlocksMinSizeForTesting(size_t minSize)
mDefaultUniformStorage.setMinimumSizeForTesting(minSize); mDefaultUniformStorage.setMinimumSizeForTesting(minSize);
} }
angle::Result ContextVk::updateRenderPassDepthAccess() angle::Result ContextVk::updateRenderPassDepthStencilAccess()
{ {
if (hasStartedRenderPass()) if (hasStartedRenderPass() && mDrawFramebuffer->getDepthStencilRenderTarget())
{ {
vk::ResourceAccess access = GetDepthAccess(mState.getDepthStencilState()); const gl::DepthStencilState &dsState = mState.getDepthStencilState();
vk::ResourceAccess depthAccess = GetDepthAccess(dsState);
vk::ResourceAccess stencilAccess = GetStencilAccess(dsState);
if (access == vk::ResourceAccess::Write && mDrawFramebuffer->isReadOnlyDepthMode()) if ((depthAccess == vk::ResourceAccess::Write ||
stencilAccess == vk::ResourceAccess::Write) &&
mDrawFramebuffer->isReadOnlyDepthFeedbackLoopMode())
{ {
// If we are switching out of read only mode and we are in feedback loop, we must end
// renderpass here. Otherwise, updating it to writeable layout will produce a writable
// feedback loop that is illegal in vulkan and will trigger validation errors that depth
// texture is using the writable layout.
ANGLE_TRY(flushCommandsAndEndRenderPass()); ANGLE_TRY(flushCommandsAndEndRenderPass());
// Clear read-only depth feedback mode.
// Clear read-only depth mode. mDrawFramebuffer->setReadOnlyDepthFeedbackLoopMode(false);
mDrawFramebuffer->setReadOnlyDepthMode(false);
} }
else else
{ {
if (mRenderPassCommands->onDepthAccess(access)) if (mRenderPassCommands->onDepthAccess(depthAccess))
{ {
// The attachment is no longer invalidated, so set mContentDefined to true // The attachment is no longer invalidated, so set mContentDefined to true
mDrawFramebuffer->restoreDepthStencilDefinedContents(); mDrawFramebuffer->restoreDepthStencilDefinedContents();
} }
if (mRenderPassCommands->onStencilAccess(stencilAccess))
{
// The attachment is no longer invalidated, so set mContentDefined to true
mDrawFramebuffer->restoreDepthStencilDefinedContents();
}
ANGLE_TRY(
mDrawFramebuffer->updateRenderPassReadOnlyDepthMode(this, mRenderPassCommands));
} }
} }
return angle::Result::Continue; return angle::Result::Continue;
} }
bool ContextVk::shouldSwitchToDepthReadOnlyMode(const gl::Context *context, bool ContextVk::shouldSwitchToReadOnlyDepthFeedbackLoopMode(const gl::Context *context,
gl::Texture *texture) const gl::Texture *texture) const
{ {
const gl::ProgramExecutable *programExecutable = mState.getProgramExecutable(); const gl::ProgramExecutable *programExecutable = mState.getProgramExecutable();
...@@ -5065,6 +5085,6 @@ bool ContextVk::shouldSwitchToDepthReadOnlyMode(const gl::Context *context, ...@@ -5065,6 +5085,6 @@ bool ContextVk::shouldSwitchToDepthReadOnlyMode(const gl::Context *context,
return texture->isDepthOrStencil() && return texture->isDepthOrStencil() &&
texture->isBoundToFramebuffer(mDrawFramebuffer->getState().getFramebufferSerial()) && texture->isBoundToFramebuffer(mDrawFramebuffer->getState().getFramebufferSerial()) &&
!mDrawFramebuffer->isReadOnlyDepthMode(); !mDrawFramebuffer->isReadOnlyDepthFeedbackLoopMode();
} }
} // namespace rx } // namespace rx
...@@ -936,8 +936,9 @@ class ContextVk : public ContextImpl, public vk::Context ...@@ -936,8 +936,9 @@ class ContextVk : public ContextImpl, public vk::Context
void growDesciptorCapacity(std::vector<T> *descriptorVector, size_t newSize); void growDesciptorCapacity(std::vector<T> *descriptorVector, size_t newSize);
angle::Result updateScissorImpl(const gl::State &glState, bool shouldEndRenderPass); angle::Result updateScissorImpl(const gl::State &glState, bool shouldEndRenderPass);
angle::Result updateRenderPassDepthAccess(); angle::Result updateRenderPassDepthStencilAccess();
bool shouldSwitchToDepthReadOnlyMode(const gl::Context *context, gl::Texture *texture) const; bool shouldSwitchToReadOnlyDepthFeedbackLoopMode(const gl::Context *context,
gl::Texture *texture) const;
std::array<DirtyBitHandler, DIRTY_BIT_MAX> mGraphicsDirtyBitHandlers; std::array<DirtyBitHandler, DIRTY_BIT_MAX> mGraphicsDirtyBitHandlers;
std::array<DirtyBitHandler, DIRTY_BIT_MAX> mComputeDirtyBitHandlers; std::array<DirtyBitHandler, DIRTY_BIT_MAX> mComputeDirtyBitHandlers;
......
...@@ -116,6 +116,7 @@ class FramebufferVk : public FramebufferImpl ...@@ -116,6 +116,7 @@ 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();
...@@ -133,9 +134,13 @@ class FramebufferVk : public FramebufferImpl ...@@ -133,9 +134,13 @@ class FramebufferVk : public FramebufferImpl
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 setReadOnlyDepthMode(bool readOnlyDepthEnabled); void setReadOnlyDepthFeedbackLoopMode(bool readOnlyDepthFeedbackModeEnabled)
angle::Result restartRenderPassInReadOnlyDepthMode(ContextVk *contextVk, {
vk::CommandBufferHelper *renderPass); mReadOnlyDepthFeedbackLoopMode = readOnlyDepthFeedbackModeEnabled;
}
bool isReadOnlyDepthFeedbackLoopMode() const { return mReadOnlyDepthFeedbackLoopMode; }
angle::Result updateRenderPassReadOnlyDepthMode(ContextVk *contextVk,
vk::CommandBufferHelper *renderPass);
private: private:
FramebufferVk(RendererVk *renderer, FramebufferVk(RendererVk *renderer,
...@@ -189,19 +194,20 @@ class FramebufferVk : public FramebufferImpl ...@@ -189,19 +194,20 @@ class FramebufferVk : public FramebufferImpl
uint8_t stencilMask, uint8_t stencilMask,
const VkClearColorValue &clearColorValue, const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue); const VkClearDepthStencilValue &clearDepthStencilValue);
void clearWithLoadOp(ContextVk *contextVk, angle::Result clearWithLoadOp(ContextVk *contextVk,
gl::DrawBufferMask clearColorBuffers, gl::DrawBufferMask clearColorBuffers,
bool clearDepth, bool clearDepth,
bool clearStencil, bool clearStencil,
const VkClearColorValue &clearColorValue, const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue); const VkClearDepthStencilValue &clearDepthStencilValue);
void clearWithCommand(vk::CommandBuffer *renderPassCommandBuffer, angle::Result clearWithCommand(ContextVk *contextVk,
const gl::Rectangle &scissoredRenderArea, vk::CommandBufferHelper *renderpassCommands,
gl::DrawBufferMask clearColorBuffers, const gl::Rectangle &scissoredRenderArea,
bool clearDepth, gl::DrawBufferMask clearColorBuffers,
bool clearStencil, bool clearDepth,
const VkClearColorValue &clearColorValue, bool clearStencil,
const VkClearDepthStencilValue &clearDepthStencilValue); const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue);
void updateActiveColorMasks(size_t colorIndex, bool r, bool g, bool b, bool a); void updateActiveColorMasks(size_t colorIndex, bool r, bool g, bool b, bool a);
void updateRenderPassDesc(); void updateRenderPassDesc();
angle::Result updateColorAttachment(const gl::Context *context, angle::Result updateColorAttachment(const gl::Context *context,
...@@ -226,6 +232,8 @@ class FramebufferVk : public FramebufferImpl ...@@ -226,6 +232,8 @@ 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;
...@@ -248,6 +256,11 @@ class FramebufferVk : public FramebufferImpl ...@@ -248,6 +256,11 @@ class FramebufferVk : public FramebufferImpl
angle::HashMap<vk::FramebufferDesc, vk::FramebufferHelper> mFramebufferCache; angle::HashMap<vk::FramebufferDesc, vk::FramebufferHelper> mFramebufferCache;
vk::ClearValuesArray mDeferredClears; vk::ClearValuesArray mDeferredClears;
// 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
// the loop instead of update the layout.
bool mReadOnlyDepthFeedbackLoopMode;
}; };
} // namespace rx } // namespace rx
......
...@@ -1327,6 +1327,20 @@ angle::Result UtilsVk::clearFramebuffer(ContextVk *contextVk, ...@@ -1327,6 +1327,20 @@ angle::Result UtilsVk::clearFramebuffer(ContextVk *contextVk,
ANGLE_TRY(contextVk->startRenderPass(scissoredRenderArea, &commandBuffer)); ANGLE_TRY(contextVk->startRenderPass(scissoredRenderArea, &commandBuffer));
} }
if (params.clearStencil)
{
vk::CommandBufferHelper *renderpassCommands;
renderpassCommands = &contextVk->getStartedRenderPassCommands();
// Because clear is not affected by stencil test, we have to explicitly mark stencil write
// here.
renderpassCommands->onStencilAccess(vk::ResourceAccess::Write);
// We may have changed depth stencil access mode, so update read only depth stencil mode
// here.
ANGLE_TRY(framebuffer->updateRenderPassReadOnlyDepthMode(contextVk, renderpassCommands));
}
ImageClearShaderParams shaderParams; ImageClearShaderParams shaderParams;
shaderParams.clearValue = params.colorClearValue; shaderParams.clearValue = params.colorClearValue;
...@@ -1587,7 +1601,7 @@ angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk, ...@@ -1587,7 +1601,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, params.blitArea, &commandBuffer)); ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, false, params.blitArea, &commandBuffer));
contextVk->onImageRenderPassRead(src->getAspectFlags(), vk::ImageLayout::FragmentShaderReadOnly, contextVk->onImageRenderPassRead(src->getAspectFlags(), vk::ImageLayout::FragmentShaderReadOnly,
src); src);
......
...@@ -606,8 +606,8 @@ CommandBufferHelper::CommandBufferHelper() ...@@ -606,8 +606,8 @@ CommandBufferHelper::CommandBufferHelper()
mValidTransformFeedbackBufferCount(0), mValidTransformFeedbackBufferCount(0),
mRebindTransformFeedbackBuffers(false), mRebindTransformFeedbackBuffers(false),
mIsRenderPassCommandBuffer(false), mIsRenderPassCommandBuffer(false),
mDepthStartAccess(ResourceAccess::Unused), mDepthAccess(ResourceAccess::Unused),
mStencilStartAccess(ResourceAccess::Unused), mStencilAccess(ResourceAccess::Unused),
mDepthCmdSizeInvalidated(kInfiniteCmdSize), mDepthCmdSizeInvalidated(kInfiniteCmdSize),
mDepthCmdSizeDisabled(kInfiniteCmdSize), mDepthCmdSizeDisabled(kInfiniteCmdSize),
mStencilCmdSizeInvalidated(kInfiniteCmdSize), mStencilCmdSizeInvalidated(kInfiniteCmdSize),
...@@ -754,9 +754,7 @@ void CommandBufferHelper::imageWrite(ResourceUseList *resourceUseList, ...@@ -754,9 +754,7 @@ void CommandBufferHelper::imageWrite(ResourceUseList *resourceUseList,
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
UpdateAccess(&mDepthStartAccess, access); UpdateAccess(&mDepthAccess, access);
ASSERT((mRenderPassDesc.getDepthStencilAccess() != ResourceAccess::ReadOnly) ||
mDepthStartAccess != ResourceAccess::Write);
// 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); return onDepthStencilAccess(access, &mDepthCmdSizeInvalidated, &mDepthCmdSizeDisabled);
...@@ -765,7 +763,7 @@ bool CommandBufferHelper::onDepthAccess(ResourceAccess access) ...@@ -765,7 +763,7 @@ bool CommandBufferHelper::onDepthAccess(ResourceAccess access)
bool CommandBufferHelper::onStencilAccess(ResourceAccess access) bool 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(&mStencilStartAccess, 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); return onDepthStencilAccess(access, &mStencilCmdSizeInvalidated, &mStencilCmdSizeDisabled);
...@@ -881,15 +879,17 @@ void CommandBufferHelper::beginRenderPass(const Framebuffer &framebuffer, ...@@ -881,15 +879,17 @@ void CommandBufferHelper::beginRenderPass(const Framebuffer &framebuffer,
mCounter++; mCounter++;
} }
void CommandBufferHelper::restartRenderPassWithReadOnlyDepth(const Framebuffer &framebuffer, void CommandBufferHelper::updateStartedRenderPassWithDepthMode(const Framebuffer &framebuffer,
const RenderPassDesc &renderPassDesc) const RenderPassDesc &renderPassDesc,
bool readOnlyDepth)
{ {
ASSERT(mIsRenderPassCommandBuffer); ASSERT(mIsRenderPassCommandBuffer);
ASSERT(mRenderPassStarted); ASSERT(mRenderPassStarted);
mRenderPassDesc = renderPassDesc; mRenderPassDesc = renderPassDesc;
mAttachmentOps.setLayouts(mDepthStencilAttachmentIndex, ImageLayout::DepthStencilReadOnly, ImageLayout depthStencilLayout =
ImageLayout::DepthStencilReadOnly); readOnlyDepth ? ImageLayout::DepthStencilReadOnly : ImageLayout::DepthStencilAttachment;
mAttachmentOps.setLayouts(mDepthStencilAttachmentIndex, depthStencilLayout, depthStencilLayout);
mFramebuffer.setHandle(framebuffer.getHandle()); mFramebuffer.setHandle(framebuffer.getHandle());
// Barrier aggregation messes up with RenderPass restarting. // Barrier aggregation messes up with RenderPass restarting.
...@@ -919,13 +919,12 @@ void CommandBufferHelper::endRenderPass(ContextVk *contextVk) ...@@ -919,13 +919,12 @@ void CommandBufferHelper::endRenderPass(ContextVk *contextVk)
// 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.
if (mDepthStartAccess == ResourceAccess::Unused && if (mDepthAccess == ResourceAccess::Unused && dsOps.storeOp == VK_ATTACHMENT_STORE_OP_DONT_CARE)
dsOps.storeOp == VK_ATTACHMENT_STORE_OP_DONT_CARE)
{ {
dsOps.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; dsOps.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
} }
if (mStencilStartAccess == ResourceAccess::Unused && if (mStencilAccess == ResourceAccess::Unused &&
dsOps.stencilStoreOp == VK_ATTACHMENT_STORE_OP_DONT_CARE) dsOps.stencilStoreOp == VK_ATTACHMENT_STORE_OP_DONT_CARE)
{ {
dsOps.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; dsOps.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
...@@ -933,7 +932,7 @@ void CommandBufferHelper::endRenderPass(ContextVk *contextVk) ...@@ -933,7 +932,7 @@ void CommandBufferHelper::endRenderPass(ContextVk *contextVk)
// Ensure we don't write to a read-only RenderPass. (ReadOnly -> !Write) // Ensure we don't write to a read-only RenderPass. (ReadOnly -> !Write)
ASSERT((mRenderPassDesc.getDepthStencilAccess() != ResourceAccess::ReadOnly) || ASSERT((mRenderPassDesc.getDepthStencilAccess() != ResourceAccess::ReadOnly) ||
mDepthStartAccess != ResourceAccess::Write); mDepthAccess != ResourceAccess::Write);
// Fill out perf counters // Fill out perf counters
PerfCounters &counters = contextVk->getPerfCounters(); PerfCounters &counters = contextVk->getPerfCounters();
...@@ -944,6 +943,9 @@ void CommandBufferHelper::endRenderPass(ContextVk *contextVk) ...@@ -944,6 +943,9 @@ void CommandBufferHelper::endRenderPass(ContextVk *contextVk)
counters.stencilClears += dsOps.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_CLEAR ? 1 : 0; counters.stencilClears += dsOps.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_CLEAR ? 1 : 0;
counters.stencilLoads += dsOps.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_LOAD ? 1 : 0; counters.stencilLoads += dsOps.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_LOAD ? 1 : 0;
counters.stencilStores += dsOps.stencilStoreOp == VK_ATTACHMENT_STORE_OP_STORE ? 1 : 0; counters.stencilStores += dsOps.stencilStoreOp == VK_ATTACHMENT_STORE_OP_STORE ? 1 : 0;
counters.readOnlyDepthStencilRenderPasses +=
static_cast<ImageLayout>(dsOps.finalLayout) == vk::ImageLayout::DepthStencilReadOnly ? 1
: 0;
} }
void CommandBufferHelper::beginTransformFeedback(size_t validBufferCount, void CommandBufferHelper::beginTransformFeedback(size_t validBufferCount,
...@@ -1141,8 +1143,8 @@ void CommandBufferHelper::reset() ...@@ -1141,8 +1143,8 @@ void CommandBufferHelper::reset()
mRenderPassStarted = false; mRenderPassStarted = false;
mValidTransformFeedbackBufferCount = 0; mValidTransformFeedbackBufferCount = 0;
mRebindTransformFeedbackBuffers = false; mRebindTransformFeedbackBuffers = false;
mDepthStartAccess = ResourceAccess::Unused; mDepthAccess = ResourceAccess::Unused;
mStencilStartAccess = ResourceAccess::Unused; mStencilAccess = ResourceAccess::Unused;
mDepthCmdSizeInvalidated = kInfiniteCmdSize; mDepthCmdSizeInvalidated = kInfiniteCmdSize;
mDepthCmdSizeDisabled = kInfiniteCmdSize; mDepthCmdSizeDisabled = kInfiniteCmdSize;
mStencilCmdSizeInvalidated = kInfiniteCmdSize; mStencilCmdSizeInvalidated = kInfiniteCmdSize;
......
...@@ -981,8 +981,9 @@ class CommandBufferHelper : angle::NonCopyable ...@@ -981,8 +981,9 @@ class CommandBufferHelper : angle::NonCopyable
void endRenderPass(ContextVk *contextVk); void endRenderPass(ContextVk *contextVk);
void restartRenderPassWithReadOnlyDepth(const Framebuffer &framebuffer, void updateStartedRenderPassWithDepthMode(const Framebuffer &framebuffer,
const RenderPassDesc &renderPassDesc); const RenderPassDesc &renderPassDesc,
bool readOnlyDepth);
void beginTransformFeedback(size_t validBufferCount, void beginTransformFeedback(size_t validBufferCount,
const VkBuffer *counterBuffers, const VkBuffer *counterBuffers,
...@@ -1081,12 +1082,13 @@ class CommandBufferHelper : angle::NonCopyable ...@@ -1081,12 +1082,13 @@ class CommandBufferHelper : angle::NonCopyable
void updateRenderPassForResolve(vk::Framebuffer *newFramebuffer, void updateRenderPassForResolve(vk::Framebuffer *newFramebuffer,
const vk::RenderPassDesc &renderPassDesc); const vk::RenderPassDesc &renderPassDesc);
ResourceAccess getDepthStartAccess() const { return mDepthStartAccess; }
bool hasDepthWriteOrClear() const bool hasDepthStencilWriteOrClear() const
{ {
return mDepthStartAccess == ResourceAccess::Write || return mDepthAccess == ResourceAccess::Write || mStencilAccess == ResourceAccess::Write ||
mAttachmentOps[mDepthStencilAttachmentIndex].loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR; mAttachmentOps[mDepthStencilAttachmentIndex].loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR ||
mAttachmentOps[mDepthStencilAttachmentIndex].stencilLoadOp ==
VK_ATTACHMENT_LOAD_OP_CLEAR;
} }
private: private:
...@@ -1122,9 +1124,14 @@ class CommandBufferHelper : angle::NonCopyable ...@@ -1122,9 +1124,14 @@ class CommandBufferHelper : angle::NonCopyable
bool mIsRenderPassCommandBuffer; bool mIsRenderPassCommandBuffer;
// State tracking for whether to optimize the loadOp to DONT_CARE // State tracking for the maximum (Write been the highest) depth access during the entire
ResourceAccess mDepthStartAccess; // renderpass. Note that this does not include VK_ATTACHMENT_LOAD_OP_CLEAR which is tracked
ResourceAccess mStencilStartAccess; // separately. This is done this way to allow clear op to being optimized out when we find out
// that the depth buffer is not being used during the entire renderpass and store op is
// VK_ATTACHMENT_STORE_OP_DONTCARE.
ResourceAccess mDepthAccess;
// Similar tracking to mDepthAccess but for the stencil aspect.
ResourceAccess mStencilAccess;
// State tracking for whether to optimize the storeOp to DONT_CARE // State tracking for whether to optimize the storeOp to DONT_CARE
uint32_t mDepthCmdSizeInvalidated; uint32_t mDepthCmdSizeInvalidated;
......
...@@ -789,6 +789,7 @@ struct PerfCounters ...@@ -789,6 +789,7 @@ struct PerfCounters
uint32_t stencilClears; uint32_t stencilClears;
uint32_t stencilLoads; uint32_t stencilLoads;
uint32_t stencilStores; uint32_t stencilStores;
uint32_t readOnlyDepthStencilRenderPasses;
}; };
// A Vulkan image level index. // A Vulkan image level index.
......
...@@ -443,6 +443,7 @@ TEST_P(VulkanPerformanceCounterTest, ReadOnlyDepthStencilFeedbackLoopUsesSingleR ...@@ -443,6 +443,7 @@ TEST_P(VulkanPerformanceCounterTest, ReadOnlyDepthStencilFeedbackLoopUsesSingleR
// Draw to a first FBO to initialize the depth buffer. // Draw to a first FBO to initialize the depth buffer.
glBindFramebuffer(GL_FRAMEBUFFER, depthOnlyFBO); glBindFramebuffer(GL_FRAMEBUFFER, depthOnlyFBO);
glEnable(GL_DEPTH_TEST);
glUseProgram(redProgram); glUseProgram(redProgram);
glDrawArrays(GL_TRIANGLES, 0, 6); glDrawArrays(GL_TRIANGLES, 0, 6);
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
...@@ -451,7 +452,6 @@ TEST_P(VulkanPerformanceCounterTest, ReadOnlyDepthStencilFeedbackLoopUsesSingleR ...@@ -451,7 +452,6 @@ TEST_P(VulkanPerformanceCounterTest, ReadOnlyDepthStencilFeedbackLoopUsesSingleR
// Start new RenderPass with depth write disabled and no loop. // Start new RenderPass with depth write disabled and no loop.
glBindFramebuffer(GL_FRAMEBUFFER, depthAndColorFBO); glBindFramebuffer(GL_FRAMEBUFFER, depthAndColorFBO);
glEnable(GL_DEPTH_TEST);
glDepthMask(false); glDepthMask(false);
glDrawArrays(GL_TRIANGLES, 0, 6); glDrawArrays(GL_TRIANGLES, 0, 6);
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
...@@ -1638,6 +1638,73 @@ TEST_P(VulkanPerformanceCounterTest, RenderToTextureDepthStencilTextureShouldNot ...@@ -1638,6 +1638,73 @@ TEST_P(VulkanPerformanceCounterTest, RenderToTextureDepthStencilTextureShouldNot
EXPECT_PIXEL_COLOR_EQ(kSize / 2 - 1, kSize / 2 - 1, GLColor::red); EXPECT_PIXEL_COLOR_EQ(kSize / 2 - 1, kSize / 2 - 1, GLColor::red);
} }
// Ensures we use read-only depth layout when there is no write
TEST_P(VulkanPerformanceCounterTest, ReadOnlyDepthBufferLayout)
{
const rx::vk::PerfCounters &counters = hackANGLE();
constexpr GLsizei kSize = 64;
// Create depth only FBO and fill depth texture to leftHalf=0.0 and rightHalf=1.0. This should
// use writeable layout
uint32_t expectedReadOnlyDepthStencilCount = counters.readOnlyDepthStencilRenderPasses;
GLTexture depthTexture;
glBindTexture(GL_TEXTURE_2D, depthTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, kSize, kSize, 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 depthOnlyFBO;
glBindFramebuffer(GL_FRAMEBUFFER, depthOnlyFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_ALWAYS);
glDepthMask(GL_TRUE);
ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
glViewport(0, 0, kSize / 2, kSize);
drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.0f);
glViewport(kSize / 2, 0, kSize / 2, kSize);
drawQuad(redProgram, essl1_shaders::PositionAttrib(), 1.0f);
glViewport(0, 0, kSize, kSize);
ASSERT_GL_NO_ERROR();
// Because the layout counter is updated at end of renderpass, we need to issue a finish call
// here to end the renderpass.
glFinish();
uint32_t actualReadOnlyDepthStencilCount = counters.readOnlyDepthStencilRenderPasses;
EXPECT_EQ(expectedReadOnlyDepthStencilCount, actualReadOnlyDepthStencilCount);
// Create a color+depth FBO and use depth as read only. This should use read only layout
expectedReadOnlyDepthStencilCount = counters.readOnlyDepthStencilRenderPasses + 1;
GLTexture colorTexture;
glBindTexture(GL_TEXTURE_2D, colorTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
GLFramebuffer depthAndColorFBO;
glBindFramebuffer(GL_FRAMEBUFFER, depthAndColorFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
// Clear color to blue and draw a green quad with depth=0.5
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glDepthMask(GL_FALSE);
GLfloat *clearColor = GLColor::blue.toNormalizedVector().data();
glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
glClear(GL_COLOR_BUFFER_BIT);
drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.5f);
ASSERT_GL_NO_ERROR();
// The pixel check will end renderpass.
EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::blue);
EXPECT_PIXEL_COLOR_EQ(1 + kSize / 2, 1, GLColor::red);
actualReadOnlyDepthStencilCount = counters.readOnlyDepthStencilRenderPasses;
EXPECT_EQ(expectedReadOnlyDepthStencilCount, actualReadOnlyDepthStencilCount);
}
ANGLE_INSTANTIATE_TEST(VulkanPerformanceCounterTest, ES3_VULKAN()); ANGLE_INSTANTIATE_TEST(VulkanPerformanceCounterTest, ES3_VULKAN());
ANGLE_INSTANTIATE_TEST(VulkanPerformanceCounterTest_ES31, ES31_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