Commit bc8199fa by Mohan Maiya Committed by Commit Bot

Vulkan: Ensure tiling mode compatibility while deciding copy path

When decided whether to use transfer or the draw path to perform an image to image copy make sure to account for compatibility in tiling modes. Bug: angleproject:4743 Change-Id: I757aab0ac8628f08092dc2dfc39f06d112db5089 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2246527 Commit-Queue: Mohan Maiya <m.maiya@samsung.com> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 959037e0
......@@ -77,27 +77,47 @@ bool IsTextureLevelDefinitionCompatibleWithImage(const vk::ImageHelper &image,
return size == image.getLevelExtents(imageLevelIndexVK) && format == image.getFormat();
}
ANGLE_INLINE bool FormatHasNecessaryFeature(RendererVk *renderer,
VkFormat format,
VkImageTiling tilingMode,
VkFormatFeatureFlags featureBits)
{
return (tilingMode == VK_IMAGE_TILING_OPTIMAL)
? renderer->hasImageFormatFeatureBits(format, featureBits)
: renderer->hasLinearImageFormatFeatureBits(format, featureBits);
}
bool CanCopyWithTransfer(RendererVk *renderer,
const vk::Format &srcFormat,
const vk::Format &destFormat)
VkImageTiling srcTilingMode,
const vk::Format &destFormat,
VkImageTiling destTilingMode)
{
// NOTE(syoussefi): technically, you can transfer between formats as long as they have the same
// size and are compatible, but for now, let's just support same-format copies with transfer.
return srcFormat.internalFormat == destFormat.internalFormat &&
renderer->hasImageFormatFeatureBits(srcFormat.vkImageFormat,
VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) &&
renderer->hasImageFormatFeatureBits(destFormat.vkImageFormat,
VK_FORMAT_FEATURE_TRANSFER_DST_BIT);
bool isFormatCompatible = srcFormat.internalFormat == destFormat.internalFormat;
bool isTilingCompatible = srcTilingMode == destTilingMode;
bool srcFormatHasNecessaryFeature = FormatHasNecessaryFeature(
renderer, srcFormat.vkImageFormat, srcTilingMode, VK_FORMAT_FEATURE_TRANSFER_SRC_BIT);
bool dstFormatHasNecessaryFeature = FormatHasNecessaryFeature(
renderer, destFormat.vkImageFormat, destTilingMode, VK_FORMAT_FEATURE_TRANSFER_DST_BIT);
return isFormatCompatible && isTilingCompatible && srcFormatHasNecessaryFeature &&
dstFormatHasNecessaryFeature;
}
bool CanCopyWithDraw(RendererVk *renderer,
const vk::Format &srcFormat,
const vk::Format &destFormat)
VkImageTiling srcTilingMode,
const vk::Format &destFormat,
VkImageTiling destTilingMode)
{
return renderer->hasImageFormatFeatureBits(srcFormat.vkImageFormat,
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) &&
renderer->hasImageFormatFeatureBits(destFormat.vkImageFormat,
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT);
bool srcFormatHasNecessaryFeature = FormatHasNecessaryFeature(
renderer, srcFormat.vkImageFormat, srcTilingMode, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT);
bool dstFormatHasNecessaryFeature = FormatHasNecessaryFeature(
renderer, destFormat.vkImageFormat, destTilingMode, VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT);
return srcFormatHasNecessaryFeature && dstFormatHasNecessaryFeature;
}
bool ForceCPUPathForCopy(RendererVk *renderer, const vk::ImageHelper &image)
......@@ -508,12 +528,15 @@ angle::Result TextureVk::copySubImageImpl(const gl::Context *context,
RenderTargetVk *colorReadRT = framebufferVk->getColorReadRenderTarget();
const vk::Format &srcFormat = colorReadRT->getImageFormat();
VkImageTiling srcTilingMode = colorReadRT->getImage().getTilingMode();
const vk::Format &destFormat = renderer->getFormat(internalFormat.sizedInternalFormat);
VkImageTiling destTilingMode = getTilingMode();
bool isViewportFlipY = contextVk->isViewportFlipEnabledForReadFBO();
// If it's possible to perform the copy with a transfer, that's the best option.
if (!isViewportFlipY && CanCopyWithTransfer(renderer, srcFormat, destFormat))
if (!isViewportFlipY &&
CanCopyWithTransfer(renderer, srcFormat, srcTilingMode, destFormat, destTilingMode))
{
return copySubImageImplWithTransfer(contextVk, offsetImageIndex, modifiedDestOffset,
destFormat, colorReadRT->getLevelIndex(),
......@@ -524,7 +547,8 @@ angle::Result TextureVk::copySubImageImpl(const gl::Context *context,
bool forceCPUPath = ForceCPUPathForCopy(renderer, *mImage);
// If it's possible to perform the copy with a draw call, do that.
if (CanCopyWithDraw(renderer, srcFormat, destFormat) && !forceCPUPath)
if (CanCopyWithDraw(renderer, srcFormat, srcTilingMode, destFormat, destTilingMode) &&
!forceCPUPath)
{
// Layer count can only be 1 as the source is a framebuffer.
ASSERT(offsetImageIndex.getLayerCount() == 1);
......@@ -563,13 +587,15 @@ angle::Result TextureVk::copySubTextureImpl(ContextVk *contextVk,
ANGLE_TRY(source->ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
const vk::Format &sourceVkFormat = source->getImage().getFormat();
VkImageTiling srcTilingMode = source->getImage().getTilingMode();
const vk::Format &destVkFormat = renderer->getFormat(destFormat.sizedInternalFormat);
VkImageTiling destTilingMode = getTilingMode();
const gl::ImageIndex offsetImageIndex = getNativeImageIndex(index);
// If it's possible to perform the copy with a transfer, that's the best option.
if (!unpackFlipY && !unpackPremultiplyAlpha && !unpackUnmultiplyAlpha &&
CanCopyWithTransfer(renderer, sourceVkFormat, destVkFormat))
CanCopyWithTransfer(renderer, sourceVkFormat, srcTilingMode, destVkFormat, destTilingMode))
{
return copySubImageImplWithTransfer(contextVk, offsetImageIndex, destOffset, destVkFormat,
sourceLevel, 0, sourceArea, &source->getImage());
......@@ -579,7 +605,8 @@ angle::Result TextureVk::copySubTextureImpl(ContextVk *contextVk,
(destFormat.colorEncoding == GL_SRGB) || ForceCPUPathForCopy(renderer, *mImage);
// If it's possible to perform the copy with a draw call, do that.
if (CanCopyWithDraw(renderer, sourceVkFormat, destVkFormat) && !forceCPUPath)
if (CanCopyWithDraw(renderer, sourceVkFormat, srcTilingMode, destVkFormat, destTilingMode) &&
!forceCPUPath)
{
return copySubImageImplWithDraw(
contextVk, offsetImageIndex, destOffset, destVkFormat, sourceLevel, sourceArea, false,
......
......@@ -388,6 +388,11 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface
// support changes in the staging buffer even outside the TextureVk class.
void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
ANGLE_INLINE VkImageTiling getTilingMode()
{
return (mImage->valid()) ? mImage->getTilingMode() : VK_IMAGE_TILING_OPTIMAL;
}
bool mOwnsImage;
gl::TextureType mImageNativeType;
......
......@@ -1126,6 +1126,7 @@ class ImageHelper final : public Resource, public angle::Subject
const DeviceMemory &getDeviceMemory() const { return mDeviceMemory; }
void setTilingMode(VkImageTiling tilingMode) { mTilingMode = tilingMode; }
VkImageTiling getTilingMode() { return mTilingMode; }
VkImageType getType() const { return mImageType; }
const VkExtent3D &getExtents() const { return mExtents; }
uint32_t getLayerCount() const { return mLayerCount; }
......
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