Commit 867411a4 by Charlie Lao Committed by Commit Bot

Vulkan: Track images used for both attachment and sampler

This CL adds a new layout ImageLayout::ColorAttachmentAndShaderRead. We detect that the same ImageHelper object is used for both sampler and attachment and will pick this new layout instead of ColorAttachment. Bug: b/175584609 Change-Id: I2089f59d4dc1ad4de7edab0e067797adcfa9b020 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2749479 Commit-Queue: Charlie Lao <cclao@google.com> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 5163cd0c
......@@ -1488,6 +1488,13 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl(
// using specialized barriers without breaking the RenderPass.
textureLayout = vk::ImageLayout::DepthStencilReadOnly;
}
else if (image.hasRenderPassUseFlag(vk::RenderPassUsage::RenderTargetAttachment))
{
// Right now we set this flag only when RenderTargetAttachment is set since we do not
// track all textures in the renderpass.
image.setRenderPassUsageFlag(vk::RenderPassUsage::TextureSampler);
textureLayout = vk::ImageLayout::ColorAttachmentAndShaderRead;
}
else
{
gl::ShaderBitSet remainingShaderBits =
......
......@@ -955,9 +955,10 @@ angle::Result InitializeRenderPassFromDesc(ContextVk *contextVk,
VkAttachmentReference colorRef;
colorRef.attachment = attachmentCount.get();
colorRef.layout = needInputAttachments ? VK_IMAGE_LAYOUT_GENERAL
: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
colorRef.layout = needInputAttachments
? VK_IMAGE_LAYOUT_GENERAL
: ConvertImageLayoutToVkImageLayout(
static_cast<ImageLayout>(ops[attachmentCount].initialLayout));
colorAttachmentRefs.push_back(colorRef);
UnpackAttachmentDesc(&attachmentDescs[attachmentCount.get()], format, desc.samples(),
......
......@@ -145,6 +145,21 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
},
},
{
ImageLayout::ColorAttachmentAndShaderRead,
ImageMemoryBarrierData{
"ColorAttachmentAndShaderRead",
VK_IMAGE_LAYOUT_GENERAL,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | kAllShadersPipelineStageFlags,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | kAllShadersPipelineStageFlags,
// 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: all writes must finish before barrier.
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
ResourceAccess::Write,
PipelineStage::VertexShader,
},
},
{
ImageLayout::DepthStencilReadOnly,
ImageMemoryBarrierData{
"DepthStencilReadOnly",
......@@ -1024,6 +1039,7 @@ void CommandBufferHelper::colorImagesDraw(ResourceUseList *resourceUseList,
}
ASSERT(mColorImages[packedAttachmentIndex] == nullptr);
mColorImages[packedAttachmentIndex] = image;
image->setRenderPassUsageFlag(RenderPassUsage::RenderTargetAttachment);
if (resolveImage)
{
......@@ -1034,22 +1050,10 @@ void CommandBufferHelper::colorImagesDraw(ResourceUseList *resourceUseList,
}
ASSERT(mColorResolveImages[packedAttachmentIndex] == nullptr);
mColorResolveImages[packedAttachmentIndex] = resolveImage;
resolveImage->setRenderPassUsageFlag(RenderPassUsage::RenderTargetAttachment);
}
}
bool CommandBufferHelper::usesImageInAttachments(const ImageHelper &image)
{
ASSERT(mIsRenderPassCommandBuffer);
for (PackedAttachmentIndex index = kAttachmentIndexZero; index < mColorImagesCount; ++index)
{
if (mColorImages[index] == &image || mColorResolveImages[index] == &image)
{
return true;
}
}
return false;
}
void CommandBufferHelper::depthStencilImagesDraw(ResourceUseList *resourceUseList,
gl::LevelIndex level,
uint32_t layerStart,
......@@ -1230,8 +1234,18 @@ void CommandBufferHelper::finalizeColorImageLayout(Context *context,
ASSERT(image != nullptr);
// Do layout change.
ImageLayout imageLayout = ImageLayout::ColorAttachment;
updateImageLayoutAndBarrier(context, image, VK_IMAGE_ASPECT_COLOR_BIT, imageLayout);
ImageLayout imageLayout;
if (image->usedByCurrentRenderPassAsAttachmentAndSampler())
{
// texture code already picked layout and inserted barrier
imageLayout = image->getCurrentImageLayout();
ASSERT(imageLayout == ImageLayout::ColorAttachmentAndShaderRead);
}
else
{
imageLayout = ImageLayout::ColorAttachment;
updateImageLayoutAndBarrier(context, image, VK_IMAGE_ASPECT_COLOR_BIT, imageLayout);
}
if (!isResolveImage)
{
......@@ -1250,6 +1264,8 @@ void CommandBufferHelper::finalizeColorImageLayout(Context *context,
mImageOptimizeForPresent->getCurrentImageLayout());
mImageOptimizeForPresent = nullptr;
}
image->resetRenderPassUsageFlags();
}
void CommandBufferHelper::finalizeDepthStencilImageLayout(Context *context)
......@@ -1346,17 +1362,20 @@ void CommandBufferHelper::onImageHelperRelease(Context *context, const ImageHelp
{
ASSERT(mIsRenderPassCommandBuffer);
for (PackedAttachmentIndex index = kAttachmentIndexZero; index < mColorImagesCount; ++index)
if (image->hasRenderPassUseFlag(RenderPassUsage::RenderTargetAttachment))
{
if (mColorImages[index] == image)
{
finalizeColorImageLayout(context, mColorImages[index], index, false);
mColorImages[index] = nullptr;
}
if (mColorResolveImages[index] == image)
for (PackedAttachmentIndex index = kAttachmentIndexZero; index < mColorImagesCount; ++index)
{
finalizeColorImageLayout(context, mColorResolveImages[index], index, true);
mColorResolveImages[index] = nullptr;
if (mColorImages[index] == image)
{
finalizeColorImageLayout(context, mColorImages[index], index, false);
mColorImages[index] = nullptr;
}
else if (mColorResolveImages[index] == image)
{
finalizeColorImageLayout(context, mColorResolveImages[index], index, true);
mColorResolveImages[index] = nullptr;
}
}
}
......@@ -3637,6 +3656,7 @@ void ImageHelper::resetCachedProperties()
mLevelCount = 0;
mExternalFormat = 0;
mCurrentSingleClearValue.reset();
mRenderPassUseFlags.reset();
setEntireContentUndefined();
}
......@@ -4418,6 +4438,27 @@ bool ImageHelper::isDepthOrStencil() const
return mFormat->actualImageFormat().hasDepthOrStencilBits();
}
void ImageHelper::setRenderPassUsageFlag(RenderPassUsage flag)
{
mRenderPassUseFlags.set(flag);
}
void ImageHelper::resetRenderPassUsageFlags()
{
mRenderPassUseFlags.reset();
}
bool ImageHelper::hasRenderPassUseFlag(RenderPassUsage flag) const
{
return mRenderPassUseFlags.test(flag);
}
bool ImageHelper::usedByCurrentRenderPassAsAttachmentAndSampler() const
{
return mRenderPassUseFlags[RenderPassUsage::RenderTargetAttachment] &&
mRenderPassUseFlags[RenderPassUsage::TextureSampler];
}
bool ImageHelper::isReadBarrierNecessary(ImageLayout newLayout) const
{
// If transitioning to a different layout, we need always need a barrier.
......
......@@ -1169,7 +1169,6 @@ class CommandBufferHelper : angle::NonCopyable
bool usesBuffer(const BufferHelper &buffer) const;
bool usesBufferForWrite(const BufferHelper &buffer) const;
bool usesImageInRenderPass(const ImageHelper &image) const;
bool usesImageInAttachments(const ImageHelper &image);
size_t getUsedBuffersCount() const { return mUsedBuffers.size(); }
// Dumping the command stream is disabled by default.
......@@ -1348,6 +1347,7 @@ enum class ImageLayout
// Framebuffer attachment layouts are placed first, so they can fit in fewer bits in
// PackedAttachmentOpsDesc.
ColorAttachment,
ColorAttachmentAndShaderRead,
DepthStencilReadOnly,
DepthStencilAttachment,
DepthStencilResolveAttachment,
......@@ -1376,6 +1376,17 @@ enum class ImageLayout
VkImageLayout ConvertImageLayoutToVkImageLayout(ImageLayout imageLayout);
// How the ImageHelper object is being used by the renderpass
enum class RenderPassUsage
{
RenderTargetAttachment,
TextureSampler,
InvalidEnum,
EnumCount = InvalidEnum,
};
using RenderPassUseFlags = angle::PackedEnumBitSet<RenderPassUsage, uint16_t>;
bool FormatHasNecessaryFeature(RendererVk *renderer,
angle::FormatID formatID,
VkImageTiling tilingMode,
......@@ -1558,8 +1569,14 @@ class ImageHelper final : public Resource, public angle::Subject
// image.
gl::Extents getLevelExtents2D(LevelIndex levelVk) const;
gl::Extents getRotatedLevelExtents2D(LevelIndex levelVk) const;
bool isDepthOrStencil() const;
void setRenderPassUsageFlag(RenderPassUsage flag);
void resetRenderPassUsageFlags();
bool hasRenderPassUseFlag(RenderPassUsage flag) const;
bool usedByCurrentRenderPassAsAttachmentAndSampler() const;
// Clear either color or depth/stencil based on image format.
void clear(VkImageAspectFlags aspectFlags,
const VkClearValue &value,
......@@ -2031,6 +2048,8 @@ class ImageHelper final : public Resource, public angle::Subject
// For optimizing transition between different shader readonly layouts
ImageLayout mLastNonShaderReadOnlyLayout;
VkPipelineStageFlags mCurrentShaderReadStageMask;
// Track how it is being used by current open renderpass.
RenderPassUseFlags mRenderPassUseFlags;
// For imported images
BindingPointer<SamplerYcbcrConversion> mYuvConversionSampler;
......
......@@ -2476,8 +2476,8 @@ void main()
// (https://issuetracker.google.com/175584609) is doing exactly this.
TEST_P(FramebufferTest_ES3, SampleFromAttachedTextureWithDifferentLOD)
{
// TODO: https://issuetracker.google.com/175584609
ANGLE_SKIP_TEST_IF(IsVulkan() || IsWindows());
// TODO: https://anglebug.com/5760
ANGLE_SKIP_TEST_IF(IsVulkan() || IsD3D());
constexpr GLuint kLevel0Size = 4;
constexpr GLuint kLevel1Size = kLevel0Size / 2;
......
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