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, ...@@ -77,27 +77,47 @@ bool IsTextureLevelDefinitionCompatibleWithImage(const vk::ImageHelper &image,
return size == image.getLevelExtents(imageLevelIndexVK) && format == image.getFormat(); 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, bool CanCopyWithTransfer(RendererVk *renderer,
const vk::Format &srcFormat, 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 // 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. // size and are compatible, but for now, let's just support same-format copies with transfer.
return srcFormat.internalFormat == destFormat.internalFormat && bool isFormatCompatible = srcFormat.internalFormat == destFormat.internalFormat;
renderer->hasImageFormatFeatureBits(srcFormat.vkImageFormat, bool isTilingCompatible = srcTilingMode == destTilingMode;
VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) && bool srcFormatHasNecessaryFeature = FormatHasNecessaryFeature(
renderer->hasImageFormatFeatureBits(destFormat.vkImageFormat, renderer, srcFormat.vkImageFormat, srcTilingMode, VK_FORMAT_FEATURE_TRANSFER_SRC_BIT);
VK_FORMAT_FEATURE_TRANSFER_DST_BIT); bool dstFormatHasNecessaryFeature = FormatHasNecessaryFeature(
renderer, destFormat.vkImageFormat, destTilingMode, VK_FORMAT_FEATURE_TRANSFER_DST_BIT);
return isFormatCompatible && isTilingCompatible && srcFormatHasNecessaryFeature &&
dstFormatHasNecessaryFeature;
} }
bool CanCopyWithDraw(RendererVk *renderer, bool CanCopyWithDraw(RendererVk *renderer,
const vk::Format &srcFormat, const vk::Format &srcFormat,
const vk::Format &destFormat) VkImageTiling srcTilingMode,
const vk::Format &destFormat,
VkImageTiling destTilingMode)
{ {
return renderer->hasImageFormatFeatureBits(srcFormat.vkImageFormat, bool srcFormatHasNecessaryFeature = FormatHasNecessaryFeature(
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) && renderer, srcFormat.vkImageFormat, srcTilingMode, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT);
renderer->hasImageFormatFeatureBits(destFormat.vkImageFormat, bool dstFormatHasNecessaryFeature = FormatHasNecessaryFeature(
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT); renderer, destFormat.vkImageFormat, destTilingMode, VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT);
return srcFormatHasNecessaryFeature && dstFormatHasNecessaryFeature;
} }
bool ForceCPUPathForCopy(RendererVk *renderer, const vk::ImageHelper &image) bool ForceCPUPathForCopy(RendererVk *renderer, const vk::ImageHelper &image)
...@@ -508,12 +528,15 @@ angle::Result TextureVk::copySubImageImpl(const gl::Context *context, ...@@ -508,12 +528,15 @@ angle::Result TextureVk::copySubImageImpl(const gl::Context *context,
RenderTargetVk *colorReadRT = framebufferVk->getColorReadRenderTarget(); RenderTargetVk *colorReadRT = framebufferVk->getColorReadRenderTarget();
const vk::Format &srcFormat = colorReadRT->getImageFormat(); const vk::Format &srcFormat = colorReadRT->getImageFormat();
VkImageTiling srcTilingMode = colorReadRT->getImage().getTilingMode();
const vk::Format &destFormat = renderer->getFormat(internalFormat.sizedInternalFormat); const vk::Format &destFormat = renderer->getFormat(internalFormat.sizedInternalFormat);
VkImageTiling destTilingMode = getTilingMode();
bool isViewportFlipY = contextVk->isViewportFlipEnabledForReadFBO(); bool isViewportFlipY = contextVk->isViewportFlipEnabledForReadFBO();
// If it's possible to perform the copy with a transfer, that's the best option. // 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, return copySubImageImplWithTransfer(contextVk, offsetImageIndex, modifiedDestOffset,
destFormat, colorReadRT->getLevelIndex(), destFormat, colorReadRT->getLevelIndex(),
...@@ -524,7 +547,8 @@ angle::Result TextureVk::copySubImageImpl(const gl::Context *context, ...@@ -524,7 +547,8 @@ angle::Result TextureVk::copySubImageImpl(const gl::Context *context,
bool forceCPUPath = ForceCPUPathForCopy(renderer, *mImage); bool forceCPUPath = ForceCPUPathForCopy(renderer, *mImage);
// If it's possible to perform the copy with a draw call, do that. // 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. // Layer count can only be 1 as the source is a framebuffer.
ASSERT(offsetImageIndex.getLayerCount() == 1); ASSERT(offsetImageIndex.getLayerCount() == 1);
...@@ -563,13 +587,15 @@ angle::Result TextureVk::copySubTextureImpl(ContextVk *contextVk, ...@@ -563,13 +587,15 @@ angle::Result TextureVk::copySubTextureImpl(ContextVk *contextVk,
ANGLE_TRY(source->ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels)); ANGLE_TRY(source->ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
const vk::Format &sourceVkFormat = source->getImage().getFormat(); const vk::Format &sourceVkFormat = source->getImage().getFormat();
VkImageTiling srcTilingMode = source->getImage().getTilingMode();
const vk::Format &destVkFormat = renderer->getFormat(destFormat.sizedInternalFormat); const vk::Format &destVkFormat = renderer->getFormat(destFormat.sizedInternalFormat);
VkImageTiling destTilingMode = getTilingMode();
const gl::ImageIndex offsetImageIndex = getNativeImageIndex(index); const gl::ImageIndex offsetImageIndex = getNativeImageIndex(index);
// If it's possible to perform the copy with a transfer, that's the best option. // If it's possible to perform the copy with a transfer, that's the best option.
if (!unpackFlipY && !unpackPremultiplyAlpha && !unpackUnmultiplyAlpha && if (!unpackFlipY && !unpackPremultiplyAlpha && !unpackUnmultiplyAlpha &&
CanCopyWithTransfer(renderer, sourceVkFormat, destVkFormat)) CanCopyWithTransfer(renderer, sourceVkFormat, srcTilingMode, destVkFormat, destTilingMode))
{ {
return copySubImageImplWithTransfer(contextVk, offsetImageIndex, destOffset, destVkFormat, return copySubImageImplWithTransfer(contextVk, offsetImageIndex, destOffset, destVkFormat,
sourceLevel, 0, sourceArea, &source->getImage()); sourceLevel, 0, sourceArea, &source->getImage());
...@@ -579,7 +605,8 @@ angle::Result TextureVk::copySubTextureImpl(ContextVk *contextVk, ...@@ -579,7 +605,8 @@ angle::Result TextureVk::copySubTextureImpl(ContextVk *contextVk,
(destFormat.colorEncoding == GL_SRGB) || ForceCPUPathForCopy(renderer, *mImage); (destFormat.colorEncoding == GL_SRGB) || ForceCPUPathForCopy(renderer, *mImage);
// If it's possible to perform the copy with a draw call, do that. // 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( return copySubImageImplWithDraw(
contextVk, offsetImageIndex, destOffset, destVkFormat, sourceLevel, sourceArea, false, contextVk, offsetImageIndex, destOffset, destVkFormat, sourceLevel, sourceArea, false,
......
...@@ -388,6 +388,11 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface ...@@ -388,6 +388,11 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface
// support changes in the staging buffer even outside the TextureVk class. // support changes in the staging buffer even outside the TextureVk class.
void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override; void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
ANGLE_INLINE VkImageTiling getTilingMode()
{
return (mImage->valid()) ? mImage->getTilingMode() : VK_IMAGE_TILING_OPTIMAL;
}
bool mOwnsImage; bool mOwnsImage;
gl::TextureType mImageNativeType; gl::TextureType mImageNativeType;
......
...@@ -1126,6 +1126,7 @@ class ImageHelper final : public Resource, public angle::Subject ...@@ -1126,6 +1126,7 @@ class ImageHelper final : public Resource, public angle::Subject
const DeviceMemory &getDeviceMemory() const { return mDeviceMemory; } const DeviceMemory &getDeviceMemory() const { return mDeviceMemory; }
void setTilingMode(VkImageTiling tilingMode) { mTilingMode = tilingMode; } void setTilingMode(VkImageTiling tilingMode) { mTilingMode = tilingMode; }
VkImageTiling getTilingMode() { return mTilingMode; }
VkImageType getType() const { return mImageType; } VkImageType getType() const { return mImageType; }
const VkExtent3D &getExtents() const { return mExtents; } const VkExtent3D &getExtents() const { return mExtents; }
uint32_t getLayerCount() const { return mLayerCount; } 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