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( ...@@ -1479,15 +1479,6 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl(
textureLayout = executable->isCompute() ? vk::ImageLayout::ComputeShaderWrite textureLayout = executable->isCompute() ? vk::ImageLayout::ComputeShaderWrite
: vk::ImageLayout::AllGraphicsShadersWrite; : 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 else
{ {
gl::ShaderBitSet remainingShaderBits = gl::ShaderBitSet remainingShaderBits =
...@@ -1504,15 +1495,48 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl( ...@@ -1504,15 +1495,48 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl(
// not track all textures in the renderpass. // not track all textures in the renderpass.
image.setRenderPassUsageFlag(vk::RenderPassUsage::TextureSampler); 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 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 else
{ {
// We barrier against either: // We barrier against either:
...@@ -4550,13 +4574,6 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context) ...@@ -4550,13 +4574,6 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context)
if (!isIncompleteTexture && texture->isDepthOrStencil() && if (!isIncompleteTexture && texture->isDepthOrStencil() &&
shouldSwitchToReadOnlyDepthFeedbackLoopMode(context, texture)) 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. // Special handling for deferred clears.
ANGLE_TRY(mDrawFramebuffer->flushDeferredClears(this)); ANGLE_TRY(mDrawFramebuffer->flushDeferredClears(this));
...@@ -5549,8 +5566,13 @@ bool ContextVk::shouldSwitchToReadOnlyDepthFeedbackLoopMode(const gl::Context *c ...@@ -5549,8 +5566,13 @@ bool ContextVk::shouldSwitchToReadOnlyDepthFeedbackLoopMode(const gl::Context *c
return false; 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()) && return texture->isBoundToFramebuffer(mDrawFramebuffer->getState().getFramebufferSerial()) &&
!mDrawFramebuffer->isReadOnlyDepthFeedbackLoopMode(); !mState.isDepthWriteEnabled() && !mDrawFramebuffer->isReadOnlyDepthFeedbackLoopMode();
} }
angle::Result ContextVk::onResourceAccess(const vk::CommandBufferAccess &access) angle::Result ContextVk::onResourceAccess(const vk::CommandBufferAccess &access)
......
...@@ -76,7 +76,7 @@ constexpr size_t kDefaultPoolAllocatorPageSize = 16 * 1024; ...@@ -76,7 +76,7 @@ constexpr size_t kDefaultPoolAllocatorPageSize = 16 * 1024;
struct ImageMemoryBarrierData struct ImageMemoryBarrierData
{ {
char name[40]; char name[44];
// The Vk layout corresponding to the ImageLayout key. // The Vk layout corresponding to the ImageLayout key.
VkImageLayout layout; VkImageLayout layout;
...@@ -166,9 +166,9 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -166,9 +166,9 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | kAllShadersPipelineStageFlags, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | kAllShadersPipelineStageFlags,
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, 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, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
ResourceAccess::Write, ResourceAccess::Write,
// In case of multiple destination stages, We barrier the earliest stage // In case of multiple destination stages, We barrier the earliest stage
...@@ -176,6 +176,37 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -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, ImageLayout::DepthStencilReadOnly,
ImageMemoryBarrierData{ ImageMemoryBarrierData{
"DepthStencilReadOnly", "DepthStencilReadOnly",
...@@ -1090,6 +1121,7 @@ void CommandBufferHelper::depthStencilImagesDraw(ResourceUseList *resourceUseLis ...@@ -1090,6 +1121,7 @@ void CommandBufferHelper::depthStencilImagesDraw(ResourceUseList *resourceUseLis
mDepthStencilLevelIndex = level; mDepthStencilLevelIndex = level;
mDepthStencilLayerIndex = layerStart; mDepthStencilLayerIndex = layerStart;
mDepthStencilLayerCount = layerCount; mDepthStencilLayerCount = layerCount;
image->setRenderPassUsageFlag(RenderPassUsage::RenderTargetAttachment);
if (resolveImage) if (resolveImage)
{ {
...@@ -1099,6 +1131,7 @@ void CommandBufferHelper::depthStencilImagesDraw(ResourceUseList *resourceUseLis ...@@ -1099,6 +1131,7 @@ void CommandBufferHelper::depthStencilImagesDraw(ResourceUseList *resourceUseLis
resolveImage->retain(resourceUseList); resolveImage->retain(resourceUseList);
mRenderPassUsedImages.insert(resolveImage->getImageSerial().getValue()); mRenderPassUsedImages.insert(resolveImage->getImageSerial().getValue());
mDepthStencilResolveImage = resolveImage; mDepthStencilResolveImage = resolveImage;
resolveImage->setRenderPassUsageFlag(RenderPassUsage::RenderTargetAttachment);
} }
} }
...@@ -1294,7 +1327,18 @@ void CommandBufferHelper::finalizeDepthStencilImageLayout(Context *context) ...@@ -1294,7 +1327,18 @@ void CommandBufferHelper::finalizeDepthStencilImageLayout(Context *context)
ImageLayout imageLayout; ImageLayout imageLayout;
bool barrierRequired; 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; imageLayout = ImageLayout::DepthStencilReadOnly;
barrierRequired = mDepthStencilImage->isReadBarrierNecessary(imageLayout); barrierRequired = mDepthStencilImage->isReadBarrierNecessary(imageLayout);
...@@ -1337,6 +1381,8 @@ void CommandBufferHelper::finalizeDepthStencilImageLayout(Context *context) ...@@ -1337,6 +1381,8 @@ void CommandBufferHelper::finalizeDepthStencilImageLayout(Context *context)
mDepthStencilLayerCount, definedAspects); mDepthStencilLayerCount, definedAspects);
} }
} }
mDepthStencilImage->resetRenderPassUsageFlags();
} }
void CommandBufferHelper::finalizeDepthStencilResolveImageLayout(Context *context) void CommandBufferHelper::finalizeDepthStencilResolveImageLayout(Context *context)
...@@ -1373,6 +1419,8 @@ void CommandBufferHelper::finalizeDepthStencilResolveImageLayout(Context *contex ...@@ -1373,6 +1419,8 @@ void CommandBufferHelper::finalizeDepthStencilResolveImageLayout(Context *contex
mDepthStencilLayerCount, definedAspects); mDepthStencilLayerCount, definedAspects);
} }
} }
mDepthStencilResolveImage->resetRenderPassUsageFlags();
} }
void CommandBufferHelper::finalizeImageLayout(Context *context, const ImageHelper *image) void CommandBufferHelper::finalizeImageLayout(Context *context, const ImageHelper *image)
......
...@@ -1350,6 +1350,8 @@ enum class ImageLayout ...@@ -1350,6 +1350,8 @@ enum class ImageLayout
ColorAttachment, ColorAttachment,
ColorAttachmentAndFragmentShaderRead, ColorAttachmentAndFragmentShaderRead,
ColorAttachmentAndAllShadersRead, ColorAttachmentAndAllShadersRead,
DepthStencilAttachmentAndFragmentShaderRead,
DepthStencilAttachmentAndAllShadersRead,
DepthStencilReadOnly, DepthStencilReadOnly,
DepthStencilAttachment, DepthStencilAttachment,
DepthStencilResolveAttachment, DepthStencilResolveAttachment,
......
...@@ -2852,7 +2852,7 @@ TEST_P(FramebufferTest_ES3, RenderImmutableTextureWithSubImageWithBeyondMaxLevel ...@@ -2852,7 +2852,7 @@ TEST_P(FramebufferTest_ES3, RenderImmutableTextureWithSubImageWithBeyondMaxLevel
TEST_P(FramebufferTest_ES3, RenderSampleDepthTextureWithExcludedLevel) TEST_P(FramebufferTest_ES3, RenderSampleDepthTextureWithExcludedLevel)
{ {
// ToDo: https://issuetracker.google.com/181800403 // 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. // Set up program to copy depth texture's value to color.red.
constexpr char kVS[] = R"(precision mediump float; 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