//
// 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.
//
// FramebufferVk.cpp:
//    Implements the class methods for FramebufferVk.
//

#ifdef UNSAFE_BUFFERS_BUILD
#    pragma allow_unsafe_buffers
#endif

#include "libANGLE/renderer/vulkan/FramebufferVk.h"

#include <array>

#include "common/debug.h"
#include "common/vulkan/vk_headers.h"
#include "libANGLE/Context.h"
#include "libANGLE/Display.h"
#include "libANGLE/ErrorStrings.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/renderer_utils.h"
#include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/DisplayVk.h"
#include "libANGLE/renderer/vulkan/RenderTargetVk.h"
#include "libANGLE/renderer/vulkan/SurfaceVk.h"
#include "libANGLE/renderer/vulkan/vk_format_utils.h"
#include "libANGLE/renderer/vulkan/vk_renderer.h"
#include "libANGLE/renderer/vulkan/vk_resource.h"

namespace rx
{

namespace
{
// Clear values are only used when loadOp=Clear is set in clearWithRenderPassOp.  When starting a
// new render pass, the clear value is set to an unlikely value (bright pink) to stand out better
// in case of a bug.
constexpr VkClearValue kUninitializedClearValue = {{{0.95, 0.05, 0.95, 0.95}}};

// The value to assign an alpha channel that's emulated.  The type is unsigned int, though it will
// automatically convert to the actual data type.
constexpr unsigned int kEmulatedAlphaValue = 1;

bool HasSrcBlitFeature(vk::Renderer *renderer, RenderTargetVk *srcRenderTarget)
{
    angle::FormatID srcFormatID = srcRenderTarget->getImageActualFormatID();
    return renderer->hasImageFormatFeatureBits(srcFormatID, VK_FORMAT_FEATURE_BLIT_SRC_BIT) &&
           srcRenderTarget->getImageForCopy().canTransferFrom();
}

bool HasDstBlitFeature(vk::Renderer *renderer, RenderTargetVk *dstRenderTarget)
{
    angle::FormatID dstFormatID = dstRenderTarget->getImageActualFormatID();
    return renderer->hasImageFormatFeatureBits(dstFormatID, VK_FORMAT_FEATURE_BLIT_DST_BIT) &&
           dstRenderTarget->getImageForWrite().canTransferTo();
}

// Returns false if destination has any channel the source doesn't.  This means that channel was
// emulated and using the Vulkan blit command would overwrite that emulated channel.
bool AreSrcAndDstColorChannelsBlitCompatible(RenderTargetVk *srcRenderTarget,
                                             RenderTargetVk *dstRenderTarget)
{
    const angle::Format &srcFormat = srcRenderTarget->getImageIntendedFormat();
    const angle::Format &dstFormat = dstRenderTarget->getImageIntendedFormat();

    // Luminance/alpha formats are not renderable, so they can't have ended up in a framebuffer to
    // participate in a blit.
    ASSERT(!dstFormat.isLUMA() && !srcFormat.isLUMA());

    // All color formats have the red channel.
    ASSERT(dstFormat.redBits > 0 && srcFormat.redBits > 0);

    return (dstFormat.greenBits > 0 || srcFormat.greenBits == 0) &&
           (dstFormat.blueBits > 0 || srcFormat.blueBits == 0) &&
           (dstFormat.alphaBits > 0 || srcFormat.alphaBits == 0);
}

// Returns false if formats are not identical.  vkCmdResolveImage and resolve attachments both
// require identical formats between source and destination.  vkCmdBlitImage additionally requires
// the same for depth/stencil formats.
bool AreSrcAndDstFormatsIdentical(RenderTargetVk *srcRenderTarget, RenderTargetVk *dstRenderTarget)
{
    angle::FormatID srcFormatID = srcRenderTarget->getImageActualFormatID();
    angle::FormatID dstFormatID = dstRenderTarget->getImageActualFormatID();

    return srcFormatID == dstFormatID;
}

bool AreSrcAndDstDepthStencilChannelsBlitCompatible(RenderTargetVk *srcRenderTarget,
                                                    RenderTargetVk *dstRenderTarget)
{
    const angle::Format &srcFormat = srcRenderTarget->getImageIntendedFormat();
    const angle::Format &dstFormat = dstRenderTarget->getImageIntendedFormat();

    return (dstFormat.depthBits > 0 || srcFormat.depthBits == 0) &&
           (dstFormat.stencilBits > 0 || srcFormat.stencilBits == 0);
}

void EarlyAdjustFlipYForPreRotation(SurfaceRotation blitAngleIn,
                                    SurfaceRotation *blitAngleOut,
                                    bool *blitFlipYOut)
{
    switch (blitAngleIn)
    {
        case SurfaceRotation::Identity:
            // No adjustments needed
            break;
        case SurfaceRotation::Rotated90Degrees:
            *blitAngleOut = SurfaceRotation::Rotated90Degrees;
            *blitFlipYOut = false;
            break;
        case SurfaceRotation::Rotated180Degrees:
            *blitAngleOut = SurfaceRotation::Rotated180Degrees;
            break;
        case SurfaceRotation::Rotated270Degrees:
            *blitAngleOut = SurfaceRotation::Rotated270Degrees;
            *blitFlipYOut = false;
            break;
        default:
            UNREACHABLE();
            break;
    }
}

void AdjustBlitAreaForPreRotation(SurfaceRotation framebufferAngle,
                                  const gl::Rectangle &blitAreaIn,
                                  const gl::Rectangle &framebufferDimensions,
                                  gl::Rectangle *blitAreaOut)
{
    switch (framebufferAngle)
    {
        case SurfaceRotation::Identity:
            // No adjustments needed
            break;
        case SurfaceRotation::Rotated90Degrees:
            blitAreaOut->x = blitAreaIn.y;
            blitAreaOut->y = blitAreaIn.x;
            std::swap(blitAreaOut->width, blitAreaOut->height);
            break;
        case SurfaceRotation::Rotated180Degrees:
            blitAreaOut->x = framebufferDimensions.width - blitAreaIn.x - blitAreaIn.width;
            blitAreaOut->y = framebufferDimensions.height - blitAreaIn.y - blitAreaIn.height;
            break;
        case SurfaceRotation::Rotated270Degrees:
            blitAreaOut->x = framebufferDimensions.height - blitAreaIn.y - blitAreaIn.height;
            blitAreaOut->y = framebufferDimensions.width - blitAreaIn.x - blitAreaIn.width;
            std::swap(blitAreaOut->width, blitAreaOut->height);
            break;
        default:
            UNREACHABLE();
            break;
    }
}

void AdjustDimensionsAndFlipForPreRotation(SurfaceRotation framebufferAngle,
                                           gl::Rectangle *framebufferDimensions,
                                           bool *flipX,
                                           bool *flipY)
{
    switch (framebufferAngle)
    {
        case SurfaceRotation::Identity:
            // No adjustments needed
            break;
        case SurfaceRotation::Rotated90Degrees:
            std::swap(framebufferDimensions->width, framebufferDimensions->height);
            std::swap(*flipX, *flipY);
            break;
        case SurfaceRotation::Rotated180Degrees:
            break;
        case SurfaceRotation::Rotated270Degrees:
            std::swap(framebufferDimensions->width, framebufferDimensions->height);
            std::swap(*flipX, *flipY);
            break;
        default:
            UNREACHABLE();
            break;
    }
}

// When blitting, the source and destination areas are viewed like UVs.  For example, a 64x64
// texture if flipped should have an offset of 64 in either X or Y which corresponds to U or V of 1.
// On the other hand, when resolving, the source and destination areas are used as fragment
// coordinates to fetch from.  In that case, when flipped, the texture in the above example must
// have an offset of 63.
void AdjustBlitResolveParametersForResolve(const gl::Rectangle &sourceArea,
                                           const gl::Rectangle &destArea,
                                           UtilsVk::BlitResolveParameters *params)
{
    params->srcOffset[0] = sourceArea.x;
    params->srcOffset[1] = sourceArea.y;
    params->dstOffset[0] = destArea.x;
    params->dstOffset[1] = destArea.y;

    if (sourceArea.isReversedX())
    {
        ASSERT(sourceArea.x > 0);
        --params->srcOffset[0];
    }
    if (sourceArea.isReversedY())
    {
        ASSERT(sourceArea.y > 0);
        --params->srcOffset[1];
    }
    if (destArea.isReversedX())
    {
        ASSERT(destArea.x > 0);
        --params->dstOffset[0];
    }
    if (destArea.isReversedY())
    {
        ASSERT(destArea.y > 0);
        --params->dstOffset[1];
    }
}

// Potentially make adjustments for pre-rotatation.  Depending on the angle some of the params need
// to be swapped and/or changes made to which axis are flipped.
void AdjustBlitResolveParametersForPreRotation(SurfaceRotation framebufferAngle,
                                               SurfaceRotation srcFramebufferAngle,
                                               UtilsVk::BlitResolveParameters *params)
{
    switch (framebufferAngle)
    {
        case SurfaceRotation::Identity:
            break;
        case SurfaceRotation::Rotated90Degrees:
            std::swap(params->stretch[0], params->stretch[1]);
            std::swap(params->srcOffset[0], params->srcOffset[1]);
            std::swap(params->rotatedOffsetFactor[0], params->rotatedOffsetFactor[1]);
            std::swap(params->flipX, params->flipY);
            if (srcFramebufferAngle == framebufferAngle)
            {
                std::swap(params->dstOffset[0], params->dstOffset[1]);
                std::swap(params->stretch[0], params->stretch[1]);
            }
            break;
        case SurfaceRotation::Rotated180Degrees:
            // Combine flip info with api flip.
            params->flipX = !params->flipX;
            params->flipY = !params->flipY;
            break;
        case SurfaceRotation::Rotated270Degrees:
            std::swap(params->stretch[0], params->stretch[1]);
            std::swap(params->srcOffset[0], params->srcOffset[1]);
            std::swap(params->rotatedOffsetFactor[0], params->rotatedOffsetFactor[1]);
            if (srcFramebufferAngle == framebufferAngle)
            {
                std::swap(params->stretch[0], params->stretch[1]);
            }
            // Combine flip info with api flip.
            params->flipX = !params->flipX;
            params->flipY = !params->flipY;
            std::swap(params->flipX, params->flipY);

            break;
        default:
            UNREACHABLE();
            break;
    }
}

void AdjustBlitAreas(RenderTargetVk *readRenderTarget,
                     gl::Rectangle *sourceArea,
                     gl::Rectangle *destArea,
                     gl::Rectangle *srcFramebufferDimensions,
                     const gl::Rectangle &dstFramebufferDimensions,
                     SurfaceRotation srcFramebufferRotation,
                     SurfaceRotation *dstFramebufferRotation,
                     SurfaceRotation rotation,
                     bool srcFramebufferFlippedY,
                     bool dstFramebufferFlippedY,
                     const bool isResolve,
                     bool *flipX,
                     bool *flipY,
                     const bool isDefault,
                     UtilsVk::BlitResolveParameters *params)
{
    const gl::Extents readExtent = readRenderTarget->getExtents();
    gl::Rectangle srcAttachmentDimensions =
        gl::Rectangle(0, 0, readExtent.width, readExtent.height);
    if (isDefault)
    {
        // The readExtent size of the default framebuffer is the same as the window size. Choose
        // to use the framebuffer size instead.
        srcAttachmentDimensions = *srcFramebufferDimensions;
    }
    // If framebuffers are flipped in Y, flip the source and destination area (which define the
    // transformation regardless of clipping), as well as the blit area (which is the clipped
    // destination area).
    if (srcFramebufferFlippedY)
    {
        sourceArea->y      = srcAttachmentDimensions.height - sourceArea->y;
        sourceArea->height = -sourceArea->height;
    }

    *flipX = sourceArea->isReversedX() != destArea->isReversedX();
    *flipY = sourceArea->isReversedY() != destArea->isReversedY();

    // GLES doesn't allow flipping the parameters of glBlitFramebuffer if performing a resolve.
    ASSERT(!isResolve ||
           (*flipX == false && *flipY == (srcFramebufferFlippedY != dstFramebufferFlippedY)));

    // Again, transfer the destination flip to source, so destination is unflipped.  Note that
    // destArea was not reversed until the final possible Y-flip.
    ASSERT(!destArea->isReversedX());
    *sourceArea = sourceArea->flip(false, destArea->isReversedY());
    *destArea   = destArea->removeReversal();

    // Now that clipping and flipping is done, rotate certain values that will be used for
    // UtilsVk::BlitResolveParameters
    gl::Rectangle sourceAreaOld = *sourceArea;
    gl::Rectangle destAreaOld   = *destArea;
    if (srcFramebufferRotation == rotation)
    {
        AdjustBlitAreaForPreRotation(srcFramebufferRotation, sourceAreaOld, srcAttachmentDimensions,
                                     sourceArea);
        AdjustDimensionsAndFlipForPreRotation(srcFramebufferRotation, &srcAttachmentDimensions,
                                              flipX, flipY);
    }
    SurfaceRotation rememberDestFramebufferRotation = *dstFramebufferRotation;
    if (srcFramebufferRotation == SurfaceRotation::Rotated90Degrees)
    {
        *dstFramebufferRotation = rotation;
    }
    AdjustBlitAreaForPreRotation(*dstFramebufferRotation, destAreaOld, dstFramebufferDimensions,
                                 destArea);
    *dstFramebufferRotation = rememberDestFramebufferRotation;

    params->srcOffset[0]           = sourceArea->x;
    params->srcOffset[1]           = sourceArea->y;
    params->dstOffset[0]           = destArea->x;
    params->dstOffset[1]           = destArea->y;
    params->rotatedOffsetFactor[0] = std::abs(sourceArea->width);
    params->rotatedOffsetFactor[1] = std::abs(sourceArea->height);
    params->srcExtents[0]          = srcAttachmentDimensions.width;
    params->srcExtents[1]          = srcAttachmentDimensions.height;
    params->flipX                  = *flipX;
    params->flipY                  = *flipY;
    params->srcMip =
        readRenderTarget->getImageForCopy().toVkLevel(readRenderTarget->getLevelIndex());
    params->srcLayer               = readRenderTarget->getLayerIndex();
}

vk::FramebufferNonResolveAttachmentMask MakeUnresolveAttachmentMask(const vk::RenderPassDesc &desc)
{
    vk::FramebufferNonResolveAttachmentMask unresolveMask(
        desc.getColorUnresolveAttachmentMask().bits());
    if (desc.hasDepthUnresolveAttachment() || desc.hasStencilUnresolveAttachment())
    {
        // This mask only needs to know if the depth/stencil attachment needs to be unresolved, and
        // is agnostic of the aspect.
        unresolveMask.set(vk::kUnpackedDepthIndex);
    }
    return unresolveMask;
}

bool IsAnyAttachment3DWithoutAllLayers(const RenderTargetCache<RenderTargetVk> &renderTargetCache,
                                       gl::DrawBufferMask colorAttachmentsMask,
                                       uint32_t framebufferLayerCount)
{
    const auto &colorRenderTargets = renderTargetCache.getColors();
    for (size_t colorIndexGL : colorAttachmentsMask)
    {
        RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
        ASSERT(colorRenderTarget);

        const vk::ImageHelper &image = colorRenderTarget->getImageForRenderPass();

        if (image.getType() == VK_IMAGE_TYPE_3D && image.getExtents().depth > framebufferLayerCount)
        {
            return true;
        }
    }

    // Depth/stencil attachments cannot be 3D.
    ASSERT(renderTargetCache.getDepthStencil() == nullptr ||
           renderTargetCache.getDepthStencil()->getImageForRenderPass().getType() !=
               VK_IMAGE_TYPE_3D);

    return false;
}

// Should be called when the image type is VK_IMAGE_TYPE_3D.  Typically, the subresource, offsets
// and extents are filled in as if images are 2D layers (because depth slices of 3D images are also
// specified through "layers" everywhere, particularly by gl::ImageIndex).  This function adjusts
// the layer base/count and offsets.z/extents.z appropriately after these structs are set up.
void AdjustLayersAndDepthFor3DImages(VkImageSubresourceLayers *subresource,
                                     VkOffset3D *offsetsStart,
                                     VkOffset3D *offsetsEnd)
{
    // The struct must be set up as if the image was 2D array.
    ASSERT(offsetsStart->z == 0);
    ASSERT(offsetsEnd->z == 1);

    offsetsStart->z = subresource->baseArrayLayer;
    offsetsEnd->z   = subresource->baseArrayLayer + subresource->layerCount;

    subresource->baseArrayLayer = 0;
    subresource->layerCount     = 1;
}

bool AllowAddingResolveAttachmentsToSubpass(const vk::RenderPassDesc &desc)
{
    // When in render-to-texture emulation mode, there are already resolve attachments present, and
    // render pass compatibility rules would require packing those first before packing resolve
    // attachments that may be added later (through glBlitFramebuffer).  While supporting that is
    // not onerous, the code is simplified by not supporting this combination.  In practice no
    // application should be mixing MSRTT textures and and truly multisampled textures in the same
    // framebuffer (they could be using MSRTT for both).
    //
    // For the same reason, adding resolve attachments after the fact is disabled with YUV resolve.
    return !desc.isRenderToTexture() && !desc.hasYUVResolveAttachment();
}

angle::Result UnresolveYuvImage(ContextVk *contextVk,
                                RenderTargetVk *colorRenderTarget,
                                const gl::Rectangle &renderArea)
{
    vk::ImageHelper *dst = &colorRenderTarget->getImageForRenderPass();
    vk::ImageHelper *src = &colorRenderTarget->getResolveImageForRenderPass();

    // The Y2Y sampler is used for the source image in the unresolve copy.
    vk::DeviceScoped<vk::ImageView> srcViewY2Y(contextVk->getDevice());
    ANGLE_TRY(src->initLayerImageViewWithYuvModeOverride(
        contextVk, gl::TextureType::_2D, VK_IMAGE_ASPECT_COLOR_BIT, gl::SwizzleState(),
        &srcViewY2Y.get(), vk::LevelIndex(0), 1, 0, 1, gl::YuvSamplingMode::Y2Y,
        VK_IMAGE_USAGE_SAMPLED_BIT, GL_NONE));
    const vk::ImageView *dstView = nullptr;
    ANGLE_TRY(colorRenderTarget->getImageView(contextVk, &dstView));

    UtilsVk::CopyImageParameters params  = {};
    params.srcOffset[0]                  = renderArea.x;
    params.srcOffset[1]                  = renderArea.y;
    params.srcExtents[0]                 = renderArea.width;
    params.srcExtents[1]                 = renderArea.height;
    params.copyYuvWithoutColorConversion = true;

    ANGLE_TRY(
        contextVk->getUtils().copyImage(contextVk, dst, dstView, src, &srcViewY2Y.get(), params));

    // Mark our temp view as garbage immediately
    vk::ImageView srcViewObject = srcViewY2Y.release();
    contextVk->addGarbage(&srcViewObject);
    return angle::Result::Continue;
}
}  // anonymous namespace

FramebufferVk::FramebufferVk(vk::Renderer *renderer, const gl::FramebufferState &state)
    : FramebufferImpl(state), mBackbuffer(nullptr), mActiveColorComponentMasksForClear(0)
{
    if (mState.isDefault())
    {
        // These are immutable for system default framebuffer.
        mCurrentFramebufferDesc.updateLayerCount(1);
        mCurrentFramebufferDesc.updateIsMultiview(false);
    }

    mIsCurrentFramebufferCached = !renderer->getFeatures().supportsImagelessFramebuffer.enabled;
    mIsYUVResolve               = false;
    mRasterizationSamples       = -1;
}

FramebufferVk::~FramebufferVk() = default;

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

    if (mFragmentShadingRateImage.valid())
    {
        contextVk->finalizeImageLayout(&mFragmentShadingRateImage);

        vk::Renderer *renderer = contextVk->getRenderer();
        mFragmentShadingRateImageView.release(renderer, mFragmentShadingRateImage.getResourceUse());
        mFragmentShadingRateImage.releaseImage(renderer);
    }

    releaseCurrentFramebuffer(contextVk);
}

void FramebufferVk::insertCache(ContextVk *contextVk,
                                const vk::FramebufferDesc &desc,
                                vk::Framebuffer &&newFramebuffer)
{
    // Add it into per context cache
    contextVk->getFramebufferCache().insert(contextVk, desc, std::move(newFramebuffer));

    // Create a refcounted cache key object and have each attachment keep a refcount to it so that
    // it can be destroyed promptly if those attachments change.
    const vk::SharedFramebufferCacheKey sharedFramebufferCacheKey =
        vk::CreateSharedFramebufferCacheKey(desc);

    // Ask each attachment to hold a reference to the cache so that when any attachment is
    // released, the cache can be destroyed.
    const auto &colorRenderTargets = mRenderTargetCache.getColors();
    for (size_t colorIndexGL : mState.getColorAttachmentsMask())
    {
        colorRenderTargets[colorIndexGL]->onNewFramebuffer(sharedFramebufferCacheKey);
    }

    if (getDepthStencilRenderTarget())
    {
        getDepthStencilRenderTarget()->onNewFramebuffer(sharedFramebufferCacheKey);
    }
}

angle::Result FramebufferVk::discard(const gl::Context *context,
                                     size_t count,
                                     const GLenum *attachments)
{
    return invalidate(context, count, attachments);
}

angle::Result FramebufferVk::invalidate(const gl::Context *context,
                                        size_t count,
                                        const GLenum *attachments)
{
    ContextVk *contextVk = vk::GetImpl(context);

    ANGLE_TRY(invalidateImpl(contextVk, count, attachments, false,
                             getRotatedCompleteRenderArea(contextVk)));
    return angle::Result::Continue;
}

