Commit e689d316 by Jamie Madill Committed by Commit Bot

Vulkan: Don't end RenderPass on DS feedback loops.

Instead of always switching the Framebuffer to mask out depth/stencil loops we now switch the RenderPass to a "read-only" depth/stencil mode. Reduces the RenderPass count in Manhattan from 18->15. There are still a couple extra RenderPasses inserted that we can get rid. We can merge a few RenderPasses by retroactively changing a started RenderPass to "read-only" when there are no prior recorded depth writes or clears. Also adds a test to count the number of RenderPasses ANGLE generates in DS feedback loop situaions. Bug: angleproject:4959 Change-Id: I1855a45959655fc27ccd47a3469c1c672fc8fd9e Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2357973 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCharlie Lao <cclao@google.com> Reviewed-by: 's avatarTim Van Patten <timvp@google.com>
parent c060d8d6
...@@ -168,6 +168,7 @@ class State : angle::NonCopyable ...@@ -168,6 +168,7 @@ class State : angle::NonCopyable
// Depth test state manipulation // Depth test state manipulation
bool isDepthTestEnabled() const { return mDepthStencil.depthTest; } bool isDepthTestEnabled() const { return mDepthStencil.depthTest; }
bool isDepthWriteEnabled() const { return mDepthStencil.depthTest && mDepthStencil.depthMask; }
void setDepthTest(bool enabled); void setDepthTest(bool enabled);
void setDepthFunc(GLenum depthFunc); void setDepthFunc(GLenum depthFunc);
void setDepthRange(float zNear, float zFar); void setDepthRange(float zNear, float zFar);
......
...@@ -572,6 +572,11 @@ class Texture final : public RefCountObject<TextureID>, ...@@ -572,6 +572,11 @@ class Texture final : public RefCountObject<TextureID>,
return false; return false;
} }
bool isDepthOrStencil() const
{
return mState.getBaseLevelDesc().format.info->isDepthOrStencil();
}
enum DirtyBitType enum DirtyBitType
{ {
// Sampler state // Sampler state
......
...@@ -1384,6 +1384,15 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl( ...@@ -1384,6 +1384,15 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl(
textureLayout = executable->isCompute() ? vk::ImageLayout::ComputeShaderWrite textureLayout = executable->isCompute() ? vk::ImageLayout::ComputeShaderWrite
: vk::ImageLayout::AllGraphicsShadersWrite; : vk::ImageLayout::AllGraphicsShadersWrite;
} }
else if (image.isDepthOrStencil())
{
// We always use a depth-stencil read-only layout for any depth Textures to simplify our
// implementation's handling of depth-stencil read-only mode. We don't have to split a
// RenderPass to transition a depth texture from shader-read to read-only. This improves
// performance in Manhattan. Future optimizations are likely possible here including
// using specialized barriers without breaking the RenderPass.
textureLayout = vk::ImageLayout::DepthStencilReadOnly;
}
else else
{ {
gl::ShaderBitSet remainingShaderBits = gl::ShaderBitSet remainingShaderBits =
...@@ -2864,11 +2873,7 @@ angle::Result ContextVk::syncState(const gl::Context *context, ...@@ -2864,11 +2873,7 @@ angle::Result ContextVk::syncState(const gl::Context *context,
mGraphicsPipelineDesc->updateDepthTestEnabled(&mGraphicsPipelineTransition, mGraphicsPipelineDesc->updateDepthTestEnabled(&mGraphicsPipelineTransition,
glState.getDepthStencilState(), glState.getDepthStencilState(),
glState.getDrawFramebuffer()); glState.getDrawFramebuffer());
if (mState.isDepthTestEnabled() && mRenderPassCommands->started()) ANGLE_TRY(updateRenderPassDepthAccess());
{
vk::ResourceAccess access = GetDepthAccess(mState.getDepthStencilState());
mRenderPassCommands->onDepthAccess(access);
}
break; break;
} }
case gl::State::DIRTY_BIT_DEPTH_FUNC: case gl::State::DIRTY_BIT_DEPTH_FUNC:
...@@ -2880,11 +2885,7 @@ angle::Result ContextVk::syncState(const gl::Context *context, ...@@ -2880,11 +2885,7 @@ angle::Result ContextVk::syncState(const gl::Context *context,
mGraphicsPipelineDesc->updateDepthWriteEnabled(&mGraphicsPipelineTransition, mGraphicsPipelineDesc->updateDepthWriteEnabled(&mGraphicsPipelineTransition,
glState.getDepthStencilState(), glState.getDepthStencilState(),
glState.getDrawFramebuffer()); glState.getDrawFramebuffer());
if (mState.isDepthTestEnabled() && mRenderPassCommands->started()) ANGLE_TRY(updateRenderPassDepthAccess());
{
vk::ResourceAccess access = GetDepthAccess(mState.getDepthStencilState());
mRenderPassCommands->onDepthAccess(access);
}
break; break;
} }
case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED: case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED:
...@@ -3867,15 +3868,14 @@ void ContextVk::handleError(VkResult errorCode, ...@@ -3867,15 +3868,14 @@ void ContextVk::handleError(VkResult errorCode,
angle::Result ContextVk::updateActiveTextures(const gl::Context *context) angle::Result ContextVk::updateActiveTextures(const gl::Context *context)
{ {
const gl::State &glState = mState; const gl::ProgramExecutable *executable = mState.getProgramExecutable();
const gl::ProgramExecutable *executable = glState.getProgramExecutable();
ASSERT(executable); ASSERT(executable);
uint32_t prevMaxIndex = mActiveTexturesDesc.getMaxIndex(); uint32_t prevMaxIndex = mActiveTexturesDesc.getMaxIndex();
memset(mActiveTextures.data(), 0, sizeof(mActiveTextures[0]) * prevMaxIndex); memset(mActiveTextures.data(), 0, sizeof(mActiveTextures[0]) * prevMaxIndex);
mActiveTexturesDesc.reset(); mActiveTexturesDesc.reset();
const gl::ActiveTexturesCache &textures = glState.getActiveTexturesCache(); const gl::ActiveTexturesCache &textures = mState.getActiveTexturesCache();
const gl::ActiveTextureMask &activeTextures = executable->getActiveSamplersMask(); const gl::ActiveTextureMask &activeTextures = executable->getActiveSamplersMask();
const gl::ActiveTextureTypeArray &textureTypes = executable->getActiveSamplerTypes(); const gl::ActiveTextureTypeArray &textureTypes = executable->getActiveSamplerTypes();
...@@ -3887,11 +3887,32 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context) ...@@ -3887,11 +3887,32 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context)
gl::TextureType textureType = textureTypes[textureUnit]; gl::TextureType textureType = textureTypes[textureUnit];
ASSERT(textureType != gl::TextureType::InvalidEnum); ASSERT(textureType != gl::TextureType::InvalidEnum);
vk::TextureUnit &activeTexture = mActiveTextures[textureUnit];
// Null textures represent incomplete textures. // Null textures represent incomplete textures.
if (texture == nullptr) if (texture == nullptr)
{ {
ANGLE_TRY(getIncompleteTexture(context, textureType, &texture)); ANGLE_TRY(getIncompleteTexture(context, textureType, &texture));
} }
else if (shouldSwitchToDepthReadOnlyMode(context, texture))
{
ASSERT(!mState.isDepthWriteEnabled());
// Special handling for deferred clears.
if (mDrawFramebuffer->hasDeferredClears())
{
gl::Rectangle scissoredRenderArea =
mDrawFramebuffer->getRotatedScissoredRenderArea(this);
ANGLE_TRY(mDrawFramebuffer->flushDeferredClears(this, scissoredRenderArea));
}
// TODO(jmadill): Don't end RenderPass. http://anglebug.com/4959
if (hasStartedRenderPass())
{
ANGLE_TRY(flushCommandsAndEndRenderPass());
}
mDrawFramebuffer->setReadOnlyDepthMode(true);
}
TextureVk *textureVk = vk::GetImpl(texture); TextureVk *textureVk = vk::GetImpl(texture);
ASSERT(textureVk != nullptr); ASSERT(textureVk != nullptr);
...@@ -3899,8 +3920,8 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context) ...@@ -3899,8 +3920,8 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context)
const vk::SamplerHelper &samplerVk = const vk::SamplerHelper &samplerVk =
sampler ? vk::GetImpl(sampler)->getSampler() : textureVk->getSampler(); sampler ? vk::GetImpl(sampler)->getSampler() : textureVk->getSampler();
mActiveTextures[textureUnit].texture = textureVk; activeTexture.texture = textureVk;
mActiveTextures[textureUnit].sampler = &samplerVk; activeTexture.sampler = &samplerVk;
vk::ImageViewSubresourceSerial imageViewSerial = textureVk->getImageViewSubresourceSerial(); vk::ImageViewSubresourceSerial imageViewSerial = textureVk->getImageViewSubresourceSerial();
mActiveTexturesDesc.update(textureUnit, imageViewSerial, samplerVk.getSamplerSerial()); mActiveTexturesDesc.update(textureUnit, imageViewSerial, samplerVk.getSamplerSerial());
...@@ -4823,4 +4844,41 @@ void ContextVk::setDefaultUniformBlocksMinSizeForTesting(size_t minSize) ...@@ -4823,4 +4844,41 @@ void ContextVk::setDefaultUniformBlocksMinSizeForTesting(size_t minSize)
mDefaultUniformStorage.setMinimumSizeForTesting(minSize); mDefaultUniformStorage.setMinimumSizeForTesting(minSize);
} }
angle::Result ContextVk::updateRenderPassDepthAccess()
{
if (mState.isDepthTestEnabled() && mRenderPassCommands->started())
{
vk::ResourceAccess access = GetDepthAccess(mState.getDepthStencilState());
if (access == vk::ResourceAccess::Write && mDrawFramebuffer->isReadOnlyDepthMode())
{
ANGLE_TRY(flushCommandsAndEndRenderPass());
// Clear read-only depth mode.
mDrawFramebuffer->setReadOnlyDepthMode(false);
}
else
{
mRenderPassCommands->onDepthAccess(access);
}
}
return angle::Result::Continue;
}
bool ContextVk::shouldSwitchToDepthReadOnlyMode(const gl::Context *context,
gl::Texture *texture) const
{
const gl::ProgramExecutable *programExecutable = mState.getProgramExecutable();
// When running compute we don't have a draw FBO.
if (programExecutable->isCompute())
{
return false;
}
return texture->isDepthOrStencil() &&
texture->isBoundToFramebuffer(mDrawFramebuffer->getState().getFramebufferSerial()) &&
!mDrawFramebuffer->isReadOnlyDepthMode();
}
} // namespace rx } // namespace rx
...@@ -926,6 +926,8 @@ class ContextVk : public ContextImpl, public vk::Context ...@@ -926,6 +926,8 @@ 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();
bool shouldSwitchToDepthReadOnlyMode(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;
......
...@@ -1735,12 +1735,21 @@ angle::Result FramebufferVk::syncState(const gl::Context *context, ...@@ -1735,12 +1735,21 @@ angle::Result FramebufferVk::syncState(const gl::Context *context,
ANGLE_TRY(flushDeferredClears(contextVk, rotatedScissoredRenderArea)); ANGLE_TRY(flushDeferredClears(contextVk, rotatedScissoredRenderArea));
} }
// We cannot use read-only depth mode for clears.
if (mDeferredClears.any())
{
mCurrentFramebufferDesc.updateReadOnlyDepth(false);
}
// No-op redundant changes to prevent closing the RenderPass. // No-op redundant changes to prevent closing the RenderPass.
if (mCurrentFramebufferDesc == priorFramebufferDesc) if (mCurrentFramebufferDesc == priorFramebufferDesc)
{ {
return angle::Result::Continue; return angle::Result::Continue;
} }
// Default to writable depth on any Framebuffer change.
mCurrentFramebufferDesc.updateReadOnlyDepth(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));
...@@ -1808,9 +1817,12 @@ void FramebufferVk::updateRenderPassDesc() ...@@ -1808,9 +1817,12 @@ void FramebufferVk::updateRenderPassDesc()
RenderTargetVk *depthStencilRenderTarget = getDepthStencilRenderTarget(); RenderTargetVk *depthStencilRenderTarget = getDepthStencilRenderTarget();
if (depthStencilRenderTarget) if (depthStencilRenderTarget)
{ {
vk::ResourceAccess dsAccess =
isReadOnlyDepthMode() ? vk::ResourceAccess::ReadOnly : vk::ResourceAccess::Write;
mRenderPassDesc.packDepthStencilAttachment( mRenderPassDesc.packDepthStencilAttachment(
depthStencilRenderTarget->getImageForRenderPass().getFormat().intendedFormatID, depthStencilRenderTarget->getImageForRenderPass().getFormat().intendedFormatID,
vk::ResourceAccess::Write); dsAccess);
} }
} }
...@@ -2299,9 +2311,10 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk, ...@@ -2299,9 +2311,10 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
} }
renderPassAttachmentOps.setLayouts(depthStencilAttachmentIndex, vk::ImageLayout dsLayout = isReadOnlyDepthMode() ? vk::ImageLayout::DepthStencilReadOnly
vk::ImageLayout::DepthStencilAttachment, : vk::ImageLayout::DepthStencilAttachment;
vk::ImageLayout::DepthStencilAttachment);
renderPassAttachmentOps.setLayouts(depthStencilAttachmentIndex, dsLayout, dsLayout);
if (mDeferredClears.testDepth() || mDeferredClears.testStencil()) if (mDeferredClears.testDepth() || mDeferredClears.testStencil())
{ {
...@@ -2368,7 +2381,7 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk, ...@@ -2368,7 +2381,7 @@ 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); depthStencilRenderTarget->onDepthStencilDraw(contextVk, isReadOnlyDepthMode());
} }
return angle::Result::Continue; return angle::Result::Continue;
...@@ -2480,4 +2493,14 @@ angle::Result FramebufferVk::flushDeferredClears(ContextVk *contextVk, ...@@ -2480,4 +2493,14 @@ angle::Result FramebufferVk::flushDeferredClears(ContextVk *contextVk,
return contextVk->startRenderPass(renderArea, nullptr); return contextVk->startRenderPass(renderArea, nullptr);
} }
void FramebufferVk::setReadOnlyDepthMode(bool readOnlyDepthEnabled)
{
if (isReadOnlyDepthMode() != readOnlyDepthEnabled)
{
mCurrentFramebufferDesc.updateReadOnlyDepth(readOnlyDepthEnabled);
mFramebuffer = nullptr;
updateRenderPassDesc();
}
}
} // namespace rx } // namespace rx
...@@ -134,6 +134,12 @@ class FramebufferVk : public FramebufferImpl ...@@ -134,6 +134,12 @@ class FramebufferVk : public FramebufferImpl
vk::Framebuffer **framebufferOut, vk::Framebuffer **framebufferOut,
const vk::ImageView *resolveImageViewIn); const vk::ImageView *resolveImageViewIn);
bool isReadOnlyDepthMode() const { return mCurrentFramebufferDesc.isReadOnlyDepth(); }
bool hasDeferredClears() const { return !mDeferredClears.empty(); }
angle::Result flushDeferredClears(ContextVk *contextVk, const gl::Rectangle &renderArea);
void setReadOnlyDepthMode(bool readOnlyDepthEnabled);
private: private:
FramebufferVk(RendererVk *renderer, FramebufferVk(RendererVk *renderer,
const gl::FramebufferState &state, const gl::FramebufferState &state,
...@@ -221,7 +227,6 @@ class FramebufferVk : public FramebufferImpl ...@@ -221,7 +227,6 @@ class FramebufferVk : public FramebufferImpl
RenderTargetVk *getReadPixelsRenderTarget(GLenum format) const; RenderTargetVk *getReadPixelsRenderTarget(GLenum format) const;
VkImageAspectFlagBits getReadPixelsAspectFlags(GLenum format) const; VkImageAspectFlagBits getReadPixelsAspectFlags(GLenum format) const;
angle::Result flushDeferredClears(ContextVk *contextVk, const gl::Rectangle &renderArea);
VkClearValue getCorrectedColorClearValue(size_t colorIndexGL, VkClearValue getCorrectedColorClearValue(size_t colorIndexGL,
const VkClearColorValue &clearColor) const; const VkClearColorValue &clearColor) const;
......
...@@ -107,19 +107,29 @@ void RenderTargetVk::onColorDraw(ContextVk *contextVk) ...@@ -107,19 +107,29 @@ void RenderTargetVk::onColorDraw(ContextVk *contextVk)
mContentDefined = true; mContentDefined = true;
} }
void RenderTargetVk::onDepthStencilDraw(ContextVk *contextVk) void RenderTargetVk::onDepthStencilDraw(ContextVk *contextVk, bool isReadOnly)
{ {
ASSERT(mImage->getFormat().actualImageFormat().hasDepthOrStencilBits()); const angle::Format &format = mImage->getFormat().actualImageFormat();
ASSERT(format.hasDepthOrStencilBits());
const angle::Format &format = mImage->getFormat().actualImageFormat();
VkImageAspectFlags aspectFlags = vk::GetDepthStencilAspectFlags(format); VkImageAspectFlags aspectFlags = vk::GetDepthStencilAspectFlags(format);
contextVk->onImageRenderPassWrite(aspectFlags, vk::ImageLayout::DepthStencilAttachment, mImage); if (isReadOnly)
if (mResolveImage) {
ASSERT(!mResolveImage);
contextVk->onImageRenderPassRead(aspectFlags, vk::ImageLayout::DepthStencilReadOnly,
mImage);
}
else
{ {
contextVk->onImageRenderPassWrite(aspectFlags, vk::ImageLayout::DepthStencilAttachment, contextVk->onImageRenderPassWrite(aspectFlags, vk::ImageLayout::DepthStencilAttachment,
mResolveImage); mImage);
if (mResolveImage)
{
contextVk->onImageRenderPassWrite(aspectFlags, vk::ImageLayout::DepthStencilAttachment,
mResolveImage);
}
} }
retainImageViews(contextVk); retainImageViews(contextVk);
mContentDefined = true; mContentDefined = true;
......
...@@ -56,7 +56,7 @@ class RenderTargetVk final : public FramebufferAttachmentRenderTarget ...@@ -56,7 +56,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); void onDepthStencilDraw(ContextVk *contextVk, bool isReadOnly);
vk::ImageHelper &getImageForRenderPass(); vk::ImageHelper &getImageForRenderPass();
const vk::ImageHelper &getImageForRenderPass() const; const vk::ImageHelper &getImageForRenderPass() const;
......
...@@ -138,6 +138,9 @@ constexpr const char *kSkippedMessages[] = { ...@@ -138,6 +138,9 @@ constexpr const char *kSkippedMessages[] = {
// https://issuetracker.google.com/issues/159493191 // https://issuetracker.google.com/issues/159493191
"VUID-vkCmdDraw-None-02690", "VUID-vkCmdDraw-None-02690",
"VUID-vkCmdDrawIndexed-None-02690", "VUID-vkCmdDrawIndexed-None-02690",
// http://anglebug.com/4975
"VUID-vkCmdDraw-None-02687",
"VUID-vkCmdDrawIndexed-None-02687",
// Best Practices Skips issuetracker.google.com/156661359 // Best Practices Skips issuetracker.google.com/156661359
"UNASSIGNED-BestPractices-vkCreateCommandPool-command-buffer-reset", "UNASSIGNED-BestPractices-vkCreateCommandPool-command-buffer-reset",
"UNASSIGNED-BestPractices-pipeline-stage-flags", "UNASSIGNED-BestPractices-pipeline-stage-flags",
...@@ -1819,7 +1822,7 @@ void RendererVk::initFeatures(DisplayVk *displayVk, const ExtensionNameList &dev ...@@ -1819,7 +1822,7 @@ void RendererVk::initFeatures(DisplayVk *displayVk, const ExtensionNameList &dev
// Currently disabled by default: http://anglebug.com/3078 // Currently disabled by default: http://anglebug.com/3078
ANGLE_FEATURE_CONDITION(&mFeatures, enablePrecisionQualifiers, false); ANGLE_FEATURE_CONDITION(&mFeatures, enablePrecisionQualifiers, false);
ANGLE_FEATURE_CONDITION(&mFeatures, supportDepthStencilRenderingFeedbackLoops, true); ANGLE_FEATURE_CONDITION(&mFeatures, supportDepthStencilRenderingFeedbackLoops, false);
ANGLE_FEATURE_CONDITION(&mFeatures, preferAggregateBarrierCalls, isNvidia || isAMD || isIntel); ANGLE_FEATURE_CONDITION(&mFeatures, preferAggregateBarrierCalls, isNvidia || isAMD || isIntel);
......
...@@ -939,6 +939,7 @@ class FramebufferDesc ...@@ -939,6 +939,7 @@ class FramebufferDesc
bool operator==(const FramebufferDesc &other) const; bool operator==(const FramebufferDesc &other) const;
uint32_t attachmentCount() const; uint32_t attachmentCount() const;
bool isReadOnlyDepth() const { return mReadOnlyDepth != 0; }
ImageViewSubresourceSerial getColorImageViewSerial(uint32_t index) ImageViewSubresourceSerial getColorImageViewSerial(uint32_t index)
{ {
......
...@@ -3236,6 +3236,11 @@ gl::Extents ImageHelper::getLevelExtents2D(uint32_t levelVK) const ...@@ -3236,6 +3236,11 @@ gl::Extents ImageHelper::getLevelExtents2D(uint32_t levelVK) const
return extents; return extents;
} }
bool ImageHelper::isDepthOrStencil() const
{
return mFormat->actualImageFormat().hasDepthOrStencilBits();
}
bool ImageHelper::isReadBarrierNecessary(ImageLayout newLayout) const bool ImageHelper::isReadBarrierNecessary(ImageLayout newLayout) const
{ {
// If transitioning to a different layout, we need always need a barrier. // If transitioning to a different layout, we need always need a barrier.
......
...@@ -981,7 +981,13 @@ class CommandBufferHelper : angle::NonCopyable ...@@ -981,7 +981,13 @@ 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;
void onDepthAccess(ResourceAccess access) { UpdateAccess(&mDepthStartAccess, access); } void onDepthAccess(ResourceAccess access)
{
UpdateAccess(&mDepthStartAccess, access);
ASSERT((mRenderPassDesc.getDepthStencilAccess() != ResourceAccess::ReadOnly) ||
mDepthStartAccess != ResourceAccess::Write);
}
void onStencilAccess(ResourceAccess access) { UpdateAccess(&mStencilStartAccess, access); } void onStencilAccess(ResourceAccess access) { UpdateAccess(&mStencilStartAccess, access); }
void updateRenderPassForResolve(vk::Framebuffer *newFramebuffer, void updateRenderPassForResolve(vk::Framebuffer *newFramebuffer,
...@@ -1218,6 +1224,7 @@ class ImageHelper final : public Resource, public angle::Subject ...@@ -1218,6 +1224,7 @@ class ImageHelper final : public Resource, public angle::Subject
// Helper function to calculate the extents of a render target created for a certain mip of the // Helper function to calculate the extents of a render target created for a certain mip of the
// image. // image.
gl::Extents getLevelExtents2D(uint32_t level) const; gl::Extents getLevelExtents2D(uint32_t level) const;
bool isDepthOrStencil() const;
// Clear either color or depth/stencil based on image format. // Clear either color or depth/stencil based on image format.
void clear(VkImageAspectFlags aspectFlags, void clear(VkImageAspectFlags aspectFlags,
......
...@@ -681,6 +681,7 @@ class ClearValuesArray final ...@@ -681,6 +681,7 @@ class ClearValuesArray final
const VkClearValue *data() const { return mValues.data(); } const VkClearValue *data() const { return mValues.data(); }
bool empty() const { return mEnabled.none(); } bool empty() const { return mEnabled.none(); }
bool any() const { return mEnabled.any(); }
gl::DrawBufferMask getEnabledColorAttachmentsMask() const gl::DrawBufferMask getEnabledColorAttachmentsMask() const
{ {
......
...@@ -1655,9 +1655,8 @@ TEST_P(FramebufferTest_ES3, AttachmentStateChange) ...@@ -1655,9 +1655,8 @@ TEST_P(FramebufferTest_ES3, AttachmentStateChange)
} }
// Tests that we can support a feedback loop between a depth textures and the depth buffer. // Tests that we can support a feedback loop between a depth textures and the depth buffer.
// Does not totally mirror the case used in Manhattan. The Manhattan case seems to handle // The test emulates the read-only feedback loop in Manhattan.
// "clear" specially instead of rendering to depth in the same RP. TEST_P(FramebufferTest_ES3, ReadOnlyDepthFeedbackLoopSupported)
TEST_P(FramebufferTest_ES3, DepthFeedbackLoopSupported)
{ {
// Feedback loops not supported on D3D11 and may not ever be. // Feedback loops not supported on D3D11 and may not ever be.
ANGLE_SKIP_TEST_IF(IsD3D11()); ANGLE_SKIP_TEST_IF(IsD3D11());
...@@ -1711,9 +1710,10 @@ void main() ...@@ -1711,9 +1710,10 @@ void main()
glClearDepthf(0.5f); glClearDepthf(0.5f);
glClear(GL_DEPTH_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT);
// Disable the depth mask. Although this does not remove the feedback loop as defined by the // Disable depth. Although this does not remove the feedback loop as defined by the
// spec it mimics what gfxbench does in its rendering tests. // spec it mimics what gfxbench does in its rendering tests.
glDepthMask(false); glDepthMask(false);
glDisable(GL_DEPTH_TEST);
// Verify we can sample the depth texture and get 0.5. // Verify we can sample the depth texture and get 0.5.
drawQuad(program, essl1_shaders::PositionAttrib(), 0.5); drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
......
...@@ -317,6 +317,95 @@ TEST_P(VulkanPerformanceCounterTest_ES31, MultisampleResolveWithBlit) ...@@ -317,6 +317,95 @@ TEST_P(VulkanPerformanceCounterTest_ES31, MultisampleResolveWithBlit)
EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 239, 239, 0, 255, 1.0); // Yellow EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 239, 239, 0, 255, 1.0); // Yellow
} }
// Ensures a read-only depth-stencil feedback loop works in a single RenderPass.
TEST_P(VulkanPerformanceCounterTest, ReadOnlyDepthStencilFeedbackLoopUsesSingleRenderPass)
{
const rx::vk::PerfCounters &counters = hackANGLE();
constexpr GLsizei kSize = 4;
ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
ANGLE_GL_PROGRAM(texProgram, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
GLTexture colorTexture;
glBindTexture(GL_TEXTURE_2D, colorTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
setupQuadVertexBuffer(0.5f, 1.0f);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
// Set up a depth texture and fill it with an arbitrary initial value.
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);
glBindTexture(GL_TEXTURE_2D, 0);
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);
GLFramebuffer depthOnlyFBO;
glBindFramebuffer(GL_FRAMEBUFFER, depthOnlyFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
// Draw to a first FBO to initialize the depth buffer.
glBindFramebuffer(GL_FRAMEBUFFER, depthOnlyFBO);
glUseProgram(redProgram);
glDrawArrays(GL_TRIANGLES, 0, 6);
ASSERT_GL_NO_ERROR();
// TODO(jmadill): Remove extra RenderPass. http://anglebug.com/4959
uint32_t expectedRenderPassCount = counters.renderPasses + 2;
// Start new RenderPass with depth write disabled and no loop.
glBindFramebuffer(GL_FRAMEBUFFER, depthAndColorFBO);
glEnable(GL_DEPTH_TEST);
glDepthMask(false);
glDrawArrays(GL_TRIANGLES, 0, 6);
ASSERT_GL_NO_ERROR();
// Now set up the read-only feedback loop.
glBindTexture(GL_TEXTURE_2D, depthTexture);
glUseProgram(texProgram);
glDrawArrays(GL_TRIANGLES, 0, 6);
ASSERT_GL_NO_ERROR();
// Tweak the bits to keep it read-only.
glEnable(GL_DEPTH_TEST);
glDrawArrays(GL_TRIANGLES, 0, 6);
ASSERT_GL_NO_ERROR();
// Render with just the depth attachment.
glUseProgram(redProgram);
glBindTexture(GL_TEXTURE_2D, 0);
glDrawArrays(GL_TRIANGLES, 0, 6);
ASSERT_GL_NO_ERROR();
// Rebind the depth texture.
glUseProgram(texProgram);
glDepthMask(GL_FALSE);
glEnable(GL_DEPTH_TEST);
glBindTexture(GL_TEXTURE_2D, depthTexture);
glDrawArrays(GL_TRIANGLES, 0, 6);
ASSERT_GL_NO_ERROR();
uint32_t actualRenderPassCount = counters.renderPasses;
EXPECT_EQ(expectedRenderPassCount, actualRenderPassCount);
// Do a final write to depth to make sure we can switch out of read-only mode.
glBindTexture(GL_TEXTURE_2D, 0);
glDepthMask(GL_TRUE);
glDrawArrays(GL_TRIANGLES, 0, 6);
ASSERT_GL_NO_ERROR();
}
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