//
// Copyright 2016 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// TextureVk.cpp:
//    Implements the class methods for TextureVk.
//

#ifdef UNSAFE_BUFFERS_BUILD
#    pragma allow_unsafe_buffers
#endif

#include "libANGLE/renderer/vulkan/TextureVk.h"
#include <vulkan/vulkan.h>

#include "common/debug.h"
#include "image_util/generatemip.inc"
#include "libANGLE/Config.h"
#include "libANGLE/Context.h"
#include "libANGLE/Image.h"
#include "libANGLE/MemoryObject.h"
#include "libANGLE/Surface.h"
#include "libANGLE/renderer/renderer_utils.h"
#include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/FramebufferVk.h"
#include "libANGLE/renderer/vulkan/ImageVk.h"
#include "libANGLE/renderer/vulkan/MemoryObjectVk.h"
#include "libANGLE/renderer/vulkan/RenderbufferVk.h"
#include "libANGLE/renderer/vulkan/SurfaceVk.h"
#include "libANGLE/renderer/vulkan/UtilsVk.h"
#include "libANGLE/renderer/vulkan/vk_format_utils.h"
#include "libANGLE/renderer/vulkan/vk_helpers.h"
#include "libANGLE/renderer/vulkan/vk_renderer.h"
#include "libANGLE/renderer/vulkan/vk_utils.h"

namespace rx
{
namespace
{
constexpr VkImageUsageFlags kColorAttachmentImageFlags =
    VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;

constexpr VkImageUsageFlags kDrawStagingImageFlags =
    vk::kImageUsageTransferBits | kColorAttachmentImageFlags;

constexpr VkFormatFeatureFlags kBlitFeatureFlags =
    VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT;

constexpr VkImageAspectFlags kDepthStencilAspects =
    VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT;

constexpr angle::SubjectIndex kTextureImageSubjectIndex = 0;

// Test whether a texture level is within the range of levels for which the current image is
// allocated.  This is used to ensure out-of-range updates are staged in the image, and not
// attempted to be directly applied.
bool IsTextureLevelInAllocatedImage(const vk::ImageHelper &image,
                                    gl::LevelIndex textureLevelIndexGL)
{
    gl::LevelIndex imageFirstAllocateLevel = image.getFirstAllocatedLevel();
    if (textureLevelIndexGL < imageFirstAllocateLevel)
    {
        return false;
    }

    vk::LevelIndex imageLevelIndexVk = image.toVkLevel(textureLevelIndexGL);
    return imageLevelIndexVk < vk::LevelIndex(image.getLevelCount());
}

// Test whether a redefined texture level is compatible with the currently allocated image.  Returns
// true if the given size and format match the corresponding mip in the allocated image (taking
// base level into account).  This could return false when:
//
// - Defining a texture level that is outside the range of the image levels.  In this case, changes
//   to this level should remain staged until the texture is redefined to include this level.
// - Redefining a texture level that is within the range of the image levels, but has a different
//   size or format.  In this case too, changes to this level should remain staged as the texture
//   is no longer complete as is.
bool IsTextureLevelDefinitionCompatibleWithImage(const vk::ImageHelper &image,
                                                 gl::LevelIndex textureLevelIndexGL,
                                                 const gl::Extents &size,
                                                 angle::FormatID intendedFormatID,
                                                 angle::FormatID actualFormatID)
{
    if (!IsTextureLevelInAllocatedImage(image, textureLevelIndexGL))
    {
        return false;
    }

    vk::LevelIndex imageLevelIndexVk = image.toVkLevel(textureLevelIndexGL);
    return size == image.getLevelExtents(imageLevelIndexVk) &&
           intendedFormatID == image.getIntendedFormatID() &&
           actualFormatID == image.getActualFormatID();
}

bool CanCopyWithTransferForTexImage(vk::Renderer *renderer,
                                    const vk::ImageHelper &srcImage,
                                    angle::FormatID dstIntendedFormatID,
                                    angle::FormatID dstActualFormatID,
                                    VkImageTiling dstTilingMode,
                                    bool isViewportFlipY)
{
    // For glTex[Sub]Image, only accept same-format transfers.
    // There are cases that two images' actual format is the same, but intended formats are
    // different due to one is using the fallback format (for example, RGB fallback to RGBA). In
    // these situations CanCopyWithTransfer will say yes. But if we use transfer to do copy, the
    // alpha channel will be also be copied with source data which is wrong.
    bool isFormatCompatible = srcImage.getIntendedFormatID() == dstIntendedFormatID &&
                              srcImage.getActualFormatID() == dstActualFormatID;

    return !isViewportFlipY && isFormatCompatible &&
           vk::CanCopyWithTransfer(renderer, srcImage.getUsage(), dstActualFormatID, dstTilingMode);
}

bool CanCopyWithTransferForCopyTexture(vk::Renderer *renderer,
                                       const vk::ImageHelper &srcImage,
                                       angle::FormatID destIntendedFormatID,
                                       angle::FormatID destActualFormatID,
                                       VkImageTiling destTilingMode,
                                       bool unpackFlipY,
                                       bool unpackPremultiplyAlpha,
                                       bool unpackUnmultiplyAlpha)
{
    if (unpackFlipY || unpackPremultiplyAlpha || unpackUnmultiplyAlpha)
    {
        return false;
    }

    if (!vk::CanCopyWithTransfer(renderer, srcImage.getUsage(), destActualFormatID, destTilingMode))
    {
        return false;
    }

    // If the formats are identical, we can always transfer between them.
    if (srcImage.getIntendedFormatID() == destIntendedFormatID &&
        srcImage.getActualFormatID() == destActualFormatID)
    {
        return true;
    }

    // If either format is emulated, cannot transfer.
    if (srcImage.hasEmulatedImageFormat() ||
        vk::HasEmulatedImageFormat(destIntendedFormatID, destActualFormatID))
    {
        return false;
    }

    // Otherwise, allow transfer between compatible formats.  This is derived from the specification
    // of CHROMIUM_copy_texture.
    const angle::Format &srcAngleFormat  = srcImage.getActualFormat();
    const angle::Format &destAngleFormat = angle::Format::Get(destActualFormatID);

    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(vk::Renderer *renderer,
                     VkImageUsageFlags srcUsage,
                     const angle::FormatID dstFormatID,
                     VkImageTiling destTilingMode)
{
    // Checks that the formats in copy by drawing have the appropriate feature bits
    bool srcFormatHasNecessaryFeature = (srcUsage & VK_IMAGE_USAGE_SAMPLED_BIT) != 0;
    bool dstFormatHasNecessaryFeature = vk::FormatHasNecessaryFeature(
        renderer, dstFormatID, destTilingMode, VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT);

    return srcFormatHasNecessaryFeature && dstFormatHasNecessaryFeature;
}

bool CanGenerateMipmapWithCompute(vk::Renderer *renderer,
                                  VkImageType imageType,
                                  angle::FormatID formatID,
                                  GLint samples,
                                  bool canBeRespecified)
{
    // Feature needs to be enabled
    if (!renderer->getFeatures().allowGenerateMipmapWithCompute.enabled)
    {
        return false;
    }

    // We need to be able to respecify the backing image
    if (!canBeRespecified)
    {
        return false;
    }

    const angle::Format &angleFormat = angle::Format::Get(formatID);
    // Format must have STORAGE support.
    const bool hasStorageSupport =
        renderer->hasImageFormatFeatureBits(formatID, VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT);

    // No support for sRGB formats yet.
    const bool isSRGB = angleFormat.isSRGB;

    // No support for integer formats yet.
    const bool isInt = angleFormat.isInt();

    // Only 2D images are supported.
    const bool is2D = imageType == VK_IMAGE_TYPE_2D;

    // No support for multisampled images yet.
    const bool isMultisampled = samples > 1;

    // Only color formats are supported.
    const bool isColorFormat = !angleFormat.hasDepthOrStencilBits();

    return hasStorageSupport && !isSRGB && !isInt && is2D && !isMultisampled && isColorFormat;
}

void GetRenderTargetLayerCountAndIndex(vk::ImageHelper *image,
                                       const gl::ImageIndex &index,
                                       GLuint *layerIndex,
                                       GLuint *layerCount,
                                       GLuint *imageLayerCount)
{
    *layerIndex = index.hasLayer() ? index.getLayerIndex() : 0;
    *layerCount = index.getLayerCount();

    switch (index.getType())
    {
        case gl::TextureType::_2D:
        case gl::TextureType::_2DMultisample:
        case gl::TextureType::External:
            ASSERT(*layerIndex == 0 &&
                   (*layerCount == 1 ||
                    *layerCount == static_cast<GLuint>(gl::ImageIndex::kEntireLevel)));
            *imageLayerCount = 1;
            break;

        case gl::TextureType::CubeMap:
            ASSERT(!index.hasLayer() ||
                   *layerIndex == static_cast<GLuint>(index.cubeMapFaceIndex()));
            *imageLayerCount = gl::kCubeFaceCount;
            break;

        case gl::TextureType::_3D:
        {
            gl::LevelIndex levelGL(index.getLevelIndex());
            *imageLayerCount = image->getLevelExtents(image->toVkLevel(levelGL)).depth;
            break;
        }

        case gl::TextureType::_2DArray:
        case gl::TextureType::_2DMultisampleArray:
        case gl::TextureType::CubeMapArray:
            *imageLayerCount = image->getLayerCount();
            break;

        default:
            UNREACHABLE();
    }

    if (*layerCount == static_cast<GLuint>(gl::ImageIndex::kEntireLevel))
    {
        ASSERT(*layerIndex == 0);
        *layerCount = *imageLayerCount;
    }
}

void Set3DBaseArrayLayerAndLayerCount(VkImageSubresourceLayers *Subresource)
{
    // If the srcImage/dstImage parameters are of VkImageType VK_IMAGE_TYPE_3D, the baseArrayLayer
    // and layerCount members of the corresponding subresource must be 0 and 1, respectively.
    Subresource->baseArrayLayer = 0;
    Subresource->layerCount     = 1;
}

const vk::Format *AdjustStorageViewFormatPerWorkarounds(vk::Renderer *renderer,
                                                        const vk::Format *intended,
                                                        vk::ImageFormatSupport formatSupport)
{
    // r32f images are emulated with r32ui.
    if (renderer->getFeatures().emulateR32fImageAtomicExchange.enabled &&
        intended->getActualImageFormatID(formatSupport) == angle::FormatID::R32_FLOAT)
    {
        return &renderer->getFormat(angle::FormatID::R32_UINT);
    }

    return intended;
}

const vk::Format *AdjustViewFormatForSampler(vk::Renderer *renderer,
                                             const vk::Format *intended,
                                             gl::SamplerFormat samplerFormat)
{
    switch (samplerFormat)
    {
        case gl::SamplerFormat::Float:
            switch (intended->getIntendedFormatID())
            {
                case angle::FormatID::R8_UNORM:
                case angle::FormatID::R8G8_UNORM:
                case angle::FormatID::R8G8B8A8_UNORM:
                case angle::FormatID::R16_UNORM:
                case angle::FormatID::R16G16_UNORM:
                case angle::FormatID::R16G16B16A16_UNORM:
                case angle::FormatID::R16_FLOAT:
                case angle::FormatID::R16G16_FLOAT:
                case angle::FormatID::R16G16B16A16_FLOAT:
                case angle::FormatID::R32_FLOAT:
                case angle::FormatID::R32G32_FLOAT:
                case angle::FormatID::R32G32B32_FLOAT:
                case angle::FormatID::R32G32B32A32_FLOAT:
                    return intended;
                case angle::FormatID::R8_SINT:
                case angle::FormatID::R8_UINT:
                    return &renderer->getFormat(angle::FormatID::R8_UNORM);
                case angle::FormatID::R16_SINT:
                case angle::FormatID::R16_UINT:
                    return &renderer->getFormat(angle::FormatID::R16_FLOAT);
                case angle::FormatID::R32_SINT:
                case angle::FormatID::R32_UINT:
                    return &renderer->getFormat(angle::FormatID::R32_FLOAT);
                case angle::FormatID::R8G8_SINT:
                case angle::FormatID::R8G8_UINT:
                    return &renderer->getFormat(angle::FormatID::R8G8_UNORM);
                case angle::FormatID::R16G16_SINT:
                case angle::FormatID::R16G16_UINT:
                    return &renderer->getFormat(angle::FormatID::R16G16_FLOAT);
                case angle::FormatID::R32G32_SINT:
                case angle::FormatID::R32G32_UINT:
                    return &renderer->getFormat(angle::FormatID::R32G32_FLOAT);
                case angle::FormatID::R32G32B32_SINT:
                case angle::FormatID::R32G32B32_UINT:
                    return &renderer->getFormat(angle::FormatID::R32G32B32_FLOAT);
                case angle::FormatID::R8G8B8A8_SINT:
                case angle::FormatID::R8G8B8A8_UINT:
                    return &renderer->getFormat(angle::FormatID::R8G8B8A8_UNORM);
                case angle::FormatID::R16G16B16A16_SINT:
                case angle::FormatID::R16G16B16A16_UINT:
                    return &renderer->getFormat(angle::FormatID::R16G16B16A16_FLOAT);
                case angle::FormatID::R32G32B32A32_SINT:
                case angle::FormatID::R32G32B32A32_UINT:
                    return &renderer->getFormat(angle::FormatID::R32G32B32A32_FLOAT);
                default:
                    UNREACHABLE();
                    return intended;
            }
        case gl::SamplerFormat::Unsigned:
            switch (intended->getIntendedFormatID())
            {
                case angle::FormatID::R8_UINT:
                case angle::FormatID::R16_UINT:
                case angle::FormatID::R32_UINT:
                case angle::FormatID::R8G8_UINT:
                case angle::FormatID::R16G16_UINT:
                case angle::FormatID::R32G32_UINT:
                case angle::FormatID::R32G32B32_UINT:
                case angle::FormatID::R8G8B8A8_UINT:
                case angle::FormatID::R16G16B16A16_UINT:
                case angle::FormatID::R32G32B32A32_UINT:
                    return intended;
                case angle::FormatID::R8_UNORM:
                case angle::FormatID::R8_SINT:
                    return &renderer->getFormat(angle::FormatID::R8_UINT);
                case angle::FormatID::R16_FLOAT:
                case angle::FormatID::R16_SINT:
                    return &renderer->getFormat(angle::FormatID::R16_UINT);
                case angle::FormatID::R32_FLOAT:
                case angle::FormatID::R32_SINT:
                    return &renderer->getFormat(angle::FormatID::R32_UINT);
                case angle::FormatID::R8G8_UNORM:
                case angle::FormatID::R8G8_SINT:
                    return &renderer->getFormat(angle::FormatID::R8G8_UINT);
                case angle::FormatID::R16G16_FLOAT:
                case angle::FormatID::R16G16_SINT:
                    return &renderer->getFormat(angle::FormatID::R16G16_UINT);
                case angle::FormatID::R32G32_FLOAT:
                case angle::FormatID::R32G32_SINT:
                    return &renderer->getFormat(angle::FormatID::R32G32_UINT);
                case angle::FormatID::R32G32B32_FLOAT:
                case angle::FormatID::R32G32B32_SINT:
                    return &renderer->getFormat(angle::FormatID::R32G32B32_UINT);
                case angle::FormatID::R8G8B8A8_UNORM:
                case angle::FormatID::R8G8B8A8_SINT:
                    return &renderer->getFormat(angle::FormatID::R8G8B8A8_UINT);
                case angle::FormatID::R16G16B16A16_FLOAT:
                case angle::FormatID::R16G16B16A16_SINT:
                    return &renderer->getFormat(angle::FormatID::R16G16B16A16_UINT);
                case angle::FormatID::R32G32B32A32_FLOAT:
                case angle::FormatID::R32G32B32A32_SINT:
                    return &renderer->getFormat(angle::FormatID::R32G32B32A32_UINT);
                default:
                    UNREACHABLE();
                    return intended;
            }
        case gl::SamplerFormat::Signed:
            switch (intended->getIntendedFormatID())
            {
                case angle::FormatID::R8_SINT:
                case angle::FormatID::R16_SINT:
                case angle::FormatID::R32_SINT:
                case angle::FormatID::R8G8_SINT:
                case angle::FormatID::R16G16_SINT:
                case angle::FormatID::R32G32_SINT:
                case angle::FormatID::R32G32B32_SINT:
                case angle::FormatID::R8G8B8A8_SINT:
                case angle::FormatID::R16G16B16A16_SINT:
                case angle::FormatID::R32G32B32A32_SINT:
                    return intended;
                case angle::FormatID::R8_UNORM:
                case angle::FormatID::R8_UINT:
                    return &renderer->getFormat(angle::FormatID::R8_SINT);
                case angle::FormatID::R16_FLOAT:
                case angle::FormatID::R16_UINT:
                    return &renderer->getFormat(angle::FormatID::R16_SINT);
                case angle::FormatID::R32_FLOAT:
                case angle::FormatID::R32_UINT:
                    return &renderer->getFormat(angle::FormatID::R32_SINT);
                case angle::FormatID::R8G8_UNORM:
                case angle::FormatID::R8G8_UINT:
                    return &renderer->getFormat(angle::FormatID::R8G8_SINT);
                case angle::FormatID::R16G16_FLOAT:
                case angle::FormatID::R16G16_UINT:
                    return &renderer->getFormat(angle::FormatID::R16G16_SINT);
                case angle::FormatID::R32G32_FLOAT:
                case angle::FormatID::R32G32_UINT:
                    return &renderer->getFormat(angle::FormatID::R32G32_SINT);
                case angle::FormatID::R32G32B32_FLOAT:
                case angle::FormatID::R32G32B32_UINT:
                    return &renderer->getFormat(angle::FormatID::R32G32B32_SINT);
                case angle::FormatID::R8G8B8A8_UNORM:
                case angle::FormatID::R8G8B8A8_UINT:
                    return &renderer->getFormat(angle::FormatID::R8G8B8A8_SINT);
                case angle::FormatID::R16G16B16A16_FLOAT:
                case angle::FormatID::R16G16B16A16_UINT:
                    return &renderer->getFormat(angle::FormatID::R16G16B16A16_SINT);
                case angle::FormatID::R32G32B32A32_FLOAT:
                case angle::FormatID::R32G32B32A32_UINT:
                    return &renderer->getFormat(angle::FormatID::R32G32B32A32_SINT);
                default:
                    UNREACHABLE();
                    return intended;
            }
        default:
            UNREACHABLE();
            return intended;
    }
}

angle::FormatID GetRGBAEmulationDstFormat(angle::FormatID srcFormatID)
{
    switch (srcFormatID)
    {
        case angle::FormatID::R32G32B32_UINT:
            return angle::FormatID::R32G32B32A32_UINT;
        case angle::FormatID::R32G32B32_SINT:
            return angle::FormatID::R32G32B32A32_SINT;
        case angle::FormatID::R32G32B32_FLOAT:
            return angle::FormatID::R32G32B32A32_FLOAT;
        default:
            return angle::FormatID::NONE;
    }
}

bool NeedsRGBAEmulation(vk::Renderer *renderer, angle::FormatID formatID)
{
    if (renderer->hasBufferFormatFeatureBits(formatID, VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT))
    {
        return false;
    }
    // Vulkan driver support is required for all formats except the ones we emulate.
    ASSERT(GetRGBAEmulationDstFormat(formatID) != angle::FormatID::NONE);
    return true;
}

GLint GetFormatSupportedCompressionRates(vk::Renderer *renderer,
                                         const vk::Format &format,
                                         GLsizei bufSize,
                                         GLint *rates)
{
    if (renderer->getFeatures().supportsImageCompressionControl.enabled)
    {
        VkImageCompressionControlEXT compressionInfo = {};
        compressionInfo.sType = VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT;
        // Use default compression control flag for query
        compressionInfo.flags = VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT;

        VkImageCompressionPropertiesEXT compressionProp = {};
        compressionProp.sType = VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT;

        if (vk::ImageHelper::FormatSupportsUsage(
                renderer,
                vk::GetVkFormatFromFormatID(renderer, format.getActualRenderableImageFormatID()),
                VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
                vk::kImageUsageTransferBits | VK_IMAGE_USAGE_SAMPLED_BIT |
                    VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
                0, &compressionInfo, &compressionProp,
                vk::ImageHelper::FormatSupportCheck::OnlyQuerySuccess))
        {
            if ((compressionProp.imageCompressionFlags &
                 VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT) != 0)
            {
                return vk_gl::ConvertCompressionFlagsToGLFixedRates(
                    compressionProp.imageCompressionFixedRateFlags, bufSize, rates);
            }
        }
    }

    return 0;
}

bool GetCompressionFixedRate(VkImageCompressionControlEXT *compressionInfo,
                             VkImageCompressionFixedRateFlagsEXT *compressionRates,
                             GLenum glCompressionRate)
{
    bool rtn = true;
    ASSERT(compressionInfo->sType == VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT);
    compressionInfo->compressionControlPlaneCount = 1;

    if (glCompressionRate == GL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT)
    {
        compressionInfo->flags = VK_IMAGE_COMPRESSION_DISABLED_EXT;
    }
    else if (glCompressionRate == GL_SURFACE_COMPRESSION_FIXED_RATE_DEFAULT_EXT)
    {
        compressionInfo->flags = VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT;
    }
    else if (glCompressionRate >= GL_SURFACE_COMPRESSION_FIXED_RATE_1BPC_EXT &&
             glCompressionRate <= GL_SURFACE_COMPRESSION_FIXED_RATE_12BPC_EXT)
    {
        int offset             = glCompressionRate - GL_SURFACE_COMPRESSION_FIXED_RATE_1BPC_EXT;
        compressionInfo->flags = VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT;
        *compressionRates      = 1u << offset;
        compressionInfo->pFixedRateFlags = compressionRates;
    }
    else
    {
        // Invalid value
        rtn = false;
    }

    return rtn;
}
}  // anonymous namespace

// TextureVk implementation.
TextureVk::TextureVk(const gl::TextureState &state, vk::Renderer *renderer)
    : TextureImpl(state),
      mOwnsImage(false),
      mRequiresMutableStorage(false),
      mRequiredFormatSupport(vk::ImageFormatSupport::SampleOnly),
      mImmutableSamplerDirty(false),
      mEGLImageNativeType(gl::TextureType::InvalidEnum),
      mEGLImageLayerOffset(0),
      mEGLImageLevelOffset(0),
      mImage(nullptr),
      mImageUsageFlags(0),
      mImageCreateFlags(0),
      mImageObserverBinding(this, kTextureImageSubjectIndex),
      mCurrentBaseLevel(state.getBaseLevel()),
      mCurrentMaxLevel(state.getMaxLevel()),
      mCachedImageViewSubresourceSerialSRGBDecode{},
      mCachedImageViewSubresourceSerialSkipDecode{}
{}

TextureVk::~TextureVk() = default;

void TextureVk::onDestroy(const gl::Context *context)
{
    ContextVk *contextVk = vk::GetImpl(context);

    releaseAndDeleteImageAndViews(contextVk);
    resetSampler();
}

angle::Result TextureVk::setImage(const gl::Context *context,
                                  const gl::ImageIndex &index,
                                  GLenum internalFormat,
                                  const gl::Extents &size,
                                  GLenum format,
                                  GLenum type,
                                  const gl::PixelUnpackState &unpack,
                                  gl::Buffer *unpackBuffer,
                                  const uint8_t *pixels)
{
    const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);

    return setImageImpl(context, index, formatInfo, size, type, unpack, unpackBuffer, pixels);
}

angle::Result TextureVk::setSubImage(const gl::Context *context,
                                     const gl::ImageIndex &index,
                                     const gl::Box &area,
                                     GLenum format,
                                     GLenum type,
                                     const gl::PixelUnpackState &unpack,
                                     gl::Buffer *unpackBuffer,
                                     const uint8_t *pixels)
{
    const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
    ContextVk *contextVk                 = vk::GetImpl(context);
    const gl::ImageDesc &levelDesc       = mState.getImageDesc(index);
    const vk::Format &vkFormat =
        contextVk->getRenderer()->getFormat(levelDesc.format.info->sizedInternalFormat);

    return setSubImageImpl(context, index, area, formatInfo, type, unpack, unpackBuffer, pixels,
                           vkFormat);
}

bool TextureVk::isCompressedFormatEmulated(const gl::Context *context,
                                           gl::TextureTarget target,
                                           GLint level)
{
    const gl::ImageDesc &levelDesc = mState.getImageDesc(target, level);
    if (!levelDesc.format.info->compressed)
    {
        // If it isn't compressed, the remaining logic won't work
        return false;
    }

    // Check against the list of formats used to emulate compressed textures
    return gl::IsEmulatedCompressedFormat(levelDesc.format.info->sizedInternalFormat);
}

angle::Result TextureVk::setCompressedImage(const gl::Context *context,
                                            const gl::ImageIndex &index,
                                            GLenum internalFormat,
                                            const gl::Extents &size,
                                            const gl::PixelUnpackState &unpack,
                                            size_t imageSize,
                                            const uint8_t *pixels)
{
    const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);

    const gl::State &glState = context->getState();
    gl::Buffer *unpackBuffer = glState.getTargetBuffer(gl::BufferBinding::PixelUnpack);

    if (unpackBuffer &&
        this->isCompressedFormatEmulated(context, index.getTarget(), index.getLevelIndex()))
    {
        // TODO (anglebug.com/42265933): Can't populate from a buffer using emulated format
        UNIMPLEMENTED();
        return angle::Result::Stop;
    }

    return setImageImpl(context, index, formatInfo, size, GL_UNSIGNED_BYTE, unpack, unpackBuffer,
                        pixels);
}

angle::Result TextureVk::setCompressedSubImage(const gl::Context *context,
                                               const gl::ImageIndex &index,
                                               const gl::Box &area,
                                               GLenum format,
                                               const gl::PixelUnpackState &unpack,
                                               size_t imageSize,
                                               const uint8_t *pixels)
{

    const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, GL_UNSIGNED_BYTE);
    ContextVk *contextVk                 = vk::GetImpl(context);
    const gl::ImageDesc &levelDesc       = mState.getImageDesc(index);
    const vk::Format &vkFormat =
        contextVk->getRenderer()->getFormat(levelDesc.format.info->sizedInternalFormat);
    const gl::State &glState = contextVk->getState();
    gl::Buffer *unpackBuffer = glState.getTargetBuffer(gl::BufferBinding::PixelUnpack);

    if (unpackBuffer &&
        this->isCompressedFormatEmulated(context, index.getTarget(), index.getLevelIndex()))
    {
        // TODO (anglebug.com/42265933): Can't populate from a buffer using emulated format
        UNIMPLEMENTED();
        return angle::Result::Stop;
    }

    return setSubImageImpl(context, index, area, formatInfo, GL_UNSIGNED_BYTE, unpack, unpackBuffer,
                           pixels, vkFormat);
}