angle::Result FramebufferVk::invalidateSub(const gl::Context *context,
                                           size_t count,
                                           const GLenum *attachments,
                                           const gl::Rectangle &area)
{
    ContextVk *contextVk = vk::GetImpl(context);

    const gl::Rectangle nonRotatedCompleteRenderArea = getNonRotatedCompleteRenderArea();
    gl::Rectangle rotatedInvalidateArea;
    RotateRectangle(contextVk->getRotationDrawFramebuffer(),
                    contextVk->isViewportFlipEnabledForDrawFBO(),
                    nonRotatedCompleteRenderArea.width, nonRotatedCompleteRenderArea.height, area,
                    &rotatedInvalidateArea);

    // If invalidateSub() covers the whole framebuffer area, make it behave as invalidate().
    // The invalidate area is clipped to the render area for use inside invalidateImpl.
    const gl::Rectangle completeRenderArea = getRotatedCompleteRenderArea(contextVk);
    if (ClipRectangle(rotatedInvalidateArea, completeRenderArea, &rotatedInvalidateArea) &&
        rotatedInvalidateArea == completeRenderArea)
    {
        return invalidate(context, count, attachments);
    }

    // If there are deferred clears, restage them.  syncState may have accumulated deferred clears,
    // but if the framebuffer's attachments are used after this call not through the framebuffer,
    // those clears wouldn't get flushed otherwise (for example as the destination of
    // glCopyTex[Sub]Image, shader storage image, etc).
    restageDeferredClears(contextVk);

    // If robust resource initialization is enabled, do not invalidate sub-regions of the
    // framebuffer.  This is because otherwise the contents of that region becomes undefined and
    // ANGLE doesn't clear it back to black.
    if (!contextVk->isRobustResourceInitEnabled() && contextVk->hasActiveRenderPass() &&
        rotatedInvalidateArea.encloses(contextVk->getStartedRenderPassCommands().getRenderArea()))
    {
        // Because the render pass's render area is within the invalidated area, it is fine for
        // invalidateImpl() to use a storeOp of DONT_CARE (i.e. fine to not store the contents of
        // the invalidated area).
        ANGLE_TRY(invalidateImpl(contextVk, count, attachments, true, rotatedInvalidateArea));
    }
    else
    {
        ANGLE_VK_PERF_WARNING(
            contextVk, GL_DEBUG_SEVERITY_LOW,
            contextVk->isRobustResourceInitEnabled()
                ? "InvalidateSubFramebuffer ignored due to area not covering the entire "
                  "framebuffer while robust resource initialization is enabled"
                : "InvalidateSubFramebuffer ignored due to area not covering the render area");
    }

    return angle::Result::Continue;
}

angle::Result FramebufferVk::clear(const gl::Context *context, GLbitfield mask)
{
    ANGLE_TRACE_EVENT0("gpu.angle", "FramebufferVk::clear");
    ContextVk *contextVk = vk::GetImpl(context);

    bool clearColor   = IsMaskFlagSet(mask, static_cast<GLbitfield>(GL_COLOR_BUFFER_BIT));
    bool clearDepth   = IsMaskFlagSet(mask, static_cast<GLbitfield>(GL_DEPTH_BUFFER_BIT));
    bool clearStencil = IsMaskFlagSet(mask, static_cast<GLbitfield>(GL_STENCIL_BUFFER_BIT));
    gl::DrawBufferMask clearColorBuffers;
    if (clearColor)
    {
        clearColorBuffers = mState.getEnabledDrawBuffers();
    }

    const VkClearColorValue &clearColorValue = contextVk->getClearColorValue().color;
    const VkClearDepthStencilValue &clearDepthStencilValue =
        contextVk->getClearDepthStencilValue().depthStencil;

    return clearImpl(context, clearColorBuffers, clearDepth, clearStencil, clearColorValue,
                     clearDepthStencilValue);
}

VkClearColorValue adjustFloatClearColorPrecision(const VkClearColorValue &color,
                                                 const angle::Format &colorFormat)
{
    // Truncate x to b bits: round(x * (2^b-1)) / (2^b-1)
    // Implemented as floor(x * ((1 << b) - 1) + 0.5) / ((1 << b) - 1)

    float floatClearColorRed = color.float32[0];
    GLuint targetRedBits     = colorFormat.redBits;
    floatClearColorRed       = floor(floatClearColorRed * ((1 << targetRedBits) - 1) + 0.5f);
    floatClearColorRed       = floatClearColorRed / ((1 << targetRedBits) - 1);

    float floatClearColorGreen = color.float32[1];
    GLuint targetGreenBits     = colorFormat.greenBits;
    floatClearColorGreen       = floor(floatClearColorGreen * ((1 << targetGreenBits) - 1) + 0.5f);
    floatClearColorGreen       = floatClearColorGreen / ((1 << targetGreenBits) - 1);

    float floatClearColorBlue = color.float32[2];
    GLuint targetBlueBits     = colorFormat.blueBits;
    floatClearColorBlue       = floor(floatClearColorBlue * ((1 << targetBlueBits) - 1) + 0.5f);
    floatClearColorBlue       = floatClearColorBlue / ((1 << targetBlueBits) - 1);

    float floatClearColorAlpha = color.float32[3];
    GLuint targetAlphaBits     = colorFormat.alphaBits;
    floatClearColorAlpha       = floor(floatClearColorAlpha * ((1 << targetAlphaBits) - 1) + 0.5f);
    floatClearColorAlpha       = floatClearColorAlpha / ((1 << targetAlphaBits) - 1);

    VkClearColorValue adjustedClearColor = color;
    adjustedClearColor.float32[0]        = floatClearColorRed;
    adjustedClearColor.float32[1]        = floatClearColorGreen;
    adjustedClearColor.float32[2]        = floatClearColorBlue;
    adjustedClearColor.float32[3]        = floatClearColorAlpha;

    return adjustedClearColor;
}

angle::Result FramebufferVk::clearImpl(const gl::Context *context,
                                       gl::DrawBufferMask clearColorBuffers,
                                       bool clearDepth,
                                       bool clearStencil,
                                       const VkClearColorValue &clearColorValue,
                                       const VkClearDepthStencilValue &clearDepthStencilValue)
{
    ContextVk *contextVk = vk::GetImpl(context);

    const gl::Rectangle scissoredRenderArea = getRotatedScissoredRenderArea(contextVk);
    if (scissoredRenderArea.width == 0 || scissoredRenderArea.height == 0)
    {
        restageDeferredClears(contextVk);
        return angle::Result::Continue;
    }

    // This function assumes that only enabled attachments are asked to be cleared.
    ASSERT((clearColorBuffers & mState.getEnabledDrawBuffers()) == clearColorBuffers);
    ASSERT(!clearDepth || mState.getDepthAttachment() != nullptr);
    ASSERT(!clearStencil || mState.getStencilAttachment() != nullptr);

    gl::BlendStateExt::ColorMaskStorage::Type colorMasks = contextVk->getClearColorMasks();
    bool clearColor                                      = clearColorBuffers.any();

    // When this function is called, there should always be something to clear.
    ASSERT(clearColor || clearDepth || clearStencil);

    gl::DrawBuffersArray<VkClearColorValue> adjustedClearColorValues;
    const gl::DrawBufferMask colorAttachmentMask = mState.getColorAttachmentsMask();
    const auto &colorRenderTargets               = mRenderTargetCache.getColors();
    for (size_t colorIndexGL : colorAttachmentMask)
    {
        adjustedClearColorValues[colorIndexGL] = clearColorValue;

        RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
        ASSERT(colorRenderTarget);

        if (colorRenderTarget->isYuvResolve())
        {
            // OpenGLES spec says "clear color should be defined in yuv color space and so
            // floating point r, g, and b value will be mapped to corresponding y, u and v
            // value" https://registry.khronos.org/OpenGL/extensions/EXT/EXT_YUV_target.txt.
            // But vulkan spec says "Values in the G, B, and R channels of the color
            // attachment will be written to the Y, CB, and CR channels of the external
            // format image, respectively." So we have to adjust the component mapping from
            // GL order to vulkan order.
            adjustedClearColorValues[colorIndexGL].float32[0] = clearColorValue.float32[2];
            adjustedClearColorValues[colorIndexGL].float32[1] = clearColorValue.float32[0];
            adjustedClearColorValues[colorIndexGL].float32[2] = clearColorValue.float32[1];
        }
        else if (contextVk->getFeatures().adjustClearColorPrecision.enabled)
        {
            const angle::FormatID colorRenderTargetFormat =
                colorRenderTarget->getImageForRenderPass().getActualFormatID();
            if (colorRenderTargetFormat == angle::FormatID::R5G5B5A1_UNORM)
            {
                // Temporary workaround for https://issuetracker.google.com/292282210 to avoid
                // dithering being automatically applied
                adjustedClearColorValues[colorIndexGL] = adjustFloatClearColorPrecision(
                    clearColorValue, angle::Format::Get(colorRenderTargetFormat));
            }
        }
    }

    const uint8_t stencilMask =
        static_cast<uint8_t>(contextVk->getState().getDepthStencilState().stencilWritemask);

    // The front-end should ensure we don't attempt to clear color if all channels are masked.
    ASSERT(!clearColor || colorMasks != 0);
    // The front-end should ensure we don't attempt to clear depth if depth write is disabled.
    ASSERT(!clearDepth || contextVk->getState().getDepthStencilState().depthMask);
    // The front-end should ensure we don't attempt to clear stencil if all bits are masked.
    ASSERT(!clearStencil || stencilMask != 0);

    // Make sure to close the render pass now if in read-only depth/stencil feedback loop mode and
    // depth/stencil is being cleared.
    if (clearDepth || clearStencil)
    {
        ANGLE_TRY(contextVk->updateRenderPassDepthFeedbackLoopMode(
            clearDepth ? UpdateDepthFeedbackLoopReason::Clear : UpdateDepthFeedbackLoopReason::None,
            clearStencil ? UpdateDepthFeedbackLoopReason::Clear
                         : UpdateDepthFeedbackLoopReason::None));
    }

    const bool scissoredClear = scissoredRenderArea != getRotatedCompleteRenderArea(contextVk);

    // We use the draw path if scissored clear, or color or stencil are masked.  Note that depth
    // clearing is already disabled if there's a depth mask.
    const bool maskedClearColor = clearColor && (mActiveColorComponentMasksForClear & colorMasks) !=
                                                    mActiveColorComponentMasksForClear;
    const bool maskedClearStencil = clearStencil && stencilMask != 0xFF;

    // If a rendertarget has colorspace overrides, we need to clear with a draw
    // to make sure the colorspace override is honored.
    bool clearColorWithDraw   = clearColor && (maskedClearColor || scissoredClear ||
                                             mAttachmentWithColorSpaceOverrideMask.any());
    bool clearDepthWithDraw   = clearDepth && scissoredClear;
    bool clearStencilWithDraw = clearStencil && (maskedClearStencil || scissoredClear);

    const bool isMidRenderPassClear =
        contextVk->hasStartedRenderPassWithQueueSerial(mLastRenderPassQueueSerial) &&
        !contextVk->getStartedRenderPassCommands().getCommandBuffer().empty();
    if (isMidRenderPassClear)
    {
        // Emit debug-util markers for this mid-render-pass clear
        ANGLE_TRY(
            contextVk->handleGraphicsEventLog(rx::GraphicsEventCmdBuf::InRenderPassCmdBufQueryCmd));
    }
    else
    {
        ASSERT(!contextVk->hasActiveRenderPass() ||
               contextVk->hasStartedRenderPassWithQueueSerial(mLastRenderPassQueueSerial));
        // Emit debug-util markers for this outside-render-pass clear
        ANGLE_TRY(
            contextVk->handleGraphicsEventLog(rx::GraphicsEventCmdBuf::InOutsideCmdBufQueryCmd));
    }

    bool preferDrawOverClearAttachments =
        contextVk->getFeatures().preferDrawClearOverVkCmdClearAttachments.enabled;

    // https://issuetracker.google.com/490503954. Temporary workaround the driver bug.
    if ((contextVk->getFeatures().supportsTileMemoryHeap.enabled ||
         contextVk->getFeatures().simulateTileMemoryForTesting.enabled) &&
        (clearDepth || clearStencil) &&
        getDepthStencilRenderTarget()->getImageForRenderPass().useTileMemory())
    {
        preferDrawOverClearAttachments = true;
    }

    // Merge current clears with the deferred clears, then proceed with only processing deferred
    // clears.  This simplifies the clear paths such that they don't need to consider both the
    // current and deferred clears.  Additionally, it avoids needing to undo an unresolve
    // operation; say attachment A is deferred cleared and multisampled-render-to-texture
    // attachment B is currently cleared.  Assuming a render pass needs to start (because for
    // example attachment C needs to clear with a draw path), starting one with only deferred
    // clears and then applying the current clears won't work as attachment B is unresolved, and
    // there are no facilities to undo that.
    if (preferDrawOverClearAttachments && isMidRenderPassClear)
    {
        // On buggy hardware, prefer to clear with a draw call instead of vkCmdClearAttachments.
        // Note that it's impossible to have deferred clears in the middle of the render pass.
        ASSERT(!mDeferredClears.any());

        clearColorWithDraw   = clearColor;
        clearDepthWithDraw   = clearDepth;
        clearStencilWithDraw = clearStencil;
    }
    else
    {
        gl::DrawBufferMask clearColorDrawBuffersMask;
        if (clearColor && !clearColorWithDraw)
        {
            clearColorDrawBuffersMask = clearColorBuffers;
        }

        mergeClearsWithDeferredClears(clearColorDrawBuffersMask, clearDepth && !clearDepthWithDraw,
                                      clearStencil && !clearStencilWithDraw,
                                      adjustedClearColorValues, clearDepthStencilValue);
    }

    // If any deferred clears, we can further defer them, clear them with vkCmdClearAttachments or
    // flush them if necessary.
    if (mDeferredClears.any())
    {
        const bool clearAnyWithDraw =
            clearColorWithDraw || clearDepthWithDraw || clearStencilWithDraw;

        bool isAnyAttachment3DWithoutAllLayers =
            IsAnyAttachment3DWithoutAllLayers(mRenderTargetCache, mState.getColorAttachmentsMask(),
                                              mCurrentFramebufferDesc.getLayerCount());

        // If we are in an active renderpass that has recorded commands and the framebuffer hasn't
        // changed, inline the clear.
        if (isMidRenderPassClear)
        {
            ANGLE_VK_PERF_WARNING(
                contextVk, GL_DEBUG_SEVERITY_LOW,
                "Clear effectively discarding previous draw call results. Suggest earlier Clear "
                "followed by masked color or depth/stencil draw calls instead, or "
                "glInvalidateFramebuffer to discard data instead");

            ASSERT(!preferDrawOverClearAttachments);

            // clearWithCommand will operate on deferred clears.
            clearWithCommand(contextVk, scissoredRenderArea, ClearWithCommand::OptimizeWithLoadOp,
                             &mDeferredClears);

            // clearWithCommand will clear only those attachments that have been used in the render
            // pass, and removes them from mDeferredClears.  Any deferred clears that are left can
            // be performed with a renderpass loadOp.
            if (mDeferredClears.any())
            {
                clearWithLoadOp(contextVk);
            }
        }
        else
        {
            if (contextVk->hasActiveRenderPass())
            {
                // Typically, clears are deferred such that it's impossible to have a render pass
                // opened without any additional commands recorded on it.  This is not true for some
                // corner cases, such as with 3D or external attachments.  In those cases, a clear
                // can open a render pass that's otherwise empty, and additional clears can continue
                // to be accumulated in the render pass loadOps.
                ASSERT(isAnyAttachment3DWithoutAllLayers || hasAnyExternalAttachments());
                clearWithLoadOp(contextVk);
            }

            // This path will defer the current clears along with deferred clears.  This won't work
            // if any attachment needs to be subsequently cleared with a draw call.  In that case,
            // flush deferred clears, which will start a render pass with deferred clear values.
            // The subsequent draw call will then operate on the cleared attachments.
            //
            // Additionally, if the framebuffer is layered, any attachment is 3D and it has a larger
            // depth than the framebuffer layers, clears cannot be deferred.  This is because the
            // clear may later need to be flushed with vkCmdClearColorImage, which cannot partially
            // clear the 3D texture.  In that case, the clears are flushed immediately too.
            //
            // For external images such as from AHBs, the clears are not deferred so that they are
            // definitely applied before the application uses them outside of the control of ANGLE.
            if (clearAnyWithDraw || isAnyAttachment3DWithoutAllLayers ||
                hasAnyExternalAttachments())
            {
                ANGLE_TRY(flushDeferredClears(contextVk));
            }
            else
            {
                restageDeferredClears(contextVk);
            }
        }

        // If nothing left to clear, early out.
        if (!clearAnyWithDraw)
        {
            ASSERT(mDeferredClears.empty());
            return angle::Result::Continue;
        }
    }

    if (!clearColorWithDraw)
    {
        clearColorBuffers.reset();
    }

    // If we reach here simply because the clear is scissored (as opposed to masked), use
    // vkCmdClearAttachments to clear the attachments.  The attachments that are masked will
    // continue to use a draw call.  For depth, vkCmdClearAttachments can always be used, and no
    // shader/pipeline support would then be required (though this is pending removal of the
    // preferDrawOverClearAttachments workaround).
    //
    // A potential optimization is to use loadOp=Clear for scissored clears, but care needs to be
    // taken to either break the render pass on growRenderArea(), or to turn the op back to Load and
    // revert to vkCmdClearAttachments.  This is not currently deemed necessary.
    if (((clearColorBuffers.any() && !mEmulatedAlphaAttachmentMask.any() && !maskedClearColor) ||
         clearDepthWithDraw || (clearStencilWithDraw && !maskedClearStencil)) &&
        !preferDrawOverClearAttachments && mAttachmentWithColorSpaceOverrideMask.none())
    {
        if (!contextVk->hasActiveRenderPass())
        {
            // Start a new render pass if necessary to record the commands.
            vk::RenderPassCommandBuffer *commandBuffer;
            gl::Rectangle renderArea = getRenderArea(contextVk);
            ANGLE_TRY(contextVk->startRenderPass(renderArea, &commandBuffer, nullptr));
        }

        // Build clear values
        vk::ClearValuesArray clears;
        if (!maskedClearColor && !mEmulatedAlphaAttachmentMask.any())
        {
            VkClearValue colorClearValue = {};
            for (size_t colorIndexGL : clearColorBuffers)
            {
                colorClearValue.color = adjustedClearColorValues[colorIndexGL];
                clears.store(static_cast<uint32_t>(colorIndexGL), VK_IMAGE_ASPECT_COLOR_BIT,
                             colorClearValue);
            }
            clearColorBuffers.reset();
        }
        VkImageAspectFlags dsAspectFlags = 0;
        if (clearDepthWithDraw)
        {
            dsAspectFlags |= VK_IMAGE_ASPECT_DEPTH_BIT;
            clearDepthWithDraw = false;
        }
        if (clearStencilWithDraw && !maskedClearStencil)
        {
            dsAspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
            clearStencilWithDraw = false;
        }
        if (dsAspectFlags != 0)
        {
            VkClearValue dsClearValue = {};
            dsClearValue.depthStencil = clearDepthStencilValue;
            clears.store(vk::kUnpackedDepthIndex, dsAspectFlags, dsClearValue);
        }

        clearWithCommand(contextVk, scissoredRenderArea, ClearWithCommand::Always, &clears);

        if (!clearColorBuffers.any() && !clearStencilWithDraw)
        {
            ASSERT(!clearDepthWithDraw);
            return angle::Result::Continue;
        }
    }

    // The most costly clear mode is when we need to mask out specific color channels or stencil
    // bits. This can only be done with a draw call.
    return clearWithDraw(contextVk, scissoredRenderArea, clearColorBuffers, clearDepthWithDraw,
                         clearStencilWithDraw, colorMasks, stencilMask, adjustedClearColorValues,
                         clearDepthStencilValue);
}

angle::Result FramebufferVk::clearBufferfv(const gl::Context *context,
                                           GLenum buffer,
                                           GLint drawbuffer,
                                           const GLfloat *values)
{
    VkClearValue clearValue = {};

    bool clearDepth = false;
    gl::DrawBufferMask clearColorBuffers;

    if (buffer == GL_DEPTH)
    {
        clearDepth                    = true;
        clearValue.depthStencil.depth = values[0];
    }
    else
    {
        clearColorBuffers.set(drawbuffer);
        clearValue.color.float32[0] = values[0];
        clearValue.color.float32[1] = values[1];
        clearValue.color.float32[2] = values[2];
        clearValue.color.float32[3] = values[3];
    }

    return clearImpl(context, clearColorBuffers, clearDepth, false, clearValue.color,
                     clearValue.depthStencil);
}

angle::Result FramebufferVk::clearBufferuiv(const gl::Context *context,
                                            GLenum buffer,
                                            GLint drawbuffer,
                                            const GLuint *values)
{
    VkClearValue clearValue = {};

    gl::DrawBufferMask clearColorBuffers;
    clearColorBuffers.set(drawbuffer);

    clearValue.color.uint32[0] = values[0];
    clearValue.color.uint32[1] = values[1];
    clearValue.color.uint32[2] = values[2];
    clearValue.color.uint32[3] = values[3];

    return clearImpl(context, clearColorBuffers, false, false, clearValue.color,
                     clearValue.depthStencil);
}

angle::Result FramebufferVk::clearBufferiv(const gl::Context *context,
                                           GLenum buffer,
                                           GLint drawbuffer,
                                           const GLint *values)
{
    VkClearValue clearValue = {};

    bool clearStencil = false;
    gl::DrawBufferMask clearColorBuffers;

    if (buffer == GL_STENCIL)
    {
        clearStencil                    = true;
        clearValue.depthStencil.stencil = static_cast<uint8_t>(values[0]);
    }
    else
    {
        clearColorBuffers.set(drawbuffer);
        clearValue.color.int32[0] = values[0];
        clearValue.color.int32[1] = values[1];
        clearValue.color.int32[2] = values[2];
        clearValue.color.int32[3] = values[3];
    }

    return clearImpl(context, clearColorBuffers, false, clearStencil, clearValue.color,
                     clearValue.depthStencil);
}

angle::Result FramebufferVk::clearBufferfi(const gl::Context *context,
                                           GLenum buffer,
                                           GLint drawbuffer,
                                           GLfloat depth,
                                           GLint stencil)
{
    VkClearValue clearValue = {};

    clearValue.depthStencil.depth   = depth;
    clearValue.depthStencil.stencil = static_cast<uint8_t>(stencil);

    return clearImpl(context, gl::DrawBufferMask(), true, true, clearValue.color,
                     clearValue.depthStencil);
}

const gl::InternalFormat &FramebufferVk::getImplementationColorReadFormat(
    const gl::Context *context) const
{
    ContextVk *contextVk       = vk::GetImpl(context);
    GLenum sizedFormat         = mState.getReadAttachment()->getFormat().info->sizedInternalFormat;
    const vk::Format &vkFormat = contextVk->getRenderer()->getFormat(sizedFormat);
    GLenum implFormat = vkFormat.getActualRenderableImageFormat().fboImplementationInternalFormat;
    return gl::GetSizedInternalFormatInfo(implFormat);
}

