Commit f8070feb by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Use depthClamp to clear depth where available

This will avoid breaking render pass if clearing depth in clearWithDraw. Bug: angleproject:4836 Change-Id: I50242d1115efc91059923143f6ae5fd25fb3d36f Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2462717 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarCharlie Lao <cclao@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent dd4b6445
......@@ -2019,7 +2019,9 @@ angle::Result FramebufferVk::clearWithDraw(ContextVk *contextVk,
const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue)
{
if (clearDepth)
RendererVk *renderer = contextVk->getRenderer();
if (clearDepth && !renderer->getPhysicalDeviceFeatures().depthClamp)
{
VkClearValue clearValue;
clearValue.depthStencil = clearDepthStencilValue;
......@@ -2031,15 +2033,18 @@ angle::Result FramebufferVk::clearWithDraw(ContextVk *contextVk,
// Force start a new render pass for the depth clear to take effect.
// UtilsVk::clearFramebuffer may not start a new render pass if there's one already started.
ANGLE_TRY(flushDeferredClears(contextVk, clearArea));
clearDepth = false;
}
UtilsVk::ClearFramebufferParameters params = {};
params.clearArea = clearArea;
params.colorClearValue = clearColorValue;
params.stencilClearValue = static_cast<uint8_t>(clearDepthStencilValue.stencil);
params.stencilMask = stencilMask;
params.depthStencilClearValue = clearDepthStencilValue;
params.stencilMask = stencilMask;
params.clearColor = true;
params.clearDepth = clearDepth;
params.clearStencil = clearStencil;
const auto &colorRenderTargets = mRenderTargetCache.getColors();
......@@ -2060,12 +2065,13 @@ angle::Result FramebufferVk::clearWithDraw(ContextVk *contextVk,
ANGLE_TRY(contextVk->getUtils().clearFramebuffer(contextVk, this, params));
// Clear stencil only once!
// Clear depth/stencil only once!
params.clearDepth = false;
params.clearStencil = false;
}
// If there was no color clear, clear stencil alone.
if (params.clearStencil)
// If there was no color clear, clear depth/stencil alone.
if (params.clearDepth || params.clearStencil)
{
params.clearColor = false;
ANGLE_TRY(contextVk->getUtils().clearFramebuffer(contextVk, this, params));
......
......@@ -1336,6 +1336,8 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
enabledFeatures.features.shaderClipDistance = mPhysicalDeviceFeatures.shaderClipDistance;
// Used to support OES_sample_shading
enabledFeatures.features.sampleRateShading = mPhysicalDeviceFeatures.sampleRateShading;
// Used to support depth clears through draw calls.
enabledFeatures.features.depthClamp = mPhysicalDeviceFeatures.depthClamp;
if (!vk::CommandBuffer::ExecutesInline())
{
......
......@@ -1402,14 +1402,21 @@ angle::Result UtilsVk::clearFramebuffer(ContextVk *contextVk,
ANGLE_TRY(contextVk->startRenderPass(scissoredRenderArea, &commandBuffer));
}
if (params.clearStencil)
if (params.clearStencil || params.clearDepth)
{
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);
// Because clear is not affected by depth/stencil test, we have to explicitly mark
// depth/stencil write here.
if (params.clearDepth)
{
renderpassCommands->onDepthAccess(vk::ResourceAccess::Write);
}
if (params.clearStencil)
{
renderpassCommands->onStencilAccess(vk::ResourceAccess::Write);
}
// We may have changed depth stencil access mode, so update read only depth stencil mode
// here.
......@@ -1433,11 +1440,25 @@ angle::Result UtilsVk::clearFramebuffer(ContextVk *contextVk,
// used.
pipelineDesc.setSubpass(contextVk->getCurrentSubpassIndex());
// Clear depth by enabling depth clamping and setting the viewport depth range to the clear
// value.
if (params.clearDepth)
{
// This path requires the depthClamp Vulkan feature.
ASSERT(contextVk->getRenderer()->getPhysicalDeviceFeatures().depthClamp);
pipelineDesc.setDepthTestEnabled(true);
pipelineDesc.setDepthWriteEnabled(true);
pipelineDesc.setDepthFunc(VK_COMPARE_OP_ALWAYS);
pipelineDesc.setDepthClampEnabled(true);
}
// Clear stencil by enabling stencil write with the right mask.
if (params.clearStencil)
{
const uint8_t compareMask = 0xFF;
const uint8_t clearStencilValue = params.stencilClearValue;
const uint8_t compareMask = 0xFF;
const uint8_t clearStencilValue =
static_cast<uint8_t>(params.depthStencilClearValue.stencil);
pipelineDesc.setStencilTestEnabled(true);
pipelineDesc.setStencilFrontFuncs(clearStencilValue, VK_COMPARE_OP_ALWAYS, compareMask);
......@@ -1453,8 +1474,11 @@ angle::Result UtilsVk::clearFramebuffer(ContextVk *contextVk,
VkViewport viewport;
gl::Rectangle completeRenderArea = framebuffer->getRotatedCompleteRenderArea(contextVk);
bool invertViewport = contextVk->isViewportFlipEnabledForDrawFBO();
gl_vk::GetViewport(completeRenderArea, 0.0f, 1.0f, invertViewport, completeRenderArea.height,
&viewport);
// Set depth range to clear value. If clearing depth, the vertex shader depth output is clamped
// to this value, thus clearing the depth buffer to the desired clear value.
const float clearDepthValue = params.depthStencilClearValue.depth;
gl_vk::GetViewport(completeRenderArea, clearDepthValue, clearDepthValue, invertViewport,
completeRenderArea.height, &viewport);
pipelineDesc.setViewport(viewport);
pipelineDesc.setScissor(gl_vk::GetRect(params.clearArea));
......@@ -2576,13 +2600,14 @@ angle::Result UtilsVk::allocateDescriptorSet(ContextVk *contextVk,
UtilsVk::ClearFramebufferParameters::ClearFramebufferParameters()
: clearColor(false),
clearDepth(false),
clearStencil(false),
stencilMask(0),
colorMaskFlags(0),
colorAttachmentIndexGL(0),
colorFormat(nullptr),
colorClearValue{},
stencilClearValue(0)
depthStencilClearValue{}
{}
} // namespace rx
......@@ -20,7 +20,7 @@
// resolve on depth/stencil images.
// - Generate mipmap: Used by TextureVk::generateMipmapsWithCompute().
// - Overlay Cull/Draw: Used by OverlayVk to efficiently draw a UI for debugging.
// - Mipmap generation: Not yet implemented
// - Mipmap generation: Used by TextureVk to generate mipmaps more efficiently in compute.
//
#ifndef LIBANGLE_RENDERER_VULKAN_UTILSVK_H_
......@@ -95,8 +95,10 @@ class UtilsVk : angle::NonCopyable
gl::Rectangle clearArea;
// Note that depth clear is never needed to be done with a draw call.
// Note that depth clear is only possible if the depthClamp Vulkan feature is supported. If
// needs be, this can be emulated by exporting depth from shaders/src/ImageClear.frag.
bool clearColor;
bool clearDepth;
bool clearStencil;
uint8_t stencilMask;
......@@ -105,7 +107,7 @@ class UtilsVk : angle::NonCopyable
const angle::Format *colorFormat;
VkClearColorValue colorClearValue;
uint8_t stencilClearValue;
VkClearDepthStencilValue depthStencilClearValue;
};
struct BlitResolveParameters
......
......@@ -2178,6 +2178,11 @@ void GraphicsPipelineDesc::setDepthFunc(VkCompareOp op)
SetBitField(mDepthStencilStateInfo.depthCompareOp, op);
}
void GraphicsPipelineDesc::setDepthClampEnabled(bool enabled)
{
mRasterizationAndMultisampleStateInfo.bits.depthClampEnable = enabled;
}
void GraphicsPipelineDesc::setStencilTestEnabled(bool enabled)
{
mDepthStencilStateInfo.enable.stencilTest = enabled;
......
......@@ -623,6 +623,7 @@ class GraphicsPipelineDesc final
void setDepthTestEnabled(bool enabled);
void setDepthWriteEnabled(bool enabled);
void setDepthFunc(VkCompareOp op);
void setDepthClampEnabled(bool enabled);
void setStencilTestEnabled(bool enabled);
void setStencilFrontFuncs(uint8_t reference, VkCompareOp compareOp, uint8_t compareMask);
void setStencilBackFuncs(uint8_t reference, VkCompareOp compareOp, uint8_t compareMask);
......
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