Commit df6b7298 by Charlie Lao Committed by Commit Bot

Vulkan: Use StoreOp_None_QCOM for read only depth stencil buffer

For read only depth stencil buffers, there is no need to store depth or stencil value. But we can not use DontCare for storeOp because vulkan core spec says DontCare indicates data is undefined after this. VK_QCOM_render_pass_store_ops extension introduces a new store op that will leave data defined but skip the store. This CL utilize this if the extension is available. Bug: angleproject:5055 Change-Id: I104f3d01eb342a2d0cc900f342430e901bde1bff Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2462604 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 4c6903a4
......@@ -354,6 +354,13 @@ struct FeaturesVk : FeatureSetBase
"and the performance is better.",
&members, "http://anglebug.com/4551"};
// Whether the VkDevice supports the VK_QCOM_render_pass_store_ops extension
// http://anglebug.com/5505
Feature supportsRenderPassStoreOpNoneQCOM = {
"supports_render_pass_store_ops_none_qcom", FeatureCategory::VulkanFeatures,
"VkDevice supports VK_QCOM_render_pass_store_ops extension.", &members,
"http://anglebug.com/5055"};
// Force maxUniformBufferSize to 16K on Qualcomm's Adreno 540. Pixel2's Adreno540 reports
// maxUniformBufferSize 64k but various tests failed with that size. For that specific
// device, we set to 16k for now which is known to pass all tests.
......
......@@ -2269,9 +2269,9 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
renderPassAttachmentOps.setLayouts(colorIndexVk, vk::ImageLayout::ColorAttachment,
vk::ImageLayout::ColorAttachment);
const VkAttachmentStoreOp storeOp = colorRenderTarget->isImageTransient()
? VK_ATTACHMENT_STORE_OP_DONT_CARE
: VK_ATTACHMENT_STORE_OP_STORE;
const vk::RenderPassStoreOp storeOp = colorRenderTarget->isImageTransient()
? vk::RenderPassStoreOp::DontCare
: vk::RenderPassStoreOp::Store;
if (mDeferredClears.test(colorIndexGL))
{
......@@ -2291,7 +2291,7 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
kUninitializedClearValue);
}
renderPassAttachmentOps.setStencilOps(colorIndexVk, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_DONT_CARE);
vk::RenderPassStoreOp::DontCare);
// If there's a resolve attachment, and loadOp needs to be LOAD, the multisampled attachment
// needs to take its value from the resolve attachment. In this case, an initial subpass is
......@@ -2333,10 +2333,10 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
// depth stencil attachment always immediately follows color attachment
depthStencilAttachmentIndex = colorIndexVk;
VkAttachmentLoadOp depthLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
VkAttachmentLoadOp stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
VkAttachmentStoreOp depthStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
VkAttachmentStoreOp stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
VkAttachmentLoadOp depthLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
VkAttachmentLoadOp stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
vk::RenderPassStoreOp depthStoreOp = vk::RenderPassStoreOp::Store;
vk::RenderPassStoreOp stencilStoreOp = vk::RenderPassStoreOp::Store;
// If the image data was previously discarded (with no update in between), don't attempt to
// load the image. Additionally, if the multisampled image data is transient and there is
......@@ -2359,11 +2359,11 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
// there is no resolve/unresolve and the image data is never stored/loaded.
if (depthStencilRenderTarget->isImageTransient())
{
depthStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depthStoreOp = vk::RenderPassStoreOp::DontCare;
if (canExportStencil || depthStencilRenderTarget->isEntirelyTransient())
{
stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
stencilStoreOp = vk::RenderPassStoreOp::DontCare;
}
}
......@@ -2402,12 +2402,12 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
if (format.intendedFormat().stencilBits == 0)
{
stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
stencilStoreOp = vk::RenderPassStoreOp::DontCare;
}
if (format.intendedFormat().depthBits == 0)
{
depthLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
depthStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depthStoreOp = vk::RenderPassStoreOp::DontCare;
}
// Similar to color attachments, if there's a resolve attachment and the multisampled image
......
......@@ -1298,6 +1298,11 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
enabledDeviceExtensions.push_back(VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME);
}
if (getFeatures().supportsRenderPassStoreOpNoneQCOM.enabled)
{
enabledDeviceExtensions.push_back(VK_QCOM_render_pass_store_ops_EXTENSION_NAME);
}
std::sort(enabledDeviceExtensions.begin(), enabledDeviceExtensions.end(), StrLess);
ANGLE_VK_TRY(displayVk, VerifyExtensionsPresent(deviceExtensionNames, enabledDeviceExtensions));
......@@ -1826,6 +1831,10 @@ void RendererVk::initFeatures(DisplayVk *displayVk, const ExtensionNameList &dev
&mFeatures, supportsShaderStencilExport,
ExtensionFound(VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME, deviceExtensionNames));
ANGLE_FEATURE_CONDITION(
&mFeatures, supportsRenderPassStoreOpNoneQCOM,
ExtensionFound(VK_QCOM_render_pass_store_ops_EXTENSION_NAME, deviceExtensionNames));
ANGLE_FEATURE_CONDITION(&mFeatures, supportsTransformFeedbackExtension,
mTransformFeedbackFeatures.transformFeedback == VK_TRUE);
......
......@@ -150,13 +150,15 @@ void UnpackAttachmentDesc(VkAttachmentDescription *desc,
const vk::PackedAttachmentOpsDesc &ops)
{
// We would only need this flag for duplicated attachments. Apply it conservatively.
desc->flags = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT;
desc->format = format.vkImageFormat;
desc->samples = gl_vk::GetSamples(samples);
desc->loadOp = static_cast<VkAttachmentLoadOp>(ops.loadOp);
desc->storeOp = static_cast<VkAttachmentStoreOp>(ops.storeOp);
desc->stencilLoadOp = static_cast<VkAttachmentLoadOp>(ops.stencilLoadOp);
desc->stencilStoreOp = static_cast<VkAttachmentStoreOp>(ops.stencilStoreOp);
desc->flags = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT;
desc->format = format.vkImageFormat;
desc->samples = gl_vk::GetSamples(samples);
desc->loadOp = static_cast<VkAttachmentLoadOp>(ops.loadOp);
desc->storeOp =
ConvertRenderPassStoreOpToVkStoreOp(static_cast<RenderPassStoreOp>(ops.storeOp));
desc->stencilLoadOp = static_cast<VkAttachmentLoadOp>(ops.stencilLoadOp);
desc->stencilStoreOp =
ConvertRenderPassStoreOpToVkStoreOp(static_cast<RenderPassStoreOp>(ops.stencilStoreOp));
desc->initialLayout =
ConvertImageLayoutToVkImageLayout(static_cast<ImageLayout>(ops.initialLayout));
desc->finalLayout =
......@@ -773,11 +775,13 @@ void UpdateRenderPassDepthStencilPerfCounters(const VkRenderPassCreateInfo &crea
countersOut->depthClears += ds.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR ? 1 : 0;
countersOut->depthLoads += ds.loadOp == VK_ATTACHMENT_LOAD_OP_LOAD ? 1 : 0;
countersOut->depthStores += ds.storeOp == VK_ATTACHMENT_STORE_OP_STORE ? 1 : 0;
countersOut->depthStores +=
ds.storeOp == static_cast<uint16_t>(RenderPassStoreOp::Store) ? 1 : 0;
countersOut->stencilClears += ds.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_CLEAR ? 1 : 0;
countersOut->stencilLoads += ds.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_LOAD ? 1 : 0;
countersOut->stencilStores += ds.stencilStoreOp == VK_ATTACHMENT_STORE_OP_STORE ? 1 : 0;
countersOut->stencilStores +=
ds.stencilStoreOp == static_cast<uint16_t>(RenderPassStoreOp::Store) ? 1 : 0;
// Depth/stencil read-only mode.
countersOut->readOnlyDepthStencil +=
......@@ -807,11 +811,13 @@ void UpdateRenderPassDepthStencilResolvePerfCounters(
// Resolve depth/stencil ops counters.
countersOut->depthClears += dsResolve.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR ? 1 : 0;
countersOut->depthLoads += dsResolve.loadOp == VK_ATTACHMENT_LOAD_OP_LOAD ? 1 : 0;
countersOut->depthStores += dsResolve.storeOp == VK_ATTACHMENT_STORE_OP_STORE ? 1 : 0;
countersOut->depthStores +=
dsResolve.storeOp == static_cast<uint16_t>(RenderPassStoreOp::Store) ? 1 : 0;
countersOut->stencilClears += dsResolve.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_CLEAR ? 1 : 0;
countersOut->stencilLoads += dsResolve.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_LOAD ? 1 : 0;
countersOut->stencilStores += dsResolve.stencilStoreOp == VK_ATTACHMENT_STORE_OP_STORE ? 1 : 0;
countersOut->stencilStores +=
dsResolve.stencilStoreOp == static_cast<uint16_t>(RenderPassStoreOp::Store) ? 1 : 0;
// Depth/stencil resolve counters.
countersOut->depthAttachmentResolves +=
......@@ -2481,8 +2487,8 @@ void AttachmentOpsArray::initWithLoadStore(PackedAttachmentIndex index,
ImageLayout finalLayout)
{
setLayouts(index, initialLayout, finalLayout);
setOps(index, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE);
setStencilOps(index, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE);
setOps(index, VK_ATTACHMENT_LOAD_OP_LOAD, vk::RenderPassStoreOp::Store);
setStencilOps(index, VK_ATTACHMENT_LOAD_OP_LOAD, RenderPassStoreOp::Store);
}
void AttachmentOpsArray::setLayouts(PackedAttachmentIndex index,
......@@ -2496,7 +2502,7 @@ void AttachmentOpsArray::setLayouts(PackedAttachmentIndex index,
void AttachmentOpsArray::setOps(PackedAttachmentIndex index,
VkAttachmentLoadOp loadOp,
VkAttachmentStoreOp storeOp)
RenderPassStoreOp storeOp)
{
PackedAttachmentOpsDesc &ops = mOps[index.get()];
SetBitField(ops.loadOp, loadOp);
......@@ -2506,7 +2512,7 @@ void AttachmentOpsArray::setOps(PackedAttachmentIndex index,
void AttachmentOpsArray::setStencilOps(PackedAttachmentIndex index,
VkAttachmentLoadOp loadOp,
VkAttachmentStoreOp storeOp)
RenderPassStoreOp storeOp)
{
PackedAttachmentOpsDesc &ops = mOps[index.get()];
SetBitField(ops.stencilLoadOp, loadOp);
......
......@@ -106,6 +106,22 @@ inline void UpdateAccess(ResourceAccess *oldAccess, ResourceAccess newAccess)
}
}
enum RenderPassStoreOp
{
Store = VK_ATTACHMENT_STORE_OP_STORE,
DontCare = VK_ATTACHMENT_STORE_OP_DONT_CARE,
NoneQCOM,
};
// ConvertRenderPassStoreOpToVkStoreOp rely on the fact that only NoneQCOM is different from VK
// enums.
static_assert(RenderPassStoreOp::NoneQCOM == 2, "ConvertRenderPassStoreOpToVkStoreOp must updated");
inline VkAttachmentStoreOp ConvertRenderPassStoreOpToVkStoreOp(RenderPassStoreOp storeOp)
{
return storeOp == RenderPassStoreOp::NoneQCOM ? VK_ATTACHMENT_STORE_OP_NONE_QCOM
: static_cast<VkAttachmentStoreOp>(storeOp);
}
// There can be a maximum of IMPLEMENTATION_MAX_DRAW_BUFFERS color and resolve attachments, plus one
// depth/stencil attachment and one depth/stencil resolve attachment.
constexpr size_t kMaxFramebufferAttachments = gl::IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 + 2;
......@@ -283,11 +299,11 @@ static_assert(kRenderPassDescSize == 12, "Size check failed");
struct PackedAttachmentOpsDesc final
{
// VkAttachmentLoadOp is in range [0, 2], and VkAttachmentStoreOp is in range [0, 1].
// VkAttachmentLoadOp is in range [0, 2], and VkAttachmentStoreOp is in range [0, 2].
uint16_t loadOp : 2;
uint16_t storeOp : 1;
uint16_t storeOp : 2;
uint16_t stencilLoadOp : 2;
uint16_t stencilStoreOp : 1;
uint16_t stencilStoreOp : 2;
// If a corresponding resolve attachment exists, storeOp may already be DONT_CARE, and it's
// unclear whether the attachment was invalidated or not. This information is passed along here
// so that the resolve attachment's storeOp can be set to DONT_CARE if the attachment is
......@@ -296,7 +312,7 @@ struct PackedAttachmentOpsDesc final
// render pass compatibility rules.
uint16_t isInvalidated : 1;
uint16_t isStencilInvalidated : 1;
uint16_t padding1 : 8;
uint16_t padding1 : 6;
// 4-bits to force pad the structure to exactly 2 bytes. Note that we currently don't support
// any of the extension layouts, whose values start at 1'000'000'000.
......@@ -328,12 +344,10 @@ class AttachmentOpsArray final
void setLayouts(PackedAttachmentIndex index,
ImageLayout initialLayout,
ImageLayout finalLayout);
void setOps(PackedAttachmentIndex index,
VkAttachmentLoadOp loadOp,
VkAttachmentStoreOp storeOp);
void setOps(PackedAttachmentIndex index, VkAttachmentLoadOp loadOp, RenderPassStoreOp storeOp);
void setStencilOps(PackedAttachmentIndex index,
VkAttachmentLoadOp loadOp,
VkAttachmentStoreOp storeOp);
RenderPassStoreOp storeOp);
void setClearOp(PackedAttachmentIndex index);
void setClearStencilOp(PackedAttachmentIndex index);
......
......@@ -1069,7 +1069,7 @@ void CommandBufferHelper::endRenderPass(ContextVk *contextVk)
// First, if the attachment is invalidated, skip the store op.
if (isInvalidated(mDepthCmdSizeInvalidated, mDepthCmdSizeDisabled))
{
dsOps.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
dsOps.storeOp = RenderPassStoreOp::DontCare;
dsOps.isInvalidated = true;
}
else if (hasWriteAfterInvalidate(mDepthCmdSizeInvalidated, mDepthCmdSizeDisabled))
......@@ -1080,7 +1080,7 @@ void CommandBufferHelper::endRenderPass(ContextVk *contextVk)
}
if (isInvalidated(mStencilCmdSizeInvalidated, mStencilCmdSizeDisabled))
{
dsOps.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
dsOps.stencilStoreOp = RenderPassStoreOp::DontCare;
dsOps.isStencilInvalidated = true;
}
else if (hasWriteAfterInvalidate(mStencilCmdSizeInvalidated, mStencilCmdSizeDisabled))
......@@ -1090,6 +1090,21 @@ void CommandBufferHelper::endRenderPass(ContextVk *contextVk)
restoreStencilContent();
}
// For read only depth stencil, we can use StoreOpNone if available. DONT_CARE is still
// preferred, so do this after finish the DONT_CARE handling.
if (mReadOnlyDepthStencilMode &&
contextVk->getFeatures().supportsRenderPassStoreOpNoneQCOM.enabled)
{
if (dsOps.storeOp == RenderPassStoreOp::Store)
{
dsOps.storeOp = RenderPassStoreOp::NoneQCOM;
}
if (dsOps.stencilStoreOp == RenderPassStoreOp::Store)
{
dsOps.stencilStoreOp = RenderPassStoreOp::NoneQCOM;
}
}
// 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 (mDepthAccess == ResourceAccess::Unused && dsOps.storeOp == VK_ATTACHMENT_STORE_OP_DONT_CARE)
......@@ -1098,7 +1113,7 @@ void CommandBufferHelper::endRenderPass(ContextVk *contextVk)
}
if (mStencilAccess == ResourceAccess::Unused &&
dsOps.stencilStoreOp == VK_ATTACHMENT_STORE_OP_DONT_CARE)
dsOps.stencilStoreOp == RenderPassStoreOp::DontCare)
{
dsOps.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
}
......@@ -1215,12 +1230,14 @@ char GetLoadOpShorthand(uint32_t loadOp)
}
}
char GetStoreOpShorthand(uint32_t storeOp)
char GetStoreOpShorthand(RenderPassStoreOp storeOp)
{
switch (storeOp)
{
case VK_ATTACHMENT_STORE_OP_STORE:
case RenderPassStoreOp::Store:
return 'S';
case RenderPassStoreOp::NoneQCOM:
return 'N';
default:
return 'D';
}
......@@ -1257,7 +1274,8 @@ void CommandBufferHelper::addCommandDiagnostics(ContextVk *contextVk)
for (size_t i = 0; i < colorAttachmentCount; ++i)
{
loadOps += GetLoadOpShorthand(mAttachmentOps[attachmentIndexVk].loadOp);
storeOps += GetStoreOpShorthand(mAttachmentOps[attachmentIndexVk].storeOp);
storeOps += GetStoreOpShorthand(
static_cast<RenderPassStoreOp>(mAttachmentOps[attachmentIndexVk].storeOp));
++attachmentIndexVk;
}
}
......@@ -1272,8 +1290,10 @@ void CommandBufferHelper::addCommandDiagnostics(ContextVk *contextVk)
loadOps += GetLoadOpShorthand(mAttachmentOps[attachmentIndexVk].loadOp);
loadOps += GetLoadOpShorthand(mAttachmentOps[attachmentIndexVk].stencilLoadOp);
storeOps += GetStoreOpShorthand(mAttachmentOps[attachmentIndexVk].storeOp);
storeOps += GetStoreOpShorthand(mAttachmentOps[attachmentIndexVk].stencilStoreOp);
storeOps += GetStoreOpShorthand(
static_cast<RenderPassStoreOp>(mAttachmentOps[attachmentIndexVk].storeOp));
storeOps += GetStoreOpShorthand(
static_cast<RenderPassStoreOp>(mAttachmentOps[attachmentIndexVk].stencilStoreOp));
}
if (attachmentCount > 0)
......
......@@ -1024,7 +1024,7 @@ class CommandBufferHelper : angle::NonCopyable
void invalidateRenderPassColorAttachment(PackedAttachmentIndex attachmentIndex)
{
ASSERT(mIsRenderPassCommandBuffer);
SetBitField(mAttachmentOps[attachmentIndex].storeOp, VK_ATTACHMENT_STORE_OP_DONT_CARE);
SetBitField(mAttachmentOps[attachmentIndex].storeOp, vk::RenderPassStoreOp::DontCare);
mAttachmentOps[attachmentIndex].isInvalidated = true;
}
......
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