angle::Result FramebufferVk::readPixels(const gl::Context *context,
                                        const gl::Rectangle &area,
                                        GLenum format,
                                        GLenum type,
                                        const gl::PixelPackState &pack,
                                        gl::Buffer *packBuffer,
                                        void *pixels)
{
    ASSERT(mDeferredClears.empty());

    // Clip read area to framebuffer.
    const gl::Extents &fbSize = getState().getReadPixelsAttachment(format)->getSize();
    const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height);
    ContextVk *contextVk = vk::GetImpl(context);

    gl::Rectangle clippedArea;
    if (!ClipRectangle(area, fbRect, &clippedArea))
    {
        // nothing to read
        return angle::Result::Continue;
    }

    GLuint outputSkipBytes = 0;
    PackPixelsParams params;
    ANGLE_TRY(vk::ImageHelper::GetReadPixelsParams(contextVk, pack, packBuffer, format, type, area,
                                                   clippedArea, &params, &outputSkipBytes));

    bool flipY = contextVk->isViewportFlipEnabledForReadFBO();
    switch (params.rotation = contextVk->getRotationReadFramebuffer())
    {
        case SurfaceRotation::Identity:
            // Do not rotate gl_Position (surface matches the device's orientation):
            if (flipY)
            {
                params.area.y = fbRect.height - clippedArea.y - clippedArea.height;
            }
            break;
        case SurfaceRotation::Rotated90Degrees:
            // Rotate gl_Position 90 degrees:
            params.area.x = clippedArea.y;
            params.area.y =
                flipY ? clippedArea.x : fbRect.width - clippedArea.x - clippedArea.width;
            std::swap(params.area.width, params.area.height);
            break;
        case SurfaceRotation::Rotated180Degrees:
            // Rotate gl_Position 180 degrees:
            params.area.x = fbRect.width - clippedArea.x - clippedArea.width;
            params.area.y =
                flipY ? clippedArea.y : fbRect.height - clippedArea.y - clippedArea.height;
            break;
        case SurfaceRotation::Rotated270Degrees:
            // Rotate gl_Position 270 degrees:
            params.area.x = fbRect.height - clippedArea.y - clippedArea.height;
            params.area.y =
                flipY ? fbRect.width - clippedArea.x - clippedArea.width : clippedArea.x;
            std::swap(params.area.width, params.area.height);
            break;
        default:
            UNREACHABLE();
            break;
    }
    if (flipY)
    {
        params.reverseRowOrder = !params.reverseRowOrder;
    }

    ANGLE_TRY(readPixelsImpl(contextVk, params.area, params, getReadPixelsAspectFlags(format),
                             getReadPixelsRenderTarget(format),
                             static_cast<uint8_t *>(pixels) + outputSkipBytes));
    return angle::Result::Continue;
}

RenderTargetVk *FramebufferVk::getColorDrawRenderTarget(size_t colorIndexGL) const
{
    RenderTargetVk *renderTarget = mRenderTargetCache.getColorDraw(mState, colorIndexGL);
    ASSERT(renderTarget && renderTarget->getImageForRenderPass().valid());
    return renderTarget;
}

RenderTargetVk *FramebufferVk::getColorReadRenderTarget() const
{
    RenderTargetVk *renderTarget = mRenderTargetCache.getColorRead(mState);
    ASSERT(renderTarget && renderTarget->getImageForRenderPass().valid());
    return renderTarget;
}

RenderTargetVk *FramebufferVk::getReadPixelsRenderTarget(GLenum format) const
{
    switch (format)
    {
        case GL_DEPTH_COMPONENT:
        case GL_STENCIL_INDEX_OES:
        case GL_DEPTH_STENCIL_OES:
            return getDepthStencilRenderTarget();
        default:
            return getColorReadRenderTarget();
    }
}

VkImageAspectFlagBits FramebufferVk::getReadPixelsAspectFlags(GLenum format) const
{
    switch (format)
    {
        case GL_DEPTH_COMPONENT:
            return VK_IMAGE_ASPECT_DEPTH_BIT;
        case GL_STENCIL_INDEX_OES:
            return VK_IMAGE_ASPECT_STENCIL_BIT;
        case GL_DEPTH_STENCIL_OES:
            return vk::IMAGE_ASPECT_DEPTH_STENCIL;
        default:
            return VK_IMAGE_ASPECT_COLOR_BIT;
    }
}

angle::Result FramebufferVk::blitWithCommand(ContextVk *contextVk,
                                             const gl::Rectangle &sourceArea,
                                             const gl::Rectangle &destArea,
                                             RenderTargetVk *readRenderTarget,
                                             RenderTargetVk *drawRenderTarget,
                                             GLenum filter,
                                             bool colorBlit,
                                             bool depthBlit,
                                             bool stencilBlit,
                                             bool flipX,
                                             bool flipY)
{
    vk::Renderer *renderer = contextVk->getRenderer();

    // Since blitRenderbufferRect is called for each render buffer that needs to be blitted,
    // it should never be the case that both color and depth/stencil need to be blitted at
    // at the same time.
    ASSERT(colorBlit != (depthBlit || stencilBlit));

    vk::ImageHelper *srcImage = &readRenderTarget->getImageForCopy();
    vk::ImageHelper *dstImage = &drawRenderTarget->getImageForWrite();

    VkImageAspectFlags imageAspectMask = srcImage->getAspectFlags();
    VkImageAspectFlags blitAspectMask  = imageAspectMask;

    // Remove depth or stencil aspects if they are not requested to be blitted.
    if (!depthBlit)
    {
        blitAspectMask &= ~VK_IMAGE_ASPECT_DEPTH_BIT;
    }
    if (!stencilBlit)
    {
        blitAspectMask &= ~VK_IMAGE_ASPECT_STENCIL_BIT;
    }

    vk::CommandResources resources;
    if (srcImage != dstImage)
    {
        resources.onImageTransferRead(imageAspectMask, srcImage);
        resources.onImageTransferWrite(drawRenderTarget->getLevelIndex(), 1,
                                       drawRenderTarget->getLayerIndex(), 1, imageAspectMask,
                                       dstImage);
    }
    else
    {
        resources.onImageSelfCopy(readRenderTarget->getLevelIndex(), 1,
                                  readRenderTarget->getLayerIndex(), 1,
                                  drawRenderTarget->getLevelIndex(), 1,
                                  drawRenderTarget->getLayerIndex(), 1, imageAspectMask, srcImage);
    }

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

    VkImageBlit blit               = {};
    blit.srcSubresource.aspectMask = blitAspectMask;
    blit.srcSubresource.mipLevel   = srcImage->toVkLevel(readRenderTarget->getLevelIndex()).get();
    blit.srcSubresource.baseArrayLayer = readRenderTarget->getLayerIndex();
    blit.srcSubresource.layerCount     = 1;
    blit.srcOffsets[0]                 = {sourceArea.x0(), sourceArea.y0(), 0};
    blit.srcOffsets[1]                 = {sourceArea.x1(), sourceArea.y1(), 1};
    blit.dstSubresource.aspectMask     = blitAspectMask;
    blit.dstSubresource.mipLevel = dstImage->toVkLevel(drawRenderTarget->getLevelIndex()).get();
    blit.dstSubresource.baseArrayLayer = drawRenderTarget->getLayerIndex();
    blit.dstSubresource.layerCount     = 1;
    blit.dstOffsets[0]                 = {destArea.x0(), destArea.y0(), 0};
    blit.dstOffsets[1]                 = {destArea.x1(), destArea.y1(), 1};

    // Note: vkCmdBlitImage doesn't actually work between 3D and 2D array images due to Vulkan valid
    // usage restrictions (https://gitlab.khronos.org/vulkan/vulkan/-/issues/3490), but drivers seem
    // to work as expected anyway.  ANGLE continues to use vkCmdBlitImage in that case.

    const bool isSrc3D = srcImage->getType() == VK_IMAGE_TYPE_3D;
    const bool isDst3D = dstImage->getType() == VK_IMAGE_TYPE_3D;
    if (isSrc3D)
    {
        AdjustLayersAndDepthFor3DImages(&blit.srcSubresource, &blit.srcOffsets[0],
                                        &blit.srcOffsets[1]);
    }
    if (isDst3D)
    {
        AdjustLayersAndDepthFor3DImages(&blit.dstSubresource, &blit.dstOffsets[0],
                                        &blit.dstOffsets[1]);
    }

    commandBuffer->blitImage(srcImage->getImage(), srcImage->getCurrentLayout(renderer),
                             dstImage->getImage(), dstImage->getCurrentLayout(renderer), 1, &blit,
                             gl_vk::GetFilter(filter));

    return angle::Result::Continue;
}

angle::Result FramebufferVk::blit(const gl::Context *context,
                                  const gl::Rectangle &sourceAreaIn,
                                  const gl::Rectangle &destAreaIn,
                                  GLbitfield mask,
                                  GLenum filter)
{
    ContextVk *contextVk   = vk::GetImpl(context);
    vk::Renderer *renderer = contextVk->getRenderer();
    UtilsVk &utilsVk       = contextVk->getUtils();

    // If any clears were picked up when syncing the read framebuffer (as the blit source), restage
    // them.  They correspond to attachments that are not used in the blit.  This will cause the
    // read framebuffer to become dirty, so the attachments will be synced again on the next command
    // that might be using them.
    const gl::State &glState              = contextVk->getState();
    const gl::Framebuffer *srcFramebuffer = glState.getReadFramebuffer();
    FramebufferVk *srcFramebufferVk       = vk::GetImpl(srcFramebuffer);
    if (srcFramebufferVk->mDeferredClears.any())
    {
        srcFramebufferVk->restageDeferredClearsForReadFramebuffer(contextVk);
    }

    const bool blitColorBuffer   = (mask & GL_COLOR_BUFFER_BIT) != 0;
    const bool blitDepthBuffer   = (mask & GL_DEPTH_BUFFER_BIT) != 0;
    const bool blitStencilBuffer = (mask & GL_STENCIL_BUFFER_BIT) != 0;

    if (blitDepthBuffer || blitStencilBuffer)
    {
        RenderTargetVk *readRenderTarget = srcFramebufferVk->getDepthStencilRenderTarget();
        RenderTargetVk *drawRenderTarget = mRenderTargetCache.getDepthStencil();
        vk::ImageHelper &readImage       = readRenderTarget->getImageForCopy();
        vk::ImageHelper &drawImage       = drawRenderTarget->getImageForWrite();

        if (!readImage.canTransferFrom())
        {
            ASSERT(readImage.useTileMemory());
            ANGLE_TRY(readImage.fallbackFromTileMemory(contextVk));
        }

        if (!drawImage.canTransferTo())
        {
            ASSERT(drawImage.useTileMemory());
            ANGLE_TRY(drawImage.fallbackFromTileMemory(contextVk));
        }
    }

    // We can sometimes end up in a blit with some clear commands saved. Ensure all clear commands
    // are issued before we issue the blit command.
    ANGLE_TRY(flushDeferredClears(contextVk));

    // If a framebuffer contains a mixture of multisampled and multisampled-render-to-texture
    // attachments, this function could be simultaneously doing a blit on one attachment and resolve
    // on another.  For the most part, this means resolve semantics apply.  However, as the resolve
    // path cannot be taken for multisampled-render-to-texture attachments, the distinction of
    // whether resolve is done for each attachment or blit is made.
    const bool isColorResolve =
        blitColorBuffer &&
        srcFramebufferVk->getColorReadRenderTarget()->getImageForCopy().getSamples() > 1;
    const bool isDepthStencilResolve =
        (blitDepthBuffer || blitStencilBuffer) &&
        srcFramebufferVk->getDepthStencilRenderTarget()->getImageForCopy().getSamples() > 1;
    const bool isResolve = isColorResolve || isDepthStencilResolve;

    bool srcFramebufferFlippedY = contextVk->isViewportFlipEnabledForReadFBO();
    bool dstFramebufferFlippedY = contextVk->isViewportFlipEnabledForDrawFBO();

    gl::Rectangle sourceArea = sourceAreaIn;
    gl::Rectangle destArea   = destAreaIn;

    // Note: GLES (all 3.x versions) require source and destination area to be identical when
    // resolving.
    ASSERT(!isResolve ||
           (sourceArea.x == destArea.x && sourceArea.y == destArea.y &&
            sourceArea.width == destArea.width && sourceArea.height == destArea.height));

    gl::Rectangle srcFramebufferDimensions = srcFramebufferVk->getNonRotatedCompleteRenderArea();
    gl::Rectangle dstFramebufferDimensions = getNonRotatedCompleteRenderArea();

    // If the destination is flipped in either direction, we will flip the source instead so that
    // the destination area is always unflipped.
    sourceArea = sourceArea.flip(destArea.isReversedX(), destArea.isReversedY());
    destArea   = destArea.removeReversal();

    // Calculate the stretch factor prior to any clipping, as it needs to remain constant.
    const double stretch[2] = {
        std::abs(sourceArea.width / static_cast<double>(destArea.width)),
        std::abs(sourceArea.height / static_cast<double>(destArea.height)),
    };

    // Potentially make adjustments for pre-rotatation.  To handle various cases (e.g. clipping)
    // and to not interrupt the normal flow of the code, different adjustments are made in
    // different parts of the code.  These first adjustments are for whether or not to flip the
    // y-axis, and to note the overall rotation (regardless of whether it is the source or
    // destination that is rotated).
    SurfaceRotation srcFramebufferRotation = contextVk->getRotationReadFramebuffer();
    SurfaceRotation dstFramebufferRotation = contextVk->getRotationDrawFramebuffer();
    SurfaceRotation rotation               = SurfaceRotation::Identity;
    // Both the source and destination cannot be rotated (which would indicate both are the default
    // framebuffer (i.e. swapchain image).
    ASSERT((srcFramebufferRotation == SurfaceRotation::Identity) ||
           (dstFramebufferRotation == SurfaceRotation::Identity));
    EarlyAdjustFlipYForPreRotation(srcFramebufferRotation, &rotation, &srcFramebufferFlippedY);
    EarlyAdjustFlipYForPreRotation(dstFramebufferRotation, &rotation, &dstFramebufferFlippedY);

    // First, clip the source area to framebuffer.  That requires transforming the destination area
    // to match the clipped source.
    gl::Rectangle absSourceArea = sourceArea.removeReversal();
    gl::Rectangle clippedSourceArea;
    if (!gl::ClipRectangle(srcFramebufferDimensions, absSourceArea, &clippedSourceArea))
    {
        return angle::Result::Continue;
    }

    // Resize the destination area based on the new size of source.  Note again that stretch is
    // calculated as SrcDimension/DestDimension.
    gl::Rectangle srcClippedDestArea;
    if (isResolve)
    {
        // Source and destination areas are identical in resolve (except rotate it, if appropriate).
        srcClippedDestArea = clippedSourceArea;
        AdjustBlitAreaForPreRotation(dstFramebufferRotation, clippedSourceArea,
                                     dstFramebufferDimensions, &srcClippedDestArea);
    }
    else if (clippedSourceArea == absSourceArea)
    {
        // If there was no clipping, keep destination area as is (except rotate it, if appropriate).
        srcClippedDestArea = destArea;
        AdjustBlitAreaForPreRotation(dstFramebufferRotation, destArea, dstFramebufferDimensions,
                                     &srcClippedDestArea);
    }
    else
    {
        // Shift destination area's x0,y0,x1,y1 by as much as the source area's got shifted (taking
        // stretching into account).  Note that double is used as float doesn't have enough
        // precision near the end of int range.
        double x0Shift = std::round((clippedSourceArea.x - absSourceArea.x) / stretch[0]);
        double y0Shift = std::round((clippedSourceArea.y - absSourceArea.y) / stretch[1]);
        double x1Shift = std::round((absSourceArea.x1() - clippedSourceArea.x1()) / stretch[0]);
        double y1Shift = std::round((absSourceArea.y1() - clippedSourceArea.y1()) / stretch[1]);

        // If the source area was reversed in any direction, the shift should be applied in the
        // opposite direction as well.
        if (sourceArea.isReversedX())
        {
            std::swap(x0Shift, x1Shift);
        }

        if (sourceArea.isReversedY())
        {
            std::swap(y0Shift, y1Shift);
        }

        srcClippedDestArea.x = destArea.x0() + static_cast<int>(x0Shift);
        srcClippedDestArea.y = destArea.y0() + static_cast<int>(y0Shift);
        int x1               = destArea.x1() - static_cast<int>(x1Shift);
        int y1               = destArea.y1() - static_cast<int>(y1Shift);

        srcClippedDestArea.width  = x1 - srcClippedDestArea.x;
        srcClippedDestArea.height = y1 - srcClippedDestArea.y;

        // Rotate srcClippedDestArea if the destination is rotated
        if (dstFramebufferRotation != SurfaceRotation::Identity)
        {
            gl::Rectangle originalSrcClippedDestArea = srcClippedDestArea;
            AdjustBlitAreaForPreRotation(dstFramebufferRotation, originalSrcClippedDestArea,
                                         dstFramebufferDimensions, &srcClippedDestArea);
        }
    }

    if (dstFramebufferFlippedY)
    {
        destArea.y      = dstFramebufferDimensions.height - destArea.y;
        destArea.height = -destArea.height;

        srcClippedDestArea.y =
            dstFramebufferDimensions.height - srcClippedDestArea.y - srcClippedDestArea.height;
    }

    // Clip the destination area to the framebuffer size and scissor.  Note that we don't care
    // about the source area anymore.  The offset translation is done based on the original
    // source and destination rectangles.  The stretch factor is already calculated as well.
    gl::Rectangle blitArea;
    if (!gl::ClipRectangle(getRotatedScissoredRenderArea(contextVk), srcClippedDestArea, &blitArea))
    {
        return angle::Result::Continue;
    }

    // In case that color attachment has different size from depth attachment, need to calculate
    // blit parameters for each.
    bool isDefault                      = srcFramebuffer->isDefault();
    bool flipX                          = false;
    bool flipY                          = false;
    bool noClip                         = false;

    UtilsVk::BlitResolveParameters params;
    params.stretch[0] = static_cast<float>(stretch[0]);
    params.stretch[1] = static_cast<float>(stretch[1]);
    params.renderArea = getRotatedCompleteRenderArea(contextVk);
    params.blitArea   = blitArea;
    params.linear     = filter == GL_LINEAR && !isResolve;
    params.rotation   = rotation;

    if (blitColorBuffer)
    {
        RenderTargetVk *readRenderTarget = srcFramebufferVk->getColorReadRenderTarget();

        gl::Rectangle sourceColorArea               = sourceArea;
        gl::Rectangle destColorArea                 = destArea;
        SurfaceRotation dstColorFramebufferRotation = dstFramebufferRotation;
        AdjustBlitAreas(readRenderTarget, &sourceColorArea, &destColorArea,
                        &srcFramebufferDimensions, dstFramebufferDimensions, srcFramebufferRotation,
                        &dstColorFramebufferRotation, rotation, srcFramebufferFlippedY,
                        dstFramebufferFlippedY, isResolve, &flipX, &flipY, isDefault, &params);

        noClip = blitArea == destColorArea && stretch[0] == 1.0f && stretch[1] == 1.0f;

        // Multisampled images are not allowed to have mips.
        ASSERT(!isColorResolve || readRenderTarget->getLevelIndex() == gl::LevelIndex(0));

        // If there was no clipping and the format capabilities allow us, use Vulkan's builtin blit.
        // The reason clipping is prohibited in this path is that due to rounding errors, it would
        // be hard to guarantee the image stretching remains perfect.  That also allows us not to
        // have to transform back the destination clipping to source.
        //
        // Non-identity pre-rotation cases do not use Vulkan's builtin blit.  Additionally, blits
        // between 3D and non-3D-non-layer-0 images are forbidden (possibly due to an oversight:
        // https://gitlab.khronos.org/vulkan/vulkan/-/issues/3490)
        //
        // For simplicity, we either blit all render targets with a Vulkan command, or none.
        bool canBlitWithCommand = !isColorResolve && noClip &&
                                  HasSrcBlitFeature(renderer, readRenderTarget) &&
                                  rotation == SurfaceRotation::Identity;

        // If we need to reinterpret the colorspace of the read RenderTarget or the draw
        // RenderTarget then the blit must be done through a shader
        bool reinterpretsColorspace =
            readRenderTarget->hasColorspaceOverrideForRead() ||
            (mAttachmentWithColorSpaceOverrideMask & mState.getEnabledDrawBuffers()).any();
        bool areChannelsBlitCompatible   = true;
        bool areFormatsIdentical         = true;
        bool colorAttachmentAlreadyInUse = false;
        for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
        {
            RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[colorIndexGL];
            canBlitWithCommand =
                canBlitWithCommand && HasDstBlitFeature(renderer, drawRenderTarget);
            areChannelsBlitCompatible =
                areChannelsBlitCompatible &&
                AreSrcAndDstColorChannelsBlitCompatible(readRenderTarget, drawRenderTarget);
            areFormatsIdentical = areFormatsIdentical &&
                                  AreSrcAndDstFormatsIdentical(readRenderTarget, drawRenderTarget);

            // If any color attachment of the draw framebuffer was already in use in the currently
            // started renderpass, don't reuse the renderpass for blit.
            colorAttachmentAlreadyInUse =
                colorAttachmentAlreadyInUse || contextVk->isRenderPassStartedAndUsesImage(
                                                   drawRenderTarget->getImageForRenderPass());
        }

        // Now that all flipping is done, adjust the offsets for resolve and prerotation
        if (isColorResolve)
        {
            AdjustBlitResolveParametersForResolve(sourceColorArea, destColorArea, &params);
        }
        AdjustBlitResolveParametersForPreRotation(rotation, srcFramebufferRotation, &params);

        if (canBlitWithCommand && areChannelsBlitCompatible && !reinterpretsColorspace)
        {
            for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
            {
                RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[colorIndexGL];
                ANGLE_TRY(blitWithCommand(contextVk, sourceColorArea, destColorArea,
                                          readRenderTarget, drawRenderTarget, filter, true, false,
                                          false, flipX, flipY));
            }
        }
        // If we're not flipping or rotating, use Vulkan's builtin resolve.
        else if (isColorResolve && !flipX && !flipY && areChannelsBlitCompatible &&
                 areFormatsIdentical && rotation == SurfaceRotation::Identity &&
                 !reinterpretsColorspace)
        {
            // Resolving with a subpass resolve attachment has a few restrictions:
            // 1.) glBlitFramebuffer() needs to copy the read color attachment to all enabled
            // attachments in the draw framebuffer, but Vulkan requires a 1:1 relationship for
            // multisample attachments to resolve attachments in the render pass subpass.
            // Due to this, we currently only support using resolve attachments when there is a
            // single draw attachment enabled.
            // 2.) Using a subpass resolve attachment relies on using the render pass that performs
            // the draw to still be open, so it can be updated to use the resolve attachment to draw
            // into. If there's no render pass with commands, then the multisampled render pass is
            // already done and whose data is already flushed from the tile (in a tile-based
            // renderer), so there's no chance for the resolve attachment to take advantage of the
            // data already being present in the tile.

            // Additionally, when resolving with a resolve attachment, the src and destination
            // offsets must match, the render area must match the resolve area, and there should be
            // no flipping or rotation.  Fortunately, in GLES the blit source and destination areas
            // are already required to be identical.
            ASSERT(params.srcOffset[0] == params.dstOffset[0] &&
                   params.srcOffset[1] == params.dstOffset[1]);
            bool canResolveWithSubpass = mState.getEnabledDrawBuffers().count() == 1 &&
                                         mCurrentFramebufferDesc.getLayerCount() == 1 &&
                                         contextVk->hasStartedRenderPassWithQueueSerial(
                                             srcFramebufferVk->getLastRenderPassQueueSerial()) &&
                                         !colorAttachmentAlreadyInUse;

            if (canResolveWithSubpass)
            {
                const vk::RenderPassCommandBufferHelper &renderPassCommands =
                    contextVk->getStartedRenderPassCommands();
                const vk::RenderPassDesc &renderPassDesc = renderPassCommands.getRenderPassDesc();

                // Make sure that:
                // - The blit and render areas are identical
                // - There is no resolve attachment for the corresponding index already
                // Additionally, disable the optimization for a few corner cases that are
                // unrealistic and inconvenient.
                const uint32_t readColorIndexGL = srcFramebuffer->getState().getReadIndex();
                canResolveWithSubpass =
                    blitArea == renderPassCommands.getRenderArea() &&
                    !renderPassDesc.hasColorResolveAttachment(readColorIndexGL) &&
                    AllowAddingResolveAttachmentsToSubpass(renderPassDesc);
            }

            // Additionally, if not using dynamic rendering, the framebuffer attachments must
            // all be at least as large as the framebuffer extent.  So the resolve attachment
            // cannot be smaller even if it matches the (scissored) render area.
            if (canResolveWithSubpass && !contextVk->getFeatures().preferDynamicRendering.enabled)
            {
                uint32_t drawColorIndexGL =
                    static_cast<uint32_t>(*mState.getEnabledDrawBuffers().begin());
                RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[drawColorIndexGL];
                const gl::Extents drawExtents    = drawRenderTarget->getExtents();
                const gl::Extents readExtents    = readRenderTarget->getExtents();
                canResolveWithSubpass            = drawExtents.width >= readExtents.width &&
                                        drawExtents.height >= readExtents.height;
            }

            if (canResolveWithSubpass)
            {
                ANGLE_TRY(resolveColorWithSubpass(contextVk, params));
            }
            else
            {
                ANGLE_TRY(resolveColorWithCommand(contextVk, params,
                                                  &readRenderTarget->getImageForCopy()));
            }
        }
        else
        {
            // Otherwise use a shader to do blit or resolve.

            // 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::PrepareForBlit));

            const vk::ImageView *copyImageView = nullptr;
            ANGLE_TRY(readRenderTarget->getCopyImageView(contextVk, &copyImageView));
            ANGLE_TRY(utilsVk.colorBlitResolve(
                contextVk, this, &readRenderTarget->getImageForCopy(), copyImageView, params));
        }
    }

    if (blitDepthBuffer || blitStencilBuffer)
    {
        RenderTargetVk *readRenderTarget      = srcFramebufferVk->getDepthStencilRenderTarget();
        RenderTargetVk *drawRenderTarget      = mRenderTargetCache.getDepthStencil();

        // glBlitFramebuffer requires that depth/stencil blits have matching formats.
        ASSERT(AreSrcAndDstFormatsIdentical(readRenderTarget, drawRenderTarget));
        // Multisampled images are not allowed to have mips.
        ASSERT(!isDepthStencilResolve || readRenderTarget->getLevelIndex() == gl::LevelIndex(0));

        vk::ImageHelper *srcImage = &readRenderTarget->getImageForCopy();
        vk::ImageHelper *dstImage = &drawRenderTarget->getImageForWrite();

        AdjustBlitAreas(readRenderTarget, &sourceArea, &destArea, &srcFramebufferDimensions,
                        dstFramebufferDimensions, srcFramebufferRotation, &dstFramebufferRotation,
                        rotation, srcFramebufferFlippedY, dstFramebufferFlippedY, isResolve, &flipX,
                        &flipY, isDefault, &params);

        noClip = blitArea == destArea && stretch[0] == 1.0f && stretch[1] == 1.0f;
        const bool noFlip = !flipX && !flipY;

        const vk::ImageView *dstDepthStencilView = nullptr;
        ANGLE_TRY(drawRenderTarget->getImageView(contextVk, &dstDepthStencilView));

        gl::LevelIndex dstLevelIndex = drawRenderTarget->getLevelIndex();
        uint32_t dstLayerIndex       = drawRenderTarget->getLayerIndex();

        // Get depth- and stencil-only views for reading.
        const vk::ImageView *srcDepthView = nullptr;
        if (blitDepthBuffer)
        {
            ANGLE_TRY(readRenderTarget->getDepthOrStencilImageViewForCopy(
                contextVk, VK_IMAGE_ASPECT_DEPTH_BIT, &srcDepthView));
        }

        const vk::ImageView *srcStencilView = nullptr;
        if (blitStencilBuffer)
        {
            ANGLE_TRY(readRenderTarget->getDepthOrStencilImageViewForCopy(
                contextVk, VK_IMAGE_ASPECT_STENCIL_BIT, &srcStencilView));
        }

        // If shader stencil export is not possible, defer stencil blit/resolve to another pass.
        const bool hasShaderStencilExport =
            renderer->getFeatures().supportsShaderStencilExport.enabled;

        // When possible try to use mid render pass blit to avoid breaking current renderPass.
        bool canBlitWithMidRenderPassDraw =
            !isDepthStencilResolve && dstImage != srcImage &&
            contextVk->hasStartedRenderPassWithQueueSerial(mLastRenderPassQueueSerial) &&
            (!blitStencilBuffer || hasShaderStencilExport) &&
            !contextVk->getState().isTransformFeedbackActiveUnpaused() &&
            !contextVk->hasActiveRenderPassQuery();
        if (canBlitWithMidRenderPassDraw)
        {
            // All deferred clear must have been flushed, otherwise it will conflict with
            // params.blitArea.
            ASSERT(!hasDeferredClears());
            // If we have to use standalone renderPass for stencil, then no need for depth to use
            // midRenderPass.
            ASSERT(!blitStencilBuffer || hasShaderStencilExport);
            ASSERT(blitDepthBuffer || (blitStencilBuffer && hasShaderStencilExport));
            ASSERT(!isDepthStencilResolve);

            AdjustBlitResolveParametersForPreRotation(rotation, srcFramebufferRotation, &params);

            ANGLE_TRY(utilsVk.depthStencilBlitResolve(
                contextVk, &contextVk->getStartedRenderPassCommands(), dstImage,
                *dstDepthStencilView, dstLevelIndex, dstLayerIndex, srcImage, srcDepthView,
                srcStencilView, params));

            return angle::Result::Continue;
        }

        bool areChannelsBlitCompatible =
            AreSrcAndDstDepthStencilChannelsBlitCompatible(readRenderTarget, drawRenderTarget);

        // Similarly, only blit if there's been no clipping or rotating.
        bool canBlitWithCommand = areChannelsBlitCompatible && !isDepthStencilResolve && noClip &&
                                  HasSrcBlitFeature(renderer, readRenderTarget) &&
                                  HasDstBlitFeature(renderer, drawRenderTarget) &&
                                  rotation == SurfaceRotation::Identity;
        if (canBlitWithCommand)
        {
            return blitWithCommand(contextVk, sourceArea, destArea, readRenderTarget,
                                   drawRenderTarget, filter, false, blitDepthBuffer,
                                   blitStencilBuffer, flipX, flipY);
        }

        VkImageAspectFlags resolveAspects = 0;
        if (blitDepthBuffer)
        {
            resolveAspects |= VK_IMAGE_ASPECT_DEPTH_BIT;
        }
        if (blitStencilBuffer)
        {
            resolveAspects |= VK_IMAGE_ASPECT_STENCIL_BIT;
        }

        // See comment on canResolveWithSubpass for the color path.
        bool canResolveWithSubpass =
            isDepthStencilResolve &&
            !renderer->getFeatures().disableDepthStencilResolveThroughAttachment.enabled &&
            areChannelsBlitCompatible && mCurrentFramebufferDesc.getLayerCount() == 1 &&
            contextVk->hasStartedRenderPassWithQueueSerial(
                srcFramebufferVk->getLastRenderPassQueueSerial()) &&
            !contextVk->isRenderPassStartedAndUsesImage(
                drawRenderTarget->getImageForRenderPass()) &&
            noFlip && rotation == SurfaceRotation::Identity;
        if (canResolveWithSubpass)
        {
            const vk::RenderPassCommandBufferHelper &renderPassCommands =
                contextVk->getStartedRenderPassCommands();
            const vk::RenderPassDesc &renderPassDesc = renderPassCommands.getRenderPassDesc();

            const VkImageAspectFlags srcImageAspects = srcImage->getAspectFlags();
            const bool resolvesAllAspects = (resolveAspects & srcImageAspects) == srcImageAspects;

            // Make sure that:
            // - The blit and render areas are identical
            // - There is no resolve attachment already
            // Additionally, disable the optimization for a few corner cases that are
            // unrealistic and inconvenient.
            //
            // Note: currently, if two separate `glBlitFramebuffer` calls are made for each
            // aspect, only the first one is optimized as a resolve attachment.  Applications
            // should use one `glBlitFramebuffer` call with both aspects if they want to resolve
            // both.
            canResolveWithSubpass =
                blitArea == renderPassCommands.getRenderArea() &&
                (resolvesAllAspects ||
                 renderer->getFeatures().supportsDepthStencilIndependentResolveNone.enabled) &&
                !renderPassDesc.hasDepthStencilResolveAttachment() &&
                AllowAddingResolveAttachmentsToSubpass(renderPassDesc);
        }
        if (canResolveWithSubpass)
        {
            return resolveDepthStencilWithSubpass(contextVk, params, resolveAspects);
        }

        // Now that all flipping is done, adjust the offsets for resolve and prerotation
        if (isDepthStencilResolve)
        {
            AdjustBlitResolveParametersForResolve(sourceArea, destArea, &params);
        }
        AdjustBlitResolveParametersForPreRotation(rotation, srcFramebufferRotation, &params);

        // Blit depth. If shader stencil export is present, blit stencil as well.
        if (blitDepthBuffer || (blitStencilBuffer && hasShaderStencilExport))
        {
            // All deferred clear must have been flushed, otherwise it will conflict with
            // params.blitArea.
            ASSERT(!hasDeferredClears());

            ANGLE_TRY(utilsVk.depthStencilBlitResolve(
                contextVk, nullptr, dstImage, *dstDepthStencilView, dstLevelIndex, dstLayerIndex,
                srcImage, srcDepthView, hasShaderStencilExport ? srcStencilView : nullptr, params));
        }

        // If shader stencil export is not present, blit stencil through a different path.
        if (blitStencilBuffer && !hasShaderStencilExport)
        {
            ANGLE_VK_PERF_WARNING(contextVk, GL_DEBUG_SEVERITY_LOW,
                                  "Inefficient BlitFramebuffer operation on the stencil aspect "
                                  "due to lack of shader stencil export support");
            ANGLE_TRY(utilsVk.stencilBlitResolveNoShaderExport(contextVk, dstImage, dstLevelIndex,
                                                               dstLayerIndex, srcImage,
                                                               srcStencilView, params));
        }
    }

    return angle::Result::Continue;
}