angle::Result TextureVk::setImageImpl(const gl::Context *context,
                                      const gl::ImageIndex &index,
                                      const gl::InternalFormat &formatInfo,
                                      const gl::Extents &size,
                                      GLenum type,
                                      const gl::PixelUnpackState &unpack,
                                      gl::Buffer *unpackBuffer,
                                      const uint8_t *pixels)
{
    ContextVk *contextVk   = vk::GetImpl(context);
    vk::Renderer *renderer = contextVk->getRenderer();

    const vk::Format &vkFormat = renderer->getFormat(formatInfo.sizedInternalFormat);

    ANGLE_TRY(redefineLevel(context, index, vkFormat, size));

    // Early-out on empty textures, don't create a zero-sized storage.
    if (size.empty())
    {
        return angle::Result::Continue;
    }

    return setSubImageImpl(context, index, gl::Box(gl::kOffsetZero, size), formatInfo, type, unpack,
                           unpackBuffer, pixels, vkFormat);
}

bool TextureVk::isFastUnpackPossible(const gl::Box &area,
                                     GLuint rowLengthPixels,
                                     GLuint imageHeightPixels,
                                     const vk::Format &vkFormat,
                                     size_t offset,
                                     const vk::Format &bufferVkFormat,
                                     GLenum type) const
{
    // Conditions to determine if fast unpacking is possible
    // 1. Image must be well defined to unpack directly to it
    //    TODO(http://anglebug.com/42262852) Create and stage a temp image instead
    // 2. Can't perform a fast copy for depth/stencil, except from non-emulated depth or stencil
    //    to emulated depth/stencil.  GL requires depth and stencil data to be packed, while Vulkan
    //    requires them to be separate.
    // 3. Can't perform a fast copy for emulated formats, except from non-emulated depth or stencil
    //    to emulated depth/stencil.
    // 4. vkCmdCopyBufferToImage requires byte offset to be a multiple of 4.
    // 5. Actual texture format and intended buffer format must match for color formats
    // 6. rowLengthPixels must not smaller than the width of the copy area.
    // 7. imageHeight must not smaller than the height of the copy area.
    // 8. Don't need conversion to load Texture.

    if (!mImage->valid())
    {
        return false;
    }
    const angle::Format &bufferFormat = vkFormat.getActualBufferFormat();
    const bool isCombinedDepthStencil = bufferFormat.hasDepthAndStencilBits();
    const bool isDepthXorStencil = bufferFormat.hasDepthOrStencilBits() && !isCombinedDepthStencil;
    const bool isCompatibleDepth = vkFormat.getIntendedFormat().depthBits == bufferFormat.depthBits;
    const VkDeviceSize imageCopyAlignment =
        vk::GetImageCopyBufferAlignment(mImage->getActualFormatID());
    const bool formatsMatch = bufferFormat.hasDepthOrStencilBits() ||
                              (vkFormat.getActualImageFormatID(getRequiredFormatSupport()) ==
                               bufferVkFormat.getIntendedFormatID());
    const bool overlapRow   = rowLengthPixels < static_cast<uint32_t>(area.width);
    const bool overlapImage = imageHeightPixels < static_cast<uint32_t>(area.height);
    const bool needConversion =
        vkFormat.getTextureLoadFunction(getRequiredFormatSupport(), type).requiresConversion;

    return !isCombinedDepthStencil &&
           (vkFormat.getIntendedFormatID() ==
                vkFormat.getActualImageFormatID(getRequiredFormatSupport()) ||
            (isDepthXorStencil && isCompatibleDepth)) &&
           (offset % imageCopyAlignment) == 0 && formatsMatch && !overlapRow && !overlapImage &&
           !needConversion;
}

bool TextureVk::isMipImageDescDefined(gl::TextureTarget textureTarget, size_t level)
{
    // A defined image should have defined width, height, and format.
    gl::ImageDesc imageDesc = mState.getImageDesc(textureTarget, level);
    return imageDesc.size.height != 0 && imageDesc.size.width != 0 &&
           imageDesc.format.info->format != GL_NONE;
}

bool TextureVk::isMutableTextureConsistentlySpecifiedForFlush()
{
    // Disable optimization if the base level is not 0.
    if (mState.getBaseLevel() != 0)
    {
        return false;
    }

    // If the texture is a cubemap, we will have to wait until it is complete.
    if (mState.getType() == gl::TextureType::CubeMap && !mState.isCubeComplete())
    {
        return false;
    }

    // Before we initialize the mips, we make sure that the base mip level is properly defined.
    gl::TextureTarget textureTarget = (mState.getType() == gl::TextureType::CubeMap)
                                          ? gl::kCubeMapTextureTargetMin
                                          : gl::TextureTypeToTarget(mState.getType(), 0);
    if (!isMipImageDescDefined(textureTarget, 0))
    {
        return false;
    }

    // We do not flush if the texture has been bound as an attachment.
    if (mState.hasBeenBoundAsAttachment())
    {
        return false;
    }

    // For performance, flushing is skipped if the number of staged updates in a mip level is not
    // one. For a cubemap, this applies to each face of the cube instead.
    size_t maxUpdatesPerMipLevel = (mState.getType() == gl::TextureType::CubeMap) ? 6 : 1;
    if (mImage->getLevelUpdateCount(gl::LevelIndex(0)) != maxUpdatesPerMipLevel)
    {
        return false;
    }

    // The mip levels that are already defined should have attributes compatible with those of the
    // base mip level. For each defined mip level, its size, format, number of samples, and depth
    // are checked before flushing the texture updates. For complete cubemaps, there are 6 images
    // per mip level. Therefore, mState would have 6 times as many images.
    gl::ImageDesc baseImageDesc = mState.getImageDesc(textureTarget, 0);
    size_t maxImageMipLevels    = (mState.getType() == gl::TextureType::CubeMap)
                                      ? (mState.getImageDescs().size() / 6)
                                      : mState.getImageDescs().size();

    for (size_t image = 1; image < maxImageMipLevels; image++)
    {
        gl::ImageDesc mipImageDesc = mState.getImageDesc(textureTarget, image);
        if (!isMipImageDescDefined(textureTarget, image))
        {
            continue;
        }

        // If the texture is 2DArray or 3D, the depths should also be checked according to the mip
        // levels. If the texture type is a cube map array, the depth represents the number of
        // layer-faces and does not change for mipmaps. Otherwise, we skip the depth comparison.
        gl::Extents baseImageDescMipSize;
        baseImageDescMipSize.width  = std::max(baseImageDesc.size.width >> image, 1);
        baseImageDescMipSize.height = std::max(baseImageDesc.size.height >> image, 1);
        baseImageDescMipSize.depth  = std::max(baseImageDesc.size.depth >> image, 1);

        bool isDepthCompatible = (mState.getType() == gl::TextureType::_3D ||
                                  mState.getType() == gl::TextureType::_2DArray)
                                     ? (baseImageDescMipSize.depth == mipImageDesc.size.depth)
                                     : (mState.getType() != gl::TextureType::CubeMapArray ||
                                        baseImageDesc.size.depth == mipImageDesc.size.depth);

        bool isSizeCompatible = (baseImageDescMipSize.width == mipImageDesc.size.width) &&
                                (baseImageDescMipSize.height == mipImageDesc.size.height) &&
                                isDepthCompatible;
        bool isFormatCompatible          = (baseImageDesc.format.info->sizedInternalFormat ==
                                   mipImageDesc.format.info->sizedInternalFormat);
        bool isNumberOfSamplesCompatible = (baseImageDesc.samples == mipImageDesc.samples);

        bool isUpdateCompatible =
            (mImage->getLevelUpdateCount(gl::LevelIndex(static_cast<GLint>(image))) ==
             maxUpdatesPerMipLevel);

        if (!isSizeCompatible || !isFormatCompatible || !isNumberOfSamplesCompatible ||
            !isUpdateCompatible)
        {
            return false;
        }
    }

    return true;
}

bool TextureVk::updateMustBeFlushed(gl::LevelIndex textureLevelIndexGL,
                                    angle::FormatID dstImageFormatID) const
{
    ASSERT(mImage);

    // For EGLImages we should never stage the update since staged update is subject to thread
    // racing bugs when two textures in different share groups are accessed at same time.
    if (!mOwnsImage)
    {
        // EGLImage is always initialized upon creation and format should always renderable so that
        // there is no format upgrade.
        ASSERT(mImage->valid());
        ASSERT(IsTextureLevelInAllocatedImage(*mImage, textureLevelIndexGL));
        ASSERT(!IsTextureLevelRedefined(mRedefinedLevels, mState.getType(), textureLevelIndexGL));
        return true;
    }
    return false;
}

bool TextureVk::updateMustBeStaged(gl::LevelIndex textureLevelIndexGL,
                                   angle::FormatID dstImageFormatID) const
{
    ASSERT(mImage);

    // If we do not have storage yet, there is impossible to immediately do the copy, so just
    // stage it. Note that immutable texture will have a valid storage.
    if (!mImage->valid())
    {
        return true;
    }

    // If update is outside the range of image levels, it must be staged.
    if (!IsTextureLevelInAllocatedImage(*mImage, textureLevelIndexGL))
    {
        return true;
    }

    // During the process of format change, mImage's format may become stale. In that case, we
    // must always stage the update and let caller properly release mImage and initExternal and
    // flush the update.
    if (mImage->getActualFormatID() != dstImageFormatID)
    {
        return true;
    }

    // Otherwise, it can only be directly applied to the image if the level is not previously
    // incompatibly redefined.
    return IsTextureLevelRedefined(mRedefinedLevels, mState.getType(), textureLevelIndexGL);
}

angle::Result TextureVk::clearImage(const gl::Context *context,
                                    GLint level,
                                    GLenum format,
                                    GLenum type,
                                    const uint8_t *data)
{
    // All defined cubemap faces are expected to have equal width and height.
    bool isCubeMap = mState.getType() == gl::TextureType::CubeMap;
    gl::TextureTarget textureTarget =
        isCubeMap ? gl::kCubeMapTextureTargetMin : gl::TextureTypeToTarget(mState.getType(), 0);
    gl::Extents extents = mState.getImageDesc(textureTarget, level).size;

    gl::Box area = gl::Box(gl::kOffsetZero, extents);
    if (isCubeMap)
    {
        // For a cubemap, the depth offset moves between cube faces.
        ASSERT(area.depth == 1);
        area.depth = 6;
    }

    return clearSubImageImpl(context, level, area, vk::ClearTextureMode::FullClear, format, type,
                             data);
}

angle::Result TextureVk::clearSubImage(const gl::Context *context,
                                       GLint level,
                                       const gl::Box &area,
                                       GLenum format,
                                       GLenum type,
                                       const uint8_t *data)
{
    bool isCubeMap = mState.getType() == gl::TextureType::CubeMap;
    gl::TextureTarget textureTarget =
        isCubeMap ? gl::kCubeMapTextureTargetMin : gl::TextureTypeToTarget(mState.getType(), 0);
    gl::Extents extents   = mState.getImageDesc(textureTarget, level).size;
    int depthForFullClear = isCubeMap ? 6 : extents.depth;

    vk::ClearTextureMode clearMode = vk::ClearTextureMode::PartialClear;
    if (extents.width == area.width && extents.height == area.height &&
        depthForFullClear == area.depth)
    {
        clearMode = vk::ClearTextureMode::FullClear;
    }

    return clearSubImageImpl(context, level, area, clearMode, format, type, data);
}

angle::Result TextureVk::clearSubImageImpl(const gl::Context *context,
                                           GLint level,
                                           const gl::Box &clearArea,
                                           vk::ClearTextureMode clearMode,
                                           GLenum format,
                                           GLenum type,
                                           const uint8_t *data)
{
    // There should be no zero extents in the clear area, since such calls should return before
    // entering the backend with no changes to the texture. For 2D textures, depth should be 1.
    //
    // From the spec: For texture types that do not have certain dimensions, this command treats
    // those dimensions as having a size of 1.  For example, to clear a portion of a two-dimensional
    // texture, the application would use <zoffset> equal to zero and <depth> equal to one.
    ASSERT(clearArea.width != 0 && clearArea.height != 0 && clearArea.depth != 0);

    gl::TextureType textureType = mState.getType();
    bool useLayerAsDepth        = textureType == gl::TextureType::CubeMap ||
                           textureType == gl::TextureType::CubeMapArray ||
                           textureType == gl::TextureType::_2DArray ||
                           textureType == gl::TextureType::_2DMultisampleArray;

    // If the texture is renderable (including multisampled), the partial clear can be applied to
    // the image simply by opening/closing a render pass with LOAD_OP_CLEAR. Otherwise, a buffer can
    // be filled with the given pixel data on the host and staged to the image as a buffer update.
    ContextVk *contextVk = vk::GetImpl(context);

    const gl::InternalFormat &inputFormatInfo = gl::GetInternalFormatInfo(format, type);
    const vk::Format &inputVkFormat =
        contextVk->getRenderer()->getFormat(inputFormatInfo.sizedInternalFormat);

    const gl::InternalFormat &outputFormatInfo =
        gl::GetSizedInternalFormatInfo(mImage->getIntendedFormat().glInternalFormat);
    const vk::Format &outputVkFormat =
        contextVk->getRenderer()->getFormat(outputFormatInfo.sizedInternalFormat);
    const angle::FormatID &outputActualFormatID = mImage->getActualFormatID();

    bool usesBufferForClear = false;

    const VkFormatFeatureFlags clearUpdateRequiredFeature =
        clearMode == vk::ClearTextureMode::FullClear ? VK_FORMAT_FEATURE_TRANSFER_DST_BIT
        : outputFormatInfo.isDepthOrStencil() ? VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT
                                              : VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
    const VkImageUsageFlags clearUpdateRequiredUsage =
        clearMode == vk::ClearTextureMode::FullClear ? VK_IMAGE_USAGE_TRANSFER_DST_BIT
        : outputFormatInfo.isDepthOrStencil()        ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
                                                     : VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
    const bool formatFeaturesAllowClearUpdate =
        vk::FormatHasNecessaryFeature(contextVk->getRenderer(), outputActualFormatID,
                                      getTilingMode(), clearUpdateRequiredFeature);
    const bool imageUsageAllowsClearUpdate =
        (mImageUsageFlags & clearUpdateRequiredUsage) == clearUpdateRequiredUsage;
    if (formatFeaturesAllowClearUpdate && imageUsageAllowsClearUpdate)
    {
        uint32_t baseLayer  = useLayerAsDepth ? clearArea.z : 0;
        uint32_t layerCount = useLayerAsDepth ? clearArea.depth : 1;
        ANGLE_TRY(mImage->stagePartialClear(contextVk, clearArea, clearMode, mState.getType(),
                                            level, baseLayer, layerCount, type, inputFormatInfo,
                                            inputVkFormat, getRequiredFormatSupport(), data));
    }
    else
    {
        ASSERT(mImage->getSamples() <= 1);
        bool updateAppliedImmediately = false;
        usesBufferForClear            = true;

        auto pixelSize = static_cast<size_t>(inputFormatInfo.pixelBytes);
        std::vector<uint8_t> pixelValue(pixelSize, 0);
        if (data != nullptr)
        {
            memcpy(pixelValue.data(), data, pixelSize);
        }

        // For a cubemap, each face will be updated separately.
        bool isCubeMap = textureType == gl::TextureType::CubeMap;
        size_t clearBufferSize =
            isCubeMap ? clearArea.width * clearArea.height * pixelSize
                      : clearArea.width * clearArea.height * clearArea.depth * pixelSize;

        std::vector<uint8_t> clearBuffer(clearBufferSize, 0);
        ASSERT(clearBufferSize % pixelSize == 0);

        // The pixels in the temporary buffer are tightly packed.
        if (data != nullptr)
        {
            for (GLuint i = 0; i < clearBufferSize; i += pixelSize)
            {
                memcpy(&clearBuffer[i], pixelValue.data(), pixelSize);
            }
        }
        gl::PixelUnpackState pixelUnpackState = {};
        pixelUnpackState.alignment            = 1;

        if (isCubeMap)
        {
            size_t cubeFaceStart = clearArea.z;
            auto cubeFaceEnd     = static_cast<size_t>(clearArea.z + clearArea.depth);

            for (size_t cubeFace = cubeFaceStart; cubeFace < cubeFaceEnd; cubeFace++)
            {
                const gl::ImageIndex index = gl::ImageIndex::MakeFromTarget(
                    gl::CubeFaceIndexToTextureTarget(cubeFace), level, 0);

                ANGLE_TRY(mImage->stageSubresourceUpdate(
                    contextVk, getNativeImageIndex(index),
                    gl::Extents(clearArea.width, clearArea.height, 1),
                    gl::Offset(clearArea.x, clearArea.y, 0), inputFormatInfo, pixelUnpackState,
                    type, clearBuffer.data(), outputVkFormat, getRequiredFormatSupport(),
                    vk::ApplyImageUpdate::Defer, &updateAppliedImmediately));
                ASSERT(!updateAppliedImmediately);
            }
        }
        else
        {
            gl::TextureTarget textureTarget = gl::TextureTypeToTarget(textureType, 0);
            uint32_t layerCount             = useLayerAsDepth ? clearArea.depth : 0;
            const gl::ImageIndex index =
                gl::ImageIndex::MakeFromTarget(textureTarget, level, layerCount);

            ANGLE_TRY(mImage->stageSubresourceUpdate(
                contextVk, getNativeImageIndex(index),
                gl::Extents(clearArea.width, clearArea.height, clearArea.depth),
                gl::Offset(clearArea.x, clearArea.y, clearArea.z), inputFormatInfo,
                pixelUnpackState, type, clearBuffer.data(), outputVkFormat,
                getRequiredFormatSupport(), vk::ApplyImageUpdate::Defer,
                &updateAppliedImmediately));
            ASSERT(!updateAppliedImmediately);
        }
    }

    // Flush the staged updates if needed.
    ANGLE_TRY(ensureImageInitializedIfUpdatesNeedStageOrFlush(
        contextVk, gl::LevelIndex(level), outputVkFormat, vk::ApplyImageUpdate::Defer,
        usesBufferForClear));
    return angle::Result::Continue;
}

angle::Result TextureVk::ensureImageInitializedIfUpdatesNeedStageOrFlush(
    ContextVk *contextVk,
    gl::LevelIndex level,
    const vk::Format &vkFormat,
    vk::ApplyImageUpdate applyUpdate,
    bool usesBufferForUpdate)
{
    bool mustFlush =
        updateMustBeFlushed(level, vkFormat.getActualImageFormatID(getRequiredFormatSupport()));
    bool mustStage = applyUpdate == vk::ApplyImageUpdate::Defer;

    const bool canFlushStagedUpdates =
        !mustStage && mImage->valid() && mImage->hasBufferSourcedStagedUpdatesInAllLevels();

    // If texture has all levels being specified, then do the flush immediately. This tries to avoid
    // issue flush as each level is being provided which may end up flushing out the staged clear
    // that otherwise might able to be removed. It also helps tracking all updates with just one
    // VkEvent instead of one for each level.
    if (mustFlush || canFlushStagedUpdates)
    {
        ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));

        // To handle use cases where shared resources are not properly synchronized between multiple
        // contexts, forceSubmitImmutableTextureUpdates submits the staged updates to force
        // synchronization. This is limited to cases where the resource is an immutable texture and
        // there are multiple active shared contexts.
        if (canFlushStagedUpdates && contextVk->getShareGroup()->getContexts().size() > 1 &&
            mState.getImmutableFormat() &&
            contextVk->getFeatures().forceSubmitImmutableTextureUpdates.enabled)
        {
            ANGLE_TRY(contextVk->submitStagedTextureUpdates());
        }
    }
    else if (usesBufferForUpdate && contextVk->isEligibleForMutableTextureFlush() &&
             !mState.getImmutableFormat())
    {
        // Check if we should flush any mutable textures from before.
        ANGLE_TRY(contextVk->getShareGroup()->onMutableTextureUpload(contextVk, this));
    }

    return angle::Result::Continue;
}

angle::Result TextureVk::ghostOnOverwrite(ContextVk *contextVk,
                                          const gl::ImageIndex &index,
                                          const gl::Box &area)
{
    // If the texture's image is in use by the GPU but is overwritten completely, release the old
    // image and create a fresh one.  If the texture was used in a render pass, this avoids breaking
    // the render pass.  Otherwise, it allows the new image to be initialized with
    // VK_EXT_host_image_copy functionality.  In the very least, an unnecessary ?->Transfer barrier
    // is avoided.

    // Can't ghost the image if it's not owned by this texture.  For simplicity, also don't ghost
    // images if it's the target of an EGL image; this avoids the need to have to get the image
    // siblings to sync their ImageHelper pointers (http://anglebug.com/410584007).  This limitation
    // can likely be more easily lifted once http://anglebug.com/352005188 is implemented.
    //
    // If the allocateNonZeroMemory feature is enabled, the image's memory is going to be
    // initialized which puts the image back in GPU use so there's no point in ghosting the image
    // either.
    vk::Renderer *renderer = contextVk->getRenderer();
    if (!mOwnsImage || mImage == nullptr || !mImage->valid() || mImage->isForeignImage() ||
        mState.hasBeenBoundAsSourceOfEglImage() || mState.isExternalMemoryTexture() ||
        renderer->getFeatures().allocateNonZeroMemory.enabled)
    {
        return angle::Result::Continue;
    }

    // Only ghost the image if it's in use by the GPU.
    if (renderer->hasResourceUseFinished(mImage->getResourceUse()))
    {
        return angle::Result::Continue;
    }

    // Size check: Can only ghost the image if the area being overwritten covers the entire image.
    //
    // As a targeted optimization, only limit to non-array 2D color textures.  Other texture types
    // can be very easily added if need, but need additional tests similar to those that have landed
    // in http://anglebug.com/42265356 for 2D textures.
    const gl::LevelIndex overwriteLevel = gl::LevelIndex(index.getLevelIndex());
    const gl::LevelIndex imageLevel     = mImage->getFirstAllocatedLevel();

    const bool is2DImage = mImage->getLevelCount() == 1 && mImage->getLayerCount() == 1 &&
                           mImage->getType() == VK_IMAGE_TYPE_2D;
    const bool is2DUpdate  = mState.getType() == gl::TextureType::_2D && index.getLayerCount() == 1;
    const bool isWholeArea = area.x == 0 && area.y == 0 && area.z == 0 &&
                             mImage->getExtents().width == static_cast<uint32_t>(area.width) &&
                             mImage->getExtents().height == static_cast<uint32_t>(area.height) &&
                             mImage->getExtents().depth == static_cast<uint32_t>(area.depth);
    const bool isColor = mImage->getAspectFlags() == VK_IMAGE_ASPECT_COLOR_BIT;

    if (!is2DImage || !is2DUpdate || overwriteLevel != imageLevel || !isWholeArea || !isColor)
    {
        return angle::Result::Continue;
    }

    const vk::Format &format = getBaseLevelFormat(renderer);

    // Since the entire image is being overwritten, there's no reason to keep the previous contents
    // of the image around.  Just start over with a completely new image; data is about to be
    // uploaded to it.
    releaseImage(contextVk);
    ANGLE_TRY(ensureImageAllocated(contextVk, format));
    ANGLE_TRY(initImage(contextVk, format.getIntendedFormatID(),
                        format.getActualImageFormatID(getRequiredFormatSupport()),
                        ImageMipLevels::EnabledLevels));

    // The new image is now ready to be used with no dependency to the texture's previous use.  Note
    // that |releaseimage| already includes a notification to observers that the image has changed.
    ASSERT(renderer->hasResourceUseFinished(mImage->getResourceUse()));

    return angle::Result::Continue;
}

