Commit acf004a1 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Use transfer more opportunistically with copyTextureCHROMIUM

If the difference between formats is sRGB vs not or normalized vs integer, still allow the transfer path to be taken. Bug: b/159211070 Change-Id: I53334812ed29baec6ad434de1fcd6dde35049c12 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2551534 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com>
parent cf336839
......@@ -52,6 +52,7 @@ struct Format final : private angle::NonCopyable
constexpr bool hasDepthOrStencilBits() const;
constexpr bool isLUMA() const;
constexpr bool isBGRA() const;
constexpr bool isSint() const;
constexpr bool isUint() const;
......@@ -189,6 +190,12 @@ constexpr bool Format::isLUMA() const
return redBits == 0 && (luminanceBits > 0 || alphaBits > 0);
}
constexpr bool Format::isBGRA() const
{
return id == FormatID::B8G8R8A8_UNORM || id == FormatID::B8G8R8A8_UNORM_SRGB ||
id == FormatID::B8G8R8A8_TYPELESS || id == FormatID::B8G8R8A8_TYPELESS_SRGB;
}
constexpr bool Format::isSint() const
{
return componentType == GL_INT;
......
......@@ -82,18 +82,66 @@ bool IsTextureLevelDefinitionCompatibleWithImage(const vk::ImageHelper &image,
return size == image.getLevelExtents(imageLevelIndexVk) && format == image.getFormat();
}
bool CanCopyWithTransferForTexImage(RendererVk *renderer,
const vk::Format &srcFormat,
VkImageTiling srcTilingMode,
const vk::Format &destFormat,
VkImageTiling destTilingMode)
{
// For glTex[Sub]Image, only accept same-format transfers.
bool isFormatCompatible = srcFormat.intendedFormatID == destFormat.intendedFormatID;
return isFormatCompatible &&
vk::CanCopyWithTransfer(renderer, srcFormat, srcTilingMode, destFormat, destTilingMode);
}
bool CanCopyWithTransferForCopyTexture(RendererVk *renderer,
const vk::Format &srcFormat,
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.
bool isFormatCompatible = srcFormat.internalFormat == destFormat.internalFormat;
if (!vk::CanCopyWithTransfer(renderer, srcFormat, srcTilingMode, destFormat, destTilingMode))
{
return false;
}
return isFormatCompatible &&
vk::CanCopyWithTransfer(renderer, srcFormat, srcTilingMode, destFormat, destTilingMode);
// If the formats are identical, we can always transfer between them.
if (srcFormat.intendedFormatID == destFormat.intendedFormatID)
{
return true;
}
// If either format is emulated, cannot transfer.
if (srcFormat.hasEmulatedImageFormat() || destFormat.hasEmulatedImageFormat())
{
return false;
}
// Otherwise, allow transfer between compatible formats. This is derived from the specification
// of CHROMIUM_copy_texture.
const angle::Format &srcAngleFormat = srcFormat.actualImageFormat();
const angle::Format &destAngleFormat = destFormat.actualImageFormat();
const bool srcIsBGRA = srcAngleFormat.isBGRA();
const bool srcHasR8 = srcAngleFormat.redBits == 8;
const bool srcHasG8 = srcAngleFormat.greenBits == 8;
const bool srcHasB8 = srcAngleFormat.blueBits == 8;
const bool srcHasA8 = srcAngleFormat.alphaBits == 8;
const bool srcIsSigned = srcAngleFormat.isSnorm() || srcAngleFormat.isSint();
const bool destIsBGRA = destAngleFormat.isBGRA();
const bool destHasR8 = destAngleFormat.redBits == 8;
const bool destHasG8 = destAngleFormat.greenBits == 8;
const bool destHasB8 = destAngleFormat.blueBits == 8;
const bool destHasA8 = destAngleFormat.alphaBits == 8;
const bool destIsSigned = destAngleFormat.isSnorm() || destAngleFormat.isSint();
// Copy is allowed as long as they have the same number, ordering and sign of (8-bit) channels.
// CHROMIUM_copy_texture expects verbatim copy between these format, so this copy is done
// regardless of sRGB, normalized, etc.
return srcIsBGRA == destIsBGRA && srcHasR8 == destHasR8 && srcHasG8 == destHasG8 &&
srcHasB8 == destHasB8 && srcHasA8 == destHasA8 && srcIsSigned == destIsSigned;
}
bool CanCopyWithDraw(RendererVk *renderer,
......@@ -706,8 +754,8 @@ angle::Result TextureVk::copySubImageImpl(const gl::Context *context,
clippedSourceArea.width, clippedSourceArea.height, 1);
// If it's possible to perform the copy with a transfer, that's the best option.
if (!isViewportFlipY && CanCopyWithTransferForCopyTexture(renderer, srcFormat, srcTilingMode,
destFormat, destTilingMode))
if (!isViewportFlipY && CanCopyWithTransferForTexImage(renderer, srcFormat, srcTilingMode,
destFormat, destTilingMode))
{
return copySubImageImplWithTransfer(contextVk, offsetImageIndex, modifiedDestOffset,
destFormat, colorReadRT->getLevelIndex(),
......
......@@ -100,9 +100,12 @@ struct Format final : private angle::NonCopyable
size_t getImageCopyBufferAlignment() const;
size_t getValidImageCopyBufferAlignment() const;
// Returns true if the Image format has more channels than the ANGLE format.
// Returns true if the image format has more channels than the ANGLE format.
bool hasEmulatedImageChannels() const;
// Returns true if the image has a different image format than intended.
bool hasEmulatedImageFormat() const { return actualImageFormatID != intendedFormatID; }
// This is an auto-generated method in vk_format_table_autogen.cpp.
void initialize(RendererVk *renderer, const angle::Format &angleFormat);
......
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