void FramebufferVk::releaseCurrentFramebuffer(ContextVk *contextVk)
{
    if (mIsCurrentFramebufferCached)
    {
        mCurrentFramebuffer.release();
    }
    else
    {
        contextVk->addGarbage(&mCurrentFramebuffer);
    }
}

void FramebufferVk::updateLayerCount()
{
    uint32_t layerCount = std::numeric_limits<uint32_t>::max();

    // Color attachments.
    const auto &colorRenderTargets = mRenderTargetCache.getColors();
    for (size_t colorIndexGL : mState.getColorAttachmentsMask())
    {
        RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
        ASSERT(colorRenderTarget);
        layerCount = std::min(layerCount, colorRenderTarget->getLayerCount());
    }

    // Depth/stencil attachment.
    RenderTargetVk *depthStencilRenderTarget = getDepthStencilRenderTarget();
    if (depthStencilRenderTarget)
    {
        layerCount = std::min(layerCount, depthStencilRenderTarget->getLayerCount());
    }

    if (layerCount == std::numeric_limits<uint32_t>::max())
    {
        layerCount = mState.getDefaultLayers();
    }

    // While layer count and view count are mutually exclusive, they result in different render
    // passes (and thus framebuffers).  For multiview, layer count is set to view count and a flag
    // signifies that the framebuffer is multiview (as opposed to layered).
    const bool isMultiview = mState.isMultiview();
    if (isMultiview)
    {
        layerCount = mState.getNumViews();
    }

    mCurrentFramebufferDesc.updateLayerCount(layerCount);
    mCurrentFramebufferDesc.updateIsMultiview(isMultiview);
}

angle::Result FramebufferVk::ensureFragmentShadingRateImageAndViewInitialized(
    ContextVk *contextVk,
    const uint32_t fragmentShadingRateAttachmentWidth,
    const uint32_t fragmentShadingRateAttachmentHeight)
{
    vk::Renderer *renderer = contextVk->getRenderer();

    // Release current valid image iff attachment extents need to change.
    if (mFragmentShadingRateImage.valid() &&
        (mFragmentShadingRateImage.getExtents().width != fragmentShadingRateAttachmentWidth ||
         mFragmentShadingRateImage.getExtents().height != fragmentShadingRateAttachmentHeight))
    {
        mFragmentShadingRateImageView.release(renderer, mFragmentShadingRateImage.getResourceUse());
        mFragmentShadingRateImage.releaseImage(renderer);
    }

    if (!mFragmentShadingRateImage.valid())
    {
        VkImageUsageFlags imageUsageFlags =
            VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR |
            VK_IMAGE_USAGE_TRANSFER_DST_BIT;
        // Add storage usage iff we intend to generate data using compute shader
        if (!contextVk->getFeatures().generateFragmentShadingRateAttchementWithCpu.enabled)
        {
            imageUsageFlags |= VK_IMAGE_USAGE_STORAGE_BIT;
        }

        ANGLE_TRY(mFragmentShadingRateImage.init(
            contextVk, gl::TextureType::_2D,
            VkExtent3D{fragmentShadingRateAttachmentWidth, fragmentShadingRateAttachmentHeight, 1},
            renderer->getFormat(angle::FormatID::R8_UINT), 1, imageUsageFlags, gl::LevelIndex(0), 1,
            1, false, contextVk->getProtectionType() == vk::ProtectionType::Protected,
            vk::TileMemory::Prohibited));

        ANGLE_TRY(contextVk->initImageAllocation(&mFragmentShadingRateImage, false,
                                                 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
                                                 vk::MemoryAllocationType::TextureImage));

        mFragmentShadingRateImageView.init(renderer);
        ANGLE_TRY(mFragmentShadingRateImageView.initFragmentShadingRateView(
            contextVk, &mFragmentShadingRateImage));
    }

    return angle::Result::Continue;
}

angle::Result FramebufferVk::generateFragmentShadingRateWithCPU(
    ContextVk *contextVk,
    const uint32_t fragmentShadingRateWidth,
    const uint32_t fragmentShadingRateHeight,
    const uint32_t fragmentShadingRateBlockWidth,
    const uint32_t fragmentShadingRateBlockHeight,
    const uint32_t foveatedAttachmentWidth,
    const uint32_t foveatedAttachmentHeight,
    const std::vector<gl::FocalPoint> &activeFocalPoints)
{
    vk::Renderer *renderer = contextVk->getRenderer();

    // Fill in image with fragment shading rate data
    const size_t bufferSize = fragmentShadingRateWidth * fragmentShadingRateHeight;

    VkBufferCreateInfo bufferCreateInfo = {};
    bufferCreateInfo.sType              = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
    bufferCreateInfo.size               = bufferSize;
    bufferCreateInfo.usage              = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
    bufferCreateInfo.sharingMode        = VK_SHARING_MODE_EXCLUSIVE;

    vk::RendererScoped<vk::BufferHelper> stagingBuffer(contextVk->getRenderer());
    vk::BufferHelper *buffer = &stagingBuffer.get();
    ANGLE_TRY(buffer->init(contextVk, bufferCreateInfo, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));

    uint8_t *mappedBuffer;
    ANGLE_TRY(buffer->map(contextVk, &mappedBuffer));
    uint8_t val = 0;
    memset(mappedBuffer, 0, bufferSize);

    // The spec requires min_pixel_density to be computed thusly -
    //
    // min_pixel_density=0.;
    // for(int i=0;i<focalPointsPerLayer;++i)
    // {
    //     focal_point_density = 1./max((focalX[i]-px)^2*gainX[i]^2+
    //                         (focalY[i]-py)^2*gainY[i]^2-foveaArea[i],1.);
    //
    //     min_pixel_density=max(min_pixel_density,focal_point_density);
    // }
    float minPixelDensity   = 0.0f;
    float focalPointDensity = 0.0f;
    for (uint32_t y = 0; y < fragmentShadingRateHeight; y++)
    {
        for (uint32_t x = 0; x < fragmentShadingRateWidth; x++)
        {
            minPixelDensity = 0.0f;
            float px =
                (static_cast<float>(x) * fragmentShadingRateBlockWidth / foveatedAttachmentWidth -
                 0.5f) *
                2.0f;
            float py =
                (static_cast<float>(y) * fragmentShadingRateBlockHeight / foveatedAttachmentHeight -
                 0.5f) *
                2.0f;
            focalPointDensity = 0.0f;
            for (const gl::FocalPoint &focalPoint : activeFocalPoints)
            {
                float density = 1.0f / std::max(std::pow(focalPoint.focalX - px, 2.0f) *
                                                        std::pow(focalPoint.gainX, 2.0f) +
                                                    std::pow(focalPoint.focalY - py, 2.0f) *
                                                        std::pow(focalPoint.gainY, 2.0f) -
                                                    focalPoint.foveaArea,
                                                1.0f);

                // When focal points are overlapping choose the highest quality of all
                if (density > focalPointDensity)
                {
                    focalPointDensity = density;
                }
            }
            minPixelDensity = std::max(minPixelDensity, focalPointDensity);

            // https://docs.vulkan.org/spec/latest/chapters/primsrast.html#primsrast-fragment-shading-rate-attachment
            //
            // w = 2^((texel/4) & 3)
            // h = 2^(texel & 3)
            // `texel` would then be => log2(w) << 2 | log2(h).
            //
            // 1) The supported shading rates are - 1x1, 1x2, 2x1, 2x2
            // 2) log2(1) == 0, log2(2) == 1
            if (minPixelDensity > 0.75f)
            {
                // Use shading rate 1x1
                val = 0;
            }
            else if (minPixelDensity > 0.5f)
            {
                // Use shading rate 2x1
                val = (1 << 2);
            }
            else
            {
                // Use shading rate 2x2
                val = (1 << 2) | 1;
            }
            mappedBuffer[y * fragmentShadingRateWidth + x] = val;
        }
    }

    ANGLE_TRY(buffer->flush(contextVk->getRenderer(), 0, buffer->getSize()));
    buffer->unmap(contextVk->getRenderer());
    // copy data from staging buffer to image
    vk::CommandResources resources;
    resources.onBufferTransferRead(buffer);
    resources.onImageTransferWrite(gl::LevelIndex(0), 1, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT,
                                   &mFragmentShadingRateImage);
    vk::OutsideRenderPassCommandBuffer *dataUpload;
    ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &dataUpload));
    VkBufferImageCopy copy           = {};
    copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    copy.imageSubresource.layerCount = 1;
    copy.imageExtent.depth           = 1;
    copy.imageExtent.width           = fragmentShadingRateWidth;
    copy.imageExtent.height          = fragmentShadingRateHeight;
    dataUpload->copyBufferToImage(buffer->getBuffer().getHandle(),
                                  mFragmentShadingRateImage.getImage(),
                                  mFragmentShadingRateImage.getCurrentLayout(renderer), 1, &copy);

    return angle::Result::Continue;
}

angle::Result FramebufferVk::generateFragmentShadingRateWithCompute(
    ContextVk *contextVk,
    const uint32_t fragmentShadingRateWidth,
    const uint32_t fragmentShadingRateHeight,
    const uint32_t fragmentShadingRateBlockWidth,
    const uint32_t fragmentShadingRateBlockHeight,
    const uint32_t foveatedAttachmentWidth,
    const uint32_t foveatedAttachmentHeight,
    const std::vector<gl::FocalPoint> &activeFocalPoints)
{
    ASSERT(activeFocalPoints.size() < gl::IMPLEMENTATION_MAX_FOCAL_POINTS);

    UtilsVk::GenerateFragmentShadingRateParameters shadingRateParams;
    shadingRateParams.textureWidth          = foveatedAttachmentWidth;
    shadingRateParams.textureHeight         = foveatedAttachmentHeight;
    shadingRateParams.attachmentBlockWidth  = fragmentShadingRateBlockWidth;
    shadingRateParams.attachmentBlockHeight = fragmentShadingRateBlockHeight;
    shadingRateParams.attachmentWidth       = fragmentShadingRateWidth;
    shadingRateParams.attachmentHeight      = fragmentShadingRateHeight;
    shadingRateParams.numFocalPoints        = 0;

    for (const gl::FocalPoint &focalPoint : activeFocalPoints)
    {
        ASSERT(focalPoint.valid());
        shadingRateParams.focalPoints[shadingRateParams.numFocalPoints] = focalPoint;
        shadingRateParams.numFocalPoints++;
    }

    return contextVk->getUtils().generateFragmentShadingRate(
        contextVk, &mFragmentShadingRateImage, &mFragmentShadingRateImageView, shadingRateParams);
}