angle::Result TextureVk::setSubImageImpl(const gl::Context *context,
                                         const gl::ImageIndex &index,
                                         const gl::Box &area,
                                         const gl::InternalFormat &formatInfo,
                                         GLenum type,
                                         const gl::PixelUnpackState &unpack,
                                         gl::Buffer *unpackBuffer,
                                         const uint8_t *pixels,
                                         const vk::Format &vkFormat)
{
    ContextVk *contextVk = vk::GetImpl(context);

    ANGLE_TRY(ghostOnOverwrite(contextVk, index, area));

    bool mustStage =
        updateMustBeStaged(gl::LevelIndex(index.getLevelIndex()),
                           vkFormat.getActualImageFormatID(getRequiredFormatSupport()));

    vk::ApplyImageUpdate applyUpdate;
    if (mustStage)
    {
        applyUpdate = vk::ApplyImageUpdate::Defer;
    }
    else
    {
        // Cannot defer to unlocked tail call if:
        //
        // - The generate mipmap hint is set: This is because on return the Texture class would
        //   attempt to generate mipmaps, which may reallocate the image, or fall back to software
        //   mipmap generation.
        // - The texture is incomplete: This is because unlocked tail call is disabled on draw
        //   calls, but that is when incomplete textures are created and initialized.
        const bool canDeferToUnlockedTailCall =
            mState.getGenerateMipmapHint() != GL_TRUE && !mState.isInternalIncompleteTexture();

        // When possible flush out updates immediately.
        applyUpdate = canDeferToUnlockedTailCall
                          ? vk::ApplyImageUpdate::ImmediatelyInUnlockedTailCall
                          : vk::ApplyImageUpdate::Immediately;
    }
    bool updateAppliedImmediately = false;

    if (unpackBuffer)
    {
        BufferVk *unpackBufferVk       = vk::GetImpl(unpackBuffer);
        vk::BufferHelper &bufferHelper = unpackBufferVk->getBuffer();
        VkDeviceSize bufferOffset      = bufferHelper.getOffset();
        uintptr_t offset               = reinterpret_cast<uintptr_t>(pixels);
        GLuint inputRowPitch           = 0;
        GLuint inputDepthPitch         = 0;
        GLuint inputSkipBytes          = 0;

        ANGLE_TRY(mImage->calculateBufferInfo(
            contextVk, gl::Extents(area.width, area.height, area.depth), formatInfo, unpack, type,
            index.usesTex3D(), &inputRowPitch, &inputDepthPitch, &inputSkipBytes));

        size_t offsetBytes = static_cast<size_t>(bufferOffset + offset + inputSkipBytes);

        // Note: cannot directly copy from a depth/stencil PBO.  GL requires depth and stencil data
        // to be packed, while Vulkan requires them to be separate.
        const VkImageAspectFlags aspectFlags =
            vk::GetFormatAspectFlags(vkFormat.getIntendedFormat());
        const vk::Format &bufferVkFormat =
            contextVk->getRenderer()->getFormat(formatInfo.sizedInternalFormat);

        GLuint pixelSize   = formatInfo.pixelBytes;
        GLuint blockWidth  = formatInfo.compressedBlockWidth;
        GLuint blockHeight = formatInfo.compressedBlockHeight;
        if (!formatInfo.compressed)
        {
            pixelSize   = formatInfo.computePixelBytes(type);
            blockWidth  = 1;
            blockHeight = 1;
        }
        ASSERT(pixelSize != 0 && inputRowPitch != 0 && blockWidth != 0 && blockHeight != 0);

        GLuint rowLengthPixels   = inputRowPitch / pixelSize * blockWidth;
        GLuint imageHeightPixels = inputDepthPitch / inputRowPitch * blockHeight;

        if ((shouldUpdateBeFlushed(gl::LevelIndex(index.getLevelIndex()),
                                   vkFormat.getActualImageFormatID(getRequiredFormatSupport()))) &&
            isFastUnpackPossible(area, rowLengthPixels, imageHeightPixels, vkFormat, offsetBytes,
                                 bufferVkFormat, type))
        {
            ANGLE_TRY(copyBufferDataToImage(contextVk, &bufferHelper, index, rowLengthPixels,
                                            imageHeightPixels, area, offsetBytes, aspectFlags));
        }
        else
        {
            ANGLE_VK_PERF_WARNING(
                contextVk, GL_DEBUG_SEVERITY_HIGH,
                "TexSubImage with unpack buffer copied on CPU due to store, format "
                "or offset restrictions");

            void *mapPtr = nullptr;

            ANGLE_TRY(unpackBufferVk->mapForReadAccessOnly(contextVk, &mapPtr));

            const uint8_t *source =
                static_cast<const uint8_t *>(mapPtr) + reinterpret_cast<ptrdiff_t>(pixels);

            ANGLE_TRY(mImage->stageSubresourceUpdateImpl(
                contextVk, getNativeImageIndex(index),
                gl::Extents(area.width, area.height, area.depth),
                gl::Offset(area.x, area.y, area.z), formatInfo, unpack, type, source, vkFormat,
                getRequiredFormatSupport(), inputRowPitch, inputDepthPitch, inputSkipBytes,
                applyUpdate, &updateAppliedImmediately));

            ANGLE_TRY(unpackBufferVk->unmapReadAccessOnly(contextVk));
        }
    }
    else if (pixels)
    {
        ANGLE_TRY(mImage->stageSubresourceUpdate(
            contextVk, getNativeImageIndex(index), gl::Extents(area.width, area.height, area.depth),
            gl::Offset(area.x, area.y, area.z), formatInfo, unpack, type, pixels, vkFormat,
            getRequiredFormatSupport(), applyUpdate, &updateAppliedImmediately));
    }

    if (updateAppliedImmediately)
    {
        // Return if stageSubresourceUpdate already applied the update
        return angle::Result::Continue;
    }

    // Flush the staged updates if needed.
    ANGLE_TRY(ensureImageInitializedIfUpdatesNeedStageOrFlush(
        contextVk, gl::LevelIndex(index.getLevelIndex()), vkFormat, applyUpdate, true));
    return angle::Result::Continue;
}

angle::Result TextureVk::copyImage(const gl::Context *context,
                                   const gl::ImageIndex &index,
                                   const gl::Rectangle &sourceArea,
                                   GLenum internalFormat,
                                   gl::Framebuffer *source)
{
    ContextVk *contextVk   = vk::GetImpl(context);
    vk::Renderer *renderer = contextVk->getRenderer();

    gl::Extents newImageSize(sourceArea.width, sourceArea.height, 1);
    const gl::InternalFormat &internalFormatInfo =
        gl::GetInternalFormatInfo(internalFormat, GL_UNSIGNED_BYTE);
    const vk::Format &vkFormat = renderer->getFormat(internalFormatInfo.sizedInternalFormat);

    // Fall back to renderable format if copy cannot be done in transfer.  Must be done before
    // the dst format is accessed anywhere (in |redefineLevel| and |copySubImageImpl|).
    ANGLE_TRY(ensureRenderableIfCopyTexImageCannotTransfer(contextVk, internalFormatInfo, source));

    FramebufferVk *framebufferVk = vk::GetImpl(source);
    RenderTargetVk *colorReadRT  = framebufferVk->getColorReadRenderTarget();
    vk::ImageHelper *srcImage    = &colorReadRT->getImageForCopy();
    const bool isCubeMap         = index.getType() == gl::TextureType::CubeMap;
    gl::LevelIndex levelIndex(getNativeImageIndex(index).getLevelIndex());
    const uint32_t layerIndex    = index.hasLayer() ? index.getLayerIndex() : 0;
    const uint32_t redefinedFace = isCubeMap ? layerIndex : 0;
    const uint32_t sourceFace    = isCubeMap ? colorReadRT->getLayerIndex() : 0;
    const bool isSelfCopy = mImage == srcImage && levelIndex == colorReadRT->getLevelIndex() &&
                            redefinedFace == sourceFace;

    // The texture level being redefined might be the same as the one bound to the framebuffer.
    // In that case, snapshot the source image first, then redefine, then copy from the snapshot.
    vk::RendererScoped<vk::ImageHelper> sourceImageCopy(renderer);
    gl::Rectangle clippedSourceArea;
    gl::Offset modifiedDestOffset(0, 0, 0);
    bool hasCopyArea = false;

    if (isSelfCopy)
    {
        gl::Extents fbSize = source->getReadColorAttachment()->getSize();
        hasCopyArea = ClipRectangle(sourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height),
                                    &clippedSourceArea);

        if (hasCopyArea)
        {
            modifiedDestOffset = gl::Offset(clippedSourceArea.x - sourceArea.x,
                                            clippedSourceArea.y - sourceArea.y, 0);

            // Make sure the source image exists and any updates are already flushed.
            ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));

            ANGLE_TRY(sourceImageCopy.get().init2DStaging(
                contextVk, mState.hasProtectedContent(),
                gl::Extents(clippedSourceArea.width, clippedSourceArea.height, 1),
                srcImage->getIntendedFormatID(), srcImage->getActualFormatID(),
                vk::kImageUsageTransferBits | VK_IMAGE_USAGE_SAMPLED_BIT, 1));

            vk::CommandResources resources;
            resources.onImageTransferRead(VK_IMAGE_ASPECT_COLOR_BIT, srcImage);
            resources.onImageTransferWrite(gl::LevelIndex(0), 1, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT,
                                           &sourceImageCopy.get());

            vk::OutsideRenderPassCommandBuffer *commandBuffer;
            ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &commandBuffer));

            gl::Offset srcOffset(clippedSourceArea.x, clippedSourceArea.y, 0);
            gl::Extents copyExtents(clippedSourceArea.width, clippedSourceArea.height, 1);

            VkImageSubresourceLayers srcSubresource = {};
            srcSubresource.aspectMask               = VK_IMAGE_ASPECT_COLOR_BIT;
            srcSubresource.mipLevel       = srcImage->toVkLevel(colorReadRT->getLevelIndex()).get();
            srcSubresource.baseArrayLayer = sourceFace;
            srcSubresource.layerCount     = 1;

            if (srcImage->getExtents().depth > 1)
            {
                Set3DBaseArrayLayerAndLayerCount(&srcSubresource);
                srcOffset.z = static_cast<int>(colorReadRT->getLayerIndex());
            }

            VkImageSubresourceLayers destSubresource = {};
            destSubresource.aspectMask               = VK_IMAGE_ASPECT_COLOR_BIT;
            destSubresource.mipLevel                 = 0;
            destSubresource.baseArrayLayer           = 0;
            destSubresource.layerCount               = 1;

            vk::ImageHelper::Copy(renderer, srcImage, &sourceImageCopy.get(), srcOffset,
                                  gl::kOffsetZero, copyExtents, srcSubresource, destSubresource,
                                  commandBuffer);
        }
    }

    ANGLE_TRY(redefineLevel(context, index, vkFormat, newImageSize));

    if (isSelfCopy)
    {
        if (!hasCopyArea)
        {
            return angle::Result::Continue;
        }

        // Use a draw copy for format conversion.
        ANGLE_TRY(
            contextVk->flushCommandsAndEndRenderPass(RenderPassClosureReason::PrepareForImageCopy));

        vk::DeviceScoped<vk::ImageView> sourceCopyView(contextVk->getDevice());
        gl::TextureType sourceCopyTextureType =
            vk::Get2DTextureType(1, sourceImageCopy.get().getSamples());
        ANGLE_TRY(sourceImageCopy.get().initLayerImageView(
            contextVk, sourceCopyTextureType, VK_IMAGE_ASPECT_COLOR_BIT, gl::SwizzleState(),
            &sourceCopyView.get(), vk::LevelIndex(0), 1, 0, 1));

        ANGLE_TRY(copySubImageImplWithDraw(
            contextVk, index, modifiedDestOffset, vkFormat, gl::LevelIndex(0),
            gl::Box(gl::kOffsetZero,
                    gl::Extents(clippedSourceArea.width, clippedSourceArea.height, 1)),
            false, false, false, false, &sourceImageCopy.get(), &sourceCopyView.get(),
            SurfaceRotation::Identity));

        vk::ImageView sourceCopyViewObject = sourceCopyView.release();
        contextVk->addGarbage(&sourceCopyViewObject);
        return angle::Result::Continue;
    }

    return copySubImageImpl(context, index, gl::Offset(0, 0, 0), sourceArea, internalFormatInfo,
                            source);
}

angle::Result TextureVk::copySubImage(const gl::Context *context,
                                      const gl::ImageIndex &index,
                                      const gl::Offset &destOffset,
                                      const gl::Rectangle &sourceArea,
                                      gl::Framebuffer *source)
{
    const gl::InternalFormat &currentFormat = *mState.getImageDesc(index).format.info;

    // Fall back to renderable format if copy cannot be done in transfer.  Must be done before
    // the dst format is accessed anywhere (in |redefineLevel| and |copySubImageImpl|).
    ANGLE_TRY(
        ensureRenderableIfCopyTexImageCannotTransfer(vk::GetImpl(context), currentFormat, source));

    return copySubImageImpl(context, index, destOffset, sourceArea, currentFormat, source);
}

angle::Result TextureVk::copyTexture(const gl::Context *context,
                                     const gl::ImageIndex &index,
                                     GLenum internalFormat,
                                     GLenum type,
                                     GLint sourceLevelGL,
                                     bool unpackFlipY,
                                     bool unpackPremultiplyAlpha,
                                     bool unpackUnmultiplyAlpha,
                                     const gl::Texture *source)
{
    ContextVk *contextVk   = vk::GetImpl(context);
    vk::Renderer *renderer = contextVk->getRenderer();

    TextureVk *sourceVk = vk::GetImpl(source);
    const gl::ImageDesc &srcImageDesc =
        sourceVk->mState.getImageDesc(NonCubeTextureTypeToTarget(source->getType()), sourceLevelGL);
    gl::Box sourceBox(gl::kOffsetZero, srcImageDesc.size);
    const gl::InternalFormat &dstFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
    const vk::Format &dstVkFormat = renderer->getFormat(dstFormatInfo.sizedInternalFormat);

    ANGLE_TRY(sourceVk->ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));

    // Fall back to renderable format if copy cannot be done in transfer.  Must be done before
    // the dst format is accessed anywhere (in |redefineLevel| and |copySubTextureImpl|).
    ANGLE_TRY(ensureRenderableIfCopyTextureCannotTransfer(contextVk, dstFormatInfo, unpackFlipY,
                                                          unpackPremultiplyAlpha,
                                                          unpackUnmultiplyAlpha, sourceVk));

    ANGLE_TRY(redefineLevel(context, index, dstVkFormat, srcImageDesc.size));

    return copySubTextureImpl(contextVk, index, gl::kOffsetZero, dstFormatInfo,
                              gl::LevelIndex(sourceLevelGL), sourceBox, unpackFlipY,
                              unpackPremultiplyAlpha, unpackUnmultiplyAlpha, sourceVk);
}

angle::Result TextureVk::copySubTexture(const gl::Context *context,
                                        const gl::ImageIndex &index,
                                        const gl::Offset &dstOffset,
                                        GLint srcLevelGL,
                                        const gl::Box &sourceBox,
                                        bool unpackFlipY,
                                        bool unpackPremultiplyAlpha,
                                        bool unpackUnmultiplyAlpha,
                                        const gl::Texture *source)
{
    ContextVk *contextVk = vk::GetImpl(context);

    gl::TextureTarget target = index.getTarget();
    gl::LevelIndex dstLevelGL(index.getLevelIndex());
    const gl::InternalFormat &dstFormatInfo =
        *mState.getImageDesc(target, dstLevelGL.get()).format.info;

    ANGLE_TRY(
        vk::GetImpl(source)->ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));

    // Fall back to renderable format if copy cannot be done in transfer.  Must be done before
    // the dst format is accessed anywhere (in |copySubTextureImpl|).
    ANGLE_TRY(ensureRenderableIfCopyTextureCannotTransfer(
        contextVk, dstFormatInfo, unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha,
        vk::GetImpl(source)));

    return copySubTextureImpl(contextVk, index, dstOffset, dstFormatInfo,
                              gl::LevelIndex(srcLevelGL), sourceBox, unpackFlipY,
                              unpackPremultiplyAlpha, unpackUnmultiplyAlpha, vk::GetImpl(source));
}

angle::Result TextureVk::copyRenderbufferSubData(const gl::Context *context,
                                                 const gl::Renderbuffer *srcBuffer,
                                                 GLint srcLevel,
                                                 GLint srcX,
                                                 GLint srcY,
                                                 GLint srcZ,
                                                 GLint dstLevel,
                                                 GLint dstX,
                                                 GLint dstY,
                                                 GLint dstZ,
                                                 GLsizei srcWidth,
                                                 GLsizei srcHeight,
                                                 GLsizei srcDepth)
{
    ContextVk *contextVk     = vk::GetImpl(context);
    RenderbufferVk *sourceVk = vk::GetImpl(srcBuffer);

    // Make sure the source/destination targets are initialized and all staged updates are flushed.
    ANGLE_TRY(sourceVk->ensureImageInitialized(context));
    ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));

    return vk::ImageHelper::CopyImageSubData(context, sourceVk->getImage(), srcLevel, srcX, srcY,
                                             srcZ, mImage, dstLevel, dstX, dstY, dstZ, srcWidth,
                                             srcHeight, srcDepth);
}

angle::Result TextureVk::copyTextureSubData(const gl::Context *context,
                                            const gl::Texture *srcTexture,
                                            GLint srcLevel,
                                            GLint srcX,
                                            GLint srcY,
                                            GLint srcZ,
                                            GLint dstLevel,
                                            GLint dstX,
                                            GLint dstY,
                                            GLint dstZ,
                                            GLsizei srcWidth,
                                            GLsizei srcHeight,
                                            GLsizei srcDepth)
{
    ContextVk *contextVk = vk::GetImpl(context);
    TextureVk *sourceVk  = vk::GetImpl(srcTexture);

    // Make sure the source/destination targets are initialized and all staged updates are flushed.
    ANGLE_TRY(sourceVk->ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
    ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));

    return vk::ImageHelper::CopyImageSubData(context, &sourceVk->getImage(), srcLevel, srcX, srcY,
                                             srcZ, mImage, dstLevel, dstX, dstY, dstZ, srcWidth,
                                             srcHeight, srcDepth);
}

angle::Result TextureVk::copyCompressedTexture(const gl::Context *context,
                                               const gl::Texture *source)
{
    ContextVk *contextVk = vk::GetImpl(context);
    TextureVk *sourceVk  = vk::GetImpl(source);

    gl::TextureTarget sourceTarget = NonCubeTextureTypeToTarget(source->getType());
    constexpr GLint sourceLevelGL  = 0;
    constexpr GLint destLevelGL    = 0;

    const gl::InternalFormat &internalFormat = *source->getFormat(sourceTarget, sourceLevelGL).info;
    const vk::Format &vkFormat =
        contextVk->getRenderer()->getFormat(internalFormat.sizedInternalFormat);
    const gl::Extents size(static_cast<int>(source->getWidth(sourceTarget, sourceLevelGL)),
                           static_cast<int>(source->getHeight(sourceTarget, sourceLevelGL)),
                           static_cast<int>(source->getDepth(sourceTarget, sourceLevelGL)));
    const gl::ImageIndex destIndex = gl::ImageIndex::MakeFromTarget(sourceTarget, destLevelGL, 1);

    ANGLE_TRY(redefineLevel(context, destIndex, vkFormat, size));

    ANGLE_TRY(sourceVk->ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));

    return copySubImageImplWithTransfer(contextVk, destIndex, gl::kOffsetZero, vkFormat,
                                        gl::LevelIndex(sourceLevelGL), 0,
                                        gl::Box(gl::kOffsetZero, size), &sourceVk->getImage());
}

angle::Result TextureVk::copySubImageImpl(const gl::Context *context,
                                          const gl::ImageIndex &index,
                                          const gl::Offset &destOffset,
                                          const gl::Rectangle &sourceArea,
                                          const gl::InternalFormat &internalFormat,
                                          gl::Framebuffer *source)
{
    gl::Extents fbSize = source->getReadColorAttachment()->getSize();
    gl::Rectangle clippedSourceArea;
    if (!ClipRectangle(sourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height),
                       &clippedSourceArea))
    {
        return angle::Result::Continue;
    }

    ContextVk *contextVk         = vk::GetImpl(context);
    vk::Renderer *renderer       = contextVk->getRenderer();
    FramebufferVk *framebufferVk = vk::GetImpl(source);

    const gl::ImageIndex offsetImageIndex = getNativeImageIndex(index);

    // If negative offsets are given, clippedSourceArea ensures we don't read from those offsets.
    // However, that changes the sourceOffset->destOffset mapping.  Here, destOffset is shifted by
    // the same amount as clipped to correct the error.
    VkImageType imageType = gl_vk::GetImageType(mState.getType());
    int zOffset           = (imageType == VK_IMAGE_TYPE_3D) ? destOffset.z : 0;
    const gl::Offset modifiedDestOffset(destOffset.x + clippedSourceArea.x - sourceArea.x,
                                        destOffset.y + clippedSourceArea.y - sourceArea.y, zOffset);

    RenderTargetVk *colorReadRT = framebufferVk->getColorReadRenderTarget();

    const vk::Format &dstFormat         = renderer->getFormat(internalFormat.sizedInternalFormat);
    angle::FormatID dstIntendedFormatID = dstFormat.getIntendedFormatID();
    angle::FormatID dstActualFormatID =
        dstFormat.getActualImageFormatID(getRequiredFormatSupport());
    VkImageTiling destTilingMode      = getTilingMode();

    bool isViewportFlipY = contextVk->isViewportFlipEnabledForReadFBO();

    gl::Box clippedSourceBox(clippedSourceArea.x, clippedSourceArea.y, colorReadRT->getLayerIndex(),
                             clippedSourceArea.width, clippedSourceArea.height, 1);

    // If it's possible to perform the copy with a transfer, that's the best option.
    if (CanCopyWithTransferForTexImage(renderer, colorReadRT->getImageForCopy(),
                                       dstIntendedFormatID, dstActualFormatID, destTilingMode,
                                       isViewportFlipY))
    {
        return copySubImageImplWithTransfer(contextVk, offsetImageIndex, modifiedDestOffset,
                                            dstFormat, colorReadRT->getLevelIndex(),
                                            colorReadRT->getLayerIndex(), clippedSourceBox,
                                            &colorReadRT->getImageForCopy());
    }

    // If it's possible to perform the copy with a draw call, do that.
    if (CanCopyWithDraw(renderer, colorReadRT->getImageForCopy().getUsage(), dstActualFormatID,
                        destTilingMode))
    {
        // Layer count can only be 1 as the source is a framebuffer.
        ASSERT(offsetImageIndex.getLayerCount() == 1);

        // Flush the render pass, which may incur a vkQueueSubmit, before taking any views.
        // Otherwise the view serials would not reflect the render pass they are really used in.
        // http://crbug.com/1272266#c22
        ANGLE_TRY(
            contextVk->flushCommandsAndEndRenderPass(RenderPassClosureReason::PrepareForImageCopy));

        const vk::ImageView *copyImageView = nullptr;
        ANGLE_TRY(colorReadRT->getCopyImageView(contextVk, &copyImageView));

        return copySubImageImplWithDraw(contextVk, offsetImageIndex, modifiedDestOffset, dstFormat,
                                        colorReadRT->getLevelIndex(), clippedSourceBox,
                                        isViewportFlipY, false, false, false,
                                        &colorReadRT->getImageForCopy(), copyImageView,
                                        contextVk->getRotationReadFramebuffer());
    }

    ANGLE_VK_PERF_WARNING(contextVk, GL_DEBUG_SEVERITY_HIGH,
                          "Texture copied on CPU due to format restrictions");

    // Do a CPU readback that does the conversion, and then stage the change to the pixel buffer.
    ANGLE_TRY(mImage->stageSubresourceUpdateFromFramebuffer(
        context, offsetImageIndex, clippedSourceArea, modifiedDestOffset,
        gl::Extents(clippedSourceArea.width, clippedSourceArea.height, 1), internalFormat,
        getRequiredFormatSupport(), framebufferVk));

    // Flush out staged update if possible
    if (shouldUpdateBeFlushed(gl::LevelIndex(index.getLevelIndex()), dstActualFormatID))
    {
        ANGLE_TRY(flushImageStagedUpdates(contextVk));
    }

    return angle::Result::Continue;
}

angle::Result TextureVk::copySubTextureImpl(ContextVk *contextVk,
                                            const gl::ImageIndex &index,
                                            const gl::Offset &dstOffset,
                                            const gl::InternalFormat &dstFormat,
                                            gl::LevelIndex sourceLevelGL,
                                            const gl::Box &sourceBox,
                                            bool unpackFlipY,
                                            bool unpackPremultiplyAlpha,
                                            bool unpackUnmultiplyAlpha,
                                            TextureVk *source)
{
    vk::Renderer *renderer = contextVk->getRenderer();

    const angle::Format &srcIntendedFormat = source->getImage().getIntendedFormat();
    const vk::Format &dstVkFormat          = renderer->getFormat(dstFormat.sizedInternalFormat);
    angle::FormatID dstFormatID = dstVkFormat.getActualImageFormatID(getRequiredFormatSupport());
    VkImageTiling dstTilingMode = getTilingMode();

    const gl::ImageIndex offsetImageIndex = getNativeImageIndex(index);

    // If it's possible to perform the copy with a transfer, that's the best option.
    if (CanCopyWithTransferForCopyTexture(
            renderer, source->getImage(), dstVkFormat.getIntendedFormatID(), dstFormatID,
            dstTilingMode, unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha))
    {
        return copySubImageImplWithTransfer(contextVk, offsetImageIndex, dstOffset, dstVkFormat,
                                            sourceLevelGL, sourceBox.z, sourceBox,
                                            &source->getImage());
    }

    // If it's possible to perform the copy with a draw call, do that.
    if (CanCopyWithDraw(renderer, source->getImage().getUsage(), dstFormatID, dstTilingMode))
    {
        // Flush the render pass, which may incur a vkQueueSubmit, before taking any views.
        // Otherwise the view serials would not reflect the render pass they are really used in.
        // http://crbug.com/1272266#c22
        ANGLE_TRY(
            contextVk->flushCommandsAndEndRenderPass(RenderPassClosureReason::PrepareForImageCopy));

        return copySubImageImplWithDraw(
            contextVk, offsetImageIndex, dstOffset, dstVkFormat, sourceLevelGL, sourceBox, false,
            unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha, &source->getImage(),
            &source->getCopyImageView(), SurfaceRotation::Identity);
    }

    ANGLE_VK_PERF_WARNING(contextVk, GL_DEBUG_SEVERITY_HIGH,
                          "Texture copied on CPU due to format restrictions");

    // Read back the requested region of the source texture
    vk::RendererScoped<vk::BufferHelper> bufferHelper(renderer);
    uint8_t *sourceData = nullptr;
    ANGLE_TRY(source->copyImageDataToBufferAndGetData(
        contextVk, sourceLevelGL, sourceBox.depth, sourceBox, QueueSubmitReason::CopyTextureOnCPU,
        &bufferHelper.get(), &sourceData));

    const angle::Format &srcTextureFormat = source->getImage().getActualFormat();
    const angle::Format &dstTextureFormat =
        dstVkFormat.getActualImageFormat(getRequiredFormatSupport());
    size_t destinationAllocationSize =
        sourceBox.width * sourceBox.height * sourceBox.depth * dstTextureFormat.pixelBytes;

    // Allocate memory in the destination texture for the copy/conversion
    uint32_t stagingBaseLayer =
        offsetImageIndex.hasLayer() ? offsetImageIndex.getLayerIndex() : dstOffset.z;
    uint32_t stagingLayerCount = sourceBox.depth;
    gl::Offset stagingOffset   = dstOffset;
    gl::Extents stagingExtents(sourceBox.width, sourceBox.height, sourceBox.depth);
    bool is3D = gl_vk::GetImageType(mState.getType()) == VK_IMAGE_TYPE_3D;

    if (is3D)
    {
        stagingBaseLayer  = 0;
        stagingLayerCount = 1;
    }
    else
    {
        stagingOffset.z      = 0;
        stagingExtents.depth = 1;
    }

    const gl::ImageIndex stagingIndex = gl::ImageIndex::Make2DArrayRange(
        offsetImageIndex.getLevelIndex(), stagingBaseLayer, stagingLayerCount);

    uint8_t *destData = nullptr;
    ANGLE_TRY(mImage->stageSubresourceUpdateAndGetData(contextVk, destinationAllocationSize,
                                                       stagingIndex, stagingExtents, stagingOffset,
                                                       &destData, dstFormatID));

    // Source and dst data is tightly packed
    GLuint srcDataRowPitch = sourceBox.width * srcTextureFormat.pixelBytes;
    GLuint dstDataRowPitch = sourceBox.width * dstTextureFormat.pixelBytes;

    GLuint srcDataDepthPitch = srcDataRowPitch * sourceBox.height;
    GLuint dstDataDepthPitch = dstDataRowPitch * sourceBox.height;

    rx::PixelReadFunction pixelReadFunction   = srcTextureFormat.pixelReadFunction;
    rx::PixelWriteFunction pixelWriteFunction = dstTextureFormat.pixelWriteFunction;

    // Fix up the read/write functions for the sake of luminance/alpha that are emulated with
    // formats whose channels don't correspond to the original format (alpha is emulated with red,
    // and luminance/alpha is emulated with red/green).
    if (srcIntendedFormat.isLUMA())
    {
        pixelReadFunction = srcIntendedFormat.pixelReadFunction;
    }
    if (dstVkFormat.getIntendedFormat().isLUMA())
    {
        pixelWriteFunction = dstVkFormat.getIntendedFormat().pixelWriteFunction;
    }

    CopyImageCHROMIUM(sourceData, srcDataRowPitch, srcTextureFormat.pixelBytes, srcDataDepthPitch,
                      pixelReadFunction, destData, dstDataRowPitch, dstTextureFormat.pixelBytes,
                      dstDataDepthPitch, pixelWriteFunction, dstFormat.format,
                      dstFormat.componentType, sourceBox.width, sourceBox.height, sourceBox.depth,
                      unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha);

    if (shouldUpdateBeFlushed(gl::LevelIndex(index.getLevelIndex()), dstFormatID))
    {
        ANGLE_TRY(flushImageStagedUpdates(contextVk));
    }

    return angle::Result::Continue;
}

