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,
mGraphicsPipelineDesc->updateDepthTestEnabled(&mGraphicsPipelineTransition,
glState.getDepthStencilState(),
glState.getDrawFramebuffer());
ANGLE_TRY(updateRenderPassDepthAccess());
ANGLE_TRY(updateRenderPassDepthStencilAccess());
break;
}
case gl::State::DIRTY_BIT_DEPTH_FUNC:
......@@ -2931,23 +2931,17 @@ angle::Result ContextVk::syncState(const gl::Context *context,
mGraphicsPipelineDesc->updateDepthWriteEnabled(&mGraphicsPipelineTransition,
glState.getDepthStencilState(),
glState.getDrawFramebuffer());
ANGLE_TRY(updateRenderPassDepthAccess());
ANGLE_TRY(updateRenderPassDepthStencilAccess());
break;
}
case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED:
{
mGraphicsPipelineDesc->updateStencilTestEnabled(&mGraphicsPipelineTransition,
glState.getDepthStencilState(),
glState.getDrawFramebuffer());
if (mRenderPassCommands->started())
{
vk::ResourceAccess access = GetStencilAccess(mState.getDepthStencilState());
if (mRenderPassCommands->onStencilAccess(access))
{
// The attachment is no longer invalidated, so set mContentDefined to true
mDrawFramebuffer->restoreDepthStencilDefinedContents();
}
}
ANGLE_TRY(updateRenderPassDepthStencilAccess());
break;
}
case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT:
mGraphicsPipelineDesc->updateStencilFrontFuncs(&mGraphicsPipelineTransition,
glState.getStencilRef(),
......@@ -3049,7 +3043,7 @@ angle::Result ContextVk::syncState(const gl::Context *context,
gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
mDrawFramebuffer = vk::GetImpl(drawFramebuffer);
mDrawFramebuffer->setReadOnlyDepthMode(false);
mDrawFramebuffer->setReadOnlyDepthFeedbackLoopMode(false);
updateFlipViewportDrawFramebuffer(glState);
updateSurfaceRotationDrawFramebuffer(glState);
updateViewport(mDrawFramebuffer, glState.getViewport(), glState.getNearPlane(),
......@@ -4013,7 +4007,7 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context)
{
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
// 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)
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());
}
else
{
ANGLE_TRY(mDrawFramebuffer->restartRenderPassInReadOnlyDepthMode(
ANGLE_TRY(mDrawFramebuffer->updateRenderPassReadOnlyDepthMode(
this, mRenderPassCommands));
}
}
mDrawFramebuffer->setReadOnlyDepthMode(true);
mDrawFramebuffer->setReadOnlyDepthFeedbackLoopMode(true);
}
TextureVk *textureVk = vk::GetImpl(texture);
......@@ -4623,13 +4619,22 @@ angle::Result ContextVk::startRenderPass(gl::Rectangle renderArea,
vk::CommandBuffer **commandBufferOut)
{
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());
const gl::DepthStencilState &dsState = mState.getDepthStencilState();
mRenderPassCommands->onDepthAccess(GetDepthAccess(dsState));
mRenderPassCommands->onStencilAccess(GetStencilAccess(dsState));
mRenderPassCommands->onDepthAccess(depthAccess);
mRenderPassCommands->onStencilAccess(stencilAccess);
if (commandBufferOut)
{
......@@ -5026,34 +5031,49 @@ void ContextVk::setDefaultUniformBlocksMinSizeForTesting(size_t 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());
// Clear read-only depth mode.
mDrawFramebuffer->setReadOnlyDepthMode(false);
// Clear read-only depth feedback mode.
mDrawFramebuffer->setReadOnlyDepthFeedbackLoopMode(false);
}
else
{
if (mRenderPassCommands->onDepthAccess(access))
if (mRenderPassCommands->onDepthAccess(depthAccess))
{
// The attachment is no longer invalidated, so set mContentDefined to true
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;
}
bool ContextVk::shouldSwitchToDepthReadOnlyMode(const gl::Context *context,
gl::Texture *texture) const
bool ContextVk::shouldSwitchToReadOnlyDepthFeedbackLoopMode(const gl::Context *context,
gl::Texture *texture) const
{
const gl::ProgramExecutable *programExecutable = mState.getProgramExecutable();
......@@ -5065,6 +5085,6 @@ bool ContextVk::shouldSwitchToDepthReadOnlyMode(const gl::Context *context,
return texture->isDepthOrStencil() &&
texture->isBoundToFramebuffer(mDrawFramebuffer->getState().getFramebufferSerial()) &&
!mDrawFramebuffer->isReadOnlyDepthMode();
!mDrawFramebuffer->isReadOnlyDepthFeedbackLoopMode();
}
} // namespace rx
......@@ -936,8 +936,9 @@ class ContextVk : public ContextImpl, public vk::Context
void growDesciptorCapacity(std::vector<T> *descriptorVector, size_t newSize);
angle::Result updateScissorImpl(const gl::State &glState, bool shouldEndRenderPass);
angle::Result updateRenderPassDepthAccess();
bool shouldSwitchToDepthReadOnlyMode(const gl::Context *context, gl::Texture *texture) const;
angle::Result updateRenderPassDepthStencilAccess();
bool shouldSwitchToReadOnlyDepthFeedbackLoopMode(const gl::Context *context,
gl::Texture *texture) const;
std::array<DirtyBitHandler, DIRTY_BIT_MAX> mGraphicsDirtyBitHandlers;
std::array<DirtyBitHandler, DIRTY_BIT_MAX> mComputeDirtyBitHandlers;
......
......@@ -116,6 +116,7 @@ class FramebufferVk : public FramebufferImpl
RenderTargetVk *getColorReadRenderTarget() const;
angle::Result startNewRenderPass(ContextVk *contextVk,
bool readOnlyDepthMode,
const gl::Rectangle &renderArea,
vk::CommandBuffer **commandBufferOut);
void restoreDepthStencilDefinedContents();
......@@ -133,9 +134,13 @@ class FramebufferVk : public FramebufferImpl
bool hasDeferredClears() const { return !mDeferredClears.empty(); }
angle::Result flushDeferredClears(ContextVk *contextVk, const gl::Rectangle &renderArea);
void setReadOnlyDepthMode(bool readOnlyDepthEnabled);
angle::Result restartRenderPassInReadOnlyDepthMode(ContextVk *contextVk,
vk::CommandBufferHelper *renderPass);
void setReadOnlyDepthFeedbackLoopMode(bool readOnlyDepthFeedbackModeEnabled)
{
mReadOnlyDepthFeedbackLoopMode = readOnlyDepthFeedbackModeEnabled;
}
bool isReadOnlyDepthFeedbackLoopMode() const { return mReadOnlyDepthFeedbackLoopMode; }
angle::Result updateRenderPassReadOnlyDepthMode(ContextVk *contextVk,
vk::CommandBufferHelper *renderPass);
private:
FramebufferVk(RendererVk *renderer,
......@@ -189,19 +194,20 @@ class FramebufferVk : public FramebufferImpl
uint8_t stencilMask,
const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue);
void clearWithLoadOp(ContextVk *contextVk,
gl::DrawBufferMask clearColorBuffers,
bool clearDepth,
bool clearStencil,
const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue);
void clearWithCommand(vk::CommandBuffer *renderPassCommandBuffer,
const gl::Rectangle &scissoredRenderArea,
gl::DrawBufferMask clearColorBuffers,
bool clearDepth,
bool clearStencil,
const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue);
angle::Result clearWithLoadOp(ContextVk *contextVk,
gl::DrawBufferMask clearColorBuffers,
bool clearDepth,
bool clearStencil,
const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue);
angle::Result clearWithCommand(ContextVk *contextVk,
vk::CommandBufferHelper *renderpassCommands,
const gl::Rectangle &scissoredRenderArea,
gl::DrawBufferMask clearColorBuffers,
bool clearDepth,
bool clearStencil,
const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue);
void updateActiveColorMasks(size_t colorIndex, bool r, bool g, bool b, bool a);
void updateRenderPassDesc();
angle::Result updateColorAttachment(const gl::Context *context,
......@@ -226,6 +232,8 @@ class FramebufferVk : public FramebufferImpl
vk::ImageViewSubresourceSerial resolveImageViewSerial);
void removeColorResolveAttachment(uint32_t colorIndexGL);
void setReadOnlyDepthMode(bool readOnlyDepthEnabled);
WindowSurfaceVk *mBackbuffer;
vk::RenderPassDesc mRenderPassDesc;
......@@ -248,6 +256,11 @@ class FramebufferVk : public FramebufferImpl
angle::HashMap<vk::FramebufferDesc, vk::FramebufferHelper> mFramebufferCache;
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
......
......@@ -1327,6 +1327,20 @@ angle::Result UtilsVk::clearFramebuffer(ContextVk *contextVk,
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;
shaderParams.clearValue = params.colorClearValue;
......@@ -1587,7 +1601,7 @@ angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk,
pipelineDesc.setScissor(gl_vk::GetRect(params.blitArea));
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,
src);
......
......@@ -606,8 +606,8 @@ CommandBufferHelper::CommandBufferHelper()
mValidTransformFeedbackBufferCount(0),
mRebindTransformFeedbackBuffers(false),
mIsRenderPassCommandBuffer(false),
mDepthStartAccess(ResourceAccess::Unused),
mStencilStartAccess(ResourceAccess::Unused),
mDepthAccess(ResourceAccess::Unused),
mStencilAccess(ResourceAccess::Unused),
mDepthCmdSizeInvalidated(kInfiniteCmdSize),
mDepthCmdSizeDisabled(kInfiniteCmdSize),
mStencilCmdSizeInvalidated(kInfiniteCmdSize),
......@@ -754,9 +754,7 @@ void CommandBufferHelper::imageWrite(ResourceUseList *resourceUseList,
bool CommandBufferHelper::onDepthAccess(ResourceAccess access)
{
// Update the access for optimizing this render pass's loadOp
UpdateAccess(&mDepthStartAccess, access);
ASSERT((mRenderPassDesc.getDepthStencilAccess() != ResourceAccess::ReadOnly) ||
mDepthStartAccess != ResourceAccess::Write);
UpdateAccess(&mDepthAccess, access);
// Update the invalidate state for optimizing this render pass's storeOp
return onDepthStencilAccess(access, &mDepthCmdSizeInvalidated, &mDepthCmdSizeDisabled);
......@@ -765,7 +763,7 @@ bool CommandBufferHelper::onDepthAccess(ResourceAccess access)
bool CommandBufferHelper::onStencilAccess(ResourceAccess access)
{
// 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
return onDepthStencilAccess(access, &mStencilCmdSizeInvalidated, &mStencilCmdSizeDisabled);
......@@ -881,15 +879,17 @@ void CommandBufferHelper::beginRenderPass(const Framebuffer &framebuffer,
mCounter++;
}
void CommandBufferHelper::restartRenderPassWithReadOnlyDepth(const Framebuffer &framebuffer,
const RenderPassDesc &renderPassDesc)
void CommandBufferHelper::updateStartedRenderPassWithDepthMode(const Framebuffer &framebuffer,
const RenderPassDesc &renderPassDesc,
bool readOnlyDepth)
{
ASSERT(mIsRenderPassCommandBuffer);
ASSERT(mRenderPassStarted);
mRenderPassDesc = renderPassDesc;
mAttachmentOps.setLayouts(mDepthStencilAttachmentIndex, ImageLayout::DepthStencilReadOnly,
ImageLayout::DepthStencilReadOnly);
ImageLayout depthStencilLayout =
readOnlyDepth ? ImageLayout::DepthStencilReadOnly : ImageLayout::DepthStencilAttachment;
mAttachmentOps.setLayouts(mDepthStencilAttachmentIndex, depthStencilLayout, depthStencilLayout);
mFramebuffer.setHandle(framebuffer.getHandle());
// Barrier aggregation messes up with RenderPass restarting.
......@@ -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,
// and the data has also not been stored back into attachment, then just skip the load/clear op.
if (mDepthStartAccess == ResourceAccess::Unused &&
dsOps.storeOp == VK_ATTACHMENT_STORE_OP_DONT_CARE)
if (mDepthAccess == ResourceAccess::Unused && dsOps.storeOp == VK_ATTACHMENT_STORE_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.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
......@@ -933,7 +932,7 @@ void CommandBufferHelper::endRenderPass(ContextVk *contextVk)
// Ensure we don't write to a read-only RenderPass. (ReadOnly -> !Write)
ASSERT((mRenderPassDesc.getDepthStencilAccess() != ResourceAccess::ReadOnly) ||
mDepthStartAccess != ResourceAccess::Write);
mDepthAccess != ResourceAccess::Write);
// Fill out perf counters
PerfCounters &counters = contextVk->getPerfCounters();
......@@ -944,6 +943,9 @@ void CommandBufferHelper::endRenderPass(ContextVk *contextVk)
counters.stencilClears += dsOps.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_CLEAR ? 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.readOnlyDepthStencilRenderPasses +=
static_cast<ImageLayout>(dsOps.finalLayout) == vk::ImageLayout::DepthStencilReadOnly ? 1
: 0;
}
void CommandBufferHelper::beginTransformFeedback(size_t validBufferCount,
......@@ -1141,8 +1143,8 @@ void CommandBufferHelper::reset()
mRenderPassStarted = false;
mValidTransformFeedbackBufferCount = 0;
mRebindTransformFeedbackBuffers = false;
mDepthStartAccess = ResourceAccess::Unused;
mStencilStartAccess = ResourceAccess::Unused;
mDepthAccess = ResourceAccess::Unused;
mStencilAccess = ResourceAccess::Unused;
mDepthCmdSizeInvalidated = kInfiniteCmdSize;
mDepthCmdSizeDisabled = kInfiniteCmdSize;
mStencilCmdSizeInvalidated = kInfiniteCmdSize;
......
......@@ -981,8 +981,9 @@ class CommandBufferHelper : angle::NonCopyable
void endRenderPass(ContextVk *contextVk);
void restartRenderPassWithReadOnlyDepth(const Framebuffer &framebuffer,
const RenderPassDesc &renderPassDesc);
void updateStartedRenderPassWithDepthMode(const Framebuffer &framebuffer,
const RenderPassDesc &renderPassDesc,
bool readOnlyDepth);
void beginTransformFeedback(size_t validBufferCount,
const VkBuffer *counterBuffers,
......@@ -1081,12 +1082,13 @@ class CommandBufferHelper : angle::NonCopyable
void updateRenderPassForResolve(vk::Framebuffer *newFramebuffer,
const vk::RenderPassDesc &renderPassDesc);
ResourceAccess getDepthStartAccess() const { return mDepthStartAccess; }
bool hasDepthWriteOrClear() const
bool hasDepthStencilWriteOrClear() const
{
return mDepthStartAccess == ResourceAccess::Write ||
mAttachmentOps[mDepthStencilAttachmentIndex].loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR;
return mDepthAccess == ResourceAccess::Write || mStencilAccess == ResourceAccess::Write ||
mAttachmentOps[mDepthStencilAttachmentIndex].loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR ||
mAttachmentOps[mDepthStencilAttachmentIndex].stencilLoadOp ==
VK_ATTACHMENT_LOAD_OP_CLEAR;
}
private:
......@@ -1122,9 +1124,14 @@ class CommandBufferHelper : angle::NonCopyable
bool mIsRenderPassCommandBuffer;
// State tracking for whether to optimize the loadOp to DONT_CARE
ResourceAccess mDepthStartAccess;
ResourceAccess mStencilStartAccess;
// 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
// 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
uint32_t mDepthCmdSizeInvalidated;
......
......@@ -789,6 +789,7 @@ struct PerfCounters
uint32_t stencilClears;
uint32_t stencilLoads;
uint32_t stencilStores;
uint32_t readOnlyDepthStencilRenderPasses;
};
// A Vulkan image level index.
......
......@@ -443,6 +443,7 @@ TEST_P(VulkanPerformanceCounterTest, ReadOnlyDepthStencilFeedbackLoopUsesSingleR
// Draw to a first FBO to initialize the depth buffer.
glBindFramebuffer(GL_FRAMEBUFFER, depthOnlyFBO);
glEnable(GL_DEPTH_TEST);
glUseProgram(redProgram);
glDrawArrays(GL_TRIANGLES, 0, 6);
ASSERT_GL_NO_ERROR();
......@@ -451,7 +452,6 @@ TEST_P(VulkanPerformanceCounterTest, ReadOnlyDepthStencilFeedbackLoopUsesSingleR
// 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();
......@@ -1638,6 +1638,73 @@ TEST_P(VulkanPerformanceCounterTest, RenderToTextureDepthStencilTextureShouldNot
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_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