angle::Result FramebufferVk::updateFragmentShadingRateAttachment(
    ContextVk *contextVk,
    const gl::FoveationState &foveationState,
    const gl::Extents &foveatedAttachmentSize)
{
    const VkExtent2D fragmentShadingRateExtent =
        contextVk->getRenderer()->getMaxFragmentShadingRateAttachmentTexelSize();
    const uint32_t fragmentShadingRateBlockWidth  = fragmentShadingRateExtent.width;
    const uint32_t fragmentShadingRateBlockHeight = fragmentShadingRateExtent.height;
    const uint32_t foveatedAttachmentWidth        = foveatedAttachmentSize.width;
    const uint32_t foveatedAttachmentHeight       = foveatedAttachmentSize.height;
    const uint32_t fragmentShadingRateWidth =
        UnsignedCeilDivide(foveatedAttachmentWidth, fragmentShadingRateBlockWidth);
    const uint32_t fragmentShadingRateHeight =
        UnsignedCeilDivide(foveatedAttachmentHeight, fragmentShadingRateBlockHeight);

    ANGLE_TRY(ensureFragmentShadingRateImageAndViewInitialized(contextVk, fragmentShadingRateWidth,
                                                               fragmentShadingRateHeight));
    ASSERT(mFragmentShadingRateImage.valid());

    std::vector<gl::FocalPoint> activeFocalPoints;
    for (uint32_t point = 0; point < gl::IMPLEMENTATION_MAX_FOCAL_POINTS; point++)
    {
        const gl::FocalPoint &focalPoint = foveationState.getFocalPoint(0, point);
        if (focalPoint.valid())
        {
            activeFocalPoints.push_back(focalPoint);
        }
    }
    ASSERT(activeFocalPoints.size() > 0);

    if (contextVk->getFeatures().generateFragmentShadingRateAttchementWithCpu.enabled)
    {
        ANGLE_TRY(generateFragmentShadingRateWithCPU(
            contextVk, fragmentShadingRateWidth, fragmentShadingRateHeight,
            fragmentShadingRateBlockWidth, fragmentShadingRateBlockHeight, foveatedAttachmentWidth,
            foveatedAttachmentHeight, activeFocalPoints));
    }
    else
    {
        ANGLE_TRY(generateFragmentShadingRateWithCompute(
            contextVk, fragmentShadingRateWidth, fragmentShadingRateHeight,
            fragmentShadingRateBlockWidth, fragmentShadingRateBlockHeight, foveatedAttachmentWidth,
            foveatedAttachmentHeight, activeFocalPoints));
    }

    return angle::Result::Continue;
}

angle::Result FramebufferVk::updateFoveationState(ContextVk *contextVk,
                                                  const gl::FoveationState &newFoveationState,
                                                  const gl::Extents &foveatedAttachmentSize)
{
    const bool isFoveationEnabled                 = newFoveationState.isFoveated();
    vk::ImageOrBufferViewSubresourceSerial serial = vk::kInvalidImageOrBufferViewSubresourceSerial;
    if (isFoveationEnabled)
    {
        ANGLE_TRY(updateFragmentShadingRateAttachment(contextVk, newFoveationState,
                                                      foveatedAttachmentSize));
        ASSERT(mFragmentShadingRateImage.valid());

        serial = mFragmentShadingRateImageView.getSubresourceSerial(gl::LevelIndex(0), 1, 0,
                                                                    vk::LayerMode::All);
    }

    // Update state after the possible failure point.
    mFoveationState = newFoveationState;
    mCurrentFramebufferDesc.updateFragmentShadingRate(serial);
    // mRenderPassDesc will be updated later in updateRenderPassDesc() in case if
    // mCurrentFramebufferDesc was changed.
    return angle::Result::Continue;
}

angle::Result FramebufferVk::resolveColorWithSubpass(ContextVk *contextVk,
                                                     const UtilsVk::BlitResolveParameters &params)
{
    // Vulkan requires a 1:1 relationship for multisample attachments to resolve attachments in the
    // render pass subpass. Due to this, we currently only support using resolve attachments when
    // there is a single draw attachment enabled.
    ASSERT(mState.getEnabledDrawBuffers().count() == 1);
    uint32_t drawColorIndexGL = static_cast<uint32_t>(*mState.getEnabledDrawBuffers().begin());
    RenderTargetVk *drawRenderTarget      = mRenderTargetCache.getColors()[drawColorIndexGL];
    const vk::ImageView *resolveImageView = nullptr;
    ANGLE_TRY(drawRenderTarget->getImageView(contextVk, &resolveImageView));

    const gl::Framebuffer *srcFramebuffer = contextVk->getState().getReadFramebuffer();
    uint32_t readColorIndexGL             = srcFramebuffer->getState().getReadIndex();

    vk::RenderPassCommandBufferHelper &renderPassCommands =
        contextVk->getStartedRenderPassCommands();
    ASSERT(!renderPassCommands.getRenderPassDesc().hasColorResolveAttachment(readColorIndexGL));

    drawRenderTarget->onColorResolve(contextVk, mCurrentFramebufferDesc.getLayerCount(),
                                     readColorIndexGL, *resolveImageView);

    // The render pass is already closed because of the change in the draw buffer.  Just don't let
    // it reactivate now that it has a resolve attachment.
    contextVk->disableRenderPassReactivation();

    return angle::Result::Continue;
}

angle::Result FramebufferVk::resolveDepthStencilWithSubpass(
    ContextVk *contextVk,
    const UtilsVk::BlitResolveParameters &params,
    VkImageAspectFlags aspects)
{
    RenderTargetVk *drawRenderTarget      = mRenderTargetCache.getDepthStencil();
    const vk::ImageView *resolveImageView = nullptr;
    ANGLE_TRY(drawRenderTarget->getImageView(contextVk, &resolveImageView));

    vk::RenderPassCommandBufferHelper &renderPassCommands =
        contextVk->getStartedRenderPassCommands();
    ASSERT(!renderPassCommands.getRenderPassDesc().hasDepthStencilResolveAttachment());

    drawRenderTarget->onDepthStencilResolve(contextVk, mCurrentFramebufferDesc.getLayerCount(),
                                            aspects, *resolveImageView);

    // The render pass is already closed because of the change in the draw buffer.  Just don't let
    // it reactivate now that it has a resolve attachment.
    contextVk->disableRenderPassReactivation();

    return angle::Result::Continue;
}

angle::Result FramebufferVk::resolveColorWithCommand(ContextVk *contextVk,
                                                     const UtilsVk::BlitResolveParameters &params,
                                                     vk::ImageHelper *srcImage)
{
    vk::Renderer *renderer = contextVk->getRenderer();

    vk::CommandResources resources;
    resources.onImageTransferRead(VK_IMAGE_ASPECT_COLOR_BIT, srcImage);

    for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
    {
        RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[colorIndexGL];
        vk::ImageHelper &dstImage        = drawRenderTarget->getImageForWrite();

        resources.onImageTransferWrite(drawRenderTarget->getLevelIndex(), 1,
                                       drawRenderTarget->getLayerIndex(), 1,
                                       VK_IMAGE_ASPECT_COLOR_BIT, &dstImage);
    }

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

    VkImageResolve resolveRegion                = {};
    resolveRegion.srcSubresource.aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT;
    resolveRegion.srcSubresource.mipLevel       = 0;
    resolveRegion.srcSubresource.baseArrayLayer = params.srcLayer;
    resolveRegion.srcSubresource.layerCount     = 1;
    resolveRegion.srcOffset.x                   = params.blitArea.x;
    resolveRegion.srcOffset.y                   = params.blitArea.y;
    resolveRegion.srcOffset.z                   = 0;
    resolveRegion.dstSubresource.aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT;
    resolveRegion.dstSubresource.layerCount     = 1;
    resolveRegion.dstOffset.x                   = params.blitArea.x;
    resolveRegion.dstOffset.y                   = params.blitArea.y;
    resolveRegion.dstOffset.z                   = 0;
    resolveRegion.extent.width                  = params.blitArea.width;
    resolveRegion.extent.height                 = params.blitArea.height;
    resolveRegion.extent.depth                  = 1;

    angle::VulkanPerfCounters &perfCounters = contextVk->getPerfCounters();
    for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
    {
        RenderTargetVk *drawRenderTarget = mRenderTargetCache.getColors()[colorIndexGL];
        vk::ImageHelper &dstImage        = drawRenderTarget->getImageForWrite();

        vk::LevelIndex levelVk = dstImage.toVkLevel(drawRenderTarget->getLevelIndex());
        resolveRegion.dstSubresource.mipLevel       = levelVk.get();
        resolveRegion.dstSubresource.baseArrayLayer = drawRenderTarget->getLayerIndex();

        srcImage->resolve(renderer, &dstImage, resolveRegion, commandBuffer);

        perfCounters.resolveImageCommands++;
    }

    return angle::Result::Continue;
}

gl::FramebufferStatus FramebufferVk::checkStatus(const gl::Context *context) const
{
    // if we have both a depth and stencil buffer, they must refer to the same object
    // since we only support packed_depth_stencil and not separate depth and stencil
    if (mState.hasSeparateDepthAndStencilAttachments())
    {
        return gl::FramebufferStatus::Incomplete(
            GL_FRAMEBUFFER_UNSUPPORTED,
            gl::err::kFramebufferIncompleteUnsupportedSeparateDepthStencilBuffers);
    }

    return gl::FramebufferStatus::Complete();
}

angle::Result FramebufferVk::invalidateImpl(ContextVk *contextVk,
                                            size_t count,
                                            const GLenum *attachments,
                                            bool isSubInvalidate,
                                            const gl::Rectangle &invalidateArea)
{
    gl::DrawBufferMask invalidateColorBuffers;
    bool invalidateDepthBuffer   = false;
    bool invalidateStencilBuffer = false;

    for (size_t i = 0; i < count; ++i)
    {
        const GLenum attachment = attachments[i];

        switch (attachment)
        {
            case GL_DEPTH:
            case GL_DEPTH_ATTACHMENT:
                invalidateDepthBuffer = true;
                break;
            case GL_STENCIL:
            case GL_STENCIL_ATTACHMENT:
                invalidateStencilBuffer = true;
                break;
            case GL_DEPTH_STENCIL_ATTACHMENT:
                invalidateDepthBuffer   = true;
                invalidateStencilBuffer = true;
                break;
            default:
                ASSERT(
                    (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15) ||
                    (attachment == GL_COLOR));

                invalidateColorBuffers.set(
                    attachment == GL_COLOR ? 0u : (attachment - GL_COLOR_ATTACHMENT0));
        }
    }

    // Shouldn't try to issue deferred clears if invalidating sub framebuffer.
    ASSERT(mDeferredClears.empty() || !isSubInvalidate);

    if (contextVk->getFeatures().dropDepthStencilClearOnInvalidate.enabled)
    {
        // Remove deferred clears for the invalidated attachments.
        if (invalidateDepthBuffer)
        {
            mDeferredClears.reset(vk::kUnpackedDepthIndex);
        }
        if (invalidateStencilBuffer)
        {
            mDeferredClears.reset(vk::kUnpackedStencilIndex);
        }
    }
    // Limit invalidateColorBuffers to enabled draw buffers
    invalidateColorBuffers &= mState.getEnabledDrawBuffers();
    for (size_t colorIndexGL : invalidateColorBuffers)
    {
        mDeferredClears.reset(colorIndexGL);
    }

    // If there are still deferred clears, restage them. See relevant comment in invalidateSub.
    restageDeferredClears(contextVk);

    const auto &colorRenderTargets           = mRenderTargetCache.getColors();
    RenderTargetVk *depthStencilRenderTarget = mRenderTargetCache.getDepthStencil();

    // If not a partial invalidate, mark the contents of the invalidated attachments as undefined,
    // so their loadOp can be set to DONT_CARE in the following render pass.

    // If robust resource initialization is enabled, restage clears on the invalidated resources.
    // This way, STORE_OP_DONT_CARE can be used, but the application can still not observe garbage
    // data in the image.
    const bool isRobustResourceInitEnabled = contextVk->isRobustResourceInitEnabled();
    ASSERT(!(isRobustResourceInitEnabled && isSubInvalidate));
    if (!isSubInvalidate)
    {
        for (size_t colorIndexGL : invalidateColorBuffers)
        {
            RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
            ASSERT(colorRenderTarget);

            bool preferToKeepContentsDefined = false;
            colorRenderTarget->invalidateEntireContent(contextVk, &preferToKeepContentsDefined);
            if (preferToKeepContentsDefined)
            {
                invalidateColorBuffers.reset(colorIndexGL);
            }
            else if (isRobustResourceInitEnabled)
            {
                gl::ImageIndex imageIndex = colorRenderTarget->getImageIndexForClear(
                    mCurrentFramebufferDesc.getLayerCount());
                colorRenderTarget->getImageForWrite().stageRobustResourceClear(
                    imageIndex, VK_IMAGE_ASPECT_COLOR_BIT);
            }
        }

        // If we have a depth / stencil render target, invalidate its aspects.
        if (depthStencilRenderTarget)
        {
            if (invalidateDepthBuffer)
            {
                bool preferToKeepContentsDefined = false;
                depthStencilRenderTarget->invalidateEntireContent(contextVk,
                                                                  &preferToKeepContentsDefined);
                if (preferToKeepContentsDefined)
                {
                    invalidateDepthBuffer = false;
                }
            }
            if (invalidateStencilBuffer)
            {
                bool preferToKeepContentsDefined = false;
                depthStencilRenderTarget->invalidateEntireStencilContent(
                    contextVk, &preferToKeepContentsDefined);
                if (preferToKeepContentsDefined)
                {
                    invalidateStencilBuffer = false;
                }
            }

            if (isRobustResourceInitEnabled)
            {
                VkImageAspectFlags dsAspectFlags = 0;
                if (invalidateDepthBuffer)
                {
                    dsAspectFlags |= VK_IMAGE_ASPECT_DEPTH_BIT;
                }
                if (invalidateStencilBuffer)
                {
                    dsAspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
                }
                if (dsAspectFlags)
                {
                    gl::ImageIndex imageIndex = depthStencilRenderTarget->getImageIndexForClear(
                        mCurrentFramebufferDesc.getLayerCount());
                    depthStencilRenderTarget->getImageForWrite().stageRobustResourceClear(
                        imageIndex, dsAspectFlags);
                }
            }
        }
    }

    // To ensure we invalidate the right renderpass we require that the current framebuffer be the
    // same as the current renderpass' framebuffer. E.g. prevent sequence like:
    //- Bind FBO 1, draw
    //- Bind FBO 2, draw
    //- Bind FBO 1, invalidate D/S
    // to invalidate the D/S of FBO 2 since it would be the currently active renderpass.
    if (contextVk->hasStartedRenderPassWithQueueSerial(mLastRenderPassQueueSerial))
    {
        // When robust-resource init is enabled, a clear is stashed in the image after invalidating
        // it.  The render pass is closed for the same reason as with images with emulated alpha
        // channel as described below.
        bool closeRenderPass = isRobustResourceInitEnabled;

        // Mark the invalidated attachments in the render pass for loadOp and storeOp determination
        // at its end.
        vk::PackedAttachmentIndex colorIndexVk(0);
        for (size_t colorIndexGL : mState.getColorAttachmentsMask())
        {
            if (invalidateColorBuffers.test(colorIndexGL))
            {
                contextVk->getStartedRenderPassCommands().invalidateRenderPassColorAttachment(
                    contextVk->getState(), colorIndexGL, colorIndexVk, invalidateArea);

                // If invalidating a color image with emulated channels, a clear is automatically
                // staged so the emulated channels don't contain invalid data later.  This is
                // problematic with deferred clears; the clear marks the framebuffer attachment as
                // dirty, and the next command causes |FramebufferVk::syncState| to pick the clear
                // up as a deferred clear.
                //
                // This is normally correct, except if the following command is another draw call;
                // in that case, the render pass does not close, yet the clear is cached in
                // |mDeferredClears|.  When the render pass later closes, it undoes the invalidate
                // and attempts to remove the clear from the image... but it does not exist there
                // anymore (it's in |mDeferredClears|).  Next usage of the image then clears it,
                // undoing the draws after invalidate.
                //
                // In this case, the simplest approach is to close the render pass right away here.
                // Note that it is not possible to make |FramebufferVk::syncState| avoid picking up
                // the clear in |mDeferredClears|, not apply the clear, _and_ keep the render pass
                // open; because future uses of the image (like with |glReadPixels|) will not
                // trigger |FramebufferVk::syncState| and the clear won't be done.
                if (mEmulatedAlphaAttachmentMask[colorIndexGL])
                {
                    closeRenderPass = true;
                }
            }
            ++colorIndexVk;
        }

        if (depthStencilRenderTarget)
        {
            const gl::DepthStencilState &dsState = contextVk->getState().getDepthStencilState();
            if (invalidateDepthBuffer)
            {
                contextVk->getStartedRenderPassCommands().invalidateRenderPassDepthAttachment(
                    dsState, invalidateArea);
            }

            if (invalidateStencilBuffer)
            {
                contextVk->getStartedRenderPassCommands().invalidateRenderPassStencilAttachment(
                    dsState, mState.getStencilBitCount(), invalidateArea);
            }
        }

        if (closeRenderPass)
        {
            ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass(
                RenderPassClosureReason::ColorBufferWithEmulatedAlphaInvalidate));
        }
    }

    return angle::Result::Continue;
}

angle::Result FramebufferVk::updateColorAttachment(const gl::Context *context,
                                                   uint32_t colorIndexGL)
{
    ANGLE_TRY(mRenderTargetCache.updateColorRenderTarget(context, mState, colorIndexGL));

    // Update cached masks for masked clears.
    RenderTargetVk *renderTarget = mRenderTargetCache.getColors()[colorIndexGL];
    if (renderTarget)
    {
        const angle::Format &actualFormat = renderTarget->getImageActualFormat();
        updateActiveColorMasks(colorIndexGL, actualFormat.redBits > 0, actualFormat.greenBits > 0,
                               actualFormat.blueBits > 0, actualFormat.alphaBits > 0);

        const angle::Format &intendedFormat = renderTarget->getImageIntendedFormat();
        mEmulatedAlphaAttachmentMask.set(
            colorIndexGL, intendedFormat.alphaBits == 0 && actualFormat.alphaBits > 0);
    }
    else
    {
        updateActiveColorMasks(colorIndexGL, false, false, false, false);
    }

    const bool enabledColor =
        renderTarget && mState.getColorAttachments()[colorIndexGL].isAttached();
    const bool enabledResolve = enabledColor && renderTarget->hasResolveAttachment();

    if (enabledColor)
    {
        mCurrentFramebufferDesc.updateColor(colorIndexGL, renderTarget->getDrawSubresourceSerial());
        const bool isExternalImage =
            mState.getColorAttachments()[colorIndexGL].isExternalImageWithoutIndividualSync();
        mIsExternalColorAttachments.set(colorIndexGL, isExternalImage);
        mAttachmentHasFrontBufferUsage.set(
            colorIndexGL, mState.getColorAttachments()[colorIndexGL].hasFrontBufferUsage());
    }
    else
    {
        mCurrentFramebufferDesc.updateColor(colorIndexGL,
                                            vk::kInvalidImageOrBufferViewSubresourceSerial);
    }

    if (enabledResolve)
    {
        mCurrentFramebufferDesc.updateColorResolve(colorIndexGL,
                                                   renderTarget->getResolveSubresourceSerial());
    }
    else
    {
        mCurrentFramebufferDesc.updateColorResolve(colorIndexGL,
                                                   vk::kInvalidImageOrBufferViewSubresourceSerial);
    }

    return angle::Result::Continue;
}

void FramebufferVk::updateColorAttachmentColorspace(gl::SrgbWriteControlMode srgbWriteControlMode)
{
    // Update colorspace of color attachments.
    const auto &colorRenderTargets               = mRenderTargetCache.getColors();
    const gl::DrawBufferMask colorAttachmentMask = mState.getColorAttachmentsMask();
    for (size_t colorIndexGL : colorAttachmentMask)
    {
        RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
        ASSERT(colorRenderTarget);
        colorRenderTarget->updateWriteColorspace(srgbWriteControlMode);
        mAttachmentWithColorSpaceOverrideMask.set(
            colorIndexGL, colorRenderTarget->hasColorspaceOverrideForWrite());
    }
}

angle::Result FramebufferVk::updateDepthStencilAttachment(const gl::Context *context)
{
    ANGLE_TRY(mRenderTargetCache.updateDepthStencilRenderTarget(context, mState));

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

    return angle::Result::Continue;
}

void FramebufferVk::updateDepthStencilAttachmentSerial(ContextVk *contextVk)
{
    RenderTargetVk *depthStencilRT = getDepthStencilRenderTarget();

    if (depthStencilRT != nullptr)
    {
        mCurrentFramebufferDesc.updateDepthStencil(depthStencilRT->getDrawSubresourceSerial());
    }
    else
    {
        mCurrentFramebufferDesc.updateDepthStencil(vk::kInvalidImageOrBufferViewSubresourceSerial);
    }

    if (depthStencilRT != nullptr && depthStencilRT->hasResolveAttachment())
    {
        mCurrentFramebufferDesc.updateDepthStencilResolve(
            depthStencilRT->getResolveSubresourceSerial());
    }
    else
    {
        mCurrentFramebufferDesc.updateDepthStencilResolve(
            vk::kInvalidImageOrBufferViewSubresourceSerial);
    }
}

angle::Result FramebufferVk::flushColorAttachmentUpdates(const gl::Context *context,
                                                         bool deferClears,
                                                         uint32_t colorIndexGL)
{
    ContextVk *contextVk             = vk::GetImpl(context);
    RenderTargetVk *readRenderTarget = nullptr;
    RenderTargetVk *drawRenderTarget = nullptr;

    // It's possible for the read and draw color attachments to be different if different surfaces
    // are bound, so we need to flush any staged updates to both.

    // Draw
    drawRenderTarget = mRenderTargetCache.getColorDraw(mState, colorIndexGL);
    if (drawRenderTarget)
    {
        if (deferClears)
        {
            ANGLE_TRY(
                drawRenderTarget->flushStagedUpdates(contextVk, &mDeferredClears, colorIndexGL,
                                                     mCurrentFramebufferDesc.getLayerCount()));
        }
        else
        {
            ANGLE_TRY(drawRenderTarget->flushStagedUpdates(
                contextVk, nullptr, 0, mCurrentFramebufferDesc.getLayerCount()));
        }
    }

    // Read
    if (mState.getReadBufferState() != GL_NONE && mState.getReadIndex() == colorIndexGL)
    {
        // Flush staged updates to the read render target as well, but only if it's not the same as
        // the draw render target.  This can happen when the read render target is bound to another
        // surface.
        readRenderTarget = mRenderTargetCache.getColorRead(mState);
        if (readRenderTarget && readRenderTarget != drawRenderTarget)
        {
            ANGLE_TRY(readRenderTarget->flushStagedUpdates(
                contextVk, nullptr, 0, mCurrentFramebufferDesc.getLayerCount()));
        }
    }

    return angle::Result::Continue;
}

angle::Result FramebufferVk::flushDepthStencilAttachmentUpdates(const gl::Context *context,
                                                                bool deferClears)
{
    ContextVk *contextVk = vk::GetImpl(context);

    RenderTargetVk *depthStencilRT = getDepthStencilRenderTarget();
    if (depthStencilRT == nullptr)
    {
        return angle::Result::Continue;
    }

    if (deferClears)
    {
        return depthStencilRT->flushStagedUpdates(contextVk, &mDeferredClears,
                                                  vk::kUnpackedDepthIndex,
                                                  mCurrentFramebufferDesc.getLayerCount());
    }

    return depthStencilRT->flushStagedUpdates(contextVk, nullptr, 0,
                                              mCurrentFramebufferDesc.getLayerCount());
}