angle::Result TextureVk::copySubImageImplWithTransfer(ContextVk *contextVk,
                                                      const gl::ImageIndex &index,
                                                      const gl::Offset &dstOffset,
                                                      const vk::Format &dstFormat,
                                                      gl::LevelIndex sourceLevelGL,
                                                      size_t sourceLayer,
                                                      const gl::Box &sourceBox,
                                                      vk::ImageHelper *srcImage)
{
    vk::Renderer *renderer = contextVk->getRenderer();

    gl::LevelIndex level(index.getLevelIndex());
    uint32_t baseLayer  = index.hasLayer() ? index.getLayerIndex() : dstOffset.z;
    uint32_t layerCount = sourceBox.depth;

    gl::Offset srcOffset = {sourceBox.x, sourceBox.y, sourceBox.z};
    gl::Extents extents  = {sourceBox.width, sourceBox.height, sourceBox.depth};

    // Change source layout if necessary
    vk::CommandResources resources;
    resources.onImageTransferRead(VK_IMAGE_ASPECT_COLOR_BIT, srcImage);

    VkImageSubresourceLayers srcSubresource = {};
    srcSubresource.aspectMask               = VK_IMAGE_ASPECT_COLOR_BIT;
    srcSubresource.mipLevel                 = srcImage->toVkLevel(sourceLevelGL).get();
    srcSubresource.baseArrayLayer           = static_cast<uint32_t>(sourceLayer);
    srcSubresource.layerCount               = layerCount;

    bool isSrc3D  = srcImage->getExtents().depth > 1;
    bool isDest3D = gl_vk::GetImageType(mState.getType()) == VK_IMAGE_TYPE_3D;

    if (isSrc3D)
    {
        Set3DBaseArrayLayerAndLayerCount(&srcSubresource);
    }
    else
    {
        ASSERT(srcSubresource.baseArrayLayer == static_cast<uint32_t>(srcOffset.z));
        srcOffset.z = 0;
    }

    gl::Offset dstOffsetModified = dstOffset;
    if (!isDest3D)
    {
        // If destination is not 3D, destination offset must be 0.
        dstOffsetModified.z = 0;
    }

    // Perform self-copies through a staging buffer.
    // TODO: optimize to copy directly if possible.  http://anglebug.com/42263319
    bool isSelfCopy = mImage == srcImage;

    // If destination is valid, copy the source directly into it.
    if (shouldUpdateBeFlushed(level,
                              dstFormat.getActualImageFormatID(getRequiredFormatSupport())) &&
        !isSelfCopy)
    {
        // Make sure any updates to the image are already flushed.
        ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));

        resources.onImageTransferWrite(level, 1, baseLayer, layerCount, VK_IMAGE_ASPECT_COLOR_BIT,
                                       mImage);

        vk::OutsideRenderPassCommandBuffer *commandBuffer;
        ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &commandBuffer));

        VkImageSubresourceLayers destSubresource = srcSubresource;
        destSubresource.mipLevel                 = mImage->toVkLevel(level).get();
        destSubresource.baseArrayLayer           = baseLayer;
        destSubresource.layerCount               = layerCount;

        if (isDest3D)
        {
            Set3DBaseArrayLayerAndLayerCount(&destSubresource);
        }
        else if (!isSrc3D)
        {
            // extents.depth should be set to layer count if any of the source or destination is a
            // 2D Array.  If both are 2D Array, it should be set to 1.
            extents.depth = 1;
        }

        vk::ImageHelper::Copy(renderer, srcImage, mImage, srcOffset, dstOffsetModified, extents,
                              srcSubresource, destSubresource, commandBuffer);
    }
    else
    {
        // Create a temporary image to stage the copy
        std::unique_ptr<vk::RefCounted<vk::ImageHelper>> stagingImage;
        stagingImage = std::make_unique<vk::RefCounted<vk::ImageHelper>>();

        ANGLE_TRY(stagingImage->get().init2DStaging(
            contextVk, mState.hasProtectedContent(),
            gl::Extents(sourceBox.width, sourceBox.height, 1), dstFormat.getIntendedFormatID(),
            dstFormat.getActualImageFormatID(getRequiredFormatSupport()),
            vk::kImageUsageTransferBits, layerCount));

        resources.onImageTransferWrite(gl::LevelIndex(0), 1, 0, layerCount,
                                       VK_IMAGE_ASPECT_COLOR_BIT, &stagingImage->get());

        vk::OutsideRenderPassCommandBuffer *commandBuffer;
        ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &commandBuffer));

        VkImageSubresourceLayers destSubresource = srcSubresource;
        destSubresource.mipLevel                 = 0;
        destSubresource.baseArrayLayer           = 0;
        destSubresource.layerCount               = layerCount;

        if (!isSrc3D)
        {
            // extents.depth should be set to layer count if any of the source or destination is a
            // 2D Array.  If both are 2D Array, it should be set to 1.
            extents.depth = 1;
        }

        vk::ImageHelper::Copy(renderer, srcImage, &stagingImage->get(), srcOffset, gl::kOffsetZero,
                              extents, srcSubresource, destSubresource, commandBuffer);

        // Stage the copy for when the image storage is actually created.
        VkImageType imageType = gl_vk::GetImageType(mState.getType());
        const gl::ImageIndex stagingIndex =
            gl::ImageIndex::Make2DArrayRange(level.get(), baseLayer, layerCount);
        mImage->stageSubresourceUpdateFromImage(stagingImage.release(), stagingIndex,
                                                vk::LevelIndex(0), dstOffsetModified, extents,
                                                imageType);
    }

    return angle::Result::Continue;
}

angle::Result TextureVk::copySubImageImplWithDraw(ContextVk *contextVk,
                                                  const gl::ImageIndex &index,
                                                  const gl::Offset &dstOffset,
                                                  const vk::Format &dstFormat,
                                                  gl::LevelIndex sourceLevelGL,
                                                  const gl::Box &sourceBox,
                                                  bool isSrcFlipY,
                                                  bool unpackFlipY,
                                                  bool unpackPremultiplyAlpha,
                                                  bool unpackUnmultiplyAlpha,
                                                  vk::ImageHelper *srcImage,
                                                  const vk::ImageView *srcView,
                                                  SurfaceRotation srcFramebufferRotation)
{
    UtilsVk &utilsVk       = contextVk->getUtils();

    // Potentially make adjustments for pre-rotation.
    gl::Box rotatedSourceBox = sourceBox;
    gl::Extents srcExtents   = srcImage->getLevelExtents2D(vk::LevelIndex(0));
    switch (srcFramebufferRotation)
    {
        case SurfaceRotation::Identity:
            // No adjustments needed
            break;
        case SurfaceRotation::Rotated90Degrees:
            // Turn off y-flip for 90 degrees, as we don't want it affecting the
            // shaderParams.srcOffset calculation done in UtilsVk::copyImage().
            ASSERT(isSrcFlipY);
            isSrcFlipY = false;
            std::swap(rotatedSourceBox.x, rotatedSourceBox.y);
            std::swap(rotatedSourceBox.width, rotatedSourceBox.height);
            std::swap(srcExtents.width, srcExtents.height);
            break;
        case SurfaceRotation::Rotated180Degrees:
            ASSERT(isSrcFlipY);
            rotatedSourceBox.x = srcExtents.width - sourceBox.x - sourceBox.width - 1;
            rotatedSourceBox.y = srcExtents.height - sourceBox.y - sourceBox.height - 1;
            break;
        case SurfaceRotation::Rotated270Degrees:
            // Turn off y-flip for 270 degrees, as we don't want it affecting the
            // shaderParams.srcOffset calculation done in UtilsVk::copyImage().  It is needed
            // within the shader (when it will affect how the shader looks-up the source pixel),
            // and so shaderParams.flipY is turned on at the right time within
            // UtilsVk::copyImage().
            ASSERT(isSrcFlipY);
            isSrcFlipY         = false;
            rotatedSourceBox.x = srcExtents.height - sourceBox.y - sourceBox.height - 1;
            rotatedSourceBox.y = srcExtents.width - sourceBox.x - sourceBox.width - 1;
            std::swap(rotatedSourceBox.width, rotatedSourceBox.height);
            std::swap(srcExtents.width, srcExtents.height);
            break;
        default:
            UNREACHABLE();
            break;
    }

    gl::LevelIndex level(index.getLevelIndex());

    UtilsVk::CopyImageParameters params = {};
    params.srcOffset[0]        = rotatedSourceBox.x;
    params.srcOffset[1]        = rotatedSourceBox.y;
    params.srcExtents[0]       = rotatedSourceBox.width;
    params.srcExtents[1]       = rotatedSourceBox.height;
    params.dstOffset[0]        = dstOffset.x;
    params.dstOffset[1]        = dstOffset.y;
    params.srcMip              = srcImage->toVkLevel(sourceLevelGL);
    params.srcSampleCount      = srcImage->getSamples();
    params.srcHeight           = srcExtents.height;
    params.dstMip              = level;
    params.srcPremultiplyAlpha = unpackPremultiplyAlpha && !unpackUnmultiplyAlpha;
    params.srcUnmultiplyAlpha  = unpackUnmultiplyAlpha && !unpackPremultiplyAlpha;
    params.srcFlipY            = isSrcFlipY;
    params.dstFlipY            = unpackFlipY;
    params.srcRotation         = srcFramebufferRotation;

    uint32_t baseLayer  = index.hasLayer() ? index.getLayerIndex() : dstOffset.z;
    uint32_t layerCount = sourceBox.depth;

    gl::Extents extents = {sourceBox.width, sourceBox.height, sourceBox.depth};

    bool isSrc3D  = srcImage->getExtents().depth > 1;
    bool isDest3D = gl_vk::GetImageType(mState.getType()) == VK_IMAGE_TYPE_3D;

    // Perform self-copies through a staging buffer.
    // TODO: optimize to copy directly if possible.  http://anglebug.com/42263319
    bool isSelfCopy = mImage == srcImage;
    params.srcColorEncoding =
        gl::GetSizedInternalFormatInfo(srcImage->getIntendedFormat().glInternalFormat)
            .colorEncoding;
    params.dstColorEncoding =
        gl::GetSizedInternalFormatInfo(dstFormat.getIntendedFormat().glInternalFormat)
            .colorEncoding;

    // If destination is valid, copy the source directly into it.
    if (shouldUpdateBeFlushed(level,
                              dstFormat.getActualImageFormatID(getRequiredFormatSupport())) &&
        !isSelfCopy)
    {
        // Make sure any updates to the image are already flushed.
        ANGLE_TRY(flushImageStagedUpdates(contextVk));

        for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex)
        {
            params.srcLayer = layerIndex + sourceBox.z;
            params.dstLayer = baseLayer + layerIndex;

            const vk::ImageView *destView;
            ANGLE_TRY(getLevelLayerImageView(contextVk, level, baseLayer + layerIndex, &destView));

            ANGLE_TRY(utilsVk.copyImage(contextVk, mImage, destView, srcImage, srcView, params));
        }
    }
    else
    {
        GLint samples                      = srcImage->getSamples();
        gl::TextureType stagingTextureType = vk::Get2DTextureType(layerCount, samples);

        // Create a temporary image to stage the copy
        std::unique_ptr<vk::RefCounted<vk::ImageHelper>> stagingImage;
        stagingImage = std::make_unique<vk::RefCounted<vk::ImageHelper>>();

        ANGLE_TRY(stagingImage->get().init2DStaging(
            contextVk, mState.hasProtectedContent(),
            gl::Extents(sourceBox.width, sourceBox.height, 1), dstFormat.getIntendedFormatID(),
            dstFormat.getActualImageFormatID(getRequiredFormatSupport()), kDrawStagingImageFlags,
            layerCount));

        params.dstOffset[0] = 0;
        params.dstOffset[1] = 0;

        for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex)
        {
            params.srcLayer = layerIndex + sourceBox.z;
            params.dstLayer = layerIndex;

            // Create a temporary view for this layer.
            vk::ImageView stagingView;
            ANGLE_TRY(stagingImage->get().initLayerImageView(
                contextVk, stagingTextureType, VK_IMAGE_ASPECT_COLOR_BIT, gl::SwizzleState(),
                &stagingView, vk::LevelIndex(0), 1, layerIndex, 1));

            ANGLE_TRY(utilsVk.copyImage(contextVk, &stagingImage->get(), &stagingView, srcImage,
                                        srcView, params));

            // Queue the resource for cleanup as soon as the copy above is finished.  There's no
            // need to keep it around.
            contextVk->addGarbage(&stagingView);
        }

        if (!isSrc3D)
        {
            // extents.depth should be set to layer count if any of the source or destination is a
            // 2D Array.  If both are 2D Array, it should be set to 1.
            extents.depth = 1;
        }

        gl::Offset dstOffsetModified = dstOffset;
        if (!isDest3D)
        {
            // If destination is not 3D, destination offset must be 0.
            dstOffsetModified.z = 0;
        }

        // Stage the copy for when the image storage is actually created.
        VkImageType imageType = gl_vk::GetImageType(mState.getType());
        const gl::ImageIndex stagingIndex =
            gl::ImageIndex::Make2DArrayRange(level.get(), baseLayer, layerCount);
        mImage->stageSubresourceUpdateFromImage(stagingImage.release(), stagingIndex,
                                                vk::LevelIndex(0), dstOffsetModified, extents,
                                                imageType);
    }

    return angle::Result::Continue;
}

angle::Result TextureVk::setStorageImpl(ContextVk *contextVk,
                                        gl::TextureType type,
                                        const vk::Format &format)
{
    if (!mOwnsImage)
    {
        releaseAndDeleteImageAndViews(contextVk);
    }
    else if (mImage)
    {
        if (!contextVk->hasDisplayTextureShareGroup())
        {
            contextVk->getShareGroup()->onTextureRelease(this);
        }
        mImage->releaseStagedUpdates(contextVk->getRenderer());
    }

    // Assume all multisample texture types must be renderable.
    if (type == gl::TextureType::_2DMultisample || type == gl::TextureType::_2DMultisampleArray)
    {
        ANGLE_TRY(ensureRenderableWithFormat(contextVk, format, nullptr));
    }

    // Fixed rate compression
    if (mState.getSurfaceCompressionFixedRate() != GL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT)
    {
        ANGLE_TRY(ensureRenderableWithFormat(contextVk, format, nullptr));
    }

    ANGLE_TRY(ensureImageAllocated(contextVk, format));

    if (mImage->valid())
    {
        releaseImage(contextVk);
    }

    ASSERT(mState.getImmutableFormat());
    ASSERT(!TextureHasAnyRedefinedLevels(mRedefinedLevels));
    ANGLE_TRY(initImage(contextVk, format.getIntendedFormatID(),
                        format.getActualImageFormatID(getRequiredFormatSupport()),
                        ImageMipLevels::FullMipChainForGenerateMipmap));

    return angle::Result::Continue;
}

angle::Result TextureVk::setStorage(const gl::Context *context,
                                    gl::TextureType type,
                                    size_t levels,
                                    GLenum internalFormat,
                                    const gl::Extents &size)
{
    return setStorageMultisample(context, type, 1, internalFormat, size, true);
}

angle::Result TextureVk::setStorageMultisample(const gl::Context *context,
                                               gl::TextureType type,
                                               GLsizei samples,
                                               GLint internalformat,
                                               const gl::Extents &size,
                                               bool fixedSampleLocations)
{
    ContextVk *contextVk     = GetAs<ContextVk>(context->getImplementation());
    vk::Renderer *renderer   = contextVk->getRenderer();
    const vk::Format &format = renderer->getFormat(internalformat);

    ANGLE_TRY(setStorageImpl(contextVk, type, format));

    return angle::Result::Continue;
}

angle::Result TextureVk::setStorageExternalMemory(const gl::Context *context,
                                                  gl::TextureType type,
                                                  size_t levels,
                                                  GLenum internalFormat,
                                                  const gl::Extents &size,
                                                  gl::MemoryObject *memoryObject,
                                                  GLuint64 offset,
                                                  GLbitfield createFlags,
                                                  GLbitfield usageFlags,
                                                  const void *imageCreateInfoPNext)
{
    ContextVk *contextVk           = vk::GetImpl(context);
    MemoryObjectVk *memoryObjectVk = vk::GetImpl(memoryObject);
    vk::Renderer *renderer         = contextVk->getRenderer();

    const vk::Format &vkFormat     = renderer->getFormat(internalFormat);
    angle::FormatID actualFormatID = vkFormat.getActualRenderableImageFormatID();

    releaseAndDeleteImageAndViews(contextVk);

    setImageHelper(contextVk, new vk::ImageHelper(), gl::TextureType::InvalidEnum, 0, 0, true, {});

    mImage->setTilingMode(gl_vk::GetTilingMode(mState.getTilingMode()));

    // EXT_external_objects issue 13 says that all supported usage flags must be specified.
    // However, ANGLE_external_objects_flags allows these flags to be masked.  Note that the GL enum
    // values constituting the bits of |usageFlags| are identical to their corresponding Vulkan
    // value.
    usageFlags &= vk::GetMaximalImageUsageFlags(renderer, actualFormatID);

    // Similarly, createFlags is restricted to what is valid.
    createFlags &= vk::GetMinimalImageCreateFlags(renderer, type, usageFlags) |
                   VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;

    ANGLE_TRY(memoryObjectVk->createImage(contextVk, type, levels, internalFormat, size, offset,
                                          mImage, createFlags, usageFlags, imageCreateInfoPNext));
    mImageUsageFlags  = usageFlags;
    mImageCreateFlags = createFlags;

    constexpr VkImageUsageFlags kRenderableUsageFlags =
        kColorAttachmentImageFlags | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
    if ((usageFlags & kRenderableUsageFlags) != 0)
    {
        mRequiredFormatSupport = vk::ImageFormatSupport::Renderable;
    }

    ANGLE_TRY(initImageViews(contextVk, getImageViewLevelCount()));

    return angle::Result::Continue;
}

angle::Result TextureVk::setStorageAttribs(const gl::Context *context,
                                           gl::TextureType type,
                                           size_t levels,
                                           GLint internalformat,
                                           const gl::Extents &size,
                                           const GLint *attribList)
{
    ContextVk *contextVk     = GetAs<ContextVk>(context->getImplementation());
    vk::Renderer *renderer   = contextVk->getRenderer();
    const vk::Format &format = renderer->getFormat(internalformat);

    ANGLE_TRY(setStorageImpl(contextVk, type, format));

    return angle::Result::Continue;
}

GLint TextureVk::getImageCompressionRate(const gl::Context *context)
{
    ContextVk *contextVk   = vk::GetImpl(context);
    vk::Renderer *renderer = contextVk->getRenderer();

    ASSERT(mImage != nullptr && mImage->valid());
    ASSERT(renderer->getFeatures().supportsImageCompressionControl.enabled);

    if (!mOwnsImage)
    {
        return GL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT;
    }

    VkImageSubresource2EXT imageSubresource2      = {};
    imageSubresource2.sType                       = VK_STRUCTURE_TYPE_IMAGE_SUBRESOURCE_2_EXT;
    imageSubresource2.imageSubresource.aspectMask = mImage->getAspectFlags();

    VkImageCompressionPropertiesEXT compressionProperties = {};
    compressionProperties.sType               = VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT;
    VkSubresourceLayout2EXT subresourceLayout = {};
    subresourceLayout.sType                   = VK_STRUCTURE_TYPE_SUBRESOURCE_LAYOUT_2_EXT;
    subresourceLayout.pNext                   = &compressionProperties;

    vkGetImageSubresourceLayout2EXT(renderer->getDevice(), mImage->getImage().getHandle(),
                                    &imageSubresource2, &subresourceLayout);

    GLint compressionRate;
    // For an existing image, should only report one compression rate
    vk_gl::ConvertCompressionFlagsToGLFixedRates(
        compressionProperties.imageCompressionFixedRateFlags, 1, &compressionRate);
    return compressionRate;
}

GLint TextureVk::getFormatSupportedCompressionRates(const gl::Context *context,
                                                    GLenum internalformat,
                                                    GLsizei bufSize,
                                                    GLint *rates)
{
    ContextVk *contextVk     = vk::GetImpl(context);
    vk::Renderer *renderer   = contextVk->getRenderer();
    const vk::Format &format = renderer->getFormat(internalformat);

    return GetFormatSupportedCompressionRates(renderer, format, bufSize, rates);
}

void TextureVk::handleImmutableSamplerTransition(const vk::ImageHelper *previousImage,
                                                 const vk::ImageHelper *nextImage)
{
    // Did the previous image have an immutable sampler
    bool previousImageHadImmutableSampler =
        previousImage && previousImage->valid() && previousImage->hasImmutableSampler();

    // Does the next image require an immutable sampler?
    bool nextImageRequiresImmutableSampler =
        nextImage && nextImage->valid() && nextImage->hasImmutableSampler();

    // Has the external format changed?
    bool externalFormatChanged = false;
    if (previousImageHadImmutableSampler && nextImageRequiresImmutableSampler)
    {
        externalFormatChanged =
            previousImage->getExternalFormat() != nextImage->getExternalFormat();
    }

    // Handle transition of immutable sampler state
    if ((previousImageHadImmutableSampler != nextImageRequiresImmutableSampler) ||
        externalFormatChanged)
    {
        // The immutable sampler state is dirty.
        resetSampler();
        mImmutableSamplerDirty = true;
    }
}

angle::Result TextureVk::setEGLImageTarget(const gl::Context *context,
                                           gl::TextureType type,
                                           egl::Image *image)
{
    ContextVk *contextVk = vk::GetImpl(context);
    ImageVk *imageVk     = vk::GetImpl(image);

    // Early out if we are creating TextureVk with the exact same eglImage and target/face/level to
    // avoid unnecessarily dirty the state and allocating new ImageViews etc.
    if (mImage == imageVk->getImage() && mEGLImageNativeType == imageVk->getImageTextureType() &&
        static_cast<GLint>(mEGLImageLevelOffset) == imageVk->getImageLevel().get() &&
        mEGLImageLayerOffset == imageVk->getImageLayer())
    {
        return angle::Result::Continue;
    }

    ANGLE_TRY(contextVk->getShareGroup()->lockDefaultContextsPriority(contextVk));

    // TODO: Textures other than EGLImage targets can have immutable samplers.
    // http://anglebug.com/42264309
    handleImmutableSamplerTransition(mImage, imageVk ? imageVk->getImage() : nullptr);

    releaseAndDeleteImageAndViews(contextVk);

    UniqueSerial siblingSerial = imageVk->generateSiblingSerial();
    setImageHelper(contextVk, imageVk->getImage(), imageVk->getImageTextureType(),
                   imageVk->getImageLevel().get(), imageVk->getImageLayer(), false, siblingSerial);

    // Update ImageViewHelper's colorspace related state
    EGLenum imageColorspaceAttribute = image->getColorspaceAttribute();
    if (imageColorspaceAttribute != EGL_GL_COLORSPACE_DEFAULT_EXT)
    {
        egl::ImageColorspace imageColorspace =
            (imageColorspaceAttribute == EGL_GL_COLORSPACE_SRGB_KHR) ? egl::ImageColorspace::SRGB
                                                                     : egl::ImageColorspace::Linear;
        ASSERT(mImage != nullptr);
        mImageView.updateEglImageColorspace(*mImage, imageColorspace);
    }

    ANGLE_TRY(initImageViews(contextVk, getImageViewLevelCount()));

    return angle::Result::Continue;
}

angle::Result TextureVk::setImageExternal(const gl::Context *context,
                                          gl::TextureType type,
                                          egl::Stream *stream,
                                          const egl::Stream::GLTextureDescription &desc)
{
    ANGLE_VK_UNREACHABLE(vk::GetImpl(context));
    return angle::Result::Stop;
}

angle::Result TextureVk::setBuffer(const gl::Context *context, GLenum internalFormat)
{
    // No longer an image
    releaseAndDeleteImageAndViews(vk::GetImpl(context));
    resetSampler();

    // There's nothing else to do here.
    return angle::Result::Continue;
}

gl::ImageIndex TextureVk::getNativeImageIndex(const gl::ImageIndex &inputImageIndex) const
{
    if (mEGLImageNativeType == gl::TextureType::InvalidEnum)
    {
        return inputImageIndex;
    }

    // inputImageIndex can point to a specific layer, but only for non-2D textures.
    // mEGLImageNativeType can be a valid type, but only for 2D textures.
    // As such, both of these cannot be true at the same time.
    ASSERT(!inputImageIndex.hasLayer() && inputImageIndex.getLevelIndex() == 0);

    return gl::ImageIndex::MakeFromType(mEGLImageNativeType, mEGLImageLevelOffset,
                                        mEGLImageLayerOffset);
}

gl::LevelIndex TextureVk::getNativeImageLevel(gl::LevelIndex frontendLevel) const
{
    ASSERT(frontendLevel.get() == 0 || mEGLImageLevelOffset == 0);
    return frontendLevel + mEGLImageLevelOffset;
}

