Commit 5eac3169 by Charlie Lao Committed by Commit Bot

Vulkan: Support sample/render to depth texture with different LOD

Previously we supported read only depth attachment that attachment and sample are using the same texture. It was always assuming it will be read only if the same texture is attached to FBO and same time bound to texture unit. But we never supported if it actually writing to depth texture, but at the different level with sampling. This is supported OpenGL operation as long as the levels render to is outside [base_level, max_level]. Later on, we added support of the above operation, but limited to color buffers. This CL extends the same support of render and sample to the same depth texture with non-overlapping levels. Android game black desert mobile is running into this usage case. Bug: b/181797383 Change-Id: I7ee1d52f27603f933102ad1b098684309449c406 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2819487 Commit-Queue: Charlie Lao <cclao@google.com> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarIan Elliott <ianelliott@google.com>
parent e55462b9
......@@ -1479,15 +1479,6 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl(
textureLayout = executable->isCompute() ? vk::ImageLayout::ComputeShaderWrite
: vk::ImageLayout::AllGraphicsShadersWrite;
}
else if (image.isDepthOrStencil())
{
// We always use a depth-stencil read-only layout for any depth Textures to simplify our
// implementation's handling of depth-stencil read-only mode. We don't have to split a
// RenderPass to transition a depth texture from shader-read to read-only. This improves
// performance in Manhattan. Future optimizations are likely possible here including
// using specialized barriers without breaking the RenderPass.
textureLayout = vk::ImageLayout::DepthStencilReadOnly;
}
else
{
gl::ShaderBitSet remainingShaderBits =
......@@ -1504,15 +1495,48 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl(
// not track all textures in the renderpass.
image.setRenderPassUsageFlag(vk::RenderPassUsage::TextureSampler);
if (firstShader == gl::ShaderType::Fragment)
if (image.isDepthOrStencil())
{
textureLayout = vk::ImageLayout::ColorAttachmentAndFragmentShaderRead;
if (mRenderPassCommands->started() &&
mRenderPassCommands->isReadOnlyDepthMode())
{
textureLayout = vk::ImageLayout::DepthStencilReadOnly;
}
else
{
if (firstShader == gl::ShaderType::Fragment)
{
textureLayout =
vk::ImageLayout::DepthStencilAttachmentAndFragmentShaderRead;
}
else
{
textureLayout =
vk::ImageLayout::DepthStencilAttachmentAndAllShadersRead;
}
}
}
else
{
textureLayout = vk::ImageLayout::ColorAttachmentAndAllShadersRead;
if (firstShader == gl::ShaderType::Fragment)
{
textureLayout = vk::ImageLayout::ColorAttachmentAndFragmentShaderRead;
}
else
{
textureLayout = vk::ImageLayout::ColorAttachmentAndAllShadersRead;
}
}
}
else if (image.isDepthOrStencil())
{
// We always use a depth-stencil read-only layout for any depth Textures to simplify
// our implementation's handling of depth-stencil read-only mode. We don't have to
// split a RenderPass to transition a depth texture from shader-read to read-only.
// This improves performance in Manhattan. Future optimizations are likely possible
// here including using specialized barriers without breaking the RenderPass.
textureLayout = vk::ImageLayout::DepthStencilReadOnly;
}
else
{
// We barrier against either:
......@@ -4550,13 +4574,6 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context)
if (!isIncompleteTexture && texture->isDepthOrStencil() &&
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
// mode in the RenderPass. The tracking tells us when we can retroactively go back and
// change the RenderPass to read-only. If there are any writes we need to break and
// finish the current RP before starting the read-only one.
ASSERT(!mState.isDepthWriteEnabled());
// Special handling for deferred clears.
ANGLE_TRY(mDrawFramebuffer->flushDeferredClears(this));
......@@ -5549,8 +5566,13 @@ bool ContextVk::shouldSwitchToReadOnlyDepthFeedbackLoopMode(const gl::Context *c
return false;
}
// 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
// mode in the RenderPass. The tracking tells us when we can retroactively go back and
// change the RenderPass to read-only. If there are any writes we need to break and
// finish the current RP before starting the read-only one.
return texture->isBoundToFramebuffer(mDrawFramebuffer->getState().getFramebufferSerial()) &&
!mDrawFramebuffer->isReadOnlyDepthFeedbackLoopMode();
!mState.isDepthWriteEnabled() && !mDrawFramebuffer->isReadOnlyDepthFeedbackLoopMode();
}
angle::Result ContextVk::onResourceAccess(const vk::CommandBufferAccess &access)
......
......@@ -76,7 +76,7 @@ constexpr size_t kDefaultPoolAllocatorPageSize = 16 * 1024;
struct ImageMemoryBarrierData
{
char name[40];
char name[44];
// The Vk layout corresponding to the ImageLayout key.
VkImageLayout layout;
......@@ -166,9 +166,9 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
VK_IMAGE_LAYOUT_GENERAL,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | kAllShadersPipelineStageFlags,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | kAllShadersPipelineStageFlags,
// Transition to: all reads must happen after barrier.
// Transition to: all reads and writes must happen after barrier.
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT,
// Transition from: RAR and WAR don't need memory barrier.
// Transition from: all writes must finish before barrier.
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
ResourceAccess::Write,
// In case of multiple destination stages, We barrier the earliest stage
......@@ -176,6 +176,37 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
},
},
{
ImageLayout::DepthStencilAttachmentAndFragmentShaderRead,
ImageMemoryBarrierData{
"DepthStencilAttachmentAndFragmentShaderRead",
VK_IMAGE_LAYOUT_GENERAL,
kAllDepthStencilPipelineStageFlags | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
kAllDepthStencilPipelineStageFlags | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
// Transition to: all reads and writes must happen after barrier.
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT,
// Transition from: all writes must finish before barrier.
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
ResourceAccess::Write,
PipelineStage::FragmentShader,
},
},
{
ImageLayout::DepthStencilAttachmentAndAllShadersRead,
ImageMemoryBarrierData{
"DepthStencilAttachmentAndAllShadersRead",
VK_IMAGE_LAYOUT_GENERAL,
kAllDepthStencilPipelineStageFlags | kAllShadersPipelineStageFlags,
kAllDepthStencilPipelineStageFlags | kAllShadersPipelineStageFlags,
// Transition to: all reads and writes must happen after barrier.
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT,
// Transition from: all writes must finish before barrier.
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
ResourceAccess::Write,
// In case of multiple destination stages, We barrier the earliest stage
PipelineStage::VertexShader,
},
},
{
ImageLayout::DepthStencilReadOnly,
ImageMemoryBarrierData{
"DepthStencilReadOnly",
......@@ -1090,6 +1121,7 @@ void CommandBufferHelper::depthStencilImagesDraw(ResourceUseList *resourceUseLis
mDepthStencilLevelIndex = level;
mDepthStencilLayerIndex = layerStart;
mDepthStencilLayerCount = layerCount;
image->setRenderPassUsageFlag(RenderPassUsage::RenderTargetAttachment);
if (resolveImage)
{
......@@ -1099,6 +1131,7 @@ void CommandBufferHelper::depthStencilImagesDraw(ResourceUseList *resourceUseLis
resolveImage->retain(resourceUseList);
mRenderPassUsedImages.insert(resolveImage->getImageSerial().getValue());
mDepthStencilResolveImage = resolveImage;
resolveImage->setRenderPassUsageFlag(RenderPassUsage::RenderTargetAttachment);
}
}
......@@ -1294,7 +1327,18 @@ void CommandBufferHelper::finalizeDepthStencilImageLayout(Context *context)
ImageLayout imageLayout;
bool barrierRequired;
if (mReadOnlyDepthStencilMode)
if (mDepthStencilImage->usedByCurrentRenderPassAsAttachmentAndSampler())
{
// texture code already picked layout and inserted barrier
imageLayout = mDepthStencilImage->getCurrentImageLayout();
ASSERT(imageLayout == ImageLayout::DepthStencilAttachmentAndFragmentShaderRead ||
imageLayout == ImageLayout::DepthStencilAttachmentAndAllShadersRead ||
imageLayout == ImageLayout::DepthStencilReadOnly);
barrierRequired = imageLayout == ImageLayout::DepthStencilReadOnly
? mDepthStencilImage->isReadBarrierNecessary(imageLayout)
: true;
}
else if (mReadOnlyDepthStencilMode)
{
imageLayout = ImageLayout::DepthStencilReadOnly;
barrierRequired = mDepthStencilImage->isReadBarrierNecessary(imageLayout);
......@@ -1337,6 +1381,8 @@ void CommandBufferHelper::finalizeDepthStencilImageLayout(Context *context)
mDepthStencilLayerCount, definedAspects);
}
}
mDepthStencilImage->resetRenderPassUsageFlags();
}
void CommandBufferHelper::finalizeDepthStencilResolveImageLayout(Context *context)
......@@ -1373,6 +1419,8 @@ void CommandBufferHelper::finalizeDepthStencilResolveImageLayout(Context *contex
mDepthStencilLayerCount, definedAspects);
}
}
mDepthStencilResolveImage->resetRenderPassUsageFlags();
}
void CommandBufferHelper::finalizeImageLayout(Context *context, const ImageHelper *image)
......
......@@ -1350,6 +1350,8 @@ enum class ImageLayout
ColorAttachment,
ColorAttachmentAndFragmentShaderRead,
ColorAttachmentAndAllShadersRead,
DepthStencilAttachmentAndFragmentShaderRead,
DepthStencilAttachmentAndAllShadersRead,
DepthStencilReadOnly,
DepthStencilAttachment,
DepthStencilResolveAttachment,
......
......@@ -2852,7 +2852,7 @@ TEST_P(FramebufferTest_ES3, RenderImmutableTextureWithSubImageWithBeyondMaxLevel
TEST_P(FramebufferTest_ES3, RenderSampleDepthTextureWithExcludedLevel)
{
// ToDo: https://issuetracker.google.com/181800403
ANGLE_SKIP_TEST_IF(IsVulkan() || IsMetal());
ANGLE_SKIP_TEST_IF(IsMetal());
// Set up program to copy depth texture's value to color.red.
constexpr char kVS[] = R"(precision mediump float;
......
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