angle::Result FramebufferVk::syncState(const gl::Context *context,
                                       GLenum binding,
                                       const gl::Framebuffer::DirtyBits &dirtyBits,
                                       gl::Command command)
{
    ContextVk *contextVk = vk::GetImpl(context);

    vk::FramebufferDesc priorFramebufferDesc = mCurrentFramebufferDesc;

    // Keep track of which attachments have dirty content and need their staged updates flushed.
    // The respective functions depend on |mCurrentFramebufferDesc::mLayerCount| which is updated
    // after all attachment render targets are updated.
    gl::DrawBufferMask dirtyColorAttachments;
    bool dirtyDepthStencilAttachment = false;

    bool shouldUpdateColorMaskAndBlend = false;
    bool shouldUpdateLayerCount        = false;

    // Cache new foveation state, if any
    const gl::FoveationState *newFoveationState = nullptr;
    gl::Extents foveatedAttachmentSize;

    // For any updated attachments we'll update their Serials below
    ASSERT(dirtyBits.any());
    for (size_t dirtyBit : dirtyBits)
    {
        switch (dirtyBit)
        {
            case gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
            case gl::Framebuffer::DIRTY_BIT_DEPTH_BUFFER_CONTENTS:
            case gl::Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
            case gl::Framebuffer::DIRTY_BIT_STENCIL_BUFFER_CONTENTS:
                ANGLE_TRY(updateDepthStencilAttachment(context));
                shouldUpdateLayerCount      = true;
                dirtyDepthStencilAttachment = true;
                break;
            case gl::Framebuffer::DIRTY_BIT_READ_BUFFER:
                ANGLE_TRY(mRenderTargetCache.update(context, mState, dirtyBits));
                break;
            case gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
                shouldUpdateColorMaskAndBlend = true;
                shouldUpdateLayerCount        = true;
                break;
            case gl::Framebuffer::DIRTY_BIT_DEFAULT_WIDTH:
            case gl::Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT:
            case gl::Framebuffer::DIRTY_BIT_DEFAULT_SAMPLES:
            case gl::Framebuffer::DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS:
                // Invalidate the cache. If we have performance critical code hitting this path we
                // can add related data (such as width/height) to the cache
                releaseCurrentFramebuffer(contextVk);
                break;
            case gl::Framebuffer::DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE:
                break;
            case gl::Framebuffer::DIRTY_BIT_DEFAULT_LAYERS:
                shouldUpdateLayerCount = true;
                break;
            case gl::Framebuffer::DIRTY_BIT_FOVEATION:
                // This dirty bit is set iff the framebuffer itself is foveated
                ASSERT(mState.isFoveationEnabled());

                newFoveationState      = &mState.getFoveationState();
                foveatedAttachmentSize = mState.getExtents();
                break;
            default:
            {
                static_assert(gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0, "FB dirty bits");
                uint32_t colorIndexGL;
                if (dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX)
                {
                    colorIndexGL = static_cast<uint32_t>(
                        dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
                }
                else
                {
                    ASSERT(dirtyBit >= gl::Framebuffer::DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 &&
                           dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_BUFFER_CONTENTS_MAX);
                    colorIndexGL = static_cast<uint32_t>(
                        dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_BUFFER_CONTENTS_0);
                }

                ANGLE_TRY(updateColorAttachment(context, colorIndexGL));

                // Check if attachment has foveated rendering, if so grab foveation state
                const gl::FramebufferAttachment *attachment =
                    mState.getColorAttachment(colorIndexGL);
                if (attachment && attachment->hasFoveatedRendering())
                {
                    // If attachment is foveated the framebuffer must not be.
                    ASSERT(!mState.isFoveationEnabled());

                    newFoveationState = attachment->getFoveationState();
                    ASSERT(newFoveationState != nullptr);

                    foveatedAttachmentSize = attachment->getSize();
                }

                // Window system framebuffer only have one color attachment and its property should
                // never change unless via DIRTY_BIT_DRAW_BUFFERS bit.
                if (!mState.isDefault())
                {
                    shouldUpdateColorMaskAndBlend = true;
                    shouldUpdateLayerCount        = true;
                }
                dirtyColorAttachments.set(colorIndexGL);

                break;
            }
        }
    }

    // Update cached value of samples. Always ensure we have at least one sample since
    // GraphicsPipelineDesc can't handle 0 samples.
    mRasterizationSamples = std::max(getSamplesImpl(), 1);

    // A shared attachment's colorspace could have been modified in another context, update
    // colorspace of all attachments to reflect current context's colorspace.
    //
    // Toggling colorspace between linear and sRGB for default framebuffers is supported iff
    // VK_KHR_swapchain_mutable_format extension is supported
    if (!mState.isDefault() || contextVk->getFeatures().supportsSwapchainMutableFormat.enabled)
    {
        gl::SrgbWriteControlMode srgbWriteControlMode = mState.getWriteControlMode();
        updateColorAttachmentColorspace(srgbWriteControlMode);
        // Update current framebuffer description to reflect the new state.
        mCurrentFramebufferDesc.setWriteControlMode(srgbWriteControlMode);
    }

    if (shouldUpdateColorMaskAndBlend)
    {
        contextVk->updateColorMasks();
        contextVk->updateBlendEnabled();
        contextVk->updateBlendFuncsAndEquations();
    }

    if (shouldUpdateLayerCount)
    {
        updateLayerCount();
    }

    if (newFoveationState && mFoveationState != *newFoveationState)
    {
        ANGLE_TRY(updateFoveationState(contextVk, *newFoveationState, foveatedAttachmentSize));
    }

    // Note that deferring clears may result in a render area that completely covers the
    // framebuffer, even if the operation that follows is scissored.
    bool deferColorClears, deferDepthStencilClears;

    switch (command)
    {
        // These commands always expect deferred clears (to perform potential optimization).
        case gl::Command::Clear:
        case gl::Command::Draw:
            ASSERT(binding == GL_DRAW_FRAMEBUFFER);
            deferColorClears        = true;
            deferDepthStencilClears = true;
            break;
        // Defer clears only for draw framebuffer attachments for the invalidate operation.
        case gl::Command::Invalidate:
            ASSERT(binding == GL_DRAW_FRAMEBUFFER || binding == GL_READ_FRAMEBUFFER);
            deferColorClears        = (binding == GL_DRAW_FRAMEBUFFER);
            deferDepthStencilClears = (binding == GL_DRAW_FRAMEBUFFER);
            break;
        // These commands do not expect (handle) deferred clears.  There is no reason to defer
        // clears for CopyImage and ReadPixels, as they need to read from the image right away.
        // GetMultisample does not access attachments at all and clears are flushed for simplicity.
        // Other enum may be used for different cases, where deferred clears may be handled or not.
        // Clears are not deferred to avoid bugs.  If clears need to be deferred, operation must not
        // use the Command::Other enumeration.
        case gl::Command::CopyImage:
        case gl::Command::ReadPixels:
        case gl::Command::GetMultisample:
        case gl::Command::Other:
            // Binding for Command::Other reflects current code and may be updated as necessary.
            ASSERT(((command == gl::Command::CopyImage || command == gl::Command::ReadPixels) &&
                    binding == GL_READ_FRAMEBUFFER) ||
                   (command == gl::Command::GetMultisample && binding == GL_DRAW_FRAMEBUFFER) ||
                   (command == gl::Command::Other && binding == GL_FRAMEBUFFER));
            deferColorClears        = false;
            deferDepthStencilClears = false;
            break;
        // Defer clears for read framebuffer attachments that are not taking part in a blit
        // operation in order to restage them and possibly use as clear op in a future render pass.
        default:
            ASSERT(command >= gl::Command::Blit && command <= gl::Command::BlitAll);
            if (binding == GL_READ_FRAMEBUFFER)
            {
                const uint32_t blitMask =
                    static_cast<uint32_t>(command) - static_cast<uint32_t>(gl::Command::Blit);
                deferColorClears        = ((blitMask & gl::CommandBlitBufferColor) == 0);
                deferDepthStencilClears = ((blitMask & gl::CommandBlitBufferDepthStencil) == 0);
            }
            else
            {
                ASSERT(binding == GL_DRAW_FRAMEBUFFER);
                deferColorClears        = true;
                deferDepthStencilClears = true;
            }
            break;
    }

    // If we have deferred clears, a flushDeferredClears() or restageDeferredClears() call is
    // missing somewhere.  ASSERT this to catch these bugs.
    ASSERT(mDeferredClears.empty());

    for (size_t colorIndexGL : dirtyColorAttachments)
    {
        ANGLE_TRY(flushColorAttachmentUpdates(context, deferColorClears,
                                              static_cast<uint32_t>(colorIndexGL)));
    }
    if (dirtyDepthStencilAttachment)
    {
        ANGLE_TRY(flushDepthStencilAttachmentUpdates(context, deferDepthStencilClears));
    }

    // No-op redundant changes to prevent closing the RenderPass.
    if (mCurrentFramebufferDesc == priorFramebufferDesc &&
        mCurrentFramebufferDesc.attachmentCount() > 0 && mRenderPassDesc.samples() == getSamples())
    {
        return angle::Result::Continue;
    }

    // The cached attachment information is cleared here.
    mCachedAttachmentsInfo.clear();

    // ContextVk::onFramebufferChange will end up calling onRenderPassFinished if necessary,
    // which will trigger ending of current render pass.  |mLastRenderPassQueueSerial| is reset
    // so that the render pass will not get reactivated, since |mCurrentFramebufferDesc| has
    // changed.
    mLastRenderPassQueueSerial = QueueSerial();

    updateRenderPassDesc(contextVk);

    // Deactivate Framebuffer
    releaseCurrentFramebuffer(contextVk);

    // Notify the ContextVk to update the pipeline desc.
    return contextVk->onFramebufferChange(this, command);
}

void FramebufferVk::updateRenderPassDesc(ContextVk *contextVk)
{
    mRenderPassDesc = {};
    mRenderPassDesc.setSamples(getSamples());
    mRenderPassDesc.setViewCount(
        mState.isMultiview() && mState.getNumViews() > 1 ? mState.getNumViews() : 0);

    // Color attachments.
    const auto &colorRenderTargets               = mRenderTargetCache.getColors();
    const gl::DrawBufferMask colorAttachmentMask = mState.getColorAttachmentsMask();
    for (size_t colorIndexGL : colorAttachmentMask)
    {
        RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
        ASSERT(colorRenderTarget);

        if (colorRenderTarget->isYuvResolve())
        {
            // If this is YUV resolve target, we use resolveImage's format since image maybe
            // nullptr
            auto const &resolveImage = colorRenderTarget->getResolveImageForRenderPass();
            mRenderPassDesc.packColorAttachment(colorIndexGL, resolveImage.getActualFormatID());
            mRenderPassDesc.packYUVResolveAttachment(colorIndexGL);
        }
        else
        {
            // Account for attachments with colorspace override
            angle::FormatID actualFormat =
                colorRenderTarget->getImageForRenderPass().getActualFormatID();
            if (mAttachmentWithColorSpaceOverrideMask[colorIndexGL])
            {
                actualFormat = colorRenderTarget->getColorspaceOverrideFormatForWrite(actualFormat);
            }

            mRenderPassDesc.packColorAttachment(colorIndexGL, actualFormat);
            // Add the resolve attachment, if any.
            if (colorRenderTarget->hasResolveAttachment())
            {
                mRenderPassDesc.packColorResolveAttachment(colorIndexGL);
            }
        }
    }

    // Depth/stencil attachment.
    RenderTargetVk *depthStencilRenderTarget = getDepthStencilRenderTarget();
    if (depthStencilRenderTarget)
    {
        mRenderPassDesc.packDepthStencilAttachment(
            depthStencilRenderTarget->getImageForRenderPass().getActualFormatID());

        // Add the resolve attachment, if any.
        if (depthStencilRenderTarget->hasResolveAttachment())
        {
            mRenderPassDesc.packDepthResolveAttachment();
            mRenderPassDesc.packStencilResolveAttachment();
        }
    }

    if (!contextVk->getFeatures().preferDynamicRendering.enabled &&
        contextVk->isInColorFramebufferFetchMode())
    {
        mRenderPassDesc.setFramebufferFetchMode(vk::FramebufferFetchMode::Color);
    }

    if (contextVk->getFeatures().enableMultisampledRenderToTexture.enabled)
    {
        // Update descriptions regarding multisampled-render-to-texture use.
        bool isRenderToTexture = false;
        for (size_t colorIndexGL : mState.getColorAttachmentsMask())
        {
            const gl::FramebufferAttachment *color = mState.getColorAttachment(colorIndexGL);
            ASSERT(color);

            if (color->isRenderToTexture())
            {
                ASSERT(
                    !contextVk->getFeatures().supportsMultisampledRenderToSingleSampled.enabled ||
                    (colorRenderTargets[colorIndexGL]->getImageForRenderPass().getCreateFlags() &
                     VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT) != 0);
                isRenderToTexture = true;
                break;
            }
        }
        const gl::FramebufferAttachment *depthStencil = mState.getDepthStencilAttachment();
        if (depthStencil && depthStencil->isRenderToTexture())
        {
            ASSERT(!contextVk->getFeatures().supportsMultisampledRenderToSingleSampled.enabled ||
                   (depthStencilRenderTarget->getImageForRenderPass().getCreateFlags() &
                    VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT) != 0);
            isRenderToTexture = true;
        }

        mCurrentFramebufferDesc.updateRenderToTexture(isRenderToTexture);
        mRenderPassDesc.updateRenderToTexture(isRenderToTexture);
    }

    mCurrentFramebufferDesc.updateUnresolveMask({});
    mRenderPassDesc.setWriteControlMode(mCurrentFramebufferDesc.getWriteControlMode());
    mRenderPassDesc.setFragmentShadingAttachment(
        mCurrentFramebufferDesc.hasFragmentShadingRateAttachment());

    updateLegacyDither(contextVk);
}

angle::Result FramebufferVk::updateAttachmentsAndRenderTargets(ContextVk *contextVk)
{
    // If the cached attachment info is unchanged, it can be reused.
    if (!mCachedAttachmentsInfo.unpackedAttachments.empty())
    {
        return angle::Result::Continue;
    }

    bool anyResolveAttachments = false;

    // Color attachments.
    mIsYUVResolve                  = false;
    const auto &colorRenderTargets = mRenderTargetCache.getColors();
    for (size_t colorIndexGL : mState.getColorAttachmentsMask())
    {
        RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
        ASSERT(colorRenderTarget);

        if (colorRenderTarget->isYuvResolve())
        {
            mIsYUVResolve = true;
            if (contextVk->getRenderer()->nullColorAttachmentWithExternalFormatResolve())
            {
                // Because the color attachment will be null if
                // nullColorAttachmentWithExternalFormatResolve is VK_TRUE, push YUV resolve as
                // color attachment to ensure the coherency of other attachment information, like
                // ops and clearValues.
                const vk::ImageView *resolveImageView = nullptr;
                ANGLE_TRY(colorRenderTarget->getResolveImageView(contextVk, &resolveImageView));
                mCachedAttachmentsInfo.unpackedAttachments.push_back(resolveImageView->getHandle());
                mCachedAttachmentsInfo.packedRenderTargetsInfo.emplace_back(
                    RenderTargetInfo(colorRenderTarget, RenderTargetImage::Resolve));

                anyResolveAttachments = true;
                continue;
            }
        }
        const vk::ImageView *imageView = nullptr;
        ANGLE_TRY(colorRenderTarget->getImageViewWithColorspace(
            contextVk, mCurrentFramebufferDesc.getWriteControlMode(), &imageView));
        mCachedAttachmentsInfo.unpackedAttachments.push_back(imageView->getHandle());
        mCachedAttachmentsInfo.packedRenderTargetsInfo.emplace_back(
            RenderTargetInfo(colorRenderTarget, RenderTargetImage::Attachment));
    }

    // Depth/stencil attachment.
    RenderTargetVk *depthStencilRenderTarget = getDepthStencilRenderTarget();
    if (depthStencilRenderTarget)
    {
        const vk::ImageView *imageView = nullptr;
        ANGLE_TRY(depthStencilRenderTarget->getImageView(contextVk, &imageView));

        mCachedAttachmentsInfo.unpackedAttachments.push_back(imageView->getHandle());
        mCachedAttachmentsInfo.packedRenderTargetsInfo.emplace_back(
            RenderTargetInfo(depthStencilRenderTarget, RenderTargetImage::Attachment));
    }

    // Fragment shading rate attachment.
    if (mCurrentFramebufferDesc.hasFragmentShadingRateAttachment())
    {
        const vk::ImageViewHelper *imageViewHelper = &mFragmentShadingRateImageView;
        mCachedAttachmentsInfo.unpackedAttachments.push_back(
            imageViewHelper->getFragmentShadingRateImageView().getHandle());
        mCachedAttachmentsInfo.packedRenderTargetsInfo.emplace_back(
            nullptr, RenderTargetImage::FragmentShadingRate);
    }

    // Color resolve attachments.  From here on, the views are placed at sparse indices because of
    // |RenderPassFramebuffer|.  That allows more resolve attachments to be added later.
    mCachedAttachmentsInfo.unpackedAttachments.resize(vk::kMaxFramebufferAttachments,
                                                      VK_NULL_HANDLE);
    static_assert(vk::RenderPassFramebuffer::kColorResolveAttachmentBegin <
                  vk::kMaxFramebufferAttachments);
    static_assert(vk::RenderPassFramebuffer::kDepthStencilResolveAttachment <
                  vk::kMaxFramebufferAttachments);

    for (size_t colorIndexGL : mState.getColorAttachmentsMask())
    {
        RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
        ASSERT(colorRenderTarget);

        if (colorRenderTarget->hasResolveAttachment())
        {
            if (colorRenderTarget->isYuvResolve() &&
                contextVk->getRenderer()->nullColorAttachmentWithExternalFormatResolve())
            {
                continue;
            }

            const vk::ImageView *resolveImageView = nullptr;
            ANGLE_TRY(colorRenderTarget->getResolveImageView(contextVk, &resolveImageView));

            constexpr size_t kBaseIndex = vk::RenderPassFramebuffer::kColorResolveAttachmentBegin;
            mCachedAttachmentsInfo.unpackedAttachments[kBaseIndex + colorIndexGL] =
                resolveImageView->getHandle();
            mCachedAttachmentsInfo.packedRenderTargetsInfo.emplace_back(
                RenderTargetInfo(colorRenderTarget, RenderTargetImage::Resolve));

            anyResolveAttachments = true;
        }
    }

    // Depth/stencil resolve attachment.
    if (depthStencilRenderTarget && depthStencilRenderTarget->hasResolveAttachment())
    {
        const vk::ImageView *imageView = nullptr;
        ANGLE_TRY(depthStencilRenderTarget->getResolveImageView(contextVk, &imageView));

        mCachedAttachmentsInfo
            .unpackedAttachments[vk::RenderPassFramebuffer::kDepthStencilResolveAttachment] =
            imageView->getHandle();
        mCachedAttachmentsInfo.packedRenderTargetsInfo.emplace_back(
            RenderTargetInfo(depthStencilRenderTarget, RenderTargetImage::Resolve));

        anyResolveAttachments = true;
    }

    // Make sure |AllowAddingResolveAttachmentsToSubpass()| is guarding against all cases where a
    // resolve attachment is pre-present in the render pass.
    if (anyResolveAttachments)
    {
        ASSERT(!AllowAddingResolveAttachmentsToSubpass(mRenderPassDesc));
    }

    return angle::Result::Continue;
}

angle::Result FramebufferVk::createNewFramebuffer(ContextVk *contextVk,
                                                  uint32_t framebufferWidth,
                                                  const uint32_t framebufferHeight,
                                                  const uint32_t framebufferLayers)
{
    ASSERT(!contextVk->getFeatures().preferDynamicRendering.enabled);

    // The backbuffer framebuffer is cached in WindowSurfaceVk instead.
    ASSERT(mBackbuffer == nullptr);
    // Called only when a new framebuffer is needed.
    ASSERT(!mCurrentFramebuffer.valid());

    // When using imageless framebuffers, the framebuffer cache is not utilized.
    const bool useImagelessFramebuffer =
        contextVk->getFeatures().supportsImagelessFramebuffer.enabled;

    // Try to retrieve a framebuffer from the cache.
    if (!useImagelessFramebuffer && contextVk->getFramebufferCache().get(
                                        contextVk, mCurrentFramebufferDesc, mCurrentFramebuffer))
    {
        ASSERT(mCurrentFramebuffer.valid());
        mIsCurrentFramebufferCached = true;
        return angle::Result::Continue;
    }

    const vk::RenderPass *compatibleRenderPass = nullptr;
    ANGLE_TRY(contextVk->getCompatibleRenderPass(mRenderPassDesc, &compatibleRenderPass));

    // Create a new framebuffer.
    uint32_t currentAttachmentCount =
        static_cast<uint32_t>(mCachedAttachmentsInfo.packedRenderTargetsInfo.size());
    vk::Framebuffer newFramebuffer;

    VkFramebufferCreateInfo framebufferInfo = {};
    framebufferInfo.sType                   = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
    framebufferInfo.flags                   = 0;
    framebufferInfo.renderPass              = compatibleRenderPass->getHandle();
    framebufferInfo.attachmentCount         = currentAttachmentCount;
    framebufferInfo.width                   = framebufferWidth;
    framebufferInfo.height                  = framebufferHeight;
    framebufferInfo.layers                  = framebufferLayers;

    // Check that our description matches our attachments. Can catch implementation bugs.
    ASSERT((mIsYUVResolve &&
            contextVk->getRenderer()->nullColorAttachmentWithExternalFormatResolve()) ||
           currentAttachmentCount == mCurrentFramebufferDesc.attachmentCount());

    if (!useImagelessFramebuffer)
    {
        vk::FramebufferAttachmentsVector<VkImageView> packedAttachments =
            mCachedAttachmentsInfo.unpackedAttachments;
        vk::RenderPassFramebuffer::PackViews(&packedAttachments);

        ASSERT(currentAttachmentCount == packedAttachments.size());
        framebufferInfo.pAttachments = packedAttachments.data();

        // The cache key (|FramebufferDesc|) can't distinguish between two framebuffers with 0
        // attachments but with different sizes.  For simplicity, 0-attachment framebuffers are not
        // cached.
        ANGLE_VK_TRY(contextVk, newFramebuffer.init(contextVk->getDevice(), framebufferInfo));
        if (packedAttachments.empty())
        {
            mCurrentFramebuffer         = std::move(newFramebuffer);
            mIsCurrentFramebufferCached = false;
        }
        else
        {
            insertCache(contextVk, mCurrentFramebufferDesc, std::move(newFramebuffer));

            const bool result = contextVk->getFramebufferCache().get(
                contextVk, mCurrentFramebufferDesc, mCurrentFramebuffer);
            ASSERT(result);
            mIsCurrentFramebufferCached = true;
        }

        return angle::Result::Continue;
    }

    // For imageless framebuffers, attachment image and create info objects should be defined
    // when creating the new framebuffer.
    vk::FramebufferAttachmentsVector<VkFramebufferAttachmentImageInfo> attachmentImageInfos(
        currentAttachmentCount, {});

    for (size_t index = 0; index < currentAttachmentCount; ++index)
    {
        const RenderTargetInfo &info = mCachedAttachmentsInfo.packedRenderTargetsInfo[index];
        VkFramebufferAttachmentImageInfo &attachmentInfo = attachmentImageInfos[index];

        attachmentInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO;

        // The fragment shading rate attachment does not have a corresponding render target, and is
        // handled specially.
        if (info.renderTargetImage == RenderTargetImage::FragmentShadingRate)
        {
            attachmentInfo.width  = mFragmentShadingRateImage.getExtents().width;
            attachmentInfo.height = mFragmentShadingRateImage.getExtents().height;

            attachmentInfo.layerCount = 1;
            attachmentInfo.flags      = mFragmentShadingRateImage.getCreateFlags();
            attachmentInfo.usage      = mFragmentShadingRateImage.getUsage();
            attachmentInfo.viewFormatCount =
                static_cast<uint32_t>(mFragmentShadingRateImage.getViewFormats().size());
            attachmentInfo.pViewFormats = mFragmentShadingRateImage.getViewFormats().data();
            continue;
        }

        // Use the resolve image for both draw and resolve attachments when rendering to YUV
        // with the nullColorAttachmentWithExternalFormatResolve feature enabled.
        // If nullColorAttachmentWithExternalFormatResolve is not supported, follow default
        // behaviour.
        const bool overrideDrawAttachmentWithResolveAttachment =
            info.renderTarget->isYuvResolve() &&
            contextVk->getRenderer()->nullColorAttachmentWithExternalFormatResolve();
        vk::ImageHelper *image = (info.renderTargetImage == RenderTargetImage::Resolve ||
                                  overrideDrawAttachmentWithResolveAttachment)
                                     ? &info.renderTarget->getResolveImageForRenderPass()
                                     : &info.renderTarget->getImageForRenderPass();

        const gl::LevelIndex level = info.renderTarget->getLevelIndexForImage(*image);
        const uint32_t layerCount  = info.renderTarget->getLayerCount();
        const gl::Extents extents  = image->getLevelExtents2D(image->toVkLevel(level));

        attachmentInfo.width           = std::max(extents.width, 1);
        attachmentInfo.height          = std::max(extents.height, 1);
        attachmentInfo.layerCount      = mCurrentFramebufferDesc.isMultiview()
                                             ? std::max<uint32_t>(mRenderPassDesc.viewCount(), 1u)
                                             : layerCount;
        attachmentInfo.flags           = image->getCreateFlags();
        attachmentInfo.usage           = image->getUsage();
        attachmentInfo.viewFormatCount = static_cast<uint32_t>(image->getViewFormats().size());
        attachmentInfo.pViewFormats    = image->getViewFormats().data();
    }

    VkFramebufferAttachmentsCreateInfo attachmentsCreateInfo = {};
    attachmentsCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO;
    attachmentsCreateInfo.attachmentImageInfoCount =
        static_cast<uint32_t>(attachmentImageInfos.size());
    attachmentsCreateInfo.pAttachmentImageInfos = attachmentImageInfos.data();

    framebufferInfo.flags |= VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT;
    vk::AddToPNextChain(&framebufferInfo, &attachmentsCreateInfo);

    ANGLE_VK_TRY(contextVk, newFramebuffer.init(contextVk->getDevice(), framebufferInfo));
    mCurrentFramebuffer = std::move(newFramebuffer);

    return angle::Result::Continue;
}

angle::Result FramebufferVk::getFramebuffer(ContextVk *contextVk,
                                            vk::RenderPassFramebuffer *framebufferOut)
{
    ASSERT(!mRenderPassDesc.hasDepthStencilFramebufferFetch());
    ASSERT(mCurrentFramebufferDesc.hasColorFramebufferFetch() ==
           mRenderPassDesc.hasColorFramebufferFetch());

    const gl::Extents attachmentsSize = mState.getExtents();
    ASSERT(attachmentsSize.width != 0 && attachmentsSize.height != 0);

    uint32_t framebufferWidth        = static_cast<uint32_t>(attachmentsSize.width);
    uint32_t framebufferHeight       = static_cast<uint32_t>(attachmentsSize.height);
    const uint32_t framebufferLayers = !mCurrentFramebufferDesc.isMultiview()
                                           ? std::max(mCurrentFramebufferDesc.getLayerCount(), 1u)
                                           : 1;

    ANGLE_TRY(updateAttachmentsAndRenderTargets(contextVk));
    vk::FramebufferAttachmentsVector<VkImageView> unpackedAttachments =
        mCachedAttachmentsInfo.unpackedAttachments;

    vk::Framebuffer framebufferHandle;
    if (contextVk->getFeatures().preferDynamicRendering.enabled)
    {
        // Nothing to do with dynamic rendering.  The image views and other info are still placed in
        // |framebufferOut| to be passed to |vkCmdBeginRendering| similarly to how they are used
        // with imageless framebuffers with render pass objects.
    }
    else if (mCurrentFramebuffer.valid())
    {
        // If a valid framebuffer is already created, use it.  This is not done when the swapchain
        // is being resolved, because the appropriate framebuffer needs to be queried from the back
        // buffer.
        framebufferHandle.setHandle(mCurrentFramebuffer.getHandle());
    }
    else
    {
        // For the default framebuffer attached to a window surface, WindowSurfaceVk caches a
        // handful of framebuffer objects which are queried here.  For the rest, a framebuffer needs
        // to be created based on the current attachments to the FBO.
        if (mBackbuffer == nullptr)
        {
            // Create a new framebuffer
            ANGLE_TRY(createNewFramebuffer(contextVk, framebufferWidth, framebufferHeight,
                                           framebufferLayers));
            ASSERT(mCurrentFramebuffer.valid());
            framebufferHandle.setHandle(mCurrentFramebuffer.getHandle());
        }
        else
        {
            const vk::RenderPass *compatibleRenderPass = nullptr;
            ANGLE_TRY(contextVk->getCompatibleRenderPass(mRenderPassDesc, &compatibleRenderPass));

            // If there is a backbuffer, query the framebuffer from WindowSurfaceVk instead.
            ANGLE_TRY(mBackbuffer->getCurrentFramebuffer(
                contextVk,
                mRenderPassDesc.hasColorFramebufferFetch() ? vk::FramebufferFetchMode::Color
                                                           : vk::FramebufferFetchMode::None,
                mCurrentFramebufferDesc.getWriteControlMode(), *compatibleRenderPass,
                &framebufferHandle));
        }
    }

    if (mBackbuffer != nullptr)
    {
        // Account for swapchain pre-rotation
        framebufferWidth = mCachedAttachmentsInfo.packedRenderTargetsInfo[0]
                               .renderTarget->getRotatedExtents()
                               .width;
        framebufferHeight = mCachedAttachmentsInfo.packedRenderTargetsInfo[0]
                                .renderTarget->getRotatedExtents()
                                .height;
    }

    const vk::ImagelessFramebuffer imagelessFramebuffer =
        contextVk->getFeatures().preferDynamicRendering.enabled ||
                (contextVk->getFeatures().supportsImagelessFramebuffer.enabled &&
                 mBackbuffer == nullptr)
            ? vk::ImagelessFramebuffer::Yes
            : vk::ImagelessFramebuffer::No;
    const vk::RenderPassSource source = mBackbuffer == nullptr
                                            ? vk::RenderPassSource::FramebufferObject
                                            : vk::RenderPassSource::DefaultFramebuffer;

    framebufferOut->setFramebuffer(
        contextVk, std::move(framebufferHandle), std::move(unpackedAttachments), framebufferWidth,
        framebufferHeight, framebufferLayers, imagelessFramebuffer, source);

    return angle::Result::Continue;
}

void FramebufferVk::mergeClearsWithDeferredClears(
    gl::DrawBufferMask clearColorBuffers,
    bool clearDepth,
    bool clearStencil,
    const gl::DrawBuffersArray<VkClearColorValue> &clearColorValues,
    const VkClearDepthStencilValue &clearDepthStencilValue)
{
    // Apply clears to mDeferredClears.  Note that clears override deferred clears.

    // Color clears.
    for (size_t colorIndexGL : clearColorBuffers)
    {
        ASSERT(mState.getEnabledDrawBuffers().test(colorIndexGL));
        VkClearValue clearValue =
            getCorrectedColorClearValue(colorIndexGL, clearColorValues[colorIndexGL]);
        mDeferredClears.store(static_cast<uint32_t>(colorIndexGL), VK_IMAGE_ASPECT_COLOR_BIT,
                              clearValue);
    }

    // Depth and stencil clears.
    VkImageAspectFlags dsAspectFlags = 0;
    VkClearValue dsClearValue        = {};
    dsClearValue.depthStencil        = clearDepthStencilValue;
    if (clearDepth)
    {
        dsAspectFlags |= VK_IMAGE_ASPECT_DEPTH_BIT;
    }
    if (clearStencil)
    {
        dsAspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
    }

    if (dsAspectFlags != 0)
    {
        mDeferredClears.store(vk::kUnpackedDepthIndex, dsAspectFlags, dsClearValue);
    }
}

angle::Result FramebufferVk::clearWithDraw(
    ContextVk *contextVk,
    const gl::Rectangle &clearArea,
    gl::DrawBufferMask clearColorBuffers,
    bool clearDepth,
    bool clearStencil,
    gl::BlendStateExt::ColorMaskStorage::Type colorMasks,
    uint8_t stencilMask,
    const gl::DrawBuffersArray<VkClearColorValue> &clearColorValues,
    const VkClearDepthStencilValue &clearDepthStencilValue)
{
    // All deferred clears should be handled already.
    ASSERT(mDeferredClears.empty());

    UtilsVk::ClearFramebufferParameters params = {};
    params.clearArea                           = clearArea;
    params.depthStencilClearValue              = clearDepthStencilValue;
    params.stencilMask                         = stencilMask;

    params.clearColor   = true;
    params.clearDepth   = clearDepth;
    params.clearStencil = clearStencil;

    const auto &colorRenderTargets = mRenderTargetCache.getColors();
    for (size_t colorIndexGL : clearColorBuffers)
    {
        const RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
        ASSERT(colorRenderTarget);

        params.colorClearValue = clearColorValues[colorIndexGL];
        params.colorFormat     = &colorRenderTarget->getImageForRenderPass().getActualFormat();
        params.colorAttachmentIndexGL = static_cast<uint32_t>(colorIndexGL);
        params.colorMaskFlags =
            gl::BlendStateExt::ColorMaskStorage::GetValueIndexed(colorIndexGL, colorMasks);
        if (mEmulatedAlphaAttachmentMask[colorIndexGL])
        {
            params.colorMaskFlags &= ~VK_COLOR_COMPONENT_A_BIT;
        }

        // TODO: implement clear of layered framebuffers.  UtilsVk::clearFramebuffer should add a
        // geometry shader that is instanced layerCount times (or loops layerCount times), each time
        // selecting a different layer.
        // http://anglebug.com/42263992
        ASSERT(mCurrentFramebufferDesc.isMultiview() || colorRenderTarget->getLayerCount() == 1);

        ANGLE_TRY(contextVk->getUtils().clearFramebuffer(contextVk, this, params));

        // Clear depth/stencil only once!
        params.clearDepth   = false;
        params.clearStencil = false;
    }

    // If there was no color clear, clear depth/stencil alone.
    if (params.clearDepth || params.clearStencil)
    {
        params.clearColor = false;
        ANGLE_TRY(contextVk->getUtils().clearFramebuffer(contextVk, this, params));
    }

    return angle::Result::Continue;
}

VkClearValue FramebufferVk::getCorrectedColorClearValue(size_t colorIndexGL,
                                                        const VkClearColorValue &clearColor) const
{
    VkClearValue clearValue = {};
    clearValue.color        = clearColor;

    if (!mEmulatedAlphaAttachmentMask[colorIndexGL])
    {
        return clearValue;
    }

    // If the render target doesn't have alpha, but its emulated format has it, clear the alpha
    // to 1.
    RenderTargetVk *renderTarget = getColorDrawRenderTarget(colorIndexGL);
    const angle::Format &format  = renderTarget->getImageActualFormat();

    if (format.isUint())
    {
        clearValue.color.uint32[3] = kEmulatedAlphaValue;
    }
    else if (format.isSint())
    {
        clearValue.color.int32[3] = kEmulatedAlphaValue;
    }
    else
    {
        clearValue.color.float32[3] = kEmulatedAlphaValue;
    }

    return clearValue;
}

void FramebufferVk::restageDeferredClears(ContextVk *contextVk)
{
    // Called when restaging clears of the draw framebuffer.  In that case, there can't be any
    // render passes open, otherwise the clear would have applied to the render pass.  In the
    // exceptional occasion in blit where the read framebuffer accumulates deferred clears, it can
    // be deferred while this assumption doesn't hold (and restageDeferredClearsForReadFramebuffer
    // should be used instead).
    ASSERT(!contextVk->hasActiveRenderPass() || !mDeferredClears.any());
    restageDeferredClearsImpl(contextVk);
}

void FramebufferVk::restageDeferredClearsForReadFramebuffer(ContextVk *contextVk)
{
    restageDeferredClearsImpl(contextVk);
}

void FramebufferVk::restageDeferredClearsAfterNoopDraw(ContextVk *contextVk)
{
    restageDeferredClearsImpl(contextVk);
}

void FramebufferVk::restageDeferredClearsImpl(ContextVk *contextVk)
{
    // Set the appropriate aspect and clear values for depth and stencil.
    VkImageAspectFlags dsAspectFlags  = 0;
    VkClearValue dsClearValue         = {};
    dsClearValue.depthStencil.depth   = mDeferredClears.getDepthValue();
    dsClearValue.depthStencil.stencil = mDeferredClears.getStencilValue();

    if (mDeferredClears.testDepth())
    {
        dsAspectFlags |= VK_IMAGE_ASPECT_DEPTH_BIT;
        mDeferredClears.reset(vk::kUnpackedDepthIndex);
    }

    if (mDeferredClears.testStencil())
    {
        dsAspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
        mDeferredClears.reset(vk::kUnpackedStencilIndex);
    }

    // Go through deferred clears and stage the clears for future.
    for (size_t colorIndexGL : mDeferredClears.getColorMask())
    {
        RenderTargetVk *renderTarget = getColorDrawRenderTarget(colorIndexGL);
        gl::ImageIndex imageIndex =
            renderTarget->getImageIndexForClear(mCurrentFramebufferDesc.getLayerCount());
        renderTarget->getImageForWrite().stageClear(imageIndex, VK_IMAGE_ASPECT_COLOR_BIT,
                                                    mDeferredClears[colorIndexGL]);
        mDeferredClears.reset(colorIndexGL);
    }

    if (dsAspectFlags)
    {
        RenderTargetVk *renderTarget = getDepthStencilRenderTarget();
        ASSERT(renderTarget);

        gl::ImageIndex imageIndex =
            renderTarget->getImageIndexForClear(mCurrentFramebufferDesc.getLayerCount());
        renderTarget->getImageForWrite().stageClear(imageIndex, dsAspectFlags, dsClearValue);
    }
}

void FramebufferVk::clearWithCommand(ContextVk *contextVk,
                                     const gl::Rectangle &scissoredRenderArea,
                                     ClearWithCommand behavior,
                                     vk::ClearValuesArray *clears)
{
    // Clear is not affected by viewport, so ContextVk::updateScissor may have decided on a smaller
    // render area.  Grow the render area to the full framebuffer size as this clear path is taken
    // when not scissored.
    vk::RenderPassCommandBufferHelper *renderPassCommands =
        &contextVk->getStartedRenderPassCommands();
    renderPassCommands->growRenderArea(contextVk, scissoredRenderArea);

    gl::AttachmentVector<VkClearAttachment> attachments;

    const bool optimizeWithLoadOp = behavior == ClearWithCommand::OptimizeWithLoadOp;

    // Go through deferred clears and add them to the list of attachments to clear.  If any
    // attachment is unused, skip the clear.  clearWithLoadOp will follow and move the remaining
    // clears up to loadOp.
    //
    // If attachment is already finalized, we can't use loadOp to do clear.
    vk::PackedAttachmentIndex colorIndexVk(0);
    for (size_t colorIndexGL : mState.getColorAttachmentsMask())
    {
        if (clears->getColorMask().test(colorIndexGL))
        {
            if (renderPassCommands->hasAnyColorAccess(colorIndexVk) ||
                renderPassCommands->hasColorAttachmentFinalized(colorIndexVk) ||
                renderPassCommands->getRenderPassDesc().hasColorUnresolveAttachment(colorIndexGL) ||
                !optimizeWithLoadOp)
            {
                // With render pass objects, the clears are indexed by the subpass-mapped locations.
                // With dynamic rendering, they are indexed by the actual attachment index.
                const uint32_t clearAttachmentIndex =
                    contextVk->getFeatures().preferDynamicRendering.enabled
                        ? colorIndexVk.get()
                        : static_cast<uint32_t>(colorIndexGL);

                attachments.emplace_back(VkClearAttachment{
                    VK_IMAGE_ASPECT_COLOR_BIT, clearAttachmentIndex, (*clears)[colorIndexGL]});
                clears->reset(colorIndexGL);
                ++contextVk->getPerfCounters().colorClearAttachments;

                renderPassCommands->onColorAccess(colorIndexVk, vk::ResourceAccess::ReadWrite);
            }
            else
            {
                // Skip this attachment, so we can use a renderpass loadOp to clear it instead.
                // Note that if loadOp=Clear was already used for this color attachment, it will be
                // overriden by the new clear, which is valid because the attachment wasn't used in
                // between.
            }
        }
        ++colorIndexVk;
    }

    // Add depth and stencil to list of attachments as needed.
    VkImageAspectFlags dsAspectFlags  = 0;
    VkClearValue dsClearValue         = {};
    dsClearValue.depthStencil.depth   = clears->getDepthValue();
    dsClearValue.depthStencil.stencil = clears->getStencilValue();
    if (clears->testDepth() &&
        (renderPassCommands->hasAnyDepthAccess() ||
         renderPassCommands->hasDepthAttachmentFinalized() ||
         renderPassCommands->getRenderPassDesc().hasDepthUnresolveAttachment() ||
         !optimizeWithLoadOp))
    {
        dsAspectFlags |= VK_IMAGE_ASPECT_DEPTH_BIT;
        // Explicitly mark a depth write because we are clearing the depth buffer.
        renderPassCommands->onDepthAccess(vk::ResourceAccess::ReadWrite);
        clears->reset(vk::kUnpackedDepthIndex);
        ++contextVk->getPerfCounters().depthClearAttachments;
    }

    if (clears->testStencil() &&
        (renderPassCommands->hasAnyStencilAccess() ||
         renderPassCommands->hasStencilAttachmentFinalized() ||
         renderPassCommands->getRenderPassDesc().hasStencilUnresolveAttachment() ||
         !optimizeWithLoadOp))
    {
        dsAspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
        // Explicitly mark a stencil write because we are clearing the stencil buffer.
        renderPassCommands->onStencilAccess(vk::ResourceAccess::ReadWrite);
        clears->reset(vk::kUnpackedStencilIndex);
        ++contextVk->getPerfCounters().stencilClearAttachments;
    }

    if (dsAspectFlags != 0)
    {
        attachments.emplace_back(VkClearAttachment{dsAspectFlags, 0, dsClearValue});

        // Because we may have changed the depth/stencil access mode, update read only depth/stencil
        // mode.
        renderPassCommands->updateDepthStencilReadOnlyMode(
            contextVk->getDepthStencilAttachmentFlags(), dsAspectFlags);
    }

    if (attachments.empty())
    {
        // If called with the intent to definitely clear something with vkCmdClearAttachments, there
        // must have been something to clear!
        ASSERT(optimizeWithLoadOp);
        return;
    }

    const uint32_t layerCount = mState.isMultiview() ? 1 : mCurrentFramebufferDesc.getLayerCount();

    VkClearRect rect                                     = {};
    rect.rect.offset.x                                   = scissoredRenderArea.x;
    rect.rect.offset.y                                   = scissoredRenderArea.y;
    rect.rect.extent.width                               = scissoredRenderArea.width;
    rect.rect.extent.height                              = scissoredRenderArea.height;
    rect.layerCount                                      = layerCount;
    vk::RenderPassCommandBuffer *renderPassCommandBuffer = &renderPassCommands->getCommandBuffer();

    renderPassCommandBuffer->clearAttachments(static_cast<uint32_t>(attachments.size()),
                                              attachments.data(), 1, &rect);
    return;
}

void FramebufferVk::clearWithLoadOp(ContextVk *contextVk)
{
    vk::RenderPassCommandBufferHelper *renderPassCommands =
        &contextVk->getStartedRenderPassCommands();

    // Update the render pass loadOps to clear the attachments.
    vk::PackedAttachmentIndex colorIndexVk(0);
    for (size_t colorIndexGL : mState.getColorAttachmentsMask())
    {
        if (!mDeferredClears.test(colorIndexGL))
        {
            ++colorIndexVk;
            continue;
        }

        ASSERT(!renderPassCommands->hasAnyColorAccess(colorIndexVk));

        renderPassCommands->updateRenderPassColorClear(colorIndexVk, mDeferredClears[colorIndexGL]);

        mDeferredClears.reset(colorIndexGL);

        ++colorIndexVk;
    }

    VkClearValue dsClearValue         = {};
    dsClearValue.depthStencil.depth   = mDeferredClears.getDepthValue();
    dsClearValue.depthStencil.stencil = mDeferredClears.getStencilValue();
    VkImageAspectFlags dsAspects      = 0;

    if (mDeferredClears.testDepth())
    {
        ASSERT(!renderPassCommands->hasAnyDepthAccess());
        dsAspects |= VK_IMAGE_ASPECT_DEPTH_BIT;
        mDeferredClears.reset(vk::kUnpackedDepthIndex);
    }

    if (mDeferredClears.testStencil())
    {
        ASSERT(!renderPassCommands->hasAnyStencilAccess());
        dsAspects |= VK_IMAGE_ASPECT_STENCIL_BIT;
        mDeferredClears.reset(vk::kUnpackedStencilIndex);
    }

    if (dsAspects != 0)
    {
        renderPassCommands->updateRenderPassDepthStencilClear(dsAspects, dsClearValue);

        // The render pass can no longer be in read-only depth/stencil mode.
        renderPassCommands->updateDepthStencilReadOnlyMode(
            contextVk->getDepthStencilAttachmentFlags(), dsAspects);
    }
}

angle::Result FramebufferVk::getSamplePosition(const gl::Context *context,
                                               size_t index,
                                               GLfloat *xy) const
{
    int sampleCount = getSamples();
    rx::GetSamplePosition(sampleCount, index, xy);
    return angle::Result::Continue;
}

angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
                                                const gl::Rectangle &renderArea,
                                                vk::RenderPassCommandBuffer **commandBufferOut,
                                                bool *renderPassDescChangedOut)
{
    ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass(RenderPassClosureReason::NewRenderPass));

    // Initialize RenderPass info.
    vk::AttachmentOpsArray renderPassAttachmentOps;
    vk::PackedClearValuesArray packedClearValues;
    gl::DrawBufferMask previousUnresolveColorMask =
        mRenderPassDesc.getColorUnresolveAttachmentMask();
    const bool hasDeferredClears        = mDeferredClears.any();
    const bool previousUnresolveDepth   = mRenderPassDesc.hasDepthUnresolveAttachment();
    const bool previousUnresolveStencil = mRenderPassDesc.hasStencilUnresolveAttachment();

    // Make sure render pass and framebuffer are in agreement w.r.t unresolve attachments.
    ASSERT(mCurrentFramebufferDesc.getUnresolveAttachmentMask() ==
           MakeUnresolveAttachmentMask(mRenderPassDesc));
    // ... w.r.t sRGB write control.
    ASSERT(mCurrentFramebufferDesc.getWriteControlMode() ==
           mRenderPassDesc.getSRGBWriteControlMode());
    // ... w.r.t foveation.
    ASSERT(mCurrentFramebufferDesc.hasFragmentShadingRateAttachment() ==
           mRenderPassDesc.hasFragmentShadingAttachment());

    // Color attachments.
    const auto &colorRenderTargets = mRenderTargetCache.getColors();
    vk::PackedAttachmentIndex colorIndexVk(0);
    for (size_t colorIndexGL : mState.getColorAttachmentsMask())
    {
        RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
        ASSERT(colorRenderTarget);

        // Color render targets are never entirely transient.  Only depth/stencil
        // multisampled-render-to-texture textures can be so.
        ASSERT(!colorRenderTarget->isEntirelyTransient());
        const vk::RenderPassStoreOp storeOp = colorRenderTarget->isImageTransient()
                                                  ? vk::RenderPassStoreOp::DontCare
                                                  : vk::RenderPassStoreOp::Store;

        if (mDeferredClears.test(colorIndexGL))
        {
            renderPassAttachmentOps.setOps(colorIndexVk, vk::RenderPassLoadOp::Clear, storeOp);
            packedClearValues.storeColor(colorIndexVk, mDeferredClears[colorIndexGL]);
            mDeferredClears.reset(colorIndexGL);
        }
        else
        {
            const vk::RenderPassLoadOp loadOp = colorRenderTarget->hasDefinedContent()
                                                    ? vk::RenderPassLoadOp::Load
                                                    : vk::RenderPassLoadOp::DontCare;

            renderPassAttachmentOps.setOps(colorIndexVk, loadOp, storeOp);
            packedClearValues.storeColor(colorIndexVk, kUninitializedClearValue);
        }
        renderPassAttachmentOps.setStencilOps(colorIndexVk, vk::RenderPassLoadOp::DontCare,
                                              vk::RenderPassStoreOp::DontCare);

        // If there's a resolve attachment, and loadOp needs to be LOAD, the multisampled attachment
        // needs to take its value from the resolve attachment.  In this case, an initial subpass is
        // added for this very purpose which uses the resolve attachment as input attachment.  As a
        // result, loadOp of the multisampled attachment can remain DONT_CARE.
        //
        // Note that this only needs to be done if the multisampled image and the resolve attachment
        // come from the same source.  isImageTransient() indicates whether this should happen.
        if (colorRenderTarget->hasResolveAttachment() && colorRenderTarget->isImageTransient())
        {
            if (renderPassAttachmentOps[colorIndexVk].loadOp == VK_ATTACHMENT_LOAD_OP_LOAD)
            {
                // Unresolve for YUV render targets is done using a separate renderpass
                if (colorRenderTarget->isYuvResolve())
                {
                    ASSERT(!mRenderPassDesc.getColorUnresolveAttachmentMask().test(colorIndexGL));
                    ANGLE_TRY(UnresolveYuvImage(contextVk, colorRenderTarget, renderArea));
                }
                else
                {
                    renderPassAttachmentOps[colorIndexVk].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;

                    // Update the render pass desc to specify that this attachment should be
                    // unresolved.
                    mRenderPassDesc.packColorUnresolveAttachment(colorIndexGL);
                }
            }
            else
            {
                mRenderPassDesc.removeColorUnresolveAttachment(colorIndexGL);
            }
        }
        else
        {
            ASSERT(!mRenderPassDesc.getColorUnresolveAttachmentMask().test(colorIndexGL));
        }

        ++colorIndexVk;
    }

    // Depth/stencil attachment.
    vk::PackedAttachmentIndex depthStencilAttachmentIndex = vk::kAttachmentIndexInvalid;
    RenderTargetVk *depthStencilRenderTarget              = getDepthStencilRenderTarget();
    if (depthStencilRenderTarget)
    {
        // depth stencil attachment always immediately follows color attachment
        depthStencilAttachmentIndex = colorIndexVk;

        vk::RenderPassLoadOp depthLoadOp     = vk::RenderPassLoadOp::Load;
        vk::RenderPassLoadOp stencilLoadOp   = vk::RenderPassLoadOp::Load;
        vk::RenderPassStoreOp depthStoreOp   = vk::RenderPassStoreOp::Store;
        vk::RenderPassStoreOp stencilStoreOp = vk::RenderPassStoreOp::Store;

        // If the image data was previously discarded (with no update in between), don't attempt to
        // load the image.  Additionally, if the multisampled image data is transient and there is
        // no resolve attachment, there's no data to load.  The latter is the case with
        // depth/stencil texture attachments per GL_EXT_multisampled_render_to_texture2.
        if (!depthStencilRenderTarget->hasDefinedContent() ||
            depthStencilRenderTarget->isEntirelyTransient())
        {
            depthLoadOp = vk::RenderPassLoadOp::DontCare;
        }
        if (!depthStencilRenderTarget->hasDefinedStencilContent() ||
            depthStencilRenderTarget->isEntirelyTransient())
        {
            stencilLoadOp = vk::RenderPassLoadOp::DontCare;
        }

        // If depth/stencil image is transient, no need to store its data at the end of the render
        // pass.
        if (depthStencilRenderTarget->isImageTransient())
        {
            depthStoreOp   = vk::RenderPassStoreOp::DontCare;
            stencilStoreOp = vk::RenderPassStoreOp::DontCare;
        }

        if (mDeferredClears.testDepth() || mDeferredClears.testStencil())
        {
            VkClearValue clearValue = {};

            if (mDeferredClears.testDepth())
            {
                depthLoadOp                   = vk::RenderPassLoadOp::Clear;
                clearValue.depthStencil.depth = mDeferredClears.getDepthValue();
                mDeferredClears.reset(vk::kUnpackedDepthIndex);
            }

            if (mDeferredClears.testStencil())
            {
                stencilLoadOp                   = vk::RenderPassLoadOp::Clear;
                clearValue.depthStencil.stencil = mDeferredClears.getStencilValue();
                mDeferredClears.reset(vk::kUnpackedStencilIndex);
            }

            packedClearValues.storeDepthStencil(depthStencilAttachmentIndex, clearValue);
        }
        else
        {
            packedClearValues.storeDepthStencil(depthStencilAttachmentIndex,
                                                kUninitializedClearValue);
        }

        const angle::Format &format = depthStencilRenderTarget->getImageIntendedFormat();
        // If the format we picked has stencil but user did not ask for it due to hardware
        // limitations, use DONT_CARE for load/store. The same logic for depth follows.
        if (format.stencilBits == 0)
        {
            stencilLoadOp  = vk::RenderPassLoadOp::DontCare;
            stencilStoreOp = vk::RenderPassStoreOp::DontCare;
        }
        if (format.depthBits == 0)
        {
            depthLoadOp  = vk::RenderPassLoadOp::DontCare;
            depthStoreOp = vk::RenderPassStoreOp::DontCare;
        }

        // Similar to color attachments, if there's a resolve attachment and the multisampled image
        // is transient, depth/stencil data need to be unresolved in an initial subpass.
        if (depthStencilRenderTarget->hasResolveAttachment() &&
            depthStencilRenderTarget->isImageTransient())
        {
            const bool unresolveDepth   = depthLoadOp == vk::RenderPassLoadOp::Load;
            const bool unresolveStencil = stencilLoadOp == vk::RenderPassLoadOp::Load;

            if (unresolveDepth)
            {
                depthLoadOp = vk::RenderPassLoadOp::DontCare;
            }

            if (unresolveStencil)
            {
                stencilLoadOp = vk::RenderPassLoadOp::DontCare;

                // If VK_EXT_shader_stencil_export is not supported, stencil unresolve is done
                // through a method that requires stencil to have been cleared.
                if (!contextVk->getFeatures().supportsShaderStencilExport.enabled)
                {
                    stencilLoadOp = vk::RenderPassLoadOp::Clear;

                    VkClearValue clearValue = packedClearValues[depthStencilAttachmentIndex];
                    clearValue.depthStencil.stencil = 0;
                    packedClearValues.storeDepthStencil(depthStencilAttachmentIndex, clearValue);
                }
            }

            if (unresolveDepth)
            {
                mRenderPassDesc.packDepthUnresolveAttachment();
            }
            else
            {
                mRenderPassDesc.removeDepthUnresolveAttachment();
            }
            if (unresolveStencil)
            {
                mRenderPassDesc.packStencilUnresolveAttachment();
            }
            else
            {
                mRenderPassDesc.removeStencilUnresolveAttachment();
            }
        }

        renderPassAttachmentOps.setOps(depthStencilAttachmentIndex, depthLoadOp, depthStoreOp);
        renderPassAttachmentOps.setStencilOps(depthStencilAttachmentIndex, stencilLoadOp,
                                              stencilStoreOp);
    }

    // If render pass description is changed, the previous render pass desc is no longer compatible.
    // Tell the context so that the graphics pipelines can be recreated.
    //
    // Note that render passes are compatible only if the differences are in loadOp/storeOp values,
    // or the existence of resolve attachments in single subpass render passes.  The modification
    // here can add/remove a subpass, or modify its input attachments.
    gl::DrawBufferMask unresolveColorMask = mRenderPassDesc.getColorUnresolveAttachmentMask();
    const bool unresolveDepth             = mRenderPassDesc.hasDepthUnresolveAttachment();
    const bool unresolveStencil           = mRenderPassDesc.hasStencilUnresolveAttachment();
    const bool unresolveChanged           = previousUnresolveColorMask != unresolveColorMask ||
                                  previousUnresolveDepth != unresolveDepth ||
                                  previousUnresolveStencil != unresolveStencil;
    if (unresolveChanged)
    {
        // Make sure framebuffer is recreated.
        releaseCurrentFramebuffer(contextVk);

        mCurrentFramebufferDesc.updateUnresolveMask(MakeUnresolveAttachmentMask(mRenderPassDesc));
    }

    vk::RenderPassFramebuffer framebuffer = {};
    ANGLE_TRY(getFramebuffer(contextVk, &framebuffer));

    // If deferred clears were used in the render pass, the render area must cover the whole
    // framebuffer.
    ASSERT(!hasDeferredClears || renderArea == getRotatedCompleteRenderArea(contextVk));

    ANGLE_TRY(contextVk->beginNewRenderPass(
        std::move(framebuffer), renderArea, mRenderPassDesc, renderPassAttachmentOps, colorIndexVk,
        depthStencilAttachmentIndex, packedClearValues, commandBufferOut));
    mLastRenderPassQueueSerial = contextVk->getStartedRenderPassCommands().getQueueSerial();

    // Add the images to the renderpass tracking list (through onColorDraw).
    vk::PackedAttachmentIndex colorAttachmentIndex(0);
    for (size_t colorIndexGL : mState.getColorAttachmentsMask())
    {
        RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
        colorRenderTarget->onColorDraw(contextVk, mCurrentFramebufferDesc.getLayerCount(),
                                       colorAttachmentIndex);
        ++colorAttachmentIndex;
    }

    if (depthStencilRenderTarget)
    {
        // This must be called after hasDefined*Content() since it will set content to valid.  If
        // the attachment ends up not used in the render pass, contents will be marked undefined at
        // endRenderPass.  The actual layout determination is also deferred until the same time.
        depthStencilRenderTarget->onDepthStencilDraw(contextVk,
                                                     mCurrentFramebufferDesc.getLayerCount());
    }

    const bool anyUnresolve = unresolveColorMask.any() || unresolveDepth || unresolveStencil;
    if (anyUnresolve)
    {
        // Unresolve attachments if any.
        UtilsVk::UnresolveParameters params;
        params.unresolveColorMask = unresolveColorMask;
        params.unresolveDepth     = unresolveDepth;
        params.unresolveStencil   = unresolveStencil;

        ANGLE_TRY(contextVk->getUtils().unresolve(contextVk, this, params));

        // The unresolve subpass has only one draw call.
        ANGLE_TRY(contextVk->startNextSubpass());
    }

    if (unresolveChanged || anyUnresolve)
    {
        contextVk->onDrawFramebufferRenderPassDescChange(this, renderPassDescChangedOut);
    }

    // Add fragment shading rate to the tracking list.
    if (mCurrentFramebufferDesc.hasFragmentShadingRateAttachment())
    {
        contextVk->onFragmentShadingRateRead(&mFragmentShadingRateImage);
    }

    return angle::Result::Continue;
}

gl::Rectangle FramebufferVk::getRenderArea(ContextVk *contextVk) const
{
    if (hasDeferredClears())
    {
        return getRotatedCompleteRenderArea(contextVk);
    }
    else
    {
        return getRotatedScissoredRenderArea(contextVk);
    }
}

void FramebufferVk::updateActiveColorMasks(size_t colorIndexGL, bool r, bool g, bool b, bool a)
{
    gl::BlendStateExt::ColorMaskStorage::SetValueIndexed(
        colorIndexGL, gl::BlendStateExt::PackColorMask(r, g, b, a),
        &mActiveColorComponentMasksForClear);
}

const gl::DrawBufferMask &FramebufferVk::getEmulatedAlphaAttachmentMask() const
{
    return mEmulatedAlphaAttachmentMask;
}

angle::Result FramebufferVk::readPixelsImpl(ContextVk *contextVk,
                                            const gl::Rectangle &area,
                                            const PackPixelsParams &packPixelsParams,
                                            VkImageAspectFlagBits copyAspectFlags,
                                            RenderTargetVk *renderTarget,
                                            void *pixels)
{
    ANGLE_TRACE_EVENT0("gpu.angle", "FramebufferVk::readPixelsImpl");
    gl::LevelIndex levelGL = renderTarget->getLevelIndex();
    uint32_t layer         = renderTarget->getLayerIndex();
    return renderTarget->getImageForCopy().readPixels(contextVk, area, packPixelsParams,
                                                      copyAspectFlags, levelGL, layer, pixels);
}

gl::Extents FramebufferVk::getReadImageExtents() const
{
    RenderTargetVk *readRenderTarget = mRenderTargetCache.getColorRead(mState);
    return readRenderTarget->getExtents();
}

// Return the framebuffer's rotated render area.  This is a gl::Rectangle that is based on the
// dimensions of the framebuffer, IS ROTATED for the draw FBO, and IS NOT y-flipped
//
// Note: Since the rectangle is not scissored (i.e. x and y are guaranteed to be zero), only the
// width and height must be swapped if the rotation is 90 or 270 degrees.
gl::Rectangle FramebufferVk::getRotatedCompleteRenderArea(ContextVk *contextVk) const
{
    gl::Rectangle renderArea = getNonRotatedCompleteRenderArea();
    if (contextVk->isRotatedAspectRatioForDrawFBO())
    {
        // The surface is rotated 90/270 degrees.  This changes the aspect ratio of the surface.
        std::swap(renderArea.width, renderArea.height);
    }
    return renderArea;
}

// Return the framebuffer's scissored and rotated render area.  This is a gl::Rectangle that is
// based on the dimensions of the framebuffer, is clipped to the scissor, IS ROTATED and IS
// Y-FLIPPED for the draw FBO.
//
// Note: Since the rectangle is scissored, it must be fully rotated, and not just have the width
// and height swapped.
gl::Rectangle FramebufferVk::getRotatedScissoredRenderArea(ContextVk *contextVk) const
{
    const gl::Rectangle renderArea = getNonRotatedCompleteRenderArea();
    bool invertViewport            = contextVk->isViewportFlipEnabledForDrawFBO();
    gl::Rectangle scissoredArea    = ClipRectToScissor(contextVk->getState(), renderArea, false);
    gl::Rectangle rotatedScissoredArea;
    RotateRectangle(contextVk->getRotationDrawFramebuffer(), invertViewport, renderArea.width,
                    renderArea.height, scissoredArea, &rotatedScissoredArea);
    return rotatedScissoredArea;
}

GLint FramebufferVk::getSamplesImpl() const
{
    const gl::FramebufferAttachment *lastAttachment = nullptr;

    for (size_t colorIndexGL : mState.getColorAttachmentsMask())
    {
        const gl::FramebufferAttachment *color = mState.getColorAttachment(colorIndexGL);
        ASSERT(color);

        if (color->isRenderToTexture())
        {
            return color->getSamples();
        }

        lastAttachment = color;
    }
    const gl::FramebufferAttachment *depthStencil = mState.getDepthOrStencilAttachment();
    if (depthStencil)
    {
        if (depthStencil->isRenderToTexture())
        {
            return depthStencil->getSamples();
        }
        lastAttachment = depthStencil;
    }

    // If none of the attachments are multisampled-render-to-texture, take the sample count from the
    // last attachment (any would have worked, as they would all have the same sample count).
    return lastAttachment ? lastAttachment->getSamples() : 1;
}

angle::Result FramebufferVk::flushDepthStencilDeferredClear(ContextVk *contextVk,
                                                            VkImageAspectFlagBits aspect)
{
    const bool isDepth = aspect == VK_IMAGE_ASPECT_DEPTH_BIT;

    // Pick out the deferred clear for the given aspect, and issue it ahead of the render pass.
    // This is used when switching this aspect to read-only mode, in which case the clear operation
    // for the aspect cannot be done as part of the render pass loadOp.
    ASSERT(!isDepth || hasDeferredDepthClear());
    ASSERT(isDepth || hasDeferredStencilClear());
    ASSERT(mState.getDepthOrStencilAttachment() != nullptr);

    RenderTargetVk *renderTarget = getDepthStencilRenderTarget();
    vk::ImageHelper &image       = renderTarget->getImageForCopy();

    // Depth/stencil attachments cannot be 3D.
    ASSERT(!renderTarget->is3DImage());

    vk::CommandResources resources;
    resources.onImageTransferWrite(renderTarget->getLevelIndex(), 1, renderTarget->getLayerIndex(),
                                   renderTarget->getLayerCount(), image.getAspectFlags(), &image);
    vk::OutsideRenderPassCommandBuffer *commandBuffer;
    ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(resources, &commandBuffer));

    VkImageSubresourceRange range = {};
    range.aspectMask              = aspect;
    range.baseMipLevel            = image.toVkLevel(renderTarget->getLevelIndex()).get();
    range.levelCount              = 1;
    range.baseArrayLayer          = renderTarget->getLayerIndex();
    range.layerCount              = renderTarget->getLayerCount();

    VkClearDepthStencilValue clearValue = {};

    if (isDepth)
    {
        clearValue.depth = mDeferredClears.getDepthValue();
        mDeferredClears.reset(vk::kUnpackedDepthIndex);
    }
    else
    {
        clearValue.stencil = mDeferredClears.getStencilValue();
        mDeferredClears.reset(vk::kUnpackedStencilIndex);
    }

    commandBuffer->clearDepthStencilImage(
        image.getImage(), image.getCurrentLayout(contextVk->getRenderer()), clearValue, 1, &range);
    return angle::Result::Continue;
}

angle::Result FramebufferVk::flushDeferredClears(ContextVk *contextVk)
{
    if (mDeferredClears.empty())
    {
        return angle::Result::Continue;
    }

    return contextVk->startRenderPass(getRotatedCompleteRenderArea(contextVk), nullptr, nullptr);
}

void FramebufferVk::switchToColorFramebufferFetchMode(ContextVk *contextVk,
                                                      bool hasColorFramebufferFetch)
{
    // Framebuffer fetch use by the shader does not affect the framebuffer object in any way with
    // dynamic rendering.
    ASSERT(!contextVk->getFeatures().preferDynamicRendering.enabled);

    // The switch happens once, and is permanent.
    if (mCurrentFramebufferDesc.hasColorFramebufferFetch() == hasColorFramebufferFetch)
    {
        return;
    }

    mCurrentFramebufferDesc.setColorFramebufferFetchMode(hasColorFramebufferFetch);

    mRenderPassDesc.setFramebufferFetchMode(hasColorFramebufferFetch
                                                ? vk::FramebufferFetchMode::Color
                                                : vk::FramebufferFetchMode::None);
    contextVk->onDrawFramebufferRenderPassDescChange(this, nullptr);

    // Make sure framebuffer is recreated.
    releaseCurrentFramebuffer(contextVk);

    // Clear the framebuffer cache, as none of the old framebuffers are usable.
    if (contextVk->getFeatures().permanentlySwitchToFramebufferFetchMode.enabled)
    {
        ASSERT(hasColorFramebufferFetch);
        releaseCurrentFramebuffer(contextVk);
    }
}

bool FramebufferVk::updateLegacyDither(ContextVk *contextVk)
{
    if (contextVk->getFeatures().supportsLegacyDithering.enabled &&
        mRenderPassDesc.isLegacyDitherEnabled() != contextVk->isDitherEnabled())
    {
        mRenderPassDesc.setLegacyDither(contextVk->isDitherEnabled());
        return true;
    }

    return false;
}

const vk::ImageHelper *FramebufferVk::getImageWithTileMemory() const
{
    RenderTargetVk *depthStencilRenderTarget = getDepthStencilRenderTarget();
    if (!depthStencilRenderTarget)
    {
        return nullptr;
    }

    const vk::ImageHelper *image = nullptr;
    if (depthStencilRenderTarget->hasResolveAttachment())
    {
        image = &depthStencilRenderTarget->getResolveImageForRenderPass();
    }
    else
    {
        image = &depthStencilRenderTarget->getImageForRenderPass();
    }

    if (image->useTileMemory())
    {
        return image;
    }

    return nullptr;
}
}  // namespace rx