uint32_t TextureVk::getNativeImageLayer(uint32_t frontendLayer) const
{
    ASSERT(frontendLayer == 0 || mEGLImageLayerOffset == 0);
    return frontendLayer + mEGLImageLayerOffset;
}

void TextureVk::releaseAndDeleteImageAndViews(ContextVk *contextVk)
{
    if (mImage)
    {
        if (mOwnsImage)
        {
            releaseStagedUpdates(contextVk);
        }
        releaseImage(contextVk);
        mImageObserverBinding.bind(nullptr);
        mRequiresMutableStorage = false;
        mRequiredFormatSupport  = vk::ImageFormatSupport::SampleOnly;
        mImageCreateFlags       = 0;
        SafeDelete(mImage);
    }

    if (!contextVk->hasDisplayTextureShareGroup())
    {
        contextVk->getShareGroup()->onTextureRelease(this);
    }

    if (getBuffer().get() != nullptr)
    {
        mBufferContentsObservers->disableForBuffer(getBuffer().get());
    }

    if (mBufferViews.isInitialized())
    {
        mBufferViews.release(contextVk);
        onStateChange(angle::SubjectMessage::SubjectChanged);
    }
    mRedefinedLevels = {};

    ASSERT(mDescriptorSetCacheManager.allValidEntriesAreCached(contextVk));
    mDescriptorSetCacheManager.releaseKeys(contextVk->getRenderer());
}

void TextureVk::initImageUsageFlags(ContextVk *contextVk,
                                    const angle::Format &intendedFormat,
                                    angle::FormatID actualFormatID)
{
    ASSERT(actualFormatID != angle::FormatID::NONE);

    mImageUsageFlags = vk::kImageUsageTransferBits | VK_IMAGE_USAGE_SAMPLED_BIT;

    // If the image has depth/stencil support, add those as possible usage.
    vk::Renderer *renderer = contextVk->getRenderer();
    if (angle::Format::Get(actualFormatID).hasDepthOrStencilBits())
    {
        // Work around a bug in the Mock ICD:
        // https://github.com/KhronosGroup/Vulkan-Tools/issues/445
        if (renderer->hasImageFormatFeatureBits(actualFormatID,
                                                VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT))
        {
            mImageUsageFlags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;

            if (renderer->getFeatures().supportsShaderFramebufferFetchDepthStencil.enabled)
            {
                mImageUsageFlags |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
            }
        }
    }
    else if (renderer->hasImageFormatFeatureBits(actualFormatID,
                                                 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))
    {
        // If the intended format is not renderable, don't add color attachment flags even if the
        // fallback format is.  This way, the image is more likely to be usable with
        // VK_EXT_host_image_copy.
        if (!intendedFormat.isLUMA() ||
            mRequiredFormatSupport == vk::ImageFormatSupport::Renderable)
        {
            mImageUsageFlags |= kColorAttachmentImageFlags;
        }
    }
}

angle::Result TextureVk::ensureImageAllocated(ContextVk *contextVk, const vk::Format &format)
{
    if (mImage == nullptr)
    {
        setImageHelper(contextVk, new vk::ImageHelper(), gl::TextureType::InvalidEnum, 0, 0, true,
                       {});
    }

    initImageUsageFlags(contextVk, format.getIntendedFormat(),
                        format.getActualImageFormatID(getRequiredFormatSupport()));

    return angle::Result::Continue;
}

void TextureVk::setImageHelper(ContextVk *contextVk,
                               vk::ImageHelper *imageHelper,
                               gl::TextureType eglImageNativeType,
                               uint32_t imageLevelOffset,
                               uint32_t imageLayerOffset,
                               bool selfOwned,
                               UniqueSerial siblingSerial)
{
    ASSERT(mImage == nullptr);

    mImageObserverBinding.bind(imageHelper);

    ASSERT(selfOwned == !siblingSerial.valid());
    mOwnsImage          = selfOwned;
    mImageSiblingSerial = siblingSerial;
    // If image is shared between other container objects, force it to renderable format since we
    // don't know if other container object will render or not.
    if (!mOwnsImage && !imageHelper->isBackedByExternalMemory())
    {
        mRequiredFormatSupport = vk::ImageFormatSupport::Renderable;
    }
    mEGLImageNativeType  = eglImageNativeType;
    mEGLImageLevelOffset = imageLevelOffset;
    mEGLImageLayerOffset = imageLayerOffset;
    mImage               = imageHelper;

    // All render targets must be already destroyed prior to this call.
    for (auto &renderTargets : mSingleLayerRenderTargets)
    {
        ASSERT(renderTargets.empty());
    }
    ASSERT(mMultiLayerRenderTargets.empty());

    if (!selfOwned)
    {
        // (!selfOwned) implies that the texture is a target sibling.
        // Inherit a few VkImage's create attributes from ImageHelper.
        mImageCreateFlags       = mImage->getCreateFlags();
        mImageUsageFlags        = mImage->getUsage();
        mRequiresMutableStorage = (mImageCreateFlags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) != 0;
    }

    vk::Renderer *renderer = contextVk->getRenderer();

    getImageViews().init(renderer);
}

angle::Result TextureVk::redefineLevel(const gl::Context *context,
                                       const gl::ImageIndex &index,
                                       const vk::Format &format,
                                       const gl::Extents &size)
{
    ContextVk *contextVk = vk::GetImpl(context);

    if (!mOwnsImage)
    {
        releaseAndDeleteImageAndViews(contextVk);
    }

    if (mImage != nullptr)
    {
        // If there are any staged changes for this index, we can remove them since we're going to
        // override them with this call.
        gl::LevelIndex levelIndexGL(index.getLevelIndex());
        const uint32_t layerIndex = index.hasLayer() ? index.getLayerIndex() : 0;
        if (gl::IsArrayTextureType(index.getType()))
        {
            // A multi-layer texture is being redefined, remove all updates to this level; the
            // number of layers may have changed.
            mImage->removeStagedUpdates(contextVk, levelIndexGL, levelIndexGL);
        }
        else
        {
            // Otherwise remove only updates to this layer.  For example, cube map updates can be
            // done through glTexImage2D, one per cube face (i.e. layer) and so should not remove
            // updates to the other layers.
            ASSERT(index.getLayerCount() == 1);
            mImage->removeSingleSubresourceStagedUpdates(contextVk, levelIndexGL, layerIndex,
                                                         index.getLayerCount());
        }

        if (mImage->valid())
        {
            TextureLevelAllocation levelAllocation =
                IsTextureLevelInAllocatedImage(*mImage, levelIndexGL)
                    ? TextureLevelAllocation::WithinAllocatedImage
                    : TextureLevelAllocation::OutsideAllocatedImage;
            TextureLevelDefinition levelDefinition =
                IsTextureLevelDefinitionCompatibleWithImage(
                    *mImage, levelIndexGL, size, format.getIntendedFormatID(),
                    format.getActualImageFormatID(getRequiredFormatSupport()))
                    ? TextureLevelDefinition::Compatible
                    : TextureLevelDefinition::Incompatible;
            if (TextureRedefineLevel(levelAllocation, levelDefinition, mState.getImmutableFormat(),
                                     mImage->getLevelCount(), layerIndex, index,
                                     mImage->getFirstAllocatedLevel(), &mRedefinedLevels))
            {
                releaseImage(contextVk);
            }
        }
    }

    // If image is not released due to an out-of-range or incompatible level definition, the image
    // is still valid and we shouldn't redefine it to use the new format.  In that case,
    // ensureImageAllocated will only use the format to update the staging buffer's alignment to
    // support both the previous and the new formats.
    ANGLE_TRY(ensureImageAllocated(contextVk, format));

    return angle::Result::Continue;
}

angle::Result TextureVk::copyImageDataToBufferAndGetData(ContextVk *contextVk,
                                                         gl::LevelIndex sourceLevelGL,
                                                         uint32_t layerCount,
                                                         const gl::Box &sourceArea,
                                                         QueueSubmitReason reason,
                                                         vk::BufferHelper *copyBuffer,
                                                         uint8_t **outDataPtr)
{
    ANGLE_TRACE_EVENT0("gpu.angle", "TextureVk::copyImageDataToBufferAndGetData");

    // Make sure the source is initialized and it's images are flushed.
    ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));

    gl::Box modifiedSourceArea = sourceArea;

    bool is3D = mImage->getExtents().depth > 1;
    if (is3D)
    {
        layerCount = 1;
    }
    else
    {
        modifiedSourceArea.depth = 1;
    }

    ANGLE_TRY(mImage->copyImageDataToBuffer(contextVk, sourceLevelGL, layerCount, 0,
                                            modifiedSourceArea, copyBuffer, outDataPtr));

    // Explicitly finish. If new use cases arise where we don't want to block we can change this.
    ANGLE_TRY(contextVk->finishImpl(reason));
    // invalidate must be called after wait for finish.
    ANGLE_TRY(copyBuffer->invalidate(contextVk->getRenderer()));

    return angle::Result::Continue;
}

angle::Result TextureVk::copyBufferDataToImage(ContextVk *contextVk,
                                               vk::BufferHelper *srcBuffer,
                                               const gl::ImageIndex index,
                                               uint32_t rowLength,
                                               uint32_t imageHeight,
                                               const gl::Box &sourceArea,
                                               size_t offset,
                                               VkImageAspectFlags aspectFlags)
{
    ANGLE_TRACE_EVENT0("gpu.angle", "TextureVk::copyBufferDataToImage");

    // Vulkan Spec requires the bufferOffset to be a multiple of pixel size for
    // vkCmdCopyBufferToImage.
    ASSERT((offset % vk::GetImageCopyBufferAlignment(mImage->getActualFormatID())) == 0);

    gl::LevelIndex level = gl::LevelIndex(index.getLevelIndex());
    GLuint layerCount    = index.getLayerCount();
    GLuint layerIndex    = 0;

    ASSERT((aspectFlags & kDepthStencilAspects) != kDepthStencilAspects);

    VkBufferImageCopy region           = {};
    region.bufferOffset                = offset;
    region.bufferRowLength             = rowLength;
    region.bufferImageHeight           = imageHeight;
    region.imageExtent.width           = sourceArea.width;
    region.imageExtent.height          = sourceArea.height;
    region.imageExtent.depth           = sourceArea.depth;
    region.imageOffset.x               = sourceArea.x;
    region.imageOffset.y               = sourceArea.y;
    region.imageOffset.z               = sourceArea.z;
    region.imageSubresource.aspectMask = aspectFlags;
    region.imageSubresource.layerCount = layerCount;
    region.imageSubresource.mipLevel   = mImage->toVkLevel(level).get();

    if (gl::IsArrayTextureType(index.getType()))
    {
        layerIndex               = sourceArea.z;
        region.imageOffset.z     = 0;
        region.imageExtent.depth = 1;
    }
    else if (index.getType() == gl::TextureType::CubeMap)
    {
        // Copy to the correct cube map face.
        layerIndex = index.getLayerIndex();
    }
    region.imageSubresource.baseArrayLayer = layerIndex;

    // Make sure the source is initialized and its images are flushed.
    ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));

    vk::CommandResources resources;
    resources.onBufferTransferRead(srcBuffer);
    resources.onImageTransferWrite(level, 1, layerIndex, layerCount, mImage->getAspectFlags(),
                                   mImage);

    vk::OutsideRenderPassCommandBuffer *commandBuffer;
    ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &commandBuffer));

    commandBuffer->copyBufferToImage(srcBuffer->getBuffer().getHandle(), mImage->getImage(),
                                     mImage->getCurrentLayout(contextVk->getRenderer()), 1,
                                     &region);

    return angle::Result::Continue;
}

angle::Result TextureVk::generateMipmapsWithCompute(ContextVk *contextVk)
{
    // Requires that the image:
    //
    // - is not sRGB
    // - is not integer
    // - is 2D or 2D array
    // - is single sample
    // - is color image
    //
    // Support for the first two can be added easily.  Supporting 3D textures, MSAA and
    // depth/stencil would be more involved.
    ASSERT(!mImage->getActualFormat().isSRGB);
    ASSERT(!mImage->getActualFormat().isInt());
    ASSERT(mImage->getType() == VK_IMAGE_TYPE_2D);
    ASSERT(mImage->getSamples() == 1);
    ASSERT(mImage->getAspectFlags() == VK_IMAGE_ASPECT_COLOR_BIT);

    // Create the appropriate sampler.
    GLenum filter = CalculateGenerateMipmapFilter(contextVk, mImage->getActualFormatID());

    gl::SamplerState samplerState;
    samplerState.setMinFilter(filter);
    samplerState.setMagFilter(filter);
    samplerState.setWrapS(GL_CLAMP_TO_EDGE);
    samplerState.setWrapT(GL_CLAMP_TO_EDGE);
    samplerState.setWrapR(GL_CLAMP_TO_EDGE);

    vk::SharedSamplerPtr sampler;
    vk::SamplerDesc samplerDesc(contextVk, samplerState, false, nullptr,
                                static_cast<angle::FormatID>(0));
    ANGLE_TRY(
        contextVk->getShareGroup()->getSamplerCache().getSampler(contextVk, samplerDesc, &sampler));

    // If the image has more levels than supported, generate as many mips as possible at a time.
    const vk::LevelIndex maxGenerateLevels(UtilsVk::GetGenerateMipmapMaxLevels(contextVk));
    vk::LevelIndex dstMaxLevelVk = mImage->toVkLevel(gl::LevelIndex(mState.getMipmapMaxLevel()));
    for (vk::LevelIndex dstBaseLevelVk =
             mImage->toVkLevel(gl::LevelIndex(mState.getEffectiveBaseLevel() + 1));
         dstBaseLevelVk <= dstMaxLevelVk; dstBaseLevelVk = dstBaseLevelVk + maxGenerateLevels.get())
    {
        vk::CommandResources resources;

        // For mipmap generation, we should make sure that there is no pending write for the source
        // mip level. If there is, a barrier should be inserted before the source mip being used.
        const vk::LevelIndex srcLevelVk = dstBaseLevelVk - 1;
        uint32_t writeLevelCount =
            std::min(maxGenerateLevels.get(), dstMaxLevelVk.get() + 1 - dstBaseLevelVk.get());

        resources.onImageComputeMipmapGenerationRead(mImage->toGLLevel(srcLevelVk), 1, 0,
                                                     mImage->getLayerCount(),
                                                     VK_IMAGE_ASPECT_COLOR_BIT, mImage);
        resources.onImageComputeShaderWrite(mImage->toGLLevel(dstBaseLevelVk), writeLevelCount, 0,
                                            mImage->getLayerCount(), VK_IMAGE_ASPECT_COLOR_BIT,
                                            mImage);

        vk::OutsideRenderPassCommandBuffer *commandBuffer;
        ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &commandBuffer));

        // Generate mipmaps for every layer separately.
        for (uint32_t layer = 0; layer < mImage->getLayerCount(); ++layer)
        {
            // Create the necessary views.
            const vk::ImageView *srcView                         = nullptr;
            UtilsVk::GenerateMipmapDestLevelViews destLevelViews = {};

            ANGLE_TRY(getImageViews().getLevelLayerDrawImageView(contextVk, *mImage, srcLevelVk,
                                                                 layer, &srcView));

            vk::LevelIndex dstLevelCount = maxGenerateLevels;
            for (vk::LevelIndex levelVk(0); levelVk < maxGenerateLevels; ++levelVk)
            {
                vk::LevelIndex dstLevelVk = dstBaseLevelVk + levelVk.get();

                // If fewer levels left than maxGenerateLevels, cut the loop short.
                if (dstLevelVk > dstMaxLevelVk)
                {
                    dstLevelCount = levelVk;
                    break;
                }

                ANGLE_TRY(getImageViews().getLevelLayerDrawImageView(
                    contextVk, *mImage, dstLevelVk, layer, &destLevelViews[levelVk.get()]));
            }

            // If the image has fewer than maximum levels, fill the last views with a unused view.
            ASSERT(dstLevelCount > vk::LevelIndex(0));
            for (vk::LevelIndex levelVk = dstLevelCount;
                 levelVk < vk::LevelIndex(UtilsVk::kGenerateMipmapMaxLevels); ++levelVk)
            {
                destLevelViews[levelVk.get()] = destLevelViews[levelVk.get() - 1];
            }

            // Generate mipmaps.
            UtilsVk::GenerateMipmapParameters params = {};
            params.srcLevel                          = srcLevelVk.get();
            params.dstLevelCount                     = dstLevelCount.get();

            ANGLE_TRY(contextVk->getUtils().generateMipmap(contextVk, mImage, srcView, mImage,
                                                           destLevelViews, sampler->get(), params));
        }
    }

    contextVk->trackImageWithOutsideRenderPassEvent(mImage);

    return angle::Result::Continue;
}

angle::Result TextureVk::generateMipmapsWithCPU(const gl::Context *context)
{
    ContextVk *contextVk = vk::GetImpl(context);

    gl::LevelIndex baseLevelGL(mState.getEffectiveBaseLevel());
    vk::LevelIndex baseLevelVk         = mImage->toVkLevel(baseLevelGL);
    const gl::Extents baseLevelExtents = mImage->getLevelExtents(baseLevelVk);
    uint32_t imageLayerCount           = mImage->getLayerCount();

    uint8_t *imageData = nullptr;
    gl::Box imageArea(0, 0, 0, baseLevelExtents.width, baseLevelExtents.height,
                      baseLevelExtents.depth);

    vk::RendererScoped<vk::BufferHelper> bufferHelper(contextVk->getRenderer());
    ANGLE_TRY(copyImageDataToBufferAndGetData(contextVk, baseLevelGL, imageLayerCount, imageArea,
                                              QueueSubmitReason::GenerateMipmapOnCPU,
                                              &bufferHelper.get(), &imageData));

    const angle::Format &angleFormat = mImage->getActualFormat();
    GLuint sourceRowPitch            = baseLevelExtents.width * angleFormat.pixelBytes;
    GLuint sourceDepthPitch          = sourceRowPitch * baseLevelExtents.height;
    size_t baseLevelAllocationSize   = sourceDepthPitch * baseLevelExtents.depth;

    // We now have the base level available to be manipulated in the imageData pointer. Generate all
    // the missing mipmaps with the slow path. For each layer, use the copied data to generate all
    // the mips.
    for (GLuint layer = 0; layer < imageLayerCount; layer++)
    {
        size_t bufferOffset = layer * baseLevelAllocationSize;

        ANGLE_TRY(generateMipmapLevelsWithCPU(contextVk, angleFormat, layer, baseLevelGL + 1,
                                              gl::LevelIndex(mState.getMipmapMaxLevel()),
                                              baseLevelExtents.width, baseLevelExtents.height,
                                              baseLevelExtents.depth, sourceRowPitch,
                                              sourceDepthPitch, imageData + bufferOffset));
    }

    ASSERT(!TextureHasAnyRedefinedLevels(mRedefinedLevels));
    return flushImageStagedUpdates(contextVk);
}

angle::Result TextureVk::generateMipmap(const gl::Context *context)
{
    ContextVk *contextVk   = vk::GetImpl(context);
    vk::Renderer *renderer = contextVk->getRenderer();

    // The image should already be allocated by a prior syncState.
    ASSERT(mImage->valid());

    // If base level has changed, the front-end should have called syncState already.
    ASSERT(mState.getImmutableFormat() ||
           mImage->getFirstAllocatedLevel() == gl::LevelIndex(mState.getEffectiveBaseLevel()));

    // Only staged update here is the robust resource init if any.
    ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::FullMipChainForGenerateMipmap));

    vk::LevelIndex baseLevel = mImage->toVkLevel(gl::LevelIndex(mState.getEffectiveBaseLevel()));
    vk::LevelIndex maxLevel  = mImage->toVkLevel(gl::LevelIndex(mState.getMipmapMaxLevel()));
    ASSERT(maxLevel != vk::LevelIndex(0));

    const bool colorspaceOverrideForRead  = getImageViews().hasColorspaceOverrideForRead(*mImage);
    const bool colorspaceOverrideForWrite = getImageViews().hasColorspaceOverrideForWrite(*mImage);

    if (colorspaceOverrideForRead || colorspaceOverrideForWrite)
    {
        angle::FormatID actualFormatID =
            colorspaceOverrideForRead
                ? getImageViews().getColorspaceOverrideFormatForRead(mImage->getActualFormatID())
                : getImageViews().getColorspaceOverrideFormatForWrite(mImage->getActualFormatID());

        return contextVk->getUtils().generateMipmapWithDraw(
            contextVk, mImage, actualFormatID,
            gl::IsMipmapFiltered(mState.getSamplerState().getMinFilter()));
    }

    // If it's possible to generate mipmap in compute, that would give the best possible
    // performance on some hardware.
    if (CanGenerateMipmapWithCompute(renderer, mImage->getType(), mImage->getActualFormatID(),
                                     mImage->getSamples(), mOwnsImage))
    {
        ASSERT((mImageUsageFlags & VK_IMAGE_USAGE_STORAGE_BIT) != 0);
        return generateMipmapsWithCompute(contextVk);
    }
    else if (renderer->hasImageFormatFeatureBits(mImage->getActualFormatID(), kBlitFeatureFlags))
    {
        // Otherwise, use blit if possible.
        return mImage->generateMipmapsWithBlit(contextVk, baseLevel, maxLevel);
    }

    ANGLE_VK_PERF_WARNING(contextVk, GL_DEBUG_SEVERITY_HIGH,
                          "Mipmap generated on CPU due to format restrictions");

    // If not possible to generate mipmaps on the GPU, do it on the CPU for conformance.
    return generateMipmapsWithCPU(context);
}

angle::Result TextureVk::setBaseLevel(const gl::Context *context, GLuint baseLevel)
{
    return angle::Result::Continue;
}

angle::Result TextureVk::maybeUpdateBaseMaxLevels(ContextVk *contextVk,
                                                  TextureUpdateResult *updateResultOut)
{
    if (!mImage)
    {
        return angle::Result::Continue;
    }

    bool baseLevelChanged = mCurrentBaseLevel.get() != static_cast<GLint>(mState.getBaseLevel());
    bool maxLevelChanged  = mCurrentMaxLevel.get() != static_cast<GLint>(mState.getMaxLevel());

    if (!maxLevelChanged && !baseLevelChanged)
    {
        return angle::Result::Continue;
    }

    gl::LevelIndex newBaseLevel = gl::LevelIndex(mState.getEffectiveBaseLevel());
    // In edge case where base level > max level, clamp up to base level.
    gl::LevelIndex newMaxLevel =
        std::max(gl::LevelIndex(mState.getEffectiveMaxLevel()), newBaseLevel);
    ASSERT(newBaseLevel <= newMaxLevel);

    if (!mImage->valid())
    {
        // No further work to do, let staged updates handle the new levels
        return angle::Result::Continue;
    }

    if (mState.getImmutableFormat())
    {
        // For immutable texture, baseLevel/maxLevel should be a subset of the texture's actual
        // number of mip levels. We don't need to respecify an image.
        ASSERT(!baseLevelChanged || newBaseLevel >= mImage->getFirstAllocatedLevel());
        ASSERT(!maxLevelChanged || newMaxLevel < gl::LevelIndex(mImage->getLevelCount()));
    }
    else if (!baseLevelChanged && (newMaxLevel <= mImage->getLastAllocatedLevel()))
    {
        // With a valid image, check if only changing the maxLevel to a subset of the texture's
        // actual number of mip levels
        ASSERT(maxLevelChanged);
    }
    else
    {
        *updateResultOut = TextureUpdateResult::ImageRespecified;
        return respecifyImageStorage(contextVk);
    }

    // Don't need to respecify the texture; but do need to update which vkImageView's are served up
    // by ImageViewHelper

    // Update the current max level in ImageViewHelper
    ANGLE_TRY(initImageViews(contextVk, newMaxLevel - newBaseLevel + 1));

    mCurrentBaseLevel = newBaseLevel;
    mCurrentMaxLevel  = newMaxLevel;

    return angle::Result::Continue;
}

angle::Result TextureVk::copyAndStageImageData(ContextVk *contextVk,
                                               gl::LevelIndex previousFirstAllocateLevel,
                                               vk::ImageHelper *srcImage,
                                               vk::ImageHelper *dstImage)
{
    // Preserve the data in the Vulkan image.  GL texture's staged updates that correspond to
    // levels outside the range of the Vulkan image will remain intact.
    vk::Renderer *renderer = contextVk->getRenderer();

    // This path is only called when switching from !owned to owned, in which case if any level was
    // redefined it's already released and deleted by TextureVk::redefineLevel().
    ASSERT(!TextureHasAnyRedefinedLevels(mRedefinedLevels));

    // Create a temp copy of srcImage for staging.
    std::unique_ptr<vk::RefCounted<vk::ImageHelper>> stagingImage;
    stagingImage = std::make_unique<vk::RefCounted<vk::ImageHelper>>();

    const uint32_t levelCount = srcImage->getLevelCount();
    const uint32_t layerCount = srcImage->getLayerCount();

    ANGLE_TRY(stagingImage->get().initStaging(
        contextVk, mState.hasProtectedContent(), srcImage->getType(), srcImage->getExtents(),
        srcImage->getIntendedFormatID(), srcImage->getActualFormatID(), srcImage->getSamples(),
        vk::kImageUsageTransferBits, levelCount, layerCount));

    // Copy the src image wholly into the staging image
    const VkImageAspectFlags aspectFlags = srcImage->getAspectFlags();

    vk::CommandResources resources;
    resources.onImageTransferWrite(gl::LevelIndex(0), levelCount, 0, layerCount, aspectFlags,
                                   &stagingImage->get());
    resources.onImageTransferRead(aspectFlags, srcImage);

    vk::OutsideRenderPassCommandBuffer *commandBuffer;
    ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &commandBuffer));

    VkImageCopy copyRegion               = {};
    copyRegion.srcSubresource.aspectMask = aspectFlags;
    copyRegion.srcSubresource.layerCount = layerCount;
    copyRegion.dstSubresource            = copyRegion.srcSubresource;

    for (vk::LevelIndex levelVk(0); levelVk < vk::LevelIndex(levelCount); ++levelVk)
    {
        gl::Extents levelExtents = srcImage->getLevelExtents(levelVk);

        copyRegion.srcSubresource.mipLevel = levelVk.get();
        copyRegion.dstSubresource.mipLevel = levelVk.get();
        gl_vk::GetExtent(levelExtents, &copyRegion.extent);

        commandBuffer->copyImage(srcImage->getImage(), srcImage->getCurrentLayout(renderer),
                                 stagingImage->get().getImage(),
                                 stagingImage->get().getCurrentLayout(renderer), 1, &copyRegion);
    }

    // Stage the staging image in the destination
    dstImage->stageSubresourceUpdatesFromAllImageLevels(stagingImage.release(),
                                                        previousFirstAllocateLevel);

    return angle::Result::Continue;
}

