Commit 4e1abc75 by Charlie Lao Committed by Commit Bot

Vulkan: Set depthStencil loadOp to DontCare when not used and stored

If depth stencil buffer is disabled during entire renderpass, and at the end of renderpass we are not storing the data back to memory, then force the loadOP to DontCare to avoid unnecessary depth stencil load or clear. Bug: b/162080462 Change-Id: I30905a6d45bec038de68e7f363ec699eb2be09ab Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2317726 Commit-Queue: Charlie Lao <cclao@google.com> Reviewed-by: 's avatarCourtney Goeltzenleuchter <courtneygo@google.com> Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 91f54d83
...@@ -2838,6 +2838,10 @@ angle::Result ContextVk::syncState(const gl::Context *context, ...@@ -2838,6 +2838,10 @@ 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())
{
mRenderPassCommands->setDepthTestEnabled();
}
break; break;
case gl::State::DIRTY_BIT_DEPTH_FUNC: case gl::State::DIRTY_BIT_DEPTH_FUNC:
mGraphicsPipelineDesc->updateDepthFunc(&mGraphicsPipelineTransition, mGraphicsPipelineDesc->updateDepthFunc(&mGraphicsPipelineTransition,
...@@ -2852,6 +2856,10 @@ angle::Result ContextVk::syncState(const gl::Context *context, ...@@ -2852,6 +2856,10 @@ angle::Result ContextVk::syncState(const gl::Context *context,
mGraphicsPipelineDesc->updateStencilTestEnabled(&mGraphicsPipelineTransition, mGraphicsPipelineDesc->updateStencilTestEnabled(&mGraphicsPipelineTransition,
glState.getDepthStencilState(), glState.getDepthStencilState(),
glState.getDrawFramebuffer()); glState.getDrawFramebuffer());
if (mState.isStencilTestEnabled() && mRenderPassCommands->started())
{
mRenderPassCommands->setStencilTestEnabled();
}
break; break;
case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT: case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT:
mGraphicsPipelineDesc->updateStencilFrontFuncs(&mGraphicsPipelineTransition, mGraphicsPipelineDesc->updateStencilFrontFuncs(&mGraphicsPipelineTransition,
...@@ -4378,6 +4386,7 @@ angle::Result ContextVk::flushAndBeginRenderPass( ...@@ -4378,6 +4386,7 @@ angle::Result ContextVk::flushAndBeginRenderPass(
const gl::Rectangle &renderArea, const gl::Rectangle &renderArea,
const vk::RenderPassDesc &renderPassDesc, const vk::RenderPassDesc &renderPassDesc,
const vk::AttachmentOpsArray &renderPassAttachmentOps, const vk::AttachmentOpsArray &renderPassAttachmentOps,
const uint32_t depthStencilAttachmentIndex,
const vk::ClearValuesArray &clearValues, const vk::ClearValuesArray &clearValues,
vk::CommandBuffer **commandBufferOut) vk::CommandBuffer **commandBufferOut)
{ {
...@@ -4388,7 +4397,8 @@ angle::Result ContextVk::flushAndBeginRenderPass( ...@@ -4388,7 +4397,8 @@ angle::Result ContextVk::flushAndBeginRenderPass(
ANGLE_TRY(endRenderPassAndGetCommandBuffer(&outsideRenderPassCommandBuffer)); ANGLE_TRY(endRenderPassAndGetCommandBuffer(&outsideRenderPassCommandBuffer));
mRenderPassCommands->beginRenderPass(framebuffer, renderArea, renderPassDesc, mRenderPassCommands->beginRenderPass(framebuffer, renderArea, renderPassDesc,
renderPassAttachmentOps, clearValues, commandBufferOut); renderPassAttachmentOps, depthStencilAttachmentIndex,
clearValues, commandBufferOut);
mRenderPassFramebuffer = framebuffer.getHandle(); mRenderPassFramebuffer = framebuffer.getHandle();
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -4409,6 +4419,15 @@ angle::Result ContextVk::startRenderPass(gl::Rectangle renderArea, ...@@ -4409,6 +4419,15 @@ angle::Result ContextVk::startRenderPass(gl::Rectangle renderArea,
this, mRenderPassCommandBuffer); this, mRenderPassCommandBuffer);
} }
if (mState.isDepthTestEnabled())
{
mRenderPassCommands->setDepthTestEnabled();
}
if (mState.isStencilTestEnabled())
{
mRenderPassCommands->setStencilTestEnabled();
}
if (commandBufferOut) if (commandBufferOut)
{ {
*commandBufferOut = mRenderPassCommandBuffer; *commandBufferOut = mRenderPassCommandBuffer;
...@@ -4466,7 +4485,7 @@ angle::Result ContextVk::endRenderPass() ...@@ -4466,7 +4485,7 @@ angle::Result ContextVk::endRenderPass()
ANGLE_TRY(flushOutsideRenderPassCommands()); ANGLE_TRY(flushOutsideRenderPassCommands());
} }
mRenderPassCommands->pauseTransformFeedbackIfStarted(); mRenderPassCommands->endRenderPass();
if (mRenderer->getFeatures().enableCommandProcessingThread.enabled) if (mRenderer->getFeatures().enableCommandProcessingThread.enabled)
{ {
......
...@@ -525,6 +525,7 @@ class ContextVk : public ContextImpl, public vk::Context ...@@ -525,6 +525,7 @@ class ContextVk : public ContextImpl, public vk::Context
const gl::Rectangle &renderArea, const gl::Rectangle &renderArea,
const vk::RenderPassDesc &renderPassDesc, const vk::RenderPassDesc &renderPassDesc,
const vk::AttachmentOpsArray &renderPassAttachmentOps, const vk::AttachmentOpsArray &renderPassAttachmentOps,
const uint32_t depthStencilAttachmentIndex,
const vk::ClearValuesArray &clearValues, const vk::ClearValuesArray &clearValues,
vk::CommandBuffer **commandBufferOut); vk::CommandBuffer **commandBufferOut);
......
...@@ -2026,14 +2026,14 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk, ...@@ -2026,14 +2026,14 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
vk::ClearValuesArray packedClearValues; vk::ClearValuesArray packedClearValues;
// Color attachments. // Color attachments.
const auto &colorRenderTargets = mRenderTargetCache.getColors(); const auto &colorRenderTargets = mRenderTargetCache.getColors();
uint32_t currentAttachmentCount = 0; uint32_t colorAttachmentCount = 0;
for (size_t colorIndexGL : mState.getEnabledDrawBuffers()) for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
{ {
RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL]; RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
ASSERT(colorRenderTarget); ASSERT(colorRenderTarget);
renderPassAttachmentOps.setLayouts(currentAttachmentCount, vk::ImageLayout::ColorAttachment, renderPassAttachmentOps.setLayouts(colorAttachmentCount, vk::ImageLayout::ColorAttachment,
vk::ImageLayout::ColorAttachment); vk::ImageLayout::ColorAttachment);
const VkAttachmentStoreOp storeOp = colorRenderTarget->isImageTransient() const VkAttachmentStoreOp storeOp = colorRenderTarget->isImageTransient()
...@@ -2042,24 +2042,23 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk, ...@@ -2042,24 +2042,23 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
if (mDeferredClears.test(colorIndexGL)) if (mDeferredClears.test(colorIndexGL))
{ {
renderPassAttachmentOps.setOps(currentAttachmentCount, VK_ATTACHMENT_LOAD_OP_CLEAR, renderPassAttachmentOps.setOps(colorAttachmentCount, VK_ATTACHMENT_LOAD_OP_CLEAR,
storeOp); storeOp);
packedClearValues.store(currentAttachmentCount, VK_IMAGE_ASPECT_COLOR_BIT, packedClearValues.store(colorAttachmentCount, VK_IMAGE_ASPECT_COLOR_BIT,
mDeferredClears[colorIndexGL]); mDeferredClears[colorIndexGL]);
mDeferredClears.reset(colorIndexGL); mDeferredClears.reset(colorIndexGL);
} }
else else
{ {
renderPassAttachmentOps.setOps(currentAttachmentCount, renderPassAttachmentOps.setOps(colorAttachmentCount,
colorRenderTarget->hasDefinedContent() colorRenderTarget->hasDefinedContent()
? VK_ATTACHMENT_LOAD_OP_LOAD ? VK_ATTACHMENT_LOAD_OP_LOAD
: VK_ATTACHMENT_LOAD_OP_DONT_CARE, : VK_ATTACHMENT_LOAD_OP_DONT_CARE,
storeOp); storeOp);
packedClearValues.store(currentAttachmentCount, VK_IMAGE_ASPECT_COLOR_BIT, packedClearValues.store(colorAttachmentCount, VK_IMAGE_ASPECT_COLOR_BIT,
kUninitializedClearValue); kUninitializedClearValue);
} }
renderPassAttachmentOps.setStencilOps(currentAttachmentCount, renderPassAttachmentOps.setStencilOps(colorAttachmentCount, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_DONT_CARE); VK_ATTACHMENT_STORE_OP_DONT_CARE);
// If there's a resolve attachment, and loadOp needs to be LOAD, the multisampled attachment // If there's a resolve attachment, and loadOp needs to be LOAD, the multisampled attachment
...@@ -2076,12 +2075,12 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk, ...@@ -2076,12 +2075,12 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
// always ever stays on a tiled renderer's tile and no memory backing is allocated for it. // always ever stays on a tiled renderer's tile and no memory backing is allocated for it.
// http://anglebug.com/4881 // http://anglebug.com/4881
if (colorRenderTarget->hasResolveAttachment() && colorRenderTarget->isImageTransient() && if (colorRenderTarget->hasResolveAttachment() && colorRenderTarget->isImageTransient() &&
renderPassAttachmentOps[currentAttachmentCount].loadOp == VK_ATTACHMENT_LOAD_OP_LOAD) renderPassAttachmentOps[colorAttachmentCount].loadOp == VK_ATTACHMENT_LOAD_OP_LOAD)
{ {
ANGLE_TRY(copyResolveToMultisampedAttachment(contextVk, colorRenderTarget)); ANGLE_TRY(copyResolveToMultisampedAttachment(contextVk, colorRenderTarget));
} }
currentAttachmentCount++; colorAttachmentCount++;
} }
// Transition the images to the correct layout (through onColorDraw) after the // Transition the images to the correct layout (through onColorDraw) after the
...@@ -2093,9 +2092,13 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk, ...@@ -2093,9 +2092,13 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
} }
// Depth/stencil attachment. // Depth/stencil attachment.
uint32_t depthStencilAttachmentIndex = vk::kInvalidAttachmentIndex;
RenderTargetVk *depthStencilRenderTarget = getDepthStencilRenderTarget(); RenderTargetVk *depthStencilRenderTarget = getDepthStencilRenderTarget();
if (depthStencilRenderTarget) if (depthStencilRenderTarget)
{ {
// depth stencil attachment always immediately follow color attachment
depthStencilAttachmentIndex = colorAttachmentCount;
VkAttachmentLoadOp depthLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; VkAttachmentLoadOp depthLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
VkAttachmentLoadOp stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; VkAttachmentLoadOp stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
VkAttachmentStoreOp depthStoreOp = VK_ATTACHMENT_STORE_OP_STORE; VkAttachmentStoreOp depthStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
...@@ -2113,7 +2116,7 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk, ...@@ -2113,7 +2116,7 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
} }
renderPassAttachmentOps.setLayouts(currentAttachmentCount, renderPassAttachmentOps.setLayouts(depthStencilAttachmentIndex,
vk::ImageLayout::DepthStencilAttachment, vk::ImageLayout::DepthStencilAttachment,
vk::ImageLayout::DepthStencilAttachment); vk::ImageLayout::DepthStencilAttachment);
...@@ -2136,12 +2139,13 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk, ...@@ -2136,12 +2139,13 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
} }
// Note the aspect is only depth here. That's intentional. // Note the aspect is only depth here. That's intentional.
packedClearValues.store(currentAttachmentCount, VK_IMAGE_ASPECT_DEPTH_BIT, clearValue); packedClearValues.store(depthStencilAttachmentIndex, VK_IMAGE_ASPECT_DEPTH_BIT,
clearValue);
} }
else else
{ {
// Note the aspect is only depth here. That's intentional. // Note the aspect is only depth here. That's intentional.
packedClearValues.store(currentAttachmentCount, VK_IMAGE_ASPECT_DEPTH_BIT, packedClearValues.store(depthStencilAttachmentIndex, VK_IMAGE_ASPECT_DEPTH_BIT,
kUninitializedClearValue); kUninitializedClearValue);
} }
...@@ -2158,8 +2162,8 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk, ...@@ -2158,8 +2162,8 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
depthLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; depthLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
depthStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; depthStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
} }
renderPassAttachmentOps.setOps(currentAttachmentCount, depthLoadOp, depthStoreOp); renderPassAttachmentOps.setOps(depthStencilAttachmentIndex, depthLoadOp, depthStoreOp);
renderPassAttachmentOps.setStencilOps(currentAttachmentCount, stencilLoadOp, renderPassAttachmentOps.setStencilOps(depthStencilAttachmentIndex, stencilLoadOp,
stencilStoreOp); stencilStoreOp);
// This must be called after hasDefinedContent() since it will set content to valid. We are // This must be called after hasDefinedContent() since it will set content to valid. We are
...@@ -2167,13 +2171,11 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk, ...@@ -2167,13 +2171,11 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
// 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
ANGLE_TRY(depthStencilRenderTarget->onDepthStencilDraw(contextVk)); ANGLE_TRY(depthStencilRenderTarget->onDepthStencilDraw(contextVk));
currentAttachmentCount++;
} }
return contextVk->flushAndBeginRenderPass(*framebuffer, renderArea, mRenderPassDesc, return contextVk->flushAndBeginRenderPass(*framebuffer, renderArea, mRenderPassDesc,
renderPassAttachmentOps, packedClearValues, renderPassAttachmentOps, depthStencilAttachmentIndex,
commandBufferOut); packedClearValues, commandBufferOut);
} }
void FramebufferVk::updateActiveColorMasks(size_t colorIndexGL, bool r, bool g, bool b, bool a) void FramebufferVk::updateActiveColorMasks(size_t colorIndexGL, bool r, bool g, bool b, bool a)
......
...@@ -1126,9 +1126,9 @@ angle::Result UtilsVk::startRenderPass(ContextVk *contextVk, ...@@ -1126,9 +1126,9 @@ angle::Result UtilsVk::startRenderPass(ContextVk *contextVk,
renderPassAttachmentOps.initWithLoadStore(0, vk::ImageLayout::ColorAttachment, renderPassAttachmentOps.initWithLoadStore(0, vk::ImageLayout::ColorAttachment,
vk::ImageLayout::ColorAttachment); vk::ImageLayout::ColorAttachment);
ANGLE_TRY(contextVk->flushAndBeginRenderPass(framebuffer, renderArea, renderPassDesc, ANGLE_TRY(contextVk->flushAndBeginRenderPass(
renderPassAttachmentOps, clearValues, framebuffer, renderArea, renderPassDesc, renderPassAttachmentOps,
commandBufferOut)); vk::kInvalidAttachmentIndex, clearValues, commandBufferOut));
contextVk->addGarbage(&framebuffer); contextVk->addGarbage(&framebuffer);
......
...@@ -544,7 +544,10 @@ CommandBufferHelper::CommandBufferHelper() ...@@ -544,7 +544,10 @@ CommandBufferHelper::CommandBufferHelper()
mValidTransformFeedbackBufferCount(0), mValidTransformFeedbackBufferCount(0),
mRebindTransformFeedbackBuffers(false), mRebindTransformFeedbackBuffers(false),
mIsRenderPassCommandBuffer(false), mIsRenderPassCommandBuffer(false),
mMergeBarriers(false) mMergeBarriers(false),
mDepthTestEverEnabled(false),
mStencilTestEverEnabled(false),
mDepthStencilAttachmentIndex(kInvalidAttachmentIndex)
{} {}
CommandBufferHelper::~CommandBufferHelper() CommandBufferHelper::~CommandBufferHelper()
...@@ -657,24 +660,51 @@ void CommandBufferHelper::beginRenderPass(const vk::Framebuffer &framebuffer, ...@@ -657,24 +660,51 @@ void CommandBufferHelper::beginRenderPass(const vk::Framebuffer &framebuffer,
const gl::Rectangle &renderArea, const gl::Rectangle &renderArea,
const vk::RenderPassDesc &renderPassDesc, const vk::RenderPassDesc &renderPassDesc,
const vk::AttachmentOpsArray &renderPassAttachmentOps, const vk::AttachmentOpsArray &renderPassAttachmentOps,
const uint32_t depthStencilAttachmentIndex,
const vk::ClearValuesArray &clearValues, const vk::ClearValuesArray &clearValues,
vk::CommandBuffer **commandBufferOut) vk::CommandBuffer **commandBufferOut)
{ {
ASSERT(mIsRenderPassCommandBuffer); ASSERT(mIsRenderPassCommandBuffer);
ASSERT(empty()); ASSERT(empty());
mRenderPassDesc = renderPassDesc; mRenderPassDesc = renderPassDesc;
mAttachmentOps = renderPassAttachmentOps; mAttachmentOps = renderPassAttachmentOps;
mDepthStencilAttachmentIndex = depthStencilAttachmentIndex;
mFramebuffer.setHandle(framebuffer.getHandle()); mFramebuffer.setHandle(framebuffer.getHandle());
mRenderArea = renderArea; mRenderArea = renderArea;
mClearValues = clearValues; mClearValues = clearValues;
*commandBufferOut = &mCommandBuffer; *commandBufferOut = &mCommandBuffer;
mRenderPassStarted = true; mRenderPassStarted = true;
mCounter++; mCounter++;
} }
void CommandBufferHelper::endRenderPass()
{
pauseTransformFeedbackIfStarted();
if (mDepthStencilAttachmentIndex == kInvalidAttachmentIndex)
{
return;
}
// Depth/Stencil buffer optimization: if we are loading or clearing the buffer, but the
// buffer has not been used, and the data has also not been stored back into buffer, then
// just skip the load/clear op.
if (!mDepthTestEverEnabled &&
mAttachmentOps[mDepthStencilAttachmentIndex].storeOp == VK_ATTACHMENT_STORE_OP_DONT_CARE)
{
mAttachmentOps[mDepthStencilAttachmentIndex].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
}
if (!mStencilTestEverEnabled && mAttachmentOps[mDepthStencilAttachmentIndex].stencilStoreOp ==
VK_ATTACHMENT_STORE_OP_DONT_CARE)
{
mAttachmentOps[mDepthStencilAttachmentIndex].stencilLoadOp =
VK_ATTACHMENT_LOAD_OP_DONT_CARE;
}
}
void CommandBufferHelper::beginTransformFeedback(size_t validBufferCount, void CommandBufferHelper::beginTransformFeedback(size_t validBufferCount,
const VkBuffer *counterBuffers, const VkBuffer *counterBuffers,
bool rebindBuffers) bool rebindBuffers)
...@@ -859,6 +889,9 @@ void CommandBufferHelper::reset() ...@@ -859,6 +889,9 @@ void CommandBufferHelper::reset()
mRenderPassStarted = false; mRenderPassStarted = false;
mValidTransformFeedbackBufferCount = 0; mValidTransformFeedbackBufferCount = 0;
mRebindTransformFeedbackBuffers = false; mRebindTransformFeedbackBuffers = false;
mDepthTestEverEnabled = false;
mStencilTestEverEnabled = false;
mDepthStencilAttachmentIndex = kInvalidAttachmentIndex;
} }
// 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);
......
...@@ -900,9 +900,12 @@ struct CommandBufferHelper : angle::NonCopyable ...@@ -900,9 +900,12 @@ struct CommandBufferHelper : angle::NonCopyable
const gl::Rectangle &renderArea, const gl::Rectangle &renderArea,
const vk::RenderPassDesc &renderPassDesc, const vk::RenderPassDesc &renderPassDesc,
const vk::AttachmentOpsArray &renderPassAttachmentOps, const vk::AttachmentOpsArray &renderPassAttachmentOps,
const uint32_t depthStencilAttachmentIndex,
const vk::ClearValuesArray &clearValues, const vk::ClearValuesArray &clearValues,
vk::CommandBuffer **commandBufferOut); vk::CommandBuffer **commandBufferOut);
void endRenderPass();
void beginTransformFeedback(size_t validBufferCount, void beginTransformFeedback(size_t validBufferCount,
const VkBuffer *counterBuffers, const VkBuffer *counterBuffers,
bool rebindBuffers); bool rebindBuffers);
...@@ -960,6 +963,9 @@ struct CommandBufferHelper : angle::NonCopyable ...@@ -960,6 +963,9 @@ struct 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 setDepthTestEnabled() { mDepthTestEverEnabled = true; }
void setStencilTestEnabled() { mStencilTestEverEnabled = true; }
private: private:
void addCommandDiagnostics(ContextVk *contextVk); void addCommandDiagnostics(ContextVk *contextVk);
// 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
...@@ -987,7 +993,12 @@ struct CommandBufferHelper : angle::NonCopyable ...@@ -987,7 +993,12 @@ struct CommandBufferHelper : angle::NonCopyable
bool mIsRenderPassCommandBuffer; bool mIsRenderPassCommandBuffer;
bool mMergeBarriers; bool mMergeBarriers;
bool mDepthTestEverEnabled;
bool mStencilTestEverEnabled;
uint32_t mDepthStencilAttachmentIndex;
}; };
static constexpr uint32_t kInvalidAttachmentIndex = -1;
// Imagine an image going through a few layout transitions: // Imagine an image going through a few layout transitions:
// //
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
// //
#include "test_utils/ANGLETest.h" #include "test_utils/ANGLETest.h"
#include "test_utils/gl_raii.h"
using namespace angle; using namespace angle;
...@@ -113,6 +114,129 @@ TEST_P(DiscardFramebufferEXTTest, NonDefaultFramebuffer) ...@@ -113,6 +114,129 @@ TEST_P(DiscardFramebufferEXTTest, NonDefaultFramebuffer)
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
} }
// ANGLE implements an optimization that if depth stencil buffer has not been used and not stored in
// the renderpass, the depth buffer clear will be dropped.
TEST_P(DiscardFramebufferEXTTest, ClearDepthThenDrawWithoutDepthTestThenDiscard)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_discard_framebuffer"));
// TODO: fix crash issue. http://anglebug.com/4141
ANGLE_SKIP_TEST_IF(IsD3D11());
ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::UniformColor());
glUseProgram(program);
GLint colorUniformLocation =
glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
ASSERT_NE(-1, colorUniformLocation);
ASSERT_GL_NO_ERROR();
constexpr GLfloat kDepthClearValue = 0.5f;
// This depth value equals to kDepthClearValue after viewport transform
constexpr GLfloat depthDrawValue = kDepthClearValue * 2.0f - 1.0f;
// This depth clear should be optimized out. We do not have a good way to verify that it
// actually gets dropped, but at least we will ensure rendering is still correct.
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glEnable(GL_DEPTH_TEST);
glClearDepthf(kDepthClearValue);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glUniform4fv(colorUniformLocation, 1, GLColor::cyan.toNormalizedVector().data());
glViewport(0, 0, getWindowWidth(), getWindowHeight());
drawQuad(program, essl1_shaders::PositionAttrib(), depthDrawValue + 0.05f);
GLenum discards = GL_DEPTH_EXT;
glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, &discards);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::cyan);
}
// This test is try to ensure that if depth test has been used, depth clear does not get optimized
// out. It also tests that if the depth buffer has not been used, the rendering is still correct.
TEST_P(DiscardFramebufferEXTTest, ClearDepthThenDrawWithDepthTestThenDiscard)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_discard_framebuffer"));
// http://anglebug.com/4914
ANGLE_SKIP_TEST_IF(IsVulkan() && IsIntel() && IsWindows());
GLTexture texture;
GLRenderbuffer renderbuffer;
GLFramebuffer framebuffer;
GLint colorUniformLocation;
constexpr GLsizei kTexWidth = 256;
constexpr GLsizei kTexHeight = 256;
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, kTexWidth, kTexHeight, 0, GL_RGB, GL_UNSIGNED_BYTE,
nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
ASSERT_GL_NO_ERROR();
glBindTexture(GL_TEXTURE_2D, 0);
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, kTexWidth, kTexWidth);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
ASSERT_GL_NO_ERROR();
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
ASSERT_GL_NO_ERROR();
ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::UniformColor());
glUseProgram(program);
colorUniformLocation = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
ASSERT_NE(-1, colorUniformLocation);
ASSERT_GL_NO_ERROR();
// Draw into FBO0
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glClearColor(0.0f, 1.0f, 0.0f, 1.0f); // clear to green
constexpr GLfloat kDepthClearValue = 0.5f;
// This depth value equals to kDepthClearValue after viewport transform
constexpr GLfloat depthDrawValue = kDepthClearValue * 2.0f - 1.0f;
glClearDepthf(kDepthClearValue);
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Draw bottom left with depth test disabled. DepthValue should remain 0.5f with blue color.
glDepthFunc(GL_LESS);
glDisable(GL_DEPTH_TEST);
glViewport(0, 0, kTexWidth / 2, kTexHeight / 2);
glUniform4fv(colorUniformLocation, 1, GLColor::blue.toNormalizedVector().data());
drawQuad(program, essl1_shaders::PositionAttrib(), depthDrawValue - 0.1f);
// Draw bottom right with depth test enabled. DepthValue should be 0.45f with blue color.
glEnable(GL_DEPTH_TEST);
glViewport(kTexWidth / 2, 0, kTexWidth / 2, kTexHeight / 2);
drawQuad(program, essl1_shaders::PositionAttrib(), depthDrawValue - 0.1f);
// Draw to top left with depth test disabled. DepthValue should remain 0.5f with blue color
glDisable(GL_DEPTH_TEST);
glViewport(0, kTexHeight / 2, kTexWidth / 2, kTexHeight / 2);
drawQuad(program, essl1_shaders::PositionAttrib(), depthDrawValue + 0.1f);
// Draw to top right with depth test enabled. DepthValue should remain 0.5f with green color
glEnable(GL_DEPTH_TEST);
glViewport(kTexWidth / 2, kTexHeight / 2, kTexWidth / 2, kTexHeight / 2);
drawQuad(program, essl1_shaders::PositionAttrib(), depthDrawValue + 0.1f);
// Now draw the full quad with depth test enabled to verify the depth value is expected.
// It should fail depth test in bottom right which will keep it with blue color. All other
// quarters will pass depth test and draw a red quad.
glEnable(GL_DEPTH_TEST);
glUniform4fv(colorUniformLocation, 1, GLColor::red.toNormalizedVector().data());
glViewport(0, 0, kTexWidth, kTexHeight);
drawQuad(program, essl1_shaders::PositionAttrib(), depthDrawValue - 0.05f);
// Invalidate depth buffer. This will trigger depth value not been written to buffer but the
// depth load/clear should not optimize out
GLenum discards = GL_DEPTH_ATTACHMENT;
glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, &discards);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red);
EXPECT_PIXEL_COLOR_EQ(kTexWidth / 2 + 1, 1, GLColor::blue);
EXPECT_PIXEL_COLOR_EQ(1, kTexHeight / 2 + 1, GLColor::red);
EXPECT_PIXEL_COLOR_EQ(kTexWidth / 2 + 1, kTexHeight / 2 + 1, GLColor::red);
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these // Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against. // tests should be run against.
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(DiscardFramebufferEXTTest); ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(DiscardFramebufferEXTTest);
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