//
// 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);
}

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

// 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())
    {
        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::FramebufferHelper &&newFramebuffer)
{
    // Add it into per share group cache
    contextVk->getShareGroup()->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 (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,
            "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();
    bool anyAttachmentWithColorspaceOverride     = false;
    for (size_t colorIndexGL = 0; colorIndexGL < colorAttachmentMask.size(); ++colorIndexGL)
    {
        if (colorAttachmentMask[colorIndexGL])
        {
            adjustedClearColorValues[colorIndexGL] = clearColorValue;

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

            // If a rendertarget has colorspace overrides, we need to clear with a draw
            // to make sure the colorspace override is honored.
            anyAttachmentWithColorspaceOverride =
                anyAttachmentWithColorspaceOverride ||
                colorRenderTarget->hasColorspaceOverrideForWrite();

            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;

    bool clearColorWithDraw =
        clearColor && (maskedClearColor || scissoredClear || anyAttachmentWithColorspaceOverride);
    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));
    }

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

    // 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 && !anyAttachmentWithColorspaceOverride)
    {
        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);
    }

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

    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 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;
    bool noFlip                         = false;
    bool disableFlippingBlitWithCommand = false;

    UtilsVk::BlitResolveParameters params;
    params.stretch[0] = static_cast<float>(stretch[0]);
    params.stretch[1] = static_cast<float>(stretch[1]);
    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;
        noFlip = !flipX && !flipY;
        disableFlippingBlitWithCommand =
            renderer->getFeatures().disableFlippingBlitWithCommand.enabled;

        // 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 && (noFlip || !disableFlippingBlitWithCommand) &&
            HasSrcBlitFeature(renderer, readRenderTarget) && rotation == SurfaceRotation::Identity;

        // If we need to reinterpret the colorspace of the read RenderTarget then the blit must be
        // done through a shader
        bool reinterpretsColorspace      = readRenderTarget->hasColorspaceOverrideForRead();
        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());

            // If we need to reinterpret the colorspace of the draw RenderTarget then the blit must
            // be done through a shader
            reinterpretsColorspace =
                reinterpretsColorspace || drawRenderTarget->hasColorspaceOverrideForWrite();
        }

        // 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);
            }

            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();

        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;
        noFlip = !flipX && !flipY;
        disableFlippingBlitWithCommand =
            renderer->getFeatures().disableFlippingBlitWithCommand.enabled;

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

        // Similarly, only blit if there's been no clipping or rotating.
        bool canBlitWithCommand =
            !isDepthStencilResolve && noClip && (noFlip || !disableFlippingBlitWithCommand) &&
            HasSrcBlitFeature(renderer, readRenderTarget) &&
            HasDstBlitFeature(renderer, drawRenderTarget) && rotation == SurfaceRotation::Identity;
        bool areChannelsBlitCompatible =
            AreSrcAndDstDepthStencilChannelsBlitCompatible(readRenderTarget, drawRenderTarget);

        // glBlitFramebuffer requires that depth/stencil blits have matching formats.
        ASSERT(AreSrcAndDstFormatsIdentical(readRenderTarget, drawRenderTarget));

        if (canBlitWithCommand && areChannelsBlitCompatible)
        {
            ANGLE_TRY(blitWithCommand(contextVk, sourceArea, destArea, readRenderTarget,
                                      drawRenderTarget, filter, false, blitDepthBuffer,
                                      blitStencilBuffer, flipX, flipY));
        }
        else
        {
            vk::ImageHelper *depthStencilImage = &readRenderTarget->getImageForCopy();

            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 depthStencilImageAspects =
                    depthStencilImage->getAspectFlags();
                const bool resolvesAllAspects =
                    (resolveAspects & depthStencilImageAspects) == depthStencilImageAspects;

                // 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)
            {
                ANGLE_TRY(resolveDepthStencilWithSubpass(contextVk, params, resolveAspects));
            }
            else
            {
                // See comment for the draw-based color blit.  The render pass must be flushed
                // before creating the views.
                ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass(
                    RenderPassClosureReason::PrepareForBlit));

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

                // Get depth- and stencil-only views for reading.
                const vk::ImageView *depthView   = nullptr;
                const vk::ImageView *stencilView = nullptr;

                if (blitDepthBuffer)
                {
                    ANGLE_TRY(readRenderTarget->getDepthOrStencilImageViewForCopy(
                        contextVk, VK_IMAGE_ASPECT_DEPTH_BIT, &depthView));
                }

                if (blitStencilBuffer)
                {
                    ANGLE_TRY(readRenderTarget->getDepthOrStencilImageViewForCopy(
                        contextVk, VK_IMAGE_ASPECT_STENCIL_BIT, &stencilView));
                }

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

                // Blit depth. If shader stencil export is present, blit stencil as well.
                if (blitDepthBuffer || (blitStencilBuffer && hasShaderStencilExport))
                {
                    ANGLE_TRY(utilsVk.depthStencilBlitResolve(
                        contextVk, this, depthStencilImage, depthView,
                        hasShaderStencilExport ? stencilView : 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, this, depthStencilImage, stencilView, 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));

        ANGLE_TRY(contextVk->initImageAllocation(
            &mFragmentShadingRateImage, false, renderer->getMemoryProperties(),
            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);

    // Remove deferred clears for the invalidated attachments.
    if (invalidateDepthBuffer)
    {
        mDeferredClears.reset(vk::kUnpackedDepthIndex);
    }
    if (invalidateStencilBuffer)
    {
        mDeferredClears.reset(vk::kUnpackedStencilIndex);
    }
    for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
    {
        if (invalidateColorBuffers.test(colorIndexGL))
        {
            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 (!isSubInvalidate)
    {
        for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
        {
            if (invalidateColorBuffers.test(colorIndexGL))
            {
                RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndexGL];
                ASSERT(colorRenderTarget);

                bool preferToKeepContentsDefined = false;
                colorRenderTarget->invalidateEntireContent(contextVk, &preferToKeepContentsDefined);
                if (preferToKeepContentsDefined)
                {
                    invalidateColorBuffers.reset(colorIndexGL);
                }
            }
        }

        // 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;
                }
            }
        }
    }

    // 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))
    {
        bool closeRenderPass = false;

        // 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 (mState.getEnabledDrawBuffers()[colorIndexGL] &&
                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);
    }
}

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 colospace could have been modified in another context, update
    // colorspace of all attachments to reflect current context's colorspace.
    gl::SrgbWriteControlMode srgbWriteControlMode = mState.getWriteControlMode();
    updateColorAttachmentColorspace(srgbWriteControlMode);
    // Update current framebuffer descriptor to reflect the new state.
    mCurrentFramebufferDesc.setWriteControlMode(srgbWriteControlMode);

    if (shouldUpdateColorMaskAndBlend)
    {
        contextVk->updateColorMasks();
        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;
    }

    // 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 = 0; colorIndexGL < colorAttachmentMask.size(); ++colorIndexGL)
    {
        if (colorAttachmentMask[colorIndexGL])
        {
            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 (colorRenderTarget->hasColorspaceOverrideForWrite())
                {
                    actualFormat =
                        colorRenderTarget->getColorspaceOverrideFormatForWrite(actualFormat);
                }

                mRenderPassDesc.packColorAttachment(colorIndexGL, actualFormat);
                // Add the resolve attachment, if any.
                if (colorRenderTarget->hasResolveAttachment())
                {
                    mRenderPassDesc.packColorResolveAttachment(colorIndexGL);
                }
            }
        }
        else
        {
            mRenderPassDesc.packColorAttachmentGap(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.getEnabledDrawBuffers())
        {
            const gl::FramebufferAttachment *color = mState.getColorAttachment(colorIndexGL);
            ASSERT(color);

            if (color->isRenderToTexture())
            {
                isRenderToTexture = true;
                break;
            }
        }
        const gl::FramebufferAttachment *depthStencil = mState.getDepthStencilAttachment();
        if (depthStencil && depthStencil->isRenderToTexture())
        {
            isRenderToTexture = true;
        }

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

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

    updateLegacyDither(contextVk);
}