angle::Result TextureVk::reinitImageAsRenderable(ContextVk *contextVk, const vk::Format &format)
{
    ASSERT(mImage->valid());
    vk::Renderer *renderer = contextVk->getRenderer();

    const uint32_t levelCount = mImage->getLevelCount();
    const uint32_t layerCount = mImage->getLayerCount();

    // Make sure the source is initialized and its staged updates are flushed.
    ANGLE_TRY(flushImageStagedUpdates(contextVk));

    const angle::Format &srcFormat = mImage->getActualFormat();
    const angle::Format &dstFormat = format.getActualImageFormat(getRequiredFormatSupport());

    // If layerCount or levelCount is bigger than 1, we go for the slow path for now. The problem
    // with draw path is that in the multiple level/layer case, we have to do copy in a loop.
    // Currently copySubImageImplWithDraw() calls ensureImageInitalized which forces flush out
    // staged updates that we just staged inside the loop which is wrong.
    if (levelCount == 1 && layerCount == 1 &&
        !IsTextureLevelRedefined(mRedefinedLevels, mState.getType(),
                                 mImage->getFirstAllocatedLevel()))
    {
        ANGLE_VK_PERF_WARNING(contextVk, GL_DEBUG_SEVERITY_LOW,
                              "Copying image data due to texture format fallback");

        ASSERT(CanCopyWithDraw(renderer, mImage->getUsage(),
                               format.getActualImageFormatID(getRequiredFormatSupport()),
                               getTilingMode()));
        vk::LevelIndex levelVk(0);
        gl::LevelIndex sourceLevelGL = mImage->toGLLevel(levelVk);
        gl::Box sourceBox(gl::kOffsetZero, mImage->getLevelExtents(levelVk));
        const gl::ImageIndex index =
            gl::ImageIndex::MakeFromType(mState.getType(), sourceLevelGL.get());

        // Flush the render pass, which may incur a vkQueueSubmit, before taking any views.
        // Otherwise the view serials would not reflect the render pass they are really used in.
        // http://crbug.com/1272266#c22
        ANGLE_TRY(
            contextVk->flushCommandsAndEndRenderPass(RenderPassClosureReason::PrepareForImageCopy));

        return copySubImageImplWithDraw(contextVk, index, gl::kOffsetZero, format, sourceLevelGL,
                                        sourceBox, false, false, false, false, mImage,
                                        &getCopyImageView(), SurfaceRotation::Identity);
    }

    for (vk::LevelIndex levelVk(0); levelVk < vk::LevelIndex(levelCount); ++levelVk)
    {
        gl::LevelIndex levelGL = mImage->toGLLevel(levelVk);
        if (IsTextureLevelRedefined(mRedefinedLevels, mState.getType(), levelGL))
        {
            continue;
        }

        ANGLE_VK_PERF_WARNING(contextVk, GL_DEBUG_SEVERITY_HIGH,
                              "GPU stall due to texture format fallback");

        gl::Box sourceBox(gl::kOffsetZero, mImage->getLevelExtents(levelVk));
        // copy and stage entire layer
        const gl::ImageIndex index =
            gl::ImageIndex::MakeFromType(mState.getType(), levelGL.get(), 0, layerCount);

        // Read back the requested region of the source texture
        vk::RendererScoped<vk::BufferHelper> bufferHelper(renderer);
        vk::BufferHelper *srcBuffer = &bufferHelper.get();
        uint8_t *srcData            = nullptr;
        ANGLE_TRY(mImage->copyImageDataToBuffer(contextVk, levelGL, layerCount, 0, sourceBox,
                                                srcBuffer, &srcData));

        // Explicitly finish. If new use cases arise where we don't want to block we can change
        // this.
        ANGLE_TRY(contextVk->finishImpl(QueueSubmitReason::TextureReformatToRenderable));
        // invalidate must be called after wait for finish.
        ANGLE_TRY(srcBuffer->invalidate(renderer));

        size_t dstBufferSize = sourceBox.width * sourceBox.height * sourceBox.depth *
                               dstFormat.pixelBytes * layerCount;

        // Allocate memory in the destination texture for the copy/conversion.
        uint8_t *dstData = nullptr;
        ANGLE_TRY(mImage->stageSubresourceUpdateAndGetData(
            contextVk, dstBufferSize, index, mImage->getLevelExtents(levelVk), gl::kOffsetZero,
            &dstData, dstFormat.id));

        // Source and destination data is tightly packed
        GLuint srcDataRowPitch = sourceBox.width * srcFormat.pixelBytes;
        GLuint dstDataRowPitch = sourceBox.width * dstFormat.pixelBytes;

        GLuint srcDataDepthPitch = srcDataRowPitch * sourceBox.height;
        GLuint dstDataDepthPitch = dstDataRowPitch * sourceBox.height;

        GLuint srcDataLayerPitch = srcDataDepthPitch * sourceBox.depth;
        GLuint dstDataLayerPitch = dstDataDepthPitch * sourceBox.depth;

        rx::PixelReadFunction pixelReadFunction   = srcFormat.pixelReadFunction;
        rx::PixelWriteFunction pixelWriteFunction = dstFormat.pixelWriteFunction;

        const gl::InternalFormat &dstFormatInfo = *mState.getImageDesc(index).format.info;
        for (uint32_t layer = 0; layer < layerCount; layer++)
        {
            CopyImageCHROMIUM(srcData + layer * srcDataLayerPitch, srcDataRowPitch,
                              srcFormat.pixelBytes, srcDataDepthPitch, pixelReadFunction,
                              dstData + layer * dstDataLayerPitch, dstDataRowPitch,
                              dstFormat.pixelBytes, dstDataDepthPitch, pixelWriteFunction,
                              dstFormatInfo.format, dstFormatInfo.componentType, sourceBox.width,
                              sourceBox.height, sourceBox.depth, false, false, false);
        }
    }

    return angle::Result::Continue;
}

angle::Result TextureVk::respecifyImageStorage(ContextVk *contextVk)
{
    if (!mImage->valid())
    {
        ASSERT(!TextureHasAnyRedefinedLevels(mRedefinedLevels));
        return angle::Result::Continue;
    }

    // Recreate the image to reflect new base or max levels.
    // First, flush any pending updates so we have good data in the current mImage
    if (mImage->hasStagedUpdatesInAllocatedLevels())
    {
        ANGLE_TRY(flushImageStagedUpdates(contextVk));
    }

    if (!mOwnsImage)
    {
        // Cache values needed for copy and stage operations
        vk::ImageHelper *srcImage = mImage;
        const vk::Format &format  = getBaseLevelFormat(contextVk->getRenderer());

        // If any level was redefined but the image was not owned by the Texture, it's already
        // released and deleted by TextureVk::redefineLevel().
        ASSERT(!TextureHasAnyRedefinedLevels(mRedefinedLevels));

        // Save previousFirstAllocateLevel before mImage becomes invalid
        gl::LevelIndex previousFirstAllocateLevel = mImage->getFirstAllocatedLevel();

        // If the current level is less than levelCount, Angle needs to generate the required
        // levelCount for it.
        const bool levelIncomplete =
            mImage->getLevelCount() <
            getMipLevelCount(ImageMipLevels::FullMipChainForGenerateMipmap);

        // If we didn't own the image, release the current and create a new one
        releaseImage(contextVk);

        // Create the image helper
        ANGLE_TRY(ensureImageAllocated(contextVk, format));
        ANGLE_TRY(initImage(contextVk, format.getIntendedFormatID(),
                            format.getActualImageFormatID(getRequiredFormatSupport()),
                            mState.getImmutableFormat() || levelIncomplete
                                ? ImageMipLevels::FullMipChainForGenerateMipmap
                                : ImageMipLevels::EnabledLevels));

        // Make a copy of the old image (that's being released) and stage that as an update to the
        // new image.
        ANGLE_TRY(copyAndStageImageData(contextVk, previousFirstAllocateLevel, srcImage, mImage));
    }
    else
    {
        const vk::Format &format = getBaseLevelFormat(contextVk->getRenderer());
        if (mImage->getActualFormatID() !=
                format.getActualImageFormatID(getRequiredFormatSupport()) &&
            mImage->getLevelCount() == getMipLevelCount(ImageMipLevels::EnabledLevels))
        {
            ANGLE_TRY(reinitImageAsRenderable(contextVk, format));
        }
        else
        {
            stageSelfAsSubresourceUpdates(contextVk);
        }
        // Release the current image so that it will be recreated with the correct number of mip
        // levels, base level, and max level.
        releaseImage(contextVk);
    }

    return angle::Result::Continue;
}

angle::Result TextureVk::bindTexImage(const gl::Context *context, egl::Surface *surface)
{
    ContextVk *contextVk = vk::GetImpl(context);

    releaseAndDeleteImageAndViews(contextVk);

    // eglBindTexImage can only be called with pbuffer (offscreen) surfaces
    OffscreenSurfaceVk *offscreenSurface = GetImplAs<OffscreenSurfaceVk>(surface);
    // Surface can only have single target. Just generate valid serial with throw-away generator.
    UniqueSerial siblingSerial = UniqueSerialFactory().generate();
    setImageHelper(contextVk, offscreenSurface->getColorAttachmentImage(),
                   gl::TextureType::InvalidEnum, 0, 0, false, siblingSerial);

    ASSERT(mImage->getLayerCount() == 1);
    return initImageViews(contextVk, getImageViewLevelCount());
}

angle::Result TextureVk::releaseTexImage(const gl::Context *context)
{
    ContextVk *contextVk = vk::GetImpl(context);

    releaseImage(contextVk);

    return angle::Result::Continue;
}

angle::Result TextureVk::getAttachmentRenderTarget(const gl::Context *context,
                                                   GLenum binding,
                                                   const gl::ImageIndex &imageIndex,
                                                   GLsizei samples,
                                                   FramebufferAttachmentRenderTarget **rtOut)
{
    GLint requestedLevel = imageIndex.getLevelIndex();
    ASSERT(requestedLevel >= 0);

    ContextVk *contextVk = vk::GetImpl(context);

    // Sync the texture's image.  See comment on this function in the header.
    ANGLE_TRY(respecifyImageStorageIfNecessary(contextVk, gl::Command::Draw));

    // Don't flush staged updates here. We'll handle that in FramebufferVk so we can defer clears.

    if (!mImage->valid())
    {
        const vk::Format &format = getBaseLevelFormat(contextVk->getRenderer());
        ANGLE_TRY(initImage(contextVk, format.getIntendedFormatID(),
                            format.getActualImageFormatID(getRequiredFormatSupport()),
                            ImageMipLevels::EnabledLevels));
    }

    const bool hasRenderToTextureEXT =
        contextVk->getFeatures().supportsMultisampledRenderToSingleSampled.enabled;

    // If samples > 1 here, we have a singlesampled texture that's being multisampled rendered to.
    // In this case, create a multisampled image that is otherwise identical to the single sampled
    // image.  That multisampled image is used as color or depth/stencil attachment, while the
    // original image is used as the resolve attachment.
    const gl::RenderToTextureImageIndex renderToTextureIndex =
        hasRenderToTextureEXT
            ? gl::RenderToTextureImageIndex::Default
            : static_cast<gl::RenderToTextureImageIndex>(PackSampleCount(samples));

    if (samples > 1 && !hasRenderToTextureEXT)
    {
        // Initialize mMultisampledImages and mMultisampledImageViews if necessary
        if (mMultisampledImages == nullptr)
        {
            mMultisampledImages     = std::make_unique<MultiSampleImages>();
            mMultisampledImageViews = std::make_unique<MultiSampleImageViews>();
        }

        ASSERT(mState.getBaseLevelDesc().samples <= 1);

        vk::ImageHelper &multisampledImage =
            mMultisampledImages->at(renderToTextureIndex)[requestedLevel];
        if (!multisampledImage.valid())
        {
            // Ensure the view serial is valid.
            vk::Renderer *renderer = contextVk->getRenderer();
            mMultisampledImageViews->at(renderToTextureIndex)[requestedLevel].init(renderer);

            // The MSAA image always comes from the single sampled one, so disable robust init.
            bool useRobustInit = false;

            // Calculate extents for multisample image
            VkExtent3D extents = {};
            gl_vk::GetExtent(
                mImage->getLevelExtents(mImage->toVkLevel(gl::LevelIndex(requestedLevel))),
                &extents);

            // Create the implicit multisampled image.
            ANGLE_TRY(multisampledImage.initImplicitMultisampledRenderToTexture(
                contextVk, mState.hasProtectedContent(), mState.getType(), samples, *mImage,
                extents, useRobustInit));
        }
    }

    // If rendering to a YUV image and nullColorAttachmentWithExternalFormatResolve is not supported
    // create an RGB image that is otherwise identical to the YUV image. This new RGB image
    // will be used as the draw attachment, while the original YUV image is used as the resolve
    // attachment.
    if (mImage->isYuvExternalFormat() && mRgbDrawImageForYuvResolve == nullptr &&
        !contextVk->getRenderer()->nullColorAttachmentWithExternalFormatResolve())
    {
        vk::Renderer *renderer = contextVk->getRenderer();

        // Allocate implicit RGB image and image view
        mRgbDrawImageForYuvResolve      = std::make_unique<vk::ImageHelper>();
        mRgbDrawImageViewsForYuvResolve = std::make_unique<vk::ImageViewHelper>();

        // Initialize implicit RGB image and image view
        ANGLE_TRY(mRgbDrawImageForYuvResolve->initRgbDrawImageForYuvResolve(
            contextVk, *mImage, contextVk->isRobustResourceInitEnabled()));
        mRgbDrawImageViewsForYuvResolve->init(renderer);
    }

    GLuint layerIndex = 0, layerCount = 0, imageLayerCount = 0;
    GetRenderTargetLayerCountAndIndex(mImage, imageIndex, &layerIndex, &layerCount,
                                      &imageLayerCount);

    if (layerCount == 1)
    {
        initSingleLayerRenderTargets(contextVk, imageLayerCount, gl::LevelIndex(requestedLevel),
                                     renderToTextureIndex);

        std::vector<RenderTargetVector> &levelRenderTargets =
            mSingleLayerRenderTargets[renderToTextureIndex];
        ASSERT(requestedLevel < static_cast<int32_t>(levelRenderTargets.size()));

        RenderTargetVector &layerRenderTargets = levelRenderTargets[requestedLevel];
        ASSERT(imageIndex.getLayerIndex() < static_cast<int32_t>(layerRenderTargets.size()));

        *rtOut = &layerRenderTargets[layerIndex];
    }
    else
    {
        ASSERT(layerCount > 0);
        *rtOut = getMultiLayerRenderTarget(contextVk, gl::LevelIndex(imageIndex.getLevelIndex()),
                                           layerIndex, layerCount);
    }

    return angle::Result::Continue;
}

angle::Result TextureVk::ensureImageInitialized(ContextVk *contextVk, ImageMipLevels mipLevels)
{
    if (mImage->valid() && !mImage->hasStagedUpdatesInAllocatedLevels())
    {
        return angle::Result::Continue;
    }

    if (!mImage->valid())
    {
        ASSERT(!TextureHasAnyRedefinedLevels(mRedefinedLevels));

        const vk::Format &format = getBaseLevelFormat(contextVk->getRenderer());
        ANGLE_TRY(initImage(contextVk, format.getIntendedFormatID(),
                            format.getActualImageFormatID(getRequiredFormatSupport()), mipLevels));
        if (mipLevels == ImageMipLevels::FullMipChainForGenerateMipmap)
        {
            // Remove staged updates to non-base mips when generating mipmaps.  These can only be
            // emulated format init clears that are staged in initImage.
            mImage->removeStagedUpdates(contextVk,
                                        gl::LevelIndex(mState.getEffectiveBaseLevel() + 1),
                                        gl::LevelIndex(mState.getMipmapMaxLevel()));
        }
    }

    return flushImageStagedUpdates(contextVk);
}

angle::Result TextureVk::flushImageStagedUpdates(ContextVk *contextVk)
{
    ASSERT(mImage->valid());

    gl::LevelIndex firstLevelGL = getNativeImageLevel(mImage->getFirstAllocatedLevel());
    uint32_t firstLayer         = getNativeImageLayer(0);

    return mImage->flushStagedUpdates(contextVk, firstLevelGL,
                                      firstLevelGL + getImageViewLevelCount(), firstLayer,
                                      firstLayer + getImageViewLayerCount(), mRedefinedLevels);
}

void TextureVk::initSingleLayerRenderTargets(ContextVk *contextVk,
                                             GLuint layerCount,
                                             gl::LevelIndex levelIndex,
                                             gl::RenderToTextureImageIndex renderToTextureIndex)
{
    GLint requestedLevel = levelIndex.get();
    std::vector<RenderTargetVector> &allLevelsRenderTargets =
        mSingleLayerRenderTargets[renderToTextureIndex];

    if (allLevelsRenderTargets.size() <= static_cast<uint32_t>(requestedLevel))
    {
        allLevelsRenderTargets.resize(requestedLevel + 1);
    }

    RenderTargetVector &renderTargets = allLevelsRenderTargets[requestedLevel];

    // Lazy init. Check if already initialized.
    if (!renderTargets.empty())
    {
        return;
    }

    // There are |layerCount| render targets, one for each layer
    renderTargets.resize(layerCount);

    const bool isMultisampledRenderToTexture =
        renderToTextureIndex != gl::RenderToTextureImageIndex::Default;

    vk::ImageHelper *drawImage             = mImage;
    vk::ImageViewHelper *drawImageViews    = &getImageViews();
    vk::ImageHelper *resolveImage          = nullptr;
    vk::ImageViewHelper *resolveImageViews = nullptr;

    RenderTargetTransience transience = RenderTargetTransience::Default;

    // If multisampled render to texture, use the multisampled image as draw image instead, and
    // resolve into the texture's image automatically.
    if (isMultisampledRenderToTexture)
    {
        ASSERT(mMultisampledImages->at(renderToTextureIndex)[requestedLevel].valid());
        ASSERT(!mImage->isYuvExternalFormat());

        resolveImage      = drawImage;
        resolveImageViews = drawImageViews;
        drawImage         = &mMultisampledImages->at(renderToTextureIndex)[requestedLevel];
        drawImageViews    = &mMultisampledImageViews->at(renderToTextureIndex)[requestedLevel];

        // If the texture is depth/stencil, GL_EXT_multisampled_render_to_texture2 explicitly
        // indicates that there is no need for the image to be resolved.  In that case, mark the
        // render target as entirely transient.
        if (mImage->getAspectFlags() != VK_IMAGE_ASPECT_COLOR_BIT)
        {
            transience = RenderTargetTransience::EntirelyTransient;
        }
        else
        {
            transience = RenderTargetTransience::MultisampledTransient;
        }
    }
    else if (mImage->isYuvExternalFormat())
    {
        // If rendering to YUV, similar to multisampled render to texture
        resolveImage      = drawImage;
        resolveImageViews = drawImageViews;

        if (contextVk->getRenderer()->nullColorAttachmentWithExternalFormatResolve())
        {
            // If null color attachment, we still keep drawImage as is (the same as
            // resolveImage) to avoid special treatment in many places where they assume there must
            // be a color attachment if there is a resolve attachment. But when renderPass is
            // created, color attachment will be ignored.
        }
        else
        {
            transience     = RenderTargetTransience::YuvResolveTransient;
            drawImage      = mRgbDrawImageForYuvResolve.get();
            drawImageViews = mRgbDrawImageViewsForYuvResolve.get();
        }
    }

    for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex)
    {
        renderTargets[layerIndex].init(drawImage, drawImageViews, resolveImage, resolveImageViews,
                                       mImageSiblingSerial, getNativeImageLevel(levelIndex),
                                       getNativeImageLayer(layerIndex), 1, transience);
    }
}

RenderTargetVk *TextureVk::getMultiLayerRenderTarget(ContextVk *contextVk,
                                                     gl::LevelIndex level,
                                                     GLuint layerIndex,
                                                     GLuint layerCount)
{
    vk::ImageViewHelper *imageViews = &getImageViews();
    vk::ImageSubresourceRange range = imageViews->getSubresourceDrawRange(
        level, layerIndex, vk::GetLayerMode(*mImage, layerCount));

    auto iter = mMultiLayerRenderTargets.find(range);
    if (iter != mMultiLayerRenderTargets.end())
    {
        return iter->second.get();
    }

    // Create the layered render target.  Note that multisampled render to texture is not
    // allowed with layered render targets; nor is YUV rendering.
    std::unique_ptr<RenderTargetVk> &rt = mMultiLayerRenderTargets[range];
    if (!rt)
    {
        rt = std::make_unique<RenderTargetVk>();
    }

    rt->init(mImage, imageViews, nullptr, nullptr, mImageSiblingSerial, getNativeImageLevel(level),
             getNativeImageLayer(layerIndex), layerCount, RenderTargetTransience::Default);

    return rt.get();
}

void TextureVk::prepareForGenerateMipmap(ContextVk *contextVk)
{
    gl::LevelIndex baseLevel(mState.getEffectiveBaseLevel());
    gl::LevelIndex maxLevel(mState.getMipmapMaxLevel());

    // Remove staged updates to the range that's being respecified (which is all the mips except
    // baseLevel).
    gl::LevelIndex firstGeneratedLevel = baseLevel + 1;
    mImage->removeStagedUpdates(contextVk, firstGeneratedLevel, maxLevel);

    TextureRedefineGenerateMipmapLevels(baseLevel, maxLevel, firstGeneratedLevel,
                                        &mRedefinedLevels);

    // If generating mipmap and base level is incompatibly redefined, the image is going to be
    // recreated.  Don't try to preserve the other mips.
    if (IsTextureLevelRedefined(mRedefinedLevels, mState.getType(), baseLevel))
    {
        ASSERT(!mState.getImmutableFormat());
        releaseImage(contextVk);
    }

    const gl::ImageDesc &baseLevelDesc = mState.getBaseLevelDesc();
    VkImageType imageType              = gl_vk::GetImageType(mState.getType());
    const vk::Format &format           = getBaseLevelFormat(contextVk->getRenderer());
    const GLint samples                = baseLevelDesc.samples ? baseLevelDesc.samples : 1;

    // If the compute path is to be used to generate mipmaps, add the STORAGE usage.
    if (CanGenerateMipmapWithCompute(contextVk->getRenderer(), imageType,
                                     format.getActualImageFormatID(getRequiredFormatSupport()),
                                     samples, mOwnsImage))
    {
        mImageUsageFlags |= VK_IMAGE_USAGE_STORAGE_BIT;
    }
}

angle::Result TextureVk::respecifyImageStorageIfNecessary(ContextVk *contextVk, gl::Command source)
{
    ASSERT(mState.getBuffer().get() == nullptr);

    VkImageUsageFlags oldUsageFlags   = mImageUsageFlags;
    VkImageCreateFlags oldCreateFlags = mImageCreateFlags;

    // Create a new image if the storage state is enabled for the first time.
    if (mState.hasBeenBoundAsImage())
    {
        mImageUsageFlags |= VK_IMAGE_USAGE_STORAGE_BIT;
        mRequiresMutableStorage = true;
    }

    // If we're handling dirty srgb decode/override state, we may have to reallocate the image with
    // VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT. Vulkan requires this bit to be set in order to use
    // imageviews with a format that does not match the texture's internal format.
    if (isSRGBOverrideEnabled())
    {
        mRequiresMutableStorage = true;
    }

    if (mRequiresMutableStorage)
    {
        mImageCreateFlags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
    }

    // Create a new image if used as attachment for the first time. This must be called before
    // prepareForGenerateMipmap since this changes the format which prepareForGenerateMipmap relies
    // on.
    if (mState.hasBeenBoundAsAttachment())
    {
        TextureUpdateResult updateResult = TextureUpdateResult::ImageUnaffected;
        ANGLE_TRY(ensureRenderable(contextVk, &updateResult));
        if (updateResult == TextureUpdateResult::ImageRespecified)
        {
            oldUsageFlags  = mImageUsageFlags;
            oldCreateFlags = mImageCreateFlags;
        }
    }

    // Before redefining the image for any reason, check to see if it's about to go through mipmap
    // generation.  In that case, drop every staged change for the subsequent mips after base, and
    // make sure the image is created with the complete mip chain.
    const bool isGenerateMipmap = source == gl::Command::GenerateMipmap;
    if (isGenerateMipmap)
    {
        prepareForGenerateMipmap(contextVk);
    }

    // If texture was not originally created using the MSRTSS flag, it should be recreated when it
    // is bound to an MSRTT framebuffer.
    if (contextVk->getFeatures().supportsMultisampledRenderToSingleSampled.enabled &&
        !contextVk->getFeatures().preferMSRTSSFlagByDefault.enabled &&
        mState.hasBeenBoundToMSRTTFramebuffer() &&
        ((mImageCreateFlags & VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT) == 0))
    {
        ANGLE_TRY(respecifyImageStorage(contextVk));
        oldUsageFlags  = mImageUsageFlags;
        oldCreateFlags = mImageCreateFlags;
    }

    // For immutable texture, base level does not affect allocation. Only usage flags are. If usage
    // flag changed, we respecify image storage early on. This makes the code more reliable and also
    // better performance wise. Otherwise, we will try to preserve base level by calling
    // stageSelfAsSubresourceUpdates and then later on find out the mImageUsageFlags changed and the
    // whole thing has to be respecified.
    if (mState.getImmutableFormat() &&
        (oldUsageFlags != mImageUsageFlags || oldCreateFlags != mImageCreateFlags))
    {
        ANGLE_TRY(respecifyImageStorage(contextVk));
        oldUsageFlags  = mImageUsageFlags;
        oldCreateFlags = mImageCreateFlags;
    }

    // Set base and max level before initializing the image
    TextureUpdateResult updateResult = TextureUpdateResult::ImageUnaffected;
    ANGLE_TRY(maybeUpdateBaseMaxLevels(contextVk, &updateResult));

    // Updating levels could have respecified the storage, recapture mImageCreateFlags
    if (updateResult == TextureUpdateResult::ImageRespecified)
    {
        oldUsageFlags  = mImageUsageFlags;
        oldCreateFlags = mImageCreateFlags;
    }

    // It is possible for the image to have a single level (because it doesn't use mipmapping),
    // then have more levels defined in it and mipmapping enabled.  In that case, the image needs
    // to be recreated.
    bool isMipmapEnabledByMinFilter = false;
    if (!isGenerateMipmap && mImage && mImage->valid())
    {
        isMipmapEnabledByMinFilter =
            mImage->getLevelCount() < getMipLevelCount(ImageMipLevels::EnabledLevels);
    }

    // If generating mipmaps and the image needs to be recreated (not full-mip already, or changed
    // usage flags), make sure it's recreated.
    const bool isMipmapEnabledByGenerateMipmap =
        isGenerateMipmap && mImage && mImage->valid() &&
        (oldUsageFlags != mImageUsageFlags ||
         (!mState.getImmutableFormat() &&
          mImage->getLevelCount() !=
              getMipLevelCount(ImageMipLevels::FullMipChainForGenerateMipmap)));

    // Respecify the image if it's changed in usage, not full-mip, or if any of its levels are
    // redefined and no update to base/max levels were done (otherwise the above call would have
    // already taken care of this).  Note that if both base/max and image usage are changed, the
    // image is recreated twice, which incurs unnecessary copies.  This is not expected to be
    // happening in real applications.
    if (oldUsageFlags != mImageUsageFlags || oldCreateFlags != mImageCreateFlags ||
        TextureHasAnyRedefinedLevels(mRedefinedLevels) || isMipmapEnabledByMinFilter ||
        isMipmapEnabledByGenerateMipmap)
    {
        ANGLE_TRY(respecifyImageStorage(contextVk));
    }

    return angle::Result::Continue;
}

angle::Result TextureVk::onLabelUpdate(const gl::Context *context)
{
    ContextVk *contextVk = vk::GetImpl(context);
    return updateTextureLabel(contextVk);
}

angle::Result TextureVk::updateTextureLabel(ContextVk *contextVk)
{
    vk::Renderer *renderer = contextVk->getRenderer();
    std::string label      = mState.getLabel();
    if (!label.empty() && renderer->enableDebugUtils() && imageValid())
    {
        return vk::SetDebugUtilsObjectName(contextVk, VK_OBJECT_TYPE_IMAGE,
                                           (uint64_t)(getImage().getImage().getHandle()),
                                           mState.getLabel());
    }
    return angle::Result::Continue;
}

vk::BufferHelper *TextureVk::getRGBAConversionBufferHelper(vk::Renderer *renderer,
                                                           angle::FormatID formatID) const
{
    BufferVk *bufferVk                                        = vk::GetImpl(getBuffer().get());
    const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding = mState.getBuffer();
    const VertexConversionBuffer::CacheKey cacheKey{
        formatID, 16, static_cast<size_t>(bufferBinding.getOffset()), false, true};
    ConversionBuffer *conversion = bufferVk->getVertexConversionBuffer(renderer, cacheKey);
    return conversion->getBuffer();
}

angle::Result TextureVk::convertBufferToRGBA(ContextVk *contextVk, size_t &conversionBufferSize)
{
    vk::Renderer *renderer             = contextVk->getRenderer();
    const gl::ImageDesc &baseLevelDesc = mState.getBaseLevelDesc();
    const vk::Format *imageUniformFormat =
        &renderer->getFormat(baseLevelDesc.format.info->sizedInternalFormat);
    const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding = mState.getBuffer();
    BufferVk *bufferVk                                        = vk::GetImpl(getBuffer().get());
    const size_t bindingOffset                                = bufferBinding.getOffset();
    const VkDeviceSize bufferSize                             = bufferVk->getSize();
    const VkDeviceSize bufferSizeFromOffset                   = bufferSize - bindingOffset;
    conversionBufferSize = roundUpPow2<size_t>(static_cast<size_t>((bufferSizeFromOffset / 3) * 4),
                                               4 * sizeof(uint32_t));

    const VertexConversionBuffer::CacheKey cacheKey{imageUniformFormat->getIntendedFormatID(), 16,
                                                    bindingOffset, false, true};
    ConversionBuffer *conversion = bufferVk->getVertexConversionBuffer(renderer, cacheKey);
    mBufferContentsObservers->enableForBuffer(getBuffer().get());
    if (!conversion->valid())
    {
        ANGLE_TRY(contextVk->initBufferForVertexConversion(conversion, conversionBufferSize,
                                                           vk::MemoryHostVisibility::NonVisible));
    }
    vk::BufferHelper *conversionBufferHelper = conversion->getBuffer();

    if (conversion->dirty())
    {
        vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
        UtilsVk &utilsVk               = contextVk->getUtils();
        const VkDeviceSize pixelSize   = 3 * sizeof(uint32_t);
        const VkDeviceSize pixelCount  = bufferSizeFromOffset / pixelSize;

        ANGLE_TRY(utilsVk.copyRgbToRgba(contextVk, imageUniformFormat->getIntendedFormat(),
                                        &bufferHelper, static_cast<uint32_t>(bindingOffset),
                                        static_cast<uint32_t>(pixelCount), conversionBufferHelper));
        conversion->clearDirty();
    }

    return angle::Result::Continue;
}

angle::Result TextureVk::syncState(const gl::Context *context,
                                   const gl::Texture::DirtyBits &dirtyBits,
                                   gl::Command source)
{
    ContextVk *contextVk   = vk::GetImpl(context);
    vk::Renderer *renderer = contextVk->getRenderer();

    // If this is a texture buffer, release buffer views.  There's nothing else to sync.  The
    // image must already be deleted, and the sampler reset.
    if (mState.getBuffer().get() != nullptr)
    {
        ASSERT(mImage == nullptr);

        const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding = mState.getBuffer();

        VkDeviceSize offset = bufferBinding.getOffset();
        VkDeviceSize size   = gl::GetBoundBufferAvailableSize(bufferBinding);

        if (NeedsRGBAEmulation(renderer, getBaseLevelFormat(renderer).getIntendedFormatID()))
        {
            size_t conversionBufferSize;
            ANGLE_TRY(convertBufferToRGBA(contextVk, conversionBufferSize));
            offset = 0;
            size   = conversionBufferSize;
        }

        mBufferViews.release(contextVk);
        mBufferViews.init(renderer, offset, size);
        mDescriptorSetCacheManager.releaseKeys(renderer);
        return angle::Result::Continue;
    }

    ANGLE_TRY(respecifyImageStorageIfNecessary(contextVk, source));

    // Initialize the image storage and flush the pixel buffer.
    const bool isGenerateMipmap = source == gl::Command::GenerateMipmap;
    ANGLE_TRY(ensureImageInitialized(contextVk, isGenerateMipmap
                                                    ? ImageMipLevels::FullMipChainForGenerateMipmap
                                                    : ImageMipLevels::EnabledLevels));

    // Mask out the IMPLEMENTATION dirty bit to avoid unnecessary syncs.
    // Keep it set when the border color is used and needs to be resynced.
    gl::Texture::DirtyBits localBits = dirtyBits;
    if (!mState.getSamplerState().usesBorderColor())
    {
        localBits.reset(gl::Texture::DIRTY_BIT_IMPLEMENTATION);
    }
    localBits.reset(gl::Texture::DIRTY_BIT_BASE_LEVEL);
    localBits.reset(gl::Texture::DIRTY_BIT_MAX_LEVEL);

    // For AHBs, the ImageViews are created with VkSamplerYcbcrConversionInfo's chromaFilter
    // matching min/magFilters as part of the eglEGLImageTargetTexture2DOES() call. However, the
    // min/mag filters can change later, requiring the ImageViews to be refreshed.
    if (mImage->valid() && mImage->hasImmutableSampler() &&
        (dirtyBits.test(gl::Texture::DIRTY_BIT_MIN_FILTER) ||
         dirtyBits.test(gl::Texture::DIRTY_BIT_MAG_FILTER)))
    {
        const gl::SamplerState &samplerState = mState.getSamplerState();
        VkFilter chromaFilter = samplerState.getMinFilter() == samplerState.getMagFilter()
                                    ? gl_vk::GetFilter(samplerState.getMinFilter())
                                    : vk::kDefaultYCbCrChromaFilter;
        if (mImage->updateChromaFilter(renderer, chromaFilter))
        {
            resetSampler();
            ANGLE_TRY(refreshImageViews(contextVk));
        }
    }

    if (localBits.none() && mSampler)
    {
        return angle::Result::Continue;
    }

    if (mSampler)
    {
        resetSampler();
    }

    if (localBits.test(gl::Texture::DIRTY_BIT_SWIZZLE_RED) ||
        localBits.test(gl::Texture::DIRTY_BIT_SWIZZLE_GREEN) ||
        localBits.test(gl::Texture::DIRTY_BIT_SWIZZLE_BLUE) ||
        localBits.test(gl::Texture::DIRTY_BIT_SWIZZLE_ALPHA) ||
        localBits.test(gl::Texture::DIRTY_BIT_ASTC_DECODE_PRECISION))
    {
        ANGLE_TRY(refreshImageViews(contextVk));
    }

    if (localBits.test(gl::Texture::DIRTY_BIT_SRGB_OVERRIDE) ||
        localBits.test(gl::Texture::DIRTY_BIT_SRGB_DECODE))
    {
        ASSERT(mImage != nullptr);
        gl::SrgbDecode srgbDecode = (mState.getSamplerState().getSRGBDecode() == GL_SKIP_DECODE_EXT)
                                        ? gl::SrgbDecode::Skip
                                        : gl::SrgbDecode::Default;
        mImageView.updateSrgbDecode(*mImage, srgbDecode);
        mImageView.updateSrgbOverride(*mImage, mState.getSRGBOverride());

        if (!renderer->getFeatures().supportsImageFormatList.enabled)
        {
            ANGLE_TRY(refreshImageViews(contextVk));
        }
    }

    vk::SamplerDesc samplerDesc(contextVk, mState.getSamplerState(), mState.isStencilMode(),
                                &mImage->getYcbcrConversionDesc(), mImage->getIntendedFormatID());
    auto y2yConversionDesc = mImage->getY2YConversionDesc();
    vk::SamplerDesc samplerDescSamplerExternal2DY2YEXT(contextVk, mState.getSamplerState(),
                                                       mState.isStencilMode(), &y2yConversionDesc,
                                                       mImage->getIntendedFormatID());
    ANGLE_TRY(contextVk->getShareGroup()->getSamplerCache().getSampler(contextVk, samplerDesc,
                                                                       &mSampler));
    ANGLE_TRY(contextVk->getShareGroup()->getSamplerCache().getSampler(
        contextVk, samplerDescSamplerExternal2DY2YEXT, &mY2YSampler));

    updateCachedImageViewSerials();

    return angle::Result::Continue;
}

angle::Result TextureVk::initializeContents(const gl::Context *context,
                                            GLenum binding,
                                            const gl::ImageIndex &imageIndex)
{
    ContextVk *contextVk      = vk::GetImpl(context);
    const gl::ImageDesc &desc = mState.getImageDesc(imageIndex);
    const vk::Format &format =
        contextVk->getRenderer()->getFormat(desc.format.info->sizedInternalFormat);

    ASSERT(mImage);
    // Note that we cannot ensure the image is initialized because we might be calling subImage
    // on a non-complete cube map.
    return mImage->stageRobustResourceClearWithFormat(
        contextVk, imageIndex, desc.size, format.getIntendedFormat(),
        format.getActualImageFormat(getRequiredFormatSupport()));
}

angle::Result TextureVk::initializeContentsWithBlack(const gl::Context *context,
                                                     GLenum binding,
                                                     const gl::ImageIndex &imageIndex)
{
    ContextVk *contextVk      = vk::GetImpl(context);
    const gl::ImageDesc &desc = mState.getImageDesc(imageIndex);
    const vk::Format &format =
        contextVk->getRenderer()->getFormat(desc.format.info->sizedInternalFormat);

    VkClearValue clearValue = {};
    clearValue.color        = {{0, 0, 0, 1.0f}};

    ASSERT(mImage);
    // Note that we cannot ensure the image is initialized because we might be calling subImage
    // on a non-complete cube map.
    return mImage->stageResourceClearWithFormat(
        contextVk, imageIndex, desc.size, format.getIntendedFormat(),
        format.getActualImageFormat(getRequiredFormatSupport()), clearValue);
}

void TextureVk::releaseOwnershipOfImage(const gl::Context *context)
{
    ContextVk *contextVk = vk::GetImpl(context);

    ASSERT(!mImageSiblingSerial.valid());

    mOwnsImage = false;
    releaseAndDeleteImageAndViews(contextVk);
}

const vk::ImageView &TextureVk::getReadImageView(GLenum srgbDecode,
                                                 bool texelFetchStaticUse,
                                                 bool samplerExternal2DY2YEXT) const
{
    ASSERT(mImage->valid());

    const vk::ImageViewHelper &imageViews = getImageViews();

    if (mState.isStencilMode() && imageViews.hasStencilReadImageView())
    {
        return imageViews.getStencilReadImageView();
    }

    if (samplerExternal2DY2YEXT)
    {
        ASSERT(imageViews.getSamplerExternal2DY2YEXTImageView().valid());
        return imageViews.getSamplerExternal2DY2YEXTImageView();
    }

    ASSERT(mImage != nullptr && mImage->valid());
    gl::SrgbDecode decode =
        (srgbDecode == GL_DECODE_EXT) ? gl::SrgbDecode::Default : gl::SrgbDecode::Skip;
    imageViews.updateSrgbDecode(*mImage, decode);
    imageViews.updateStaticTexelFetch(*mImage, texelFetchStaticUse);

    ASSERT(imageViews.getReadImageView().valid());
    return imageViews.getReadImageView();
}

const vk::ImageView &TextureVk::getCopyImageView() const
{
    ASSERT(mImage->valid());

    const vk::ImageViewHelper &imageViews = getImageViews();

    const angle::Format &angleFormat = mImage->getActualFormat();
    ASSERT(angleFormat.isSRGB ==
           (ConvertToLinear(mImage->getActualFormatID()) != angle::FormatID::NONE));
    if (angleFormat.isSRGB)
    {
        return imageViews.getSRGBCopyImageView();
    }
    return imageViews.getLinearCopyImageView();
}

angle::Result TextureVk::getLevelLayerImageView(ContextVk *contextVk,
                                                gl::LevelIndex level,
                                                size_t layer,
                                                const vk::ImageView **imageViewOut)
{
    ASSERT(mImage && mImage->valid());

    gl::LevelIndex levelGL = getNativeImageLevel(level);
    vk::LevelIndex levelVk = mImage->toVkLevel(levelGL);
    uint32_t nativeLayer   = getNativeImageLayer(static_cast<uint32_t>(layer));

    return getImageViews().getLevelLayerDrawImageView(contextVk, *mImage, levelVk, nativeLayer,
                                                      imageViewOut);
}

angle::Result TextureVk::getStorageImageView(ContextVk *contextVk,
                                             const gl::ImageUnit &binding,
                                             const vk::ImageView **imageViewOut)
{
    vk::Renderer *renderer = contextVk->getRenderer();

    angle::FormatID formatID = angle::Format::InternalFormatToID(binding.format);
    const vk::Format *format = &renderer->getFormat(formatID);

    format = AdjustStorageViewFormatPerWorkarounds(renderer, format, getRequiredFormatSupport());

    gl::LevelIndex nativeLevelGL =
        getNativeImageLevel(gl::LevelIndex(static_cast<uint32_t>(binding.level)));
    vk::LevelIndex nativeLevelVk = mImage->toVkLevel(nativeLevelGL);

    // If the texture does not have multiple layers or faces, the entire texture
    // level is bound, regardless of the values specified by layered and layer.
    if (binding.layered != GL_TRUE && IsLayeredTextureType(mState.getType()))
    {
        uint32_t nativeLayer = getNativeImageLayer(static_cast<uint32_t>(binding.layer));

        return getImageViews().getLevelLayerStorageImageView(
            contextVk, *mImage, nativeLevelVk, nativeLayer,
            VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT,
            format->getActualImageFormatID(getRequiredFormatSupport()), imageViewOut);
    }

    uint32_t nativeLayer = getNativeImageLayer(0);

    return getImageViews().getLevelStorageImageView(
        contextVk, mState.getType(), *mImage, nativeLevelVk, nativeLayer,
        VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT,
        format->getActualImageFormatID(getRequiredFormatSupport()), imageViewOut);
}

vk::BufferHelper *TextureVk::getPossiblyEmulatedTextureBuffer(vk::ErrorContext *context) const
{
    vk::Renderer *renderer = context->getRenderer();

    angle::FormatID format = getBaseLevelFormat(renderer).getIntendedFormatID();
    if (NeedsRGBAEmulation(renderer, format))
    {
        return getRGBAConversionBufferHelper(renderer, format);
    }

    BufferVk *bufferVk = vk::GetImpl(getBuffer().get());
    return &bufferVk->getBuffer();
}

angle::Result TextureVk::getBufferView(vk::ErrorContext *context,
                                       const vk::Format *imageUniformFormat,
                                       const gl::SamplerBinding *samplerBinding,
                                       bool isImage,
                                       const vk::BufferView **viewOut,
                                       VkFormat *viewVkFormatOut)
{
    vk::Renderer *renderer = context->getRenderer();

    ASSERT(mState.getBuffer().get() != nullptr);

    // Use the format specified by glTexBuffer if no format specified by the shader.
    if (imageUniformFormat == nullptr)
    {
        imageUniformFormat = &getBaseLevelFormat(renderer);
    }

    if (isImage)
    {
        imageUniformFormat = AdjustStorageViewFormatPerWorkarounds(renderer, imageUniformFormat,
                                                                   getRequiredFormatSupport());
    }

    const vk::BufferHelper *buffer = &vk::GetImpl(mState.getBuffer().get())->getBuffer();

    if (NeedsRGBAEmulation(renderer, imageUniformFormat->getIntendedFormatID()))
    {
        buffer = getRGBAConversionBufferHelper(renderer, imageUniformFormat->getIntendedFormatID());
        imageUniformFormat = &renderer->getFormat(
            GetRGBAEmulationDstFormat(imageUniformFormat->getIntendedFormatID()));
    }

    if (samplerBinding)
    {
        imageUniformFormat =
            AdjustViewFormatForSampler(renderer, imageUniformFormat, samplerBinding->format);
    }

    // Create a view for the required format.
    return mBufferViews.getView(context, *buffer, buffer->getOffset(), *imageUniformFormat, viewOut,
                                viewVkFormatOut);
}

angle::Result TextureVk::initImage(ContextVk *contextVk,
                                   angle::FormatID intendedImageFormatID,
                                   angle::FormatID actualImageFormatID,
                                   ImageMipLevels mipLevels)
{
    vk::Renderer *renderer = contextVk->getRenderer();

    // Create the image. For immutable texture, we always allocate the full immutable levels
    // specified by texStorage call. Otherwise we only try to allocate from base to max levels.
    const gl::ImageDesc *firstLevelDesc;
    uint32_t firstLevel, levelCount;
    if (mState.getImmutableFormat())
    {
        firstLevelDesc = &mState.getLevelZeroDesc();
        firstLevel     = 0;
        levelCount     = mState.getImmutableLevels();
    }
    else
    {
        firstLevelDesc = &mState.getBaseLevelDesc();
        firstLevel     = mState.getEffectiveBaseLevel();
        levelCount     = getMipLevelCount(mipLevels);
    }
    const gl::Extents &firstLevelExtents = firstLevelDesc->size;

    VkExtent3D vkExtent;
    uint32_t layerCount;
    gl_vk::GetExtentsAndLayerCount(mState.getType(), firstLevelExtents, &vkExtent, &layerCount);
    GLint samples = mState.getBaseLevelDesc().samples ? mState.getBaseLevelDesc().samples : 1;

    if (contextVk->getFeatures().limitSampleCountTo2.enabled)
    {
        samples = std::min(samples, 2);
    }

    if (mState.hasProtectedContent())
    {
        mImageCreateFlags |= VK_IMAGE_CREATE_PROTECTED_BIT;
    }

    if (renderer->getFeatures().supportsComputeTranscodeEtcToBc.enabled &&
        IsETCFormat(intendedImageFormatID) && IsBCFormat(actualImageFormatID))
    {
        mImageCreateFlags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT |
                             VK_IMAGE_CREATE_EXTENDED_USAGE_BIT |
                             VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT;
        mImageUsageFlags |= VK_IMAGE_USAGE_STORAGE_BIT;
    }

    const VkFormat actualImageFormat =
        rx::vk::GetVkFormatFromFormatID(renderer, actualImageFormatID);
    const VkImageType imageType     = gl_vk::GetImageType(mState.getType());
    const VkImageTiling imageTiling = mImage->getTilingMode();

    if (mipLevels == ImageMipLevels::FullMipChainForGenerateMipmap &&
        CanGenerateMipmapWithCompute(renderer, imageType, actualImageFormatID, samples, mOwnsImage))
    {
        mImageUsageFlags |= VK_IMAGE_USAGE_STORAGE_BIT;
    }

    mImageCreateFlags |=
        vk::GetMinimalImageCreateFlags(renderer, mState.getType(), mImageUsageFlags);

    // The MSRTSS bit is included in the create flag for all textures if the feature flag
    // corresponding to its preference is enabled. Otherwise, it is enabled for a texture if it is
    // bound to an MSRTT framebuffer.
    const bool shouldIncludeMSRTSSBit =
        contextVk->getFeatures().supportsMultisampledRenderToSingleSampled.enabled &&
        (contextVk->getFeatures().preferMSRTSSFlagByDefault.enabled ||
         mState.hasBeenBoundToMSRTTFramebuffer());

    if ((mImageUsageFlags & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
                             VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) != 0 &&
        mOwnsImage && samples == 1 && shouldIncludeMSRTSSBit)
    {
        VkImageCreateFlags createFlagsMultisampled =
            mImageCreateFlags | VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT;
        bool isActualFormatSRGB             = angle::Format::Get(actualImageFormatID).isSRGB;
        const VkFormat additionalViewFormat = rx::vk::GetVkFormatFromFormatID(
            renderer, isActualFormatSRGB ? ConvertToLinear(actualImageFormatID)
                                         : ConvertToSRGB(actualImageFormatID));
        const bool isAdditionalFormatValid = additionalViewFormat != VK_FORMAT_UNDEFINED;

        // If the texture has already been bound to an MSRTT framebuffer, lack of support should
        // result in failure.
        bool supportsMSRTTUsageActualFormat = vk::ImageHelper::FormatSupportsUsage(
            renderer, actualImageFormat, imageType, imageTiling, mImageUsageFlags,
            createFlagsMultisampled, nullptr, nullptr,
            vk::ImageHelper::FormatSupportCheck::RequireMultisampling);
        bool supportsMSRTTUsageAdditionalFormat =
            !isAdditionalFormatValid ||
            vk::ImageHelper::FormatSupportsUsage(
                renderer, additionalViewFormat, imageType, imageTiling, mImageUsageFlags,
                createFlagsMultisampled, nullptr, nullptr,
                vk::ImageHelper::FormatSupportCheck::RequireMultisampling);

        bool supportsMSRTTUsage =
            supportsMSRTTUsageActualFormat && supportsMSRTTUsageAdditionalFormat;
        if (ANGLE_UNLIKELY(mState.hasBeenBoundToMSRTTFramebuffer() && !supportsMSRTTUsage))
        {
            ERR() << "Texture bound to EXT_multisampled_render_to_texture framebuffer, "
                  << "but this device does not support this format.";
            ANGLE_VK_TRY(contextVk, VK_ERROR_FORMAT_NOT_SUPPORTED);
        }

        // Note: If we ever fail the following check, we should use the emulation path for this
        // texture instead of ignoring MSRTT.
        if (supportsMSRTTUsage)
        {
            // If supported by format add the MSRTSS flag because any texture might end up as an
            // MSRTT attachment.
            mImageCreateFlags |= VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT;
        }
    }

    // Any format with VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT support is required to also support
    // VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT.  So no format feature query is needed.
    // However, it's still necessary to use vkGetPhysicalDeviceImageFormatProperties2 to ensure host
    // image copy is supported for the specific usage and flags.
    //
    // All TextureVk images are expected to have VK_IMAGE_USAGE_SAMPLED_BIT, so that is not checked
    // either.
    ASSERT((mImageUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) != 0);
    if (mOwnsImage && samples == 1 && renderer->getFeatures().supportsHostImageCopy.enabled)
    {
        VkHostImageCopyDevicePerformanceQueryEXT perfQuery = {};
        perfQuery.sType = VK_STRUCTURE_TYPE_HOST_IMAGE_COPY_DEVICE_PERFORMANCE_QUERY_EXT;

        // If host image copy is supported at all ...
        if (vk::ImageHelper::FormatSupportsUsage(
                renderer, actualImageFormat, imageType, imageTiling,
                mImageUsageFlags | VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT, mImageCreateFlags, nullptr,
                &perfQuery, vk::ImageHelper::FormatSupportCheck::OnlyQuerySuccess))
        {
            // Only enable it if it has no performance impact whatsoever (or impact is tiny, given
            // feature).  For luminance/alpha formats, on some platforms it's known to be an overall
            // win despite non-optimal layout.
            const bool isLUMA = angle::Format::Get(intendedImageFormatID).isLUMA();
            if (perfQuery.identicalMemoryLayout ||
                (perfQuery.optimalDeviceAccess &&
                 renderer->getFeatures().allowHostImageCopyDespiteNonIdenticalLayout.enabled) ||
                (isLUMA && renderer->getFeatures().forceHostImageCopyForLuma.enabled))
            {
                mImageUsageFlags |= VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT;
            }
        }
    }

    // Fixed rate compression
    VkImageCompressionControlEXT *compressionInfo        = nullptr;
    VkImageCompressionControlEXT compressionInfoVar      = {};
    VkImageCompressionFixedRateFlagsEXT compressionRates = VK_IMAGE_COMPRESSION_FIXED_RATE_NONE_EXT;
    if (renderer->getFeatures().supportsImageCompressionControl.enabled && mOwnsImage &&
        mState.getSurfaceCompressionFixedRate() != GL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT)
    {
        compressionInfoVar.sType = VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT;
        // Use default compression control flag for query
        compressionInfoVar.flags = VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT;

        // If fixed rate compression is supported by this type, not support YUV now.
        const vk::Format &format = renderer->getFormat(intendedImageFormatID);
        if (!mImage->isYuvExternalFormat() &&
            (GetFormatSupportedCompressionRates(renderer, format, 0, nullptr) != 0))
        {
            GetCompressionFixedRate(&compressionInfoVar, &compressionRates,
                                    mState.getSurfaceCompressionFixedRate());
            compressionInfo = &compressionInfoVar;
        }
    }

    ANGLE_TRY(mImage->initExternal(contextVk, mState.getType(), vkExtent, intendedImageFormatID,
                                   actualImageFormatID, samples, mImageUsageFlags,
                                   mImageCreateFlags, vk::ImageAccess::Undefined, nullptr,
                                   gl::LevelIndex(firstLevel), levelCount, layerCount,
                                   contextVk->isRobustResourceInitEnabled(),
                                   mState.hasProtectedContent(), vk::TileMemory::Prohibited,
                                   vk::ImageHelper::deriveConversionDesc(
                                       contextVk, actualImageFormatID, intendedImageFormatID),
                                   compressionInfo));

    ANGLE_TRY(updateTextureLabel(contextVk));

    // Update create flags with mImage's create flags
    mImageCreateFlags |= mImage->getCreateFlags();
    mRequiresMutableStorage = (mImageCreateFlags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) != 0;

    VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
    if (mState.hasProtectedContent())
    {
        flags |= VK_MEMORY_PROPERTY_PROTECTED_BIT;
    }

    ANGLE_TRY(contextVk->initImageAllocation(mImage, mState.hasProtectedContent(), flags,
                                             vk::MemoryAllocationType::TextureImage));

    const uint32_t viewLevelCount =
        mState.getImmutableFormat() ? getMipLevelCount(ImageMipLevels::EnabledLevels) : levelCount;
    ANGLE_TRY(initImageViews(contextVk, viewLevelCount));

    mCurrentBaseLevel = gl::LevelIndex(mState.getBaseLevel());
    // In edge case where base level > max level, clamp up to base level.
    mCurrentMaxLevel = std::max(gl::LevelIndex(mState.getMaxLevel()), mCurrentBaseLevel);

    return angle::Result::Continue;
}

angle::Result TextureVk::initImageViews(ContextVk *contextVk, uint32_t levelCount)
{
    ASSERT(mImage != nullptr && mImage->valid());

    gl::LevelIndex baseLevelGL =
        getNativeImageLevel(gl::LevelIndex(mState.getEffectiveBaseLevel()));
    vk::LevelIndex baseLevelVk = mImage->toVkLevel(baseLevelGL);
    uint32_t baseLayer         = getNativeImageLayer(0);

    const gl::ImageDesc &baseLevelDesc = mState.getBaseLevelDesc();
    const bool sized                   = baseLevelDesc.format.info->sized;

    const angle::Format &intendedFormat = mImage->getIntendedFormat();
    gl::SwizzleState formatSwizzle      = GetFormatSwizzle(intendedFormat, sized);
    gl::SwizzleState readSwizzle        = ApplySwizzle(formatSwizzle, mState.getSwizzleState());

    // Use this as a proxy for the SRGB override & skip decode settings.
    bool createExtraSRGBViews = mRequiresMutableStorage;

    GLenum astcDecodePrecision = GL_NONE;
    vk::Renderer *renderer     = contextVk->getRenderer();
    if (renderer->getFeatures().supportsAstcDecodeMode.enabled)
    {
        astcDecodePrecision = mState.getASTCDecodePrecision();
    }

    const VkImageUsageFlags kDisallowedSwizzledUsage =
        VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
        VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
    ANGLE_TRY(getImageViews().initReadViews(
        contextVk, mState.getType(), *mImage, formatSwizzle, readSwizzle, baseLevelVk, levelCount,
        baseLayer, getImageViewLayerCount(), createExtraSRGBViews,
        getImage().getUsage() & ~kDisallowedSwizzledUsage, astcDecodePrecision));

    updateCachedImageViewSerials();

    return angle::Result::Continue;
}

void TextureVk::releaseImage(ContextVk *contextVk)
{
    vk::Renderer *renderer = contextVk->getRenderer();

    releaseImageViews(contextVk);

    if (mImage)
    {
        if (mOwnsImage)
        {
            mImage->releaseImageFromShareContexts(renderer, contextVk, mImageSiblingSerial);
        }
        else
        {
            mImage->finalizeImageLayoutInShareContexts(renderer, contextVk, mImageSiblingSerial);
            mImageObserverBinding.bind(nullptr);
            mImage = nullptr;
        }
    }

    if (mMultisampledImages)
    {
        for (gl::TexLevelArray<vk::ImageHelper> &images : *mMultisampledImages)
        {
            for (vk::ImageHelper &image : images)
            {
                if (image.valid())
                {
                    image.releaseImageFromShareContexts(renderer, contextVk, mImageSiblingSerial);
                }
            }
        }
        mMultisampledImages.reset();
    }

    if (mRgbDrawImageForYuvResolve)
    {
        mRgbDrawImageForYuvResolve->releaseImageFromShareContexts(renderer, contextVk,
                                                                  mImageSiblingSerial);
        mRgbDrawImageForYuvResolve.reset();
    }

    onStateChange(angle::SubjectMessage::SubjectChanged);
    mRedefinedLevels = {};
}

void TextureVk::releaseImageViews(ContextVk *contextVk)
{
    vk::Renderer *renderer = contextVk->getRenderer();

    mDescriptorSetCacheManager.releaseKeys(renderer);

    if (mImage == nullptr)
    {
        if (mMultisampledImageViews)
        {
            for (gl::TexLevelArray<vk::ImageViewHelper> &imageViewHelpers :
                 *mMultisampledImageViews)
            {
                for (vk::ImageViewHelper &imageViewHelper : imageViewHelpers)
                {
                    ASSERT(imageViewHelper.isImageViewGarbageEmpty());
                }
            }
            mMultisampledImageViews.reset();
        }
        for (auto &renderTargets : mSingleLayerRenderTargets)
        {
            ASSERT(renderTargets.empty());
        }
        ASSERT(mMultiLayerRenderTargets.empty());
        return;
    }

    mImageView.release(renderer, mImage->getResourceUse());

    if (mMultisampledImageViews)
    {
        for (gl::TexLevelArray<vk::ImageViewHelper> &imageViewHelpers : *mMultisampledImageViews)
        {
            for (vk::ImageViewHelper &imageViewHelper : imageViewHelpers)
            {
                imageViewHelper.release(renderer, mImage->getResourceUse());
            }
        }
        mMultisampledImageViews.reset();
    }

    if (mRgbDrawImageViewsForYuvResolve)
    {
        mRgbDrawImageViewsForYuvResolve->release(renderer, mImage->getResourceUse());
        mRgbDrawImageViewsForYuvResolve.reset();
    }

    for (auto &renderTargets : mSingleLayerRenderTargets)
    {
        for (RenderTargetVector &renderTargetLevels : renderTargets)
        {
            for (RenderTargetVk &renderTargetVk : renderTargetLevels)
            {
                renderTargetVk.releaseFramebuffers(contextVk);
            }
            // Clear the layers tracked for each level
            renderTargetLevels.clear();
        }
        // Then clear the levels
        renderTargets.clear();
    }

    for (auto &renderTargetPair : mMultiLayerRenderTargets)
    {
        renderTargetPair.second->releaseFramebuffers(contextVk);
    }
    mMultiLayerRenderTargets.clear();
}

void TextureVk::releaseStagedUpdates(ContextVk *contextVk)
{
    if (mImage)
    {
        mImage->releaseStagedUpdates(contextVk->getRenderer());
    }
}

uint32_t TextureVk::getMipLevelCount(ImageMipLevels mipLevels) const
{
    switch (mipLevels)
    {
        // Returns level count from base to max that has been specified, i.e, enabled.
        case ImageMipLevels::EnabledLevels:
            return mState.getEnabledLevelCount();
        // Returns all mipmap levels from base to max regardless if an image has been specified or
        // not.
        case ImageMipLevels::FullMipChainForGenerateMipmap:
            return getMaxLevelCount() - mState.getEffectiveBaseLevel();

        default:
            UNREACHABLE();
            return 0;
    }
}

uint32_t TextureVk::getMaxLevelCount() const
{
    // getMipmapMaxLevel will be 0 here if mipmaps are not used, so the levelCount is always +1.
    return mState.getMipmapMaxLevel() + 1;
}

angle::Result TextureVk::generateMipmapLevelsWithCPU(ContextVk *contextVk,
                                                     const angle::Format &sourceFormat,
                                                     GLuint layer,
                                                     gl::LevelIndex firstMipLevel,
                                                     gl::LevelIndex maxMipLevel,
                                                     const size_t sourceWidth,
                                                     const size_t sourceHeight,
                                                     const size_t sourceDepth,
                                                     const size_t sourceRowPitch,
                                                     const size_t sourceDepthPitch,
                                                     uint8_t *sourceData)
{
    size_t previousLevelWidth      = sourceWidth;
    size_t previousLevelHeight     = sourceHeight;
    size_t previousLevelDepth      = sourceDepth;
    uint8_t *previousLevelData     = sourceData;
    size_t previousLevelRowPitch   = sourceRowPitch;
    size_t previousLevelDepthPitch = sourceDepthPitch;

    for (gl::LevelIndex currentMipLevel = firstMipLevel; currentMipLevel <= maxMipLevel;
         ++currentMipLevel)
    {
        // Compute next level width and height.
        size_t mipWidth  = std::max<size_t>(1, previousLevelWidth >> 1);
        size_t mipHeight = std::max<size_t>(1, previousLevelHeight >> 1);
        size_t mipDepth  = std::max<size_t>(1, previousLevelDepth >> 1);

        // With the width and height of the next mip, we can allocate the next buffer we need.
        uint8_t *destData     = nullptr;
        size_t destRowPitch   = mipWidth * sourceFormat.pixelBytes;
        size_t destDepthPitch = destRowPitch * mipHeight;

        size_t mipAllocationSize = destDepthPitch * mipDepth;
        gl::Extents mipLevelExtents(static_cast<int>(mipWidth), static_cast<int>(mipHeight),
                                    static_cast<int>(mipDepth));

        ANGLE_TRY(mImage->stageSubresourceUpdateAndGetData(
            contextVk, mipAllocationSize,
            gl::ImageIndex::MakeFromType(mState.getType(), currentMipLevel.get(), layer),
            mipLevelExtents, gl::Offset(), &destData, sourceFormat.id));

        // Generate the mipmap into that new buffer
        sourceFormat.mipGenerationFunction(
            previousLevelWidth, previousLevelHeight, previousLevelDepth, previousLevelData,
            previousLevelRowPitch, previousLevelDepthPitch, destData, destRowPitch, destDepthPitch);

        // Swap for the next iteration
        previousLevelWidth      = mipWidth;
        previousLevelHeight     = mipHeight;
        previousLevelDepth      = mipDepth;
        previousLevelData       = destData;
        previousLevelRowPitch   = destRowPitch;
        previousLevelDepthPitch = destDepthPitch;
    }

    return angle::Result::Continue;
}

const gl::InternalFormat &TextureVk::getImplementationSizedFormat(const gl::Context *context) const
{
    GLenum sizedFormat = GL_NONE;

    if (mImage && mImage->valid())
    {
        sizedFormat = mImage->getActualFormat().glInternalFormat;
    }
    else
    {
        ContextVk *contextVk     = vk::GetImpl(context);
        const vk::Format &format = getBaseLevelFormat(contextVk->getRenderer());
        sizedFormat = format.getActualImageFormat(getRequiredFormatSupport()).glInternalFormat;
    }

    return gl::GetSizedInternalFormatInfo(sizedFormat);
}

GLenum TextureVk::getColorReadFormat(const gl::Context *context)
{
    const gl::InternalFormat &sizedFormat = getImplementationSizedFormat(context);
    return sizedFormat.format;
}

GLenum TextureVk::getColorReadType(const gl::Context *context)
{
    const gl::InternalFormat &sizedFormat = getImplementationSizedFormat(context);
    return sizedFormat.type;
}

angle::Result TextureVk::getTexImage(const gl::Context *context,
                                     const gl::PixelPackState &packState,
                                     gl::Buffer *packBuffer,
                                     gl::TextureTarget target,
                                     GLint level,
                                     GLenum format,
                                     GLenum type,
                                     void *pixels)
{
    if (packBuffer && this->isCompressedFormatEmulated(context, target, level))
    {
        // TODO (anglebug.com/42265933): Can't populate from a buffer using emulated format
        UNIMPLEMENTED();
        return angle::Result::Stop;
    }

    ContextVk *contextVk = vk::GetImpl(context);
    ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));

    GLint baseLevel = static_cast<int>(mState.getBaseLevel());
    if (level < baseLevel || level >= baseLevel + static_cast<int>(mState.getEnabledLevelCount()))
    {
        // TODO(http://anglebug.com/42264855): Handle inconsistent textures.
        WARN() << "GetTexImage for inconsistent texture levels is not implemented.";
        UNIMPLEMENTED();
        return angle::Result::Continue;
    }

    gl::MaybeOverrideLuminance(format, type, getColorReadFormat(context),
                               getColorReadType(context));

    uint32_t layer      = 0;
    uint32_t layerCount = 1;

    switch (target)
    {
        case gl::TextureTarget::CubeMapArray:
        case gl::TextureTarget::_2DArray:
            layerCount = mImage->getLayerCount();
            break;
        default:
            if (gl::IsCubeMapFaceTarget(target))
            {
                layer = static_cast<uint32_t>(gl::CubeMapTextureTargetToFaceIndex(target));
            }
            break;
    }

    return mImage->readPixelsForGetImage(contextVk, packState, packBuffer, gl::LevelIndex(level),
                                         layer, layerCount, format, type, pixels);
}

angle::Result TextureVk::getCompressedTexImage(const gl::Context *context,
                                               const gl::PixelPackState &packState,
                                               gl::Buffer *packBuffer,
                                               gl::TextureTarget target,
                                               GLint level,
                                               void *pixels)
{
    ContextVk *contextVk = vk::GetImpl(context);
    ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));

    GLint baseLevel = static_cast<int>(mState.getBaseLevel());
    if (level < baseLevel || level >= baseLevel + static_cast<int>(mState.getEnabledLevelCount()))
    {
        // TODO(http://anglebug.com/42264855): Handle inconsistent textures.
        WARN() << "GetCompressedTexImage for inconsistent texture levels is not implemented.";
        UNIMPLEMENTED();
        return angle::Result::Continue;
    }

    uint32_t layer      = 0;
    uint32_t layerCount = 1;

    switch (target)
    {
        case gl::TextureTarget::CubeMapArray:
        case gl::TextureTarget::_2DArray:
            layerCount = mImage->getLayerCount();
            break;
        default:
            if (gl::IsCubeMapFaceTarget(target))
            {
                layer = static_cast<uint32_t>(gl::CubeMapTextureTargetToFaceIndex(target));
            }
            break;
    }

    return mImage->readPixelsForCompressedGetImage(
        contextVk, packState, packBuffer, gl::LevelIndex(level), layer, layerCount, pixels);
}

const vk::Format &TextureVk::getBaseLevelFormat(vk::Renderer *renderer) const
{
    const gl::ImageDesc &baseLevelDesc = mState.getBaseLevelDesc();
    return renderer->getFormat(baseLevelDesc.format.info->sizedInternalFormat);
}

void TextureVk::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
{
    ASSERT(index == kTextureImageSubjectIndex &&
           (message == angle::SubjectMessage::SubjectChanged ||
            message == angle::SubjectMessage::InitializationComplete));

    // Forward the notification to the parent that the staging buffer changed.
    onStateChange(message);
}

vk::ImageOrBufferViewSubresourceSerial TextureVk::getImageViewSubresourceSerialImpl(
    vk::ImageViewColorspace colorspace) const
{
    gl::LevelIndex baseLevel(mState.getEffectiveBaseLevel());
    // getMipmapMaxLevel will clamp to the max level if it is smaller than the number of mips.
    uint32_t levelCount = gl::LevelIndex(mState.getMipmapMaxLevel()) - baseLevel + 1;

    return getImageViews().getSubresourceSerialForColorspace(baseLevel, levelCount, 0,
                                                             vk::LayerMode::All, colorspace);
}

vk::ImageOrBufferViewSubresourceSerial TextureVk::getBufferViewSerial() const
{
    return mBufferViews.getSerial();
}

vk::ImageOrBufferViewSubresourceSerial TextureVk::getStorageImageViewSerial(
    const gl::ImageUnit &binding) const
{
    vk::LayerMode layerMode = binding.layered == GL_TRUE ? vk::LayerMode::All : vk::LayerMode::_1;
    uint32_t frontendLayer  = binding.layered == GL_TRUE ? 0 : static_cast<uint32_t>(binding.layer);
    uint32_t nativeLayer    = getNativeImageLayer(frontendLayer);

    gl::LevelIndex baseLevel(
        getNativeImageLevel(gl::LevelIndex(static_cast<uint32_t>(binding.level))));

    return getImageViews().getSubresourceSerial(baseLevel, 1, nativeLayer, layerMode);
}

uint32_t TextureVk::getImageViewLayerCount() const
{
    // We use a special layer count here to handle EGLImages. They might only be
    // looking at one layer of a cube or 2D array texture.
    return mEGLImageNativeType == gl::TextureType::InvalidEnum ? mImage->getLayerCount() : 1;
}

uint32_t TextureVk::getImageViewLevelCount() const
{
    // We use a special level count here to handle EGLImages. They might only be
    // looking at one level of the texture's mipmap chain.
    return mEGLImageNativeType == gl::TextureType::InvalidEnum ? mImage->getLevelCount() : 1;
}

angle::Result TextureVk::refreshImageViews(ContextVk *contextVk)
{
    vk::ImageViewHelper &imageView = getImageViews();
    if (mImage == nullptr)
    {
        ASSERT(imageView.isImageViewGarbageEmpty());
    }
    else
    {
        vk::Renderer *renderer = contextVk->getRenderer();
        imageView.release(renderer, mImage->getResourceUse());

        // Since view has changed, some descriptorSet cache maybe obsolete. SO proactively release
        // cache.
        mDescriptorSetCacheManager.releaseKeys(renderer);

        for (auto &renderTargets : mSingleLayerRenderTargets)
        {
            for (RenderTargetVector &renderTargetLevels : renderTargets)
            {
                for (RenderTargetVk &renderTargetVk : renderTargetLevels)
                {
                    renderTargetVk.releaseFramebuffers(contextVk);
                }
            }
        }
        for (auto &renderTargetPair : mMultiLayerRenderTargets)
        {
            renderTargetPair.second->releaseFramebuffers(contextVk);
        }
    }

    ANGLE_TRY(initImageViews(contextVk, getImageViewLevelCount()));

    // Let any Framebuffers know we need to refresh the RenderTarget cache.
    onStateChange(angle::SubjectMessage::SubjectChanged);

    return angle::Result::Continue;
}

angle::Result TextureVk::ensureMutable(ContextVk *contextVk)
{
    if (mRequiresMutableStorage)
    {
        return angle::Result::Continue;
    }

    mRequiresMutableStorage = true;
    mImageCreateFlags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;

    ANGLE_TRY(respecifyImageStorage(contextVk));
    ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));

    return refreshImageViews(contextVk);
}

angle::Result TextureVk::ensureRenderable(ContextVk *contextVk,
                                          TextureUpdateResult *updateResultOut)
{
    return ensureRenderableWithFormat(contextVk, getBaseLevelFormat(contextVk->getRenderer()),
                                      updateResultOut);
}

angle::Result TextureVk::ensureRenderableWithFormat(ContextVk *contextVk,
                                                    const vk::Format &format,
                                                    TextureUpdateResult *updateResultOut)
{
    if (mRequiredFormatSupport == vk::ImageFormatSupport::Renderable)
    {
        return angle::Result::Continue;
    }

    mRequiredFormatSupport = vk::ImageFormatSupport::Renderable;
    if (!mImage)
    {
        // Later on when ensureImageAllocated() is called, it will ensure a renderable format is
        // used.
        return angle::Result::Continue;
    }

    if (!format.hasRenderableImageFallbackFormat())
    {
        // If there is no fallback format for renderable, then nothing to do.
        return angle::Result::Continue;
    }

    // If luminance/alpha formats ever fall back for rendering, it would only be because the
    // color attachment usage isn't specified by default.  The following wouldn't actually change
    // the format of the LUMA image because it's always emulated with a renderable format.  If
    // Vulkan ever introduces a LUMA format that ANGLE uses, the following code may not handle it
    // properly.
    ASSERT(!format.getIntendedFormat().isLUMA() ||
           (mImageUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) == 0);

    angle::FormatID previousActualFormatID =
        format.getActualImageFormatID(vk::ImageFormatSupport::SampleOnly);
    angle::FormatID actualFormatID =
        format.getActualImageFormatID(vk::ImageFormatSupport::Renderable);

    if (!mImage->valid())
    {
        // Immutable texture must already have a valid image
        ASSERT(!mState.getImmutableFormat());
        // If we have staged updates and they were encoded with different format, we need to flush
        // out these staged updates. The respecifyImageStorage should handle reading back the
        // flushed data and re-stage it with the new format.
        angle::FormatID intendedFormatID = format.getIntendedFormatID();

        gl::LevelIndex levelGLStart, levelGLEnd;
        ImageMipLevels mipLevels;
        if (mState.getImmutableFormat())
        {
            levelGLStart = gl::LevelIndex(0);
            levelGLEnd   = gl::LevelIndex(mState.getImmutableLevels());
            mipLevels    = ImageMipLevels::FullMipChainForGenerateMipmap;
        }
        else
        {
            levelGLStart = gl::LevelIndex(mState.getEffectiveBaseLevel());
            levelGLEnd =
                gl::LevelIndex(levelGLStart + getMipLevelCount(ImageMipLevels::EnabledLevels));
            mipLevels = ImageMipLevels::EnabledLevels;
        }

        if (mImage->hasStagedImageUpdatesWithMismatchedFormat(levelGLStart, levelGLEnd,
                                                              actualFormatID))
        {
            angle::FormatID sampleOnlyFormatID =
                format.getActualImageFormatID(vk::ImageFormatSupport::SampleOnly);

            ANGLE_TRY(initImage(contextVk, intendedFormatID, sampleOnlyFormatID, mipLevels));
        }
        else
        {
            // First try to convert any staged buffer updates from old format to new format using
            // CPU.
            ANGLE_TRY(mImage->reformatStagedBufferUpdates(contextVk, previousActualFormatID,
                                                          actualFormatID));
        }
    }

    // Make sure we update mImageUsage bits
    const bool imageWasInitialized = mImage->valid();
    ANGLE_TRY(ensureImageAllocated(contextVk, format));
    ANGLE_TRY(respecifyImageStorage(contextVk));
    if (imageWasInitialized)
    {
        ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
        ANGLE_TRY(refreshImageViews(contextVk));
    }

    if (updateResultOut != nullptr)
    {
        *updateResultOut = TextureUpdateResult::ImageRespecified;
    }

    return angle::Result::Continue;
}

angle::Result TextureVk::ensureRenderableIfCopyTextureCannotTransfer(
    ContextVk *contextVk,
    const gl::InternalFormat &dstFormat,
    bool unpackFlipY,
    bool unpackPremultiplyAlpha,
    bool unpackUnmultiplyAlpha,
    TextureVk *source)
{
    vk::Renderer *renderer = contextVk->getRenderer();

    const vk::Format &dstVkFormat = renderer->getFormat(dstFormat.sizedInternalFormat);
    angle::FormatID dstFormatID   = dstVkFormat.getActualImageFormatID(getRequiredFormatSupport());
    VkImageTiling dstTilingMode   = getTilingMode();

    if (!CanCopyWithTransferForCopyTexture(
            renderer, source->getImage(), dstVkFormat.getIntendedFormatID(), dstFormatID,
            dstTilingMode, unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha))
    {
        ANGLE_TRY(ensureRenderableWithFormat(contextVk, dstVkFormat, nullptr));
    }

    return angle::Result::Continue;
}

angle::Result TextureVk::ensureRenderableIfCopyTexImageCannotTransfer(
    ContextVk *contextVk,
    const gl::InternalFormat &dstFormat,
    gl::Framebuffer *source)
{
    vk::Renderer *renderer       = contextVk->getRenderer();
    FramebufferVk *framebufferVk = vk::GetImpl(source);

    RenderTargetVk *colorReadRT = framebufferVk->getColorReadRenderTarget();

    const vk::Format &dstVkFormat       = renderer->getFormat(dstFormat.sizedInternalFormat);
    angle::FormatID dstIntendedFormatID = dstVkFormat.getIntendedFormatID();
    angle::FormatID dstActualFormatID =
        dstVkFormat.getActualImageFormatID(getRequiredFormatSupport());
    VkImageTiling destTilingMode = getTilingMode();

    bool isViewportFlipY = contextVk->isViewportFlipEnabledForReadFBO();

    if (!CanCopyWithTransferForTexImage(renderer, colorReadRT->getImageForCopy(),
                                        dstIntendedFormatID, dstActualFormatID, destTilingMode,
                                        isViewportFlipY))
    {
        ANGLE_TRY(ensureRenderableWithFormat(contextVk, dstVkFormat, nullptr));
    }

    return angle::Result::Continue;
}

void TextureVk::stageSelfAsSubresourceUpdates(ContextVk *contextVk)
{
    // If we are calling stageSelfAsSubresourceUpdates(), the current image will be swapped
    // to prevImage in stageSelfAsSubresourceUpdates(), therefore we need to release the
    // imageViews first as we want to use current image.mUse to keep track of imageViews' resource
    // lifetime.
    releaseImageViews(contextVk);
    // Make the image stage itself as updates to its levels.
    ASSERT(!mImageSiblingSerial.valid());
    mImage->stageSelfAsSubresourceUpdates(contextVk, mImage->getLevelCount(), mState.getType(),
                                          mRedefinedLevels);
}

void TextureVk::updateCachedImageViewSerials()
{
    mCachedImageViewSubresourceSerialSRGBDecode =
        getImageViewSubresourceSerialImpl(vk::ImageViewColorspace::SRGB);
    mCachedImageViewSubresourceSerialSkipDecode =
        getImageViewSubresourceSerialImpl(vk::ImageViewColorspace::Linear);
}
}  // namespace rx
