Commit b6bd039c by Charlie Lao Committed by Angle LUCI CQ

Vulkan: Fine-grained depth stencil layout transition barrier

Gfxbench Manhattan uses depth attachment as texture in the same render pass, which creates a feedback loop. The layout we are using for this has kAllShadersPipelineStageFlags even though it only used by fragment shader. This creates an unnecessary vertex/fragment dependency that hurts performance on some mobile GPUs. This CL split DepthStencilReadOnly to DSAttachmentReadAndFragmentShaderRead, DSAttachmentReadAndAllShadersRead, and DepthStencilAttachmentReadOnly, so that if it is used by fragment shader, we only barrier against fragment stage. If not used by any shader, we don't block any shader stages. To make names consistent, this CL also renames DepthStencilAttachmentAndFragmentShaderRead to DSAttachmentWriteAndFragmentShaderRead, renames DepthStencilAttachmentAndAllShadersRead to DSAttachmentWriteAndAllShadersRead. Bug: b/169891513 Change-Id: Iede497e8af028861f9166a32d122f26dc7aa864a Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2453599 Commit-Queue: Charlie Lao <cclao@google.com> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com>
parent 5e631c5f
...@@ -1569,19 +1569,25 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl( ...@@ -1569,19 +1569,25 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl(
{ {
if (image.hasRenderPassUsageFlag(vk::RenderPassUsage::ReadOnlyAttachment)) if (image.hasRenderPassUsageFlag(vk::RenderPassUsage::ReadOnlyAttachment))
{ {
textureLayout = vk::ImageLayout::DepthStencilReadOnly; if (firstShader == gl::ShaderType::Fragment)
{
ASSERT(remainingShaderBits.none() && lastShader == firstShader);
textureLayout = vk::ImageLayout::DSAttachmentReadAndFragmentShaderRead;
}
else
{
textureLayout = vk::ImageLayout::DSAttachmentReadAndAllShadersRead;
}
} }
else else
{ {
if (firstShader == gl::ShaderType::Fragment) if (firstShader == gl::ShaderType::Fragment)
{ {
textureLayout = textureLayout = vk::ImageLayout::DSAttachmentWriteAndFragmentShaderRead;
vk::ImageLayout::DepthStencilAttachmentAndFragmentShaderRead;
} }
else else
{ {
textureLayout = textureLayout = vk::ImageLayout::DSAttachmentWriteAndAllShadersRead;
vk::ImageLayout::DepthStencilAttachmentAndAllShadersRead;
} }
} }
} }
...@@ -1604,7 +1610,15 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl( ...@@ -1604,7 +1610,15 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl(
// split a RenderPass to transition a depth texture from shader-read to read-only. // split a RenderPass to transition a depth texture from shader-read to read-only.
// This improves performance in Manhattan. Future optimizations are likely possible // This improves performance in Manhattan. Future optimizations are likely possible
// here including using specialized barriers without breaking the RenderPass. // here including using specialized barriers without breaking the RenderPass.
textureLayout = vk::ImageLayout::DepthStencilReadOnly; if (firstShader == gl::ShaderType::Fragment)
{
ASSERT(remainingShaderBits.none() && lastShader == firstShader);
textureLayout = vk::ImageLayout::DSAttachmentReadAndFragmentShaderRead;
}
else
{
textureLayout = vk::ImageLayout::DSAttachmentReadAndAllShadersRead;
}
} }
else else
{ {
......
...@@ -176,9 +176,9 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -176,9 +176,9 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
}, },
}, },
{ {
ImageLayout::DepthStencilAttachmentAndFragmentShaderRead, ImageLayout::DSAttachmentWriteAndFragmentShaderRead,
ImageMemoryBarrierData{ ImageMemoryBarrierData{
"DepthStencilAttachmentAndFragmentShaderRead", "DSAttachmentWriteAndFragmentShaderRead",
VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL,
kAllDepthStencilPipelineStageFlags | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, kAllDepthStencilPipelineStageFlags | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
kAllDepthStencilPipelineStageFlags | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, kAllDepthStencilPipelineStageFlags | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
...@@ -191,9 +191,9 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -191,9 +191,9 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
}, },
}, },
{ {
ImageLayout::DepthStencilAttachmentAndAllShadersRead, ImageLayout::DSAttachmentWriteAndAllShadersRead,
ImageMemoryBarrierData{ ImageMemoryBarrierData{
"DepthStencilAttachmentAndAllShadersRead", "DSAttachmentWriteAndAllShadersRead",
VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL,
kAllDepthStencilPipelineStageFlags | kAllShadersPipelineStageFlags, kAllDepthStencilPipelineStageFlags | kAllShadersPipelineStageFlags,
kAllDepthStencilPipelineStageFlags | kAllShadersPipelineStageFlags, kAllDepthStencilPipelineStageFlags | kAllShadersPipelineStageFlags,
...@@ -207,9 +207,24 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -207,9 +207,24 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
}, },
}, },
{ {
ImageLayout::DepthStencilReadOnly, ImageLayout::DSAttachmentReadAndFragmentShaderRead,
ImageMemoryBarrierData{ ImageMemoryBarrierData{
"DepthStencilReadOnly", "DSAttachmentReadAndFragmentShaderRead",
VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | kAllDepthStencilPipelineStageFlags,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | kAllDepthStencilPipelineStageFlags,
// Transition to: all reads must happen after barrier.
VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
// Transition from: RAR and WAR don't need memory barrier.
0,
ResourceAccess::ReadOnly,
PipelineStage::EarlyFragmentTest,
},
},
{
ImageLayout::DSAttachmentReadAndAllShadersRead,
ImageMemoryBarrierData{
"DSAttachmentReadAndAllShadersRead",
VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL,
kAllShadersPipelineStageFlags | kAllDepthStencilPipelineStageFlags, kAllShadersPipelineStageFlags | kAllDepthStencilPipelineStageFlags,
kAllShadersPipelineStageFlags | kAllDepthStencilPipelineStageFlags, kAllShadersPipelineStageFlags | kAllDepthStencilPipelineStageFlags,
...@@ -222,6 +237,21 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -222,6 +237,21 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
}, },
}, },
{ {
ImageLayout::DepthStencilAttachmentReadOnly,
ImageMemoryBarrierData{
"DepthStencilAttachmentReadOnly",
VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL,
kAllDepthStencilPipelineStageFlags,
kAllDepthStencilPipelineStageFlags,
// Transition to: all reads must happen after barrier.
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
// Transition from: RAR and WAR don't need memory barrier.
0,
ResourceAccess::ReadOnly,
PipelineStage::EarlyFragmentTest,
},
},
{
ImageLayout::DepthStencilAttachment, ImageLayout::DepthStencilAttachment,
ImageMemoryBarrierData{ ImageMemoryBarrierData{
"DepthStencilAttachment", "DepthStencilAttachment",
...@@ -1360,16 +1390,22 @@ void CommandBufferHelper::finalizeDepthStencilImageLayout(Context *context) ...@@ -1360,16 +1390,22 @@ void CommandBufferHelper::finalizeDepthStencilImageLayout(Context *context)
{ {
// texture code already picked layout and inserted barrier // texture code already picked layout and inserted barrier
imageLayout = mDepthStencilImage->getCurrentImageLayout(); imageLayout = mDepthStencilImage->getCurrentImageLayout();
ASSERT(imageLayout == ImageLayout::DepthStencilAttachmentAndFragmentShaderRead || if (mDepthStencilImage->hasRenderPassUsageFlag(RenderPassUsage::ReadOnlyAttachment))
imageLayout == ImageLayout::DepthStencilAttachmentAndAllShadersRead || {
imageLayout == ImageLayout::DepthStencilReadOnly); ASSERT(imageLayout == ImageLayout::DSAttachmentReadAndFragmentShaderRead ||
barrierRequired = imageLayout == ImageLayout::DepthStencilReadOnly imageLayout == ImageLayout::DSAttachmentReadAndAllShadersRead);
? mDepthStencilImage->isReadBarrierNecessary(imageLayout) barrierRequired = mDepthStencilImage->isReadBarrierNecessary(imageLayout);
: true; }
else
{
ASSERT(imageLayout == ImageLayout::DSAttachmentWriteAndFragmentShaderRead ||
imageLayout == ImageLayout::DSAttachmentWriteAndAllShadersRead);
barrierRequired = true;
}
} }
else if (mDepthStencilImage->hasRenderPassUsageFlag(RenderPassUsage::ReadOnlyAttachment)) else if (mDepthStencilImage->hasRenderPassUsageFlag(RenderPassUsage::ReadOnlyAttachment))
{ {
imageLayout = ImageLayout::DepthStencilReadOnly; imageLayout = ImageLayout::DepthStencilAttachmentReadOnly;
barrierRequired = mDepthStencilImage->isReadBarrierNecessary(imageLayout); barrierRequired = mDepthStencilImage->isReadBarrierNecessary(imageLayout);
} }
else else
...@@ -1472,7 +1508,7 @@ void CommandBufferHelper::finalizeDepthStencilLoadStore(Context *context) ...@@ -1472,7 +1508,7 @@ void CommandBufferHelper::finalizeDepthStencilLoadStore(Context *context)
ASSERT(dsOps.initialLayout != static_cast<uint16_t>(ImageLayout::Undefined)); ASSERT(dsOps.initialLayout != static_cast<uint16_t>(ImageLayout::Undefined));
// Ensure we don't write to a read-only RenderPass. (ReadOnly -> !Write) // Ensure we don't write to a read-only RenderPass. (ReadOnly -> !Write)
ASSERT(dsOps.initialLayout != static_cast<uint16_t>(ImageLayout::DepthStencilReadOnly) || ASSERT(!mDepthStencilImage->hasRenderPassUsageFlag(RenderPassUsage::ReadOnlyAttachment) ||
(mDepthAccess != ResourceAccess::Write && mStencilAccess != ResourceAccess::Write)); (mDepthAccess != ResourceAccess::Write && mStencilAccess != ResourceAccess::Write));
// If the attachment is invalidated, skip the store op. If we are not loading or clearing the // If the attachment is invalidated, skip the store op. If we are not loading or clearing the
...@@ -1508,7 +1544,7 @@ void CommandBufferHelper::finalizeDepthStencilLoadStore(Context *context) ...@@ -1508,7 +1544,7 @@ void CommandBufferHelper::finalizeDepthStencilLoadStore(Context *context)
// For read only depth stencil, we can use StoreOpNone if available. DONT_CARE is still // 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. // preferred, so do this after finish the DONT_CARE handling.
if (dsOps.initialLayout == static_cast<uint16_t>(ImageLayout::DepthStencilReadOnly) && if (mDepthStencilImage->hasRenderPassUsageFlag(RenderPassUsage::ReadOnlyAttachment) &&
context->getRenderer()->getFeatures().supportsRenderPassStoreOpNoneQCOM.enabled) context->getRenderer()->getFeatures().supportsRenderPassStoreOpNoneQCOM.enabled)
{ {
if (dsOps.storeOp == RenderPassStoreOp::Store) if (dsOps.storeOp == RenderPassStoreOp::Store)
......
...@@ -1347,9 +1347,11 @@ enum class ImageLayout ...@@ -1347,9 +1347,11 @@ enum class ImageLayout
ColorAttachment, ColorAttachment,
ColorAttachmentAndFragmentShaderRead, ColorAttachmentAndFragmentShaderRead,
ColorAttachmentAndAllShadersRead, ColorAttachmentAndAllShadersRead,
DepthStencilAttachmentAndFragmentShaderRead, DSAttachmentWriteAndFragmentShaderRead,
DepthStencilAttachmentAndAllShadersRead, DSAttachmentWriteAndAllShadersRead,
DepthStencilReadOnly, DSAttachmentReadAndFragmentShaderRead,
DSAttachmentReadAndAllShadersRead,
DepthStencilAttachmentReadOnly,
DepthStencilAttachment, DepthStencilAttachment,
DepthStencilResolveAttachment, DepthStencilResolveAttachment,
Present, Present,
......
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