angle::Result FramebufferVk::getAttachmentsAndRenderTargets(
    ContextVk *contextVk,
    vk::FramebufferAttachmentsVector<VkImageView> *unpackedAttachments,
    vk::FramebufferAttachmentsVector<RenderTargetInfo> *packedRenderTargetsInfoOut)
{
    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));
                unpackedAttachments->push_back(resolveImageView->getHandle());

                packedRenderTargetsInfoOut->emplace_back(
                    RenderTargetInfo(colorRenderTarget, RenderTargetImage::Resolve));

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

        packedRenderTargetsInfoOut->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));

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

    // Fragment shading rate attachment.
    if (mCurrentFramebufferDesc.hasFragmentShadingRateAttachment())
    {
        const vk::ImageViewHelper *imageViewHelper = &mFragmentShadingRateImageView;
        unpackedAttachments->push_back(
            imageViewHelper->getFragmentShadingRateImageView().getHandle());
        packedRenderTargetsInfoOut->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.
    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;
            (*unpackedAttachments)[kBaseIndex + colorIndexGL] = resolveImageView->getHandle();
            packedRenderTargetsInfoOut->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));

        (*unpackedAttachments)[vk::RenderPassFramebuffer::kDepthStencilResolveAttachment] =
            imageView->getHandle();
        packedRenderTargetsInfoOut->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,
    const vk::FramebufferAttachmentsVector<VkImageView> &unpackedAttachments,
    const vk::FramebufferAttachmentsVector<RenderTargetInfo> &renderTargetsInfo)
{
    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->getShareGroup()->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.
    vk::FramebufferHelper newFramebuffer;

    VkFramebufferCreateInfo framebufferInfo = {};
    framebufferInfo.sType                   = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
    framebufferInfo.flags                   = 0;
    framebufferInfo.renderPass              = compatibleRenderPass->getHandle();
    framebufferInfo.attachmentCount         = static_cast<uint32_t>(renderTargetsInfo.size());
    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()) ||
           static_cast<uint32_t>(renderTargetsInfo.size()) ==
               mCurrentFramebufferDesc.attachmentCount());

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

        ASSERT(renderTargetsInfo.size() == 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_TRY(newFramebuffer.init(contextVk, framebufferInfo));
        if (packedAttachments.empty())
        {
            mCurrentFramebuffer         = std::move(newFramebuffer.getFramebuffer());
            mIsCurrentFramebufferCached = false;
        }
        else
        {
            insertCache(contextVk, mCurrentFramebufferDesc, std::move(newFramebuffer));

            const bool result = contextVk->getShareGroup()->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(
        renderTargetsInfo.size(), {});

    for (size_t index = 0; index < renderTargetsInfo.size(); ++index)
    {
        const RenderTargetInfo &info                     = renderTargetsInfo[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_TRY(newFramebuffer.init(contextVk, framebufferInfo));
    mCurrentFramebuffer = std::move(newFramebuffer.getFramebuffer());

    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;

    vk::FramebufferAttachmentsVector<VkImageView> unpackedAttachments;
    vk::FramebufferAttachmentsVector<RenderTargetInfo> renderTargetsInfo;
    ANGLE_TRY(getAttachmentsAndRenderTargets(contextVk, &unpackedAttachments, &renderTargetsInfo));

    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, unpackedAttachments,
                                           renderTargetsInfo));
            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,
                *compatibleRenderPass, &framebufferHandle));
        }
    }

    if (mBackbuffer != nullptr)
    {
        // Account for swapchain pre-rotation
        framebufferWidth  = renderTargetsInfo[0].renderTarget->getRotatedExtents().width;
        framebufferHeight = renderTargetsInfo[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.
    vk::PackedAttachmentIndex colorIndexVk(0);
    for (size_t colorIndexGL : mState.getColorAttachmentsMask())
    {
        if (clears->getColorMask().test(colorIndexGL))
        {
            if (renderPassCommands->hasAnyColorAccess(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->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->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.getEnabledDrawBuffers() & 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(),
                                   1, 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              = 1;

    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;
}
}  // namespace rx
