/*
 * Copyright 2022 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/gpu/graphite/vk/VulkanCommandBuffer.h"

#include "include/gpu/MutableTextureState.h"
#include "include/gpu/graphite/BackendSemaphore.h"
#include "include/gpu/graphite/vk/VulkanGraphiteTypes.h"
#include "include/gpu/vk/VulkanMutableTextureState.h"
#include "include/private/SkLog.h"
#include "include/private/SkTArray.h"
#include "src/gpu/DataUtils.h"
#include "src/gpu/graphite/ContextUtils.h"
#include "src/gpu/graphite/DescriptorData.h"
#include "src/gpu/graphite/PipelineData.h"
#include "src/gpu/graphite/RenderPassDesc.h"
#include "src/gpu/graphite/Surface_Graphite.h"
#include "src/gpu/graphite/TextureProxy.h"
#include "src/gpu/graphite/UniformManager.h"
#include "src/gpu/graphite/compute/DispatchGroup.h"
#include "src/gpu/graphite/vk/VulkanBuffer.h"
#include "src/gpu/graphite/vk/VulkanCaps.h"
#include "src/gpu/graphite/vk/VulkanComputePipeline.h"
#include "src/gpu/graphite/vk/VulkanDescriptorSet.h"
#include "src/gpu/graphite/vk/VulkanFramebuffer.h"
#include "src/gpu/graphite/vk/VulkanGraphiteUtils.h"
#include "src/gpu/graphite/vk/VulkanRenderPass.h"
#include "src/gpu/graphite/vk/VulkanSampler.h"
#include "src/gpu/graphite/vk/VulkanSharedContext.h"
#include "src/gpu/graphite/vk/VulkanTexture.h"
#include "src/gpu/vk/VulkanUtilsPriv.h"

using namespace skia_private;

namespace skgpu::graphite {

class VulkanDescriptorSet;

std::unique_ptr<VulkanCommandBuffer> VulkanCommandBuffer::Make(
        const VulkanSharedContext* sharedContext,
        VulkanResourceProvider* resourceProvider,
        Protected isProtected) {
    // Create VkCommandPool
    VkCommandPoolCreateFlags cmdPoolCreateFlags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;
    if (isProtected == Protected::kYes) {
        cmdPoolCreateFlags |= VK_COMMAND_POOL_CREATE_PROTECTED_BIT;
    }

    const VkCommandPoolCreateInfo cmdPoolInfo = {
            VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,  // sType
            nullptr,                                     // pNext
            cmdPoolCreateFlags,                          // CmdPoolCreateFlags
            sharedContext->queueIndex(),                 // queueFamilyIndex
    };
    VkResult result;
    VkCommandPool pool;
    VULKAN_CALL_RESULT(sharedContext,
                       result,
                       CreateCommandPool(sharedContext->device(), &cmdPoolInfo, nullptr, &pool));
    if (result != VK_SUCCESS) {
        return nullptr;
    }

    const VkCommandBufferAllocateInfo cmdInfo = {
        VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,   // sType
        nullptr,                                          // pNext
        pool,                                             // commandPool
        VK_COMMAND_BUFFER_LEVEL_PRIMARY,                  // level
        1                                                 // bufferCount
    };

    VkCommandBuffer primaryCmdBuffer;
    VULKAN_CALL_RESULT(
            sharedContext,
            result,
            AllocateCommandBuffers(sharedContext->device(), &cmdInfo, &primaryCmdBuffer));
    if (result != VK_SUCCESS) {
        VULKAN_CALL(sharedContext->interface(),
                    DestroyCommandPool(sharedContext->device(), pool, nullptr));
        return nullptr;
    }

    return std::unique_ptr<VulkanCommandBuffer>(new VulkanCommandBuffer(pool,
                                                                        primaryCmdBuffer,
                                                                        sharedContext,
                                                                        resourceProvider,
                                                                        isProtected));
}

VulkanCommandBuffer::VulkanCommandBuffer(VkCommandPool pool,
                                         VkCommandBuffer primaryCommandBuffer,
                                         const VulkanSharedContext* sharedContext,
                                         VulkanResourceProvider* resourceProvider,
                                         Protected isProtected)
        : CommandBuffer(isProtected)
        , fPool(pool)
        , fPrimaryCommandBuffer(primaryCommandBuffer)
        , fSharedContext(sharedContext)
        , fResourceProvider(resourceProvider) {
    // When making a new command buffer, we automatically begin the command buffer
    this->begin();
}

VulkanCommandBuffer::~VulkanCommandBuffer() {
    if (fActive) {
        // Need to end command buffer before deleting it
        VULKAN_CALL(fSharedContext->interface(), EndCommandBuffer(fPrimaryCommandBuffer));
        fActive = false;
    }

    if (fTimestampQueryPool != VK_NULL_HANDLE) {
        VULKAN_CALL(fSharedContext->interface(),
                    DestroyQueryPool(fSharedContext->device(), fTimestampQueryPool, nullptr));
    }

    if (fOcclusionQueryPool != VK_NULL_HANDLE) {
        VULKAN_CALL(fSharedContext->interface(),
                    DestroyQueryPool(fSharedContext->device(), fOcclusionQueryPool, nullptr));
    }

    if (VK_NULL_HANDLE != fSubmitFence) {
        VULKAN_CALL(fSharedContext->interface(),
                    DestroyFence(fSharedContext->device(), fSubmitFence, nullptr));
    }

    // This should delete any command buffers as well.
    VULKAN_CALL(fSharedContext->interface(),
                DestroyCommandPool(fSharedContext->device(), fPool, nullptr));
}

bool VulkanCommandBuffer::startStatsQuery(GpuStatsFlags flags) {
    if (fHasStatsQuery) {
        SKIA_LOG_W(
                "startTimerQuery called more than once for the same command "
                "buffer. Currently, stats queries are only supported when "
                "each recording gets its own submission.");
        return false;
    }
    bool hasElapsedTime = SkToBool(flags & GpuStatsFlags::kElapsedTime);
    bool hasOcclusion = SkToBool(flags & GpuStatsFlags::kOcclusionPassSamples);

    if (hasElapsedTime) {
        if (fTimestampQueryPool == VK_NULL_HANDLE) {
            VkQueryPoolCreateInfo info = {};
            info.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
            info.pNext = nullptr;
            info.flags = 0;
            info.queryType = VK_QUERY_TYPE_TIMESTAMP;
            info.queryCount = 2;
            info.pipelineStatistics = 0;

            VkResult result;
            VULKAN_CALL_RESULT(
                    fSharedContext,
                    result,
                    CreateQueryPool(
                            fSharedContext->device(), &info, nullptr, &fTimestampQueryPool));
            if (result != VK_SUCCESS) {
                return false;
            }
        }
        VULKAN_CALL(fSharedContext->interface(),
                    CmdResetQueryPool(fPrimaryCommandBuffer, fTimestampQueryPool, 0, 2));
        VULKAN_CALL(fSharedContext->interface(),
                    CmdWriteTimestamp(fPrimaryCommandBuffer,
                                      VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
                                      fTimestampQueryPool,
                                      0));
    }

    if (hasOcclusion) {
        if (fOcclusionQueryPool == VK_NULL_HANDLE) {
            VkQueryPoolCreateInfo info = {};
            info.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
            info.pNext = nullptr;
            info.flags = 0;
            info.queryType = VK_QUERY_TYPE_OCCLUSION;
            info.queryCount = 1;
            info.pipelineStatistics = 0;

            VkResult result;
            VULKAN_CALL_RESULT(
                    fSharedContext,
                    result,
                    CreateQueryPool(
                            fSharedContext->device(), &info, nullptr, &fOcclusionQueryPool));
            if (result != VK_SUCCESS) {
                return false;
            }
        }
        VULKAN_CALL(fSharedContext->interface(),
                    CmdResetQueryPool(fPrimaryCommandBuffer, fOcclusionQueryPool, 0, 1));
        VULKAN_CALL(fSharedContext->interface(),
                    CmdBeginQuery(fPrimaryCommandBuffer,
                                  fOcclusionQueryPool,
                                  0,
                                  VK_QUERY_CONTROL_PRECISE_BIT));
    }

    fHasStatsQuery = true;
    return true;
}

void VulkanCommandBuffer::endStatsQuery(GpuStatsFlags flags) {
    // Only called if startTimerQuery succeeded.
    if (flags & GpuStatsFlags::kOcclusionPassSamples) {
        VULKAN_CALL(fSharedContext->interface(),
                    CmdEndQuery(fPrimaryCommandBuffer, fOcclusionQueryPool, 0));
    }
    if (flags & GpuStatsFlags::kElapsedTime) {
        VULKAN_CALL(fSharedContext->interface(),
                    CmdWriteTimestamp(fPrimaryCommandBuffer,
                                      VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
                                      fTimestampQueryPool,
                                      1));
    }
}

std::optional<GpuStats> VulkanCommandBuffer::gpuStats() {
    GpuStats stats;

    if (fTimestampQueryPool != VK_NULL_HANDLE) {
        uint64_t timestamps[2];
        VkResult result;
        VULKAN_CALL_RESULT(fSharedContext,
                           result,
                           GetQueryPoolResults(fSharedContext->device(),
                                               fTimestampQueryPool,
                                               0,
                                               2,
                                               sizeof(timestamps),
                                               timestamps,
                                               sizeof(uint64_t),
                                               VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
        if (result == VK_SUCCESS) {
            // kElapsedTime is only exposed if timestampComputeAndGraphics, which guarantees
            // timestampValidBits >= 36 on GRAPHICS and COMPUTE queues. We only ever use
            // this on graphics queues so we can assume support here.
            uint32_t validBits =
                    fSharedContext->vulkanCaps().timestampValidBits(fSharedContext->queueIndex());
            uint64_t mask = validBits == 64 ? ~0ULL : (1ULL << validBits) - 1;

            uint64_t elapsedTicks = (timestamps[1] - timestamps[0]) & mask;
            uint64_t elapsedNanos = elapsedTicks * fSharedContext->vulkanCaps().timestampPeriod();

            stats.elapsedTime = elapsedNanos;
        }
    }

    if (fOcclusionQueryPool != VK_NULL_HANDLE) {
        uint64_t occlusion = 0;
        VkResult result;
        VULKAN_CALL_RESULT(fSharedContext,
                           result,
                           GetQueryPoolResults(fSharedContext->device(),
                                               fOcclusionQueryPool,
                                               0,
                                               1,
                                               sizeof(occlusion),
                                               &occlusion,
                                               sizeof(uint64_t),
                                               VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
        if (result == VK_SUCCESS) {
            stats.numOcclusionPassSamples = occlusion;
        }
    }

    return stats;
}

void VulkanCommandBuffer::onResetCommandBuffer() {
    SkASSERT(!fActive);
    VULKAN_CALL_ERRCHECK(fSharedContext, ResetCommandPool(fSharedContext->device(), fPool, 0));
    fActiveGraphicsPipeline = nullptr;
    fBindUniformBuffers = true;
    fBoundIndirectBuffer = VK_NULL_HANDLE;
    fBoundIndirectBufferOffset = 0;
    fTargetTexture = nullptr;
    fTextureSamplerDescSetToBind = VK_NULL_HANDLE;
    fNumTextureSamplers = 0;
    fUniformBuffersToBind.fill({});
    for (int i = 0; i < 4; ++i) {
        fCachedBlendConstant[i] = -1.0;
    }
    fHasStatsQuery = false;
}

bool VulkanCommandBuffer::setNewCommandBufferResources() {
    this->begin();
    return true;
}

void VulkanCommandBuffer::begin() {
    SkASSERT(!fActive);
    VkCommandBufferBeginInfo cmdBufferBeginInfo = {};
    cmdBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
    cmdBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;

    VULKAN_CALL_ERRCHECK(fSharedContext,
                         BeginCommandBuffer(fPrimaryCommandBuffer, &cmdBufferBeginInfo));
    fActive = true;

    // Set all the dynamic state that Graphite never changes once at the beginning of the command
    // buffer.  The following state are constants in Graphite:
    //
    // * lineWidth
    // * depthBiasEnable, depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor
    // * min/maxDepthBounds, depthBoundsTestEnable
    // * primitiveRestartEnable
    // * cullMode
    // * frontFace
    // * rasterizerDiscardEnable

    if (fSharedContext->caps()->useBasicDynamicState()) {
        VULKAN_CALL(fSharedContext->interface(),
                    CmdSetLineWidth(fPrimaryCommandBuffer,
                                    /*lineWidth=*/1.0));
        VULKAN_CALL(fSharedContext->interface(),
                    CmdSetDepthBias(fPrimaryCommandBuffer,
                                    /*depthBiasConstantFactor=*/0.0f,
                                    /*depthBiasClamp=*/0.0f,
                                    /*depthBiasSlopeFactor=*/0.0f));
        VULKAN_CALL(fSharedContext->interface(),
                    CmdSetDepthBounds(fPrimaryCommandBuffer,
                                      /*minDepthBounds=*/0.0f,
                                      /*maxDepthBounds=*/1.0f));
        VULKAN_CALL(fSharedContext->interface(),
                    CmdSetDepthBoundsTestEnable(fPrimaryCommandBuffer,
                                                /*depthBoundsTestEnable=*/VK_FALSE));
        VULKAN_CALL(fSharedContext->interface(),
                    CmdSetDepthBiasEnable(fPrimaryCommandBuffer,
                                          /*depthBiasEnable=*/VK_FALSE));
        VULKAN_CALL(fSharedContext->interface(),
                    CmdSetPrimitiveRestartEnable(fPrimaryCommandBuffer,
                                                 /*primitiveRestartEnable=*/VK_FALSE));
        VULKAN_CALL(fSharedContext->interface(),
                    CmdSetCullMode(fPrimaryCommandBuffer,
                                   /*cullMode=*/VK_CULL_MODE_NONE));
        VULKAN_CALL(fSharedContext->interface(),
                    CmdSetFrontFace(fPrimaryCommandBuffer,
                                    /*frontFace=*/VK_FRONT_FACE_COUNTER_CLOCKWISE));
        VULKAN_CALL(fSharedContext->interface(),
                    CmdSetRasterizerDiscardEnable(fPrimaryCommandBuffer,
                                                  /*rasterizerDiscardEnable=*/VK_FALSE));
    }
}

void VulkanCommandBuffer::end() {
    SkASSERT(fActive);
    SkASSERT(!fActiveRenderPass);

    this->submitPipelineBarriers();

    VULKAN_CALL_ERRCHECK(fSharedContext, EndCommandBuffer(fPrimaryCommandBuffer));

    fActive = false;
}

void VulkanCommandBuffer::addWaitSemaphores(size_t numWaitSemaphores,
                                            const BackendSemaphore* waitSemaphores) {
    if (!waitSemaphores) {
        SkASSERT(numWaitSemaphores == 0);
        return;
    }

    for (size_t i = 0; i < numWaitSemaphores; ++i) {
        auto& semaphore = waitSemaphores[i];
        if (semaphore.isValid() && semaphore.backend() == BackendApi::kVulkan) {
            fWaitSemaphores.push_back(BackendSemaphores::GetVkSemaphore(semaphore));
        }
    }
}

void VulkanCommandBuffer::addSignalSemaphores(size_t numSignalSemaphores,
                                              const BackendSemaphore* signalSemaphores) {
    if (!signalSemaphores) {
        SkASSERT(numSignalSemaphores == 0);
        return;
    }

    for (size_t i = 0; i < numSignalSemaphores; ++i) {
        auto& semaphore = signalSemaphores[i];
        if (semaphore.isValid() && semaphore.backend() == BackendApi::kVulkan) {
            fSignalSemaphores.push_back(BackendSemaphores::GetVkSemaphore(semaphore));
        }
    }
}

void VulkanCommandBuffer::prepareSurfaceForStateUpdate(SkSurface* targetSurface,
                                                       const MutableTextureState* newState) {
    TextureProxy* textureProxy = static_cast<Surface*>(targetSurface)->target().proxy();
    VulkanTexture* texture = static_cast<VulkanTexture*>(textureProxy->texture());

    // Even though internally we use this helper for getting src access flags and stages they
    // can also be used for general dst flags since we don't know exactly what the client
    // plans on using the image for.
    VkImageLayout newLayout = skgpu::MutableTextureStates::GetVkImageLayout(newState);
    if (newLayout == VK_IMAGE_LAYOUT_UNDEFINED) {
        newLayout = texture->currentLayout();
    }
    VkPipelineStageFlags dstStage =
            VulkanTexture::LayoutToPipelineSrcStageFlags(newLayout, fSharedContext->vulkanCaps());
    VkAccessFlags dstAccess = VulkanTexture::LayoutToSrcAccessMask(
            newLayout, texture->vulkanTextureInfo().fImageUsageFlags);

    uint32_t currentQueueFamilyIndex = texture->currentQueueFamilyIndex();
    uint32_t newQueueFamilyIndex = skgpu::MutableTextureStates::GetVkQueueFamilyIndex(newState);
    auto isSpecialQueue = [](uint32_t queueFamilyIndex) {
        return queueFamilyIndex == VK_QUEUE_FAMILY_EXTERNAL ||
               queueFamilyIndex == VK_QUEUE_FAMILY_FOREIGN_EXT;
    };
    if (isSpecialQueue(currentQueueFamilyIndex) && isSpecialQueue(newQueueFamilyIndex)) {
        // It is illegal to have both the new and old queue be special queue families (i.e. external
        // or foreign).
        return;
    }

    this->trackResource(sk_ref_sp(texture));

    texture->setImageLayoutAndQueueIndex(this,
                                         newLayout,
                                         dstAccess,
                                         dstStage,
                                         newQueueFamilyIndex);
}

// Requests a sampler. Dynamic samplers live in the global cache, requiring no tracking, but
// immutable samplers are created on the current graphics pipeline, and may outlive it, requiring
// further tracking.
const Sampler* VulkanCommandBuffer::getSampler(
        const DrawPassCommands::BindTexturesAndSamplers* command, int32_t index) {
    auto desc = command->fSamplers[index];
    if (desc.isImmutable()) {
        const VulkanSampler* immutableSampler = fActiveGraphicsPipeline->immutableSampler(index);
        if (immutableSampler) {
            this->trackResource(sk_ref_sp<Sampler>(immutableSampler));
        }
        return immutableSampler;
    } else {
        return fSharedContext->globalCache()->getDynamicSampler(desc);
    }
}

static VkResult submit_to_queue(const VulkanSharedContext* sharedContext,
                                VkQueue queue,
                                VkFence fence,
                                uint32_t waitCount,
                                const VkSemaphore* waitSemaphores,
                                const VkPipelineStageFlags* waitStages,
                                uint32_t commandBufferCount,
                                const VkCommandBuffer* commandBuffers,
                                uint32_t signalCount,
                                const VkSemaphore* signalSemaphores,
                                Protected protectedContext,
                                MarkFrameBoundary markFrameBoundary,
                                uint64_t frameID) {
    VkSubmitInfo submitInfo = {};
    submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;

    VkProtectedSubmitInfo protectedSubmitInfo = {};
    if (protectedContext == Protected::kYes) {
        protectedSubmitInfo.sType = VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO;
        protectedSubmitInfo.protectedSubmit = VK_TRUE;

        AddToPNextChain(&submitInfo, &protectedSubmitInfo);
    }


    VkFrameBoundaryEXT frameBoundary;
    if (markFrameBoundary == MarkFrameBoundary::kYes &&
        sharedContext->vulkanCaps().supportsFrameBoundary()) {
        memset(&frameBoundary, 0, sizeof(VkFrameBoundaryEXT));
        frameBoundary.sType = VK_STRUCTURE_TYPE_FRAME_BOUNDARY_EXT;
        frameBoundary.flags = VK_FRAME_BOUNDARY_FRAME_END_BIT_EXT;
        frameBoundary.frameID = frameID;

        AddToPNextChain(&submitInfo, &frameBoundary);
    }

    submitInfo.waitSemaphoreCount = waitCount;
    submitInfo.pWaitSemaphores = waitSemaphores;
    submitInfo.pWaitDstStageMask = waitStages;
    submitInfo.commandBufferCount = commandBufferCount;
    submitInfo.pCommandBuffers = commandBuffers;
    submitInfo.signalSemaphoreCount = signalCount;
    submitInfo.pSignalSemaphores = signalSemaphores;

    VkResult result;
    VULKAN_CALL_RESULT(sharedContext, result, QueueSubmit(queue, 1, &submitInfo, fence));
    return result;
}

bool VulkanCommandBuffer::submit(VkQueue queue, const SubmitInfo& submitInfo) {
    this->end();

    auto device = fSharedContext->device();
    VkResult err;

    if (fSubmitFence == VK_NULL_HANDLE) {
        VkFenceCreateInfo fenceInfo = {};
        fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
        VULKAN_CALL_RESULT(
                fSharedContext, err, CreateFence(device, &fenceInfo, nullptr, &fSubmitFence));
        if (err) {
            fSubmitFence = VK_NULL_HANDLE;
            return false;
        }
    } else {
        // This cannot return DEVICE_LOST so we assert we succeeded.
        VULKAN_CALL_RESULT(fSharedContext, err, ResetFences(device, 1, &fSubmitFence));
        SkASSERT(err == VK_SUCCESS);
    }

    SkASSERT(fSubmitFence != VK_NULL_HANDLE);
    int waitCount = fWaitSemaphores.size();
    TArray<VkPipelineStageFlags> vkWaitStages(waitCount);
    for (int i = 0; i < waitCount; ++i) {
        vkWaitStages.push_back(VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
                               VK_PIPELINE_STAGE_TRANSFER_BIT);
    }

    VkResult submitResult = submit_to_queue(fSharedContext,
                                            queue,
                                            fSubmitFence,
                                            waitCount,
                                            fWaitSemaphores.data(),
                                            vkWaitStages.data(),
                                            /*commandBufferCount*/ 1,
                                            &fPrimaryCommandBuffer,
                                            fSignalSemaphores.size(),
                                            fSignalSemaphores.data(),
                                            this->isProtected(),
                                            submitInfo.fMarkBoundary,
                                            submitInfo.fFrameID);
    fWaitSemaphores.clear();
    fSignalSemaphores.clear();
    if (submitResult != VK_SUCCESS) {
        // If we failed to submit because of a device lost, we still need to wait for the fence to
        // signal before deleting. However, there is an ARM bug (b/359822580) where the driver early
        // outs on the fence wait if in a device lost state and thus we can't wait on it. Instead,
        // we just wait on the queue to finish. We're already in a state that's going to cause us to
        // restart the whole device, so waiting on the queue shouldn't have any performance impact.
        if (submitResult == VK_ERROR_DEVICE_LOST) {
            VULKAN_CALL(fSharedContext->interface(), QueueWaitIdle(queue));
        } else {
            SkASSERT(submitResult == VK_ERROR_OUT_OF_HOST_MEMORY ||
                     submitResult == VK_ERROR_OUT_OF_DEVICE_MEMORY);
        }

        VULKAN_CALL(fSharedContext->interface(), DestroyFence(device, fSubmitFence, nullptr));
        fSubmitFence = VK_NULL_HANDLE;
        return false;
    }
    return true;
}

bool VulkanCommandBuffer::isFinished() {
    SkASSERT(!fActive);
    if (VK_NULL_HANDLE == fSubmitFence) {
        return true;
    }

    VkResult err;
    VULKAN_CALL_RESULT_NOCHECK(fSharedContext->interface(), err,
                               GetFenceStatus(fSharedContext->device(), fSubmitFence));
    switch (err) {
        case VK_SUCCESS:
        case VK_ERROR_DEVICE_LOST:
            return true;

        case VK_NOT_READY:
            return false;

        default:
            SK_ABORT("Error calling vkGetFenceStatus. Error: %d", err);
            return false;
    }
}

void VulkanCommandBuffer::waitUntilFinished() {
    if (fSubmitFence == VK_NULL_HANDLE) {
        return;
    }
    // On some drivers vkWaitForFences() can spuriously return VK_TIMEOUT when a signal handler
    // runs. Work around this by retrying on VK_TIMEOUT.
    VkResult result = VK_TIMEOUT;
    while (result == VK_TIMEOUT) {
        VULKAN_CALL_RESULT_NOCHECK(fSharedContext->interface(),
                                   result,
                                   WaitForFences(fSharedContext->device(),
                                                 1,
                                                 &fSubmitFence,
                                                 /*waitAll=*/true,
                                                 /*timeout=*/UINT64_MAX));
    }
    if (result != VK_SUCCESS && !fSharedContext->isDeviceLost()) {
        SkDebugf("vkWaitForFences() failed. Error: %d\n", result);
    }
    SkASSERT(VK_SUCCESS == result || VK_ERROR_DEVICE_LOST == result);
    fSharedContext->checkVkResult(result);
}

void VulkanCommandBuffer::pushConstants(const PushConstantInfo& pushConstantInfo,
                                        VkPipelineLayout compatibleLayout) {
    // size must be within limits. Vulkan spec dictates each device supports at least 128 bytes
    SkASSERT(pushConstantInfo.fSize < 128);
    // offset and size must be a multiple of 4
    SkASSERT(!SkToBool(pushConstantInfo.fOffset & 0x3));
    SkASSERT(!SkToBool(pushConstantInfo.fSize & 0x3));

    VULKAN_CALL(fSharedContext->interface(),
                CmdPushConstants(fPrimaryCommandBuffer,
                                 compatibleLayout,
                                 pushConstantInfo.fShaderStageFlagBits,
                                 pushConstantInfo.fOffset,
                                 pushConstantInfo.fSize,
                                 pushConstantInfo.fValues));
}

bool VulkanCommandBuffer::onAddRenderPass(const RenderPassDesc& rpDesc,
                                          const Texture* colorTexture,
                                          const Texture* resolveTexture,
                                          const Texture* depthStencilTexture,
                                          SkIPoint resolveOffset,
                                          SkIRect viewport,
                                          const DrawPassList& drawPasses) {
    SkASSERT(resolveOffset.isZero());
    for (const auto& drawPass : drawPasses) {
        // Track resources now since the barriers will reference them.
        if (!drawPass->addResourceRefs(fResourceProvider, this)) SK_UNLIKELY {
            return false;
        }

        // Our current implementation of setting texture image layouts does not allow layout changes
        // once we have already begun a render pass, so prior to any other commands, set the layout
        // of all sampled textures from the drawpass so they can be sampled from the shader.
        for (const sk_sp<TextureProxy>& textureProxy : drawPass->sampledTextures()) {
            VulkanTexture* vulkanTexture = const_cast<VulkanTexture*>(
                                           static_cast<const VulkanTexture*>(
                                           textureProxy->texture()));
            vulkanTexture->setImageLayout(this,
                                          VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
                                          VK_ACCESS_SHADER_READ_BIT,
                                          VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
        }
    }
    if (fDstCopy.first) {
        VulkanTexture* vulkanTexture =
                const_cast<VulkanTexture*>(static_cast<const VulkanTexture*>(fDstCopy.first));
        vulkanTexture->setImageLayout(this,
                                      VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
                                      VK_ACCESS_SHADER_READ_BIT,
                                      VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
    }

    if (!this->beginRenderPass(
                rpDesc, viewport, colorTexture, resolveTexture, depthStencilTexture)) {
        return false;
    }

    // After loading msaa from resolve (if needed), perform any updates that only need to occur
    // once per renderpass.
    this->performOncePerRPUpdates(
            viewport, rpDesc.fDstReadStrategy == DstReadStrategy::kReadFromInput);

    for (const auto& drawPass : drawPasses) {
        this->addDrawPass(drawPass.get());
    }

    this->endRenderPass();
    return true;
}

void VulkanCommandBuffer::performOncePerRPUpdates(SkIRect viewport, bool bindDstAsInputAttachment) {
    // Updating push constant values and - if any draw within the RP reads from the dst as an
    // input attachment - binding the dst texture as an input attachment only need to occur once per
    // RP. This is because intrinsic constant vlues (dst copy bounds and rtAdjust) and the render
    // target do not change throughout the course of a RenderPass. Even if no pipeline is bound yet,
    // we can use a compatible mock pipeline layout to perform these operations.

    // TODO(b/374997389): Somehow convey & enforce Layout::kStd430 for push constants.
    UniformManager intrinsicValues{Layout::kStd140};
    CollectIntrinsicUniforms(fSharedContext->caps(), viewport, fDstReadBounds, &intrinsicValues);
    SkSpan<const char> bytes = intrinsicValues.finish();
    SkASSERT(bytes.size_bytes() == VulkanResourceProvider::kIntrinsicConstantSize);

    PushConstantInfo pushConstantInfo;
    pushConstantInfo.fOffset = 0;
    pushConstantInfo.fSize = VulkanResourceProvider::kIntrinsicConstantSize;
    pushConstantInfo.fShaderStageFlagBits = VulkanResourceProvider::kIntrinsicConstantStageFlags;
    pushConstantInfo.fValues = bytes.data();
    this->pushConstants(pushConstantInfo, fResourceProvider->mockPipelineLayout());

    if (bindDstAsInputAttachment) {
        this->updateAndBindInputAttachment(*fTargetTexture,
                                            VulkanGraphicsPipeline::kDstAsInputDescSetIndex,
                                            fResourceProvider->mockPipelineLayout());
    }
}

bool VulkanCommandBuffer::updateAndBindInputAttachment(const VulkanTexture& texture,
                                                       const int setIdx,
                                                       VkPipelineLayout piplineLayout) {
    // Fetch a descriptor set that contains one input attachment (we do not support using more than
    // one per set at this time).
    STArray<1, DescriptorData> inputDesc = {VulkanGraphicsPipeline::GetInputAttachmentDescriptor()};
    sk_sp<VulkanDescriptorSet> set = fResourceProvider->findOrCreateDescriptorSet(
            {&inputDesc.front(), (size_t)inputDesc.size()});
    if (!set) {
        return false;
    }

    // Update and write to the descriptor given the provided texture, binding it afterwards.
    VkDescriptorImageInfo textureInfo = {};
    textureInfo.sampler = VK_NULL_HANDLE;
    textureInfo.imageView =
            texture.getImageView(VulkanImageView::Usage::kAttachment)->imageView();
    // Even though the image is in the VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, the subpass
    // is configured to implicitly use VK_IMAGE_LAYOUT_GENERAL in VkAttachmentReference::layout as
    // part of VkSubpassDescription.
    textureInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;

    VkWriteDescriptorSet writeInfo = {};
    writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
    writeInfo.dstSet = *set->descriptorSet();
    writeInfo.dstBinding = 0;
    writeInfo.dstArrayElement = 0;
    writeInfo.descriptorCount = 1;
    writeInfo.descriptorType = DsTypeEnumToVkDs(DescriptorType::kInputAttachment);
    writeInfo.pImageInfo = &textureInfo;

    VULKAN_CALL(fSharedContext->interface(),
                UpdateDescriptorSets(fSharedContext->device(),
                                     /*descriptorWriteCount=*/1,
                                     &writeInfo,
                                     /*descriptorCopyCount=*/0,
                                     /*pDescriptorCopies=*/nullptr));

    VULKAN_CALL(fSharedContext->interface(),
                CmdBindDescriptorSets(fPrimaryCommandBuffer,
                                      VK_PIPELINE_BIND_POINT_GRAPHICS,
                                      piplineLayout,
                                      setIdx,
                                      /*setCount=*/1,
                                      set->descriptorSet(),
                                      /*dynamicOffsetCount=*/0,
                                      /*dynamicOffsets=*/nullptr));

    this->trackResource(std::move(set));
    return true;
}

bool VulkanCommandBuffer::loadMSAAFromResolve(const RenderPassDesc& rpDesc,
                                              VulkanTexture& resolveTexture,
                                              SkIRect renderArea) {
    sk_sp<VulkanGraphicsPipeline> loadPipeline =
            fResourceProvider->findOrCreateLoadMSAAPipeline(rpDesc);
    if (!loadPipeline) {
        SKIA_LOG_E("Unable to create pipeline to load resolve texture into MSAA attachment");
        return false;
    }

    // We need to load the entire render area since that is what will be resolved at the end.
    // This may be a slightly different "viewport" than what will be used for actual rendering since
    // it will have been rounded to the device's preferred granularity.
    this->setViewport(renderArea);
    this->setScissor(renderArea);

    // Bind the special load pipeline, which does not require any uniform or push constant state.
    this->bindGraphicsPipeline(loadPipeline.get());

    // Make sure we do not attempt to bind uniform or texture/sampler descriptors because we do
    // not use them for loading MSAA from resolve.
    fBindUniformBuffers = false;
    fBindTextureSamplers = false;

    if (!this->updateAndBindInputAttachment(
            resolveTexture,
            VulkanGraphicsPipeline::kLoadMsaaFromResolveInputDescSetIndex,
            fActiveGraphicsPipeline->layout())) {
        SKIA_LOG_E("Unable to update and bind an input attachment descriptor for loading MSAA "
                    "from resolve");
        return false;
    }

    this->draw(PrimitiveType::kTriangleStrip, /*baseVertex=*/0, /*vertexCount=*/4);

    // After loading the resolve attachment, proceed to the next subpass.
    this->nextSubpass();
    // While transitioning to the next subpass, the layout of the resolve texture gets changed
    // internally to accommodate its usage within the following subpass. Thus, we need to update
    // our tracking of the layout to match the new/final layout. We do not need to use a general
    // layout because we do not expect to later treat the resolve texture as a dst to read from.
    resolveTexture.updateImageLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);

    // After using a distinct descriptor set layout for loading MSAA from resolve, we will need to
    // (re-)bind any descriptor sets.
    fBindUniformBuffers = true;
    fBindTextureSamplers = true;
    return true;
}

namespace {
// Helpers for determining + updating texture layouts.
void assign_color_texture_layout(VulkanCommandBuffer* cmdBuf,
                                 VulkanTexture* colorTexture,
                                 bool rpReadsDstAsInput) {
    VkAccessFlags access =
            VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
    VkPipelineStageFlags stageFlags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    VkImageLayout layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;

    // If any draws within a render pass read from the dst color texture as an input attachment,
    // we must add additional pipeline stage + access flags.
    if (rpReadsDstAsInput) {
        stageFlags |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
        access |= VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
    }

    colorTexture->setImageLayout(cmdBuf, layout, access, stageFlags);
}

void assign_resolve_texture_layout(VulkanCommandBuffer* cmdBuf,
                                   VulkanTexture* resolveTexture,
                                   bool loadMSAAFromResolve) {
    VkPipelineStageFlags stageFlags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    VkAccessFlags access = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
    // The resolve image uses the color attachment layout. If loadMSAAFromResolve is true, the
    // additional subpass will set the appropriate layout in VkAttachmentReference::layout, and
    // layout transitions are performed automatically between subpasses.
    VkImageLayout layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;

    // If loading MSAA from resolve, then the resolve texture is used in the first subpass
    // as an input attachment and is referenced within the fragment shader. Add to the access and
    // pipeline stage flags accordingly.
    if (loadMSAAFromResolve) {
        access |= VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
        stageFlags |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
    } else {
        // Otherwise, add write access.
        access |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
    }

    resolveTexture->setImageLayout(cmdBuf, layout, access, stageFlags);
}

void setup_texture_layouts(VulkanCommandBuffer* cmdBuf,
                           VulkanTexture* colorTexture,
                           VulkanTexture* resolveTexture,
                           VulkanTexture* depthStencilTexture,
                           bool loadMSAAFromResolve,
                           bool rpReadsDstAsInput) {
    if (colorTexture) {
        assign_color_texture_layout(cmdBuf, colorTexture, rpReadsDstAsInput);
        if (resolveTexture) {
            // rpReadsDstAsInput does not matter here given that we do not anticipate reading
            // from the resolve texture as a dst input attachment.
            assign_resolve_texture_layout(cmdBuf, resolveTexture, loadMSAAFromResolve);
        }
    }

    if (depthStencilTexture) {
        depthStencilTexture->setImageLayout(cmdBuf,
                                            VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
                                            VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
                                            VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
                                            VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT);
    }
}

static constexpr int kMaxNumAttachments = 3;
void gather_clear_values(const RenderPassDesc& rpDesc,
                         STArray<kMaxNumAttachments, VkClearValue>* clearValues) {
    // NOTE: This must stay in sync with the attachment order defined in VulkanRenderPass.cpp, in
    // populate_attachment_refs().
    if (rpDesc.fColorAttachment.fFormat != TextureFormat::kUnsupported) {
        VkClearValue& colorAttachmentClear = clearValues->push_back();
        colorAttachmentClear.color = {{rpDesc.fClearColor[0],
                                       rpDesc.fClearColor[1],
                                       rpDesc.fClearColor[2],
                                       rpDesc.fClearColor[3]}};
    }
    // The resolve attachment (if defined) should never be cleared, but add a value to keep the
    // attachment indices in sync.
    if (rpDesc.fColorResolveAttachment.fFormat != TextureFormat::kUnsupported) {
        SkASSERT(rpDesc.fColorResolveAttachment.fLoadOp != LoadOp::kClear);
        clearValues->push_back({});
    }

    // Vulkan takes the clear depth and clear stencil regardless of whether or not the DS attachment
    // only has a single aspect or both.
    if (rpDesc.fDepthStencilAttachment.fFormat != TextureFormat::kUnsupported) {
        VkClearValue& depthStencilAttachmentClear = clearValues->push_back();
        depthStencilAttachmentClear.depthStencil = {rpDesc.fClearDepth, rpDesc.fClearStencil};
    }
}

// The RenderArea bounds we pass into BeginRenderPass must have a start x value that is a multiple
// of the granularity. The width must also be a multiple of the granularity or equal to the width
// of the entire attachment. Similar requirements apply to the y and height components.
SkIRect get_render_area(const SkIRect& srcBounds,
                        const VkExtent2D& granularity,
                        int maxWidth,
                        int maxHeight) {
    SkIRect dstBounds;
    // Adjust Width
    if (granularity.width == 0 || granularity.width == 1) {
        dstBounds.fLeft = srcBounds.fLeft;
        dstBounds.fRight = srcBounds.fRight;
    } else {
        // Start with the right side of rect so we know if we end up going past the maxWidth.
        int rightAdj = srcBounds.fRight % granularity.width;
        if (rightAdj != 0) {
            rightAdj = granularity.width - rightAdj;
        }
        dstBounds.fRight = srcBounds.fRight + rightAdj;
        if (dstBounds.fRight > maxWidth) {
            dstBounds.fRight = maxWidth;
            dstBounds.fLeft = 0;
        } else {
            dstBounds.fLeft = srcBounds.fLeft - srcBounds.fLeft % granularity.width;
        }
    }

    if (granularity.height == 0 || granularity.height == 1) {
        dstBounds.fTop = srcBounds.fTop;
        dstBounds.fBottom = srcBounds.fBottom;
    } else {
        // Start with the bottom side of rect so we know if we end up going past the maxHeight.
        int bottomAdj = srcBounds.fBottom % granularity.height;
        if (bottomAdj != 0) {
            bottomAdj = granularity.height - bottomAdj;
        }
        dstBounds.fBottom = srcBounds.fBottom + bottomAdj;
        if (dstBounds.fBottom > maxHeight) {
            dstBounds.fBottom = maxHeight;
            dstBounds.fTop = 0;
        } else {
            dstBounds.fTop = srcBounds.fTop - srcBounds.fTop % granularity.height;
        }
    }

    return dstBounds;
}

void populate_write_info(VulkanDescriptorSet* set,
                         TArray<VkDescriptorImageInfo>& descriptorImageInfos,
                         TArray<VkWriteDescriptorSet>& writeDescriptorSets,
                         const VulkanTexture* texture,
                         const VulkanSampler* sampler,
                         int32_t binding) {
    SkASSERT(set);
    VkDescriptorImageInfo& textureInfo = descriptorImageInfos.push_back();
    textureInfo = {};
    textureInfo.sampler = sampler ? sampler->vkSampler() : VK_NULL_HANDLE;
    textureInfo.imageView =
            texture->getImageView(VulkanImageView::Usage::kShaderInput)->imageView();
    textureInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;

    VkWriteDescriptorSet& writeInfo = writeDescriptorSets.push_back();
    writeInfo = {};
    writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
    writeInfo.dstSet = *set->descriptorSet();
    writeInfo.dstBinding = binding;
    writeInfo.dstArrayElement = 0;
    writeInfo.descriptorCount = 1;
    writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
    writeInfo.pImageInfo = &textureInfo;
}
} // anonymous namespace

bool VulkanCommandBuffer::beginRenderPass(const RenderPassDesc& rpDesc,
                                          SkIRect viewport,
                                          const Texture* colorTexture,
                                          const Texture* resolveTexture,
                                          const Texture* depthStencilTexture) {
    // Validate attachment descs and textures
    SkDEBUGCODE(const auto& colorInfo = rpDesc.fColorAttachment;)
    SkDEBUGCODE(const auto& resolveInfo = rpDesc.fColorResolveAttachment;)
    SkDEBUGCODE(const auto& depthStencilInfo = rpDesc.fDepthStencilAttachment;)
    SkASSERT(colorTexture ? colorInfo.isCompatible(colorTexture->textureInfo())
                          : colorInfo.fFormat == TextureFormat::kUnsupported);
    SkASSERT(resolveTexture ? resolveInfo.isCompatible(resolveTexture->textureInfo())
                            : resolveInfo.fFormat == TextureFormat::kUnsupported);
    SkASSERT(depthStencilTexture ? depthStencilInfo.isCompatible(depthStencilTexture->textureInfo())
                                 : depthStencilInfo.fFormat == TextureFormat::kUnsupported);

    fTargetTexture =
            const_cast<VulkanTexture*>(static_cast<const VulkanTexture*>(colorTexture));
    VulkanTexture* vulkanResolveTexture =
            const_cast<VulkanTexture*>(static_cast<const VulkanTexture*>(resolveTexture));
    VulkanTexture* vulkanDepthStencilTexture =
            const_cast<VulkanTexture*>(static_cast<const VulkanTexture*>(depthStencilTexture));

    // Determine if we need to load MSAA from resolve, and if so, make certain that key conditions
    // are met before proceeding.
    const bool loadMSAAFromResolve = RenderPassDescWillLoadMSAAFromResolve(rpDesc);
    if (loadMSAAFromResolve && (!vulkanResolveTexture || !fTargetTexture ||
                                !vulkanResolveTexture->supportsInputAttachmentUsage())) {
        SKIA_LOG_E("Cannot begin render pass. In order to load MSAA from resolve, the color "
                    "attachment must have input attachment usage and both the color and resolve "
                    "attachments must be valid.");
        return false;
    }

    // Before beginning a renderpass, set all textures to the appropriate image layout. Whether a RP
    // must support reading from the dst as an input attachment affects some layout selections.
    setup_texture_layouts(
            this,
            fTargetTexture,
            vulkanResolveTexture,
            vulkanDepthStencilTexture,
            loadMSAAFromResolve,
            /*rpReadsDstAsInput=*/rpDesc.fDstReadStrategy == DstReadStrategy::kReadFromInput);

    // Gather clear values needed for RenderPassBeginInfo. Indexed by attachment number.
    STArray<kMaxNumAttachments, VkClearValue> clearValues;
    gather_clear_values(rpDesc, &clearValues);

    sk_sp<VulkanRenderPass> vulkanRenderPass =
            fResourceProvider->findOrCreateRenderPass(rpDesc, /*compatibleOnly=*/false);
    if (!vulkanRenderPass) {
        SKIA_LOG_W("Could not create Vulkan RenderPass");
        return false;
    }
    this->submitPipelineBarriers();
    this->trackResource(vulkanRenderPass);

    sk_sp<VulkanFramebuffer> framebuffer =
            fResourceProvider->findOrCreateFramebuffer(fSharedContext,
                                                       fTargetTexture,
                                                       vulkanResolveTexture,
                                                       vulkanDepthStencilTexture,
                                                       rpDesc,
                                                       *vulkanRenderPass);
    if (!framebuffer) {
        SKIA_LOG_W("Could not find or create Vulkan Framebuffer");
        return false;
    }

    bool useFullBounds = loadMSAAFromResolve &&
                         fSharedContext->vulkanCaps().mustLoadFullImageForMSAA();

    SkISize framebufferDims = framebuffer->dimensions();
    SkIRect renderArea = get_render_area(useFullBounds ? SkIRect::MakeSize(framebufferDims)
                                                       : fRenderAreaBounds,
                                         vulkanRenderPass->granularity(),
                                         framebufferDims.width(),
                                         framebufferDims.height());

    VkRenderPassBeginInfo beginInfo = {};
    beginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
    beginInfo.renderPass = vulkanRenderPass->renderPass();
    beginInfo.framebuffer = framebuffer->framebuffer();
    beginInfo.renderArea.offset = {renderArea.fLeft, renderArea.fTop};
    beginInfo.renderArea.extent = { (uint32_t) renderArea.width(), (uint32_t) renderArea.height()};
    beginInfo.clearValueCount = clearValues.size();
    beginInfo.pClearValues = clearValues.begin();

    // Submit pipeline barriers to ensure any image layout transitions are recorded prior to
    // beginning the render pass.
    this->submitPipelineBarriers();
    // TODO: If we add support for secondary command buffers, dynamically determine subpass contents
    VULKAN_CALL(fSharedContext->interface(),
                CmdBeginRenderPass(fPrimaryCommandBuffer,
                                   &beginInfo,
                                   VK_SUBPASS_CONTENTS_INLINE));
    fActiveRenderPass = true;

    if (loadMSAAFromResolve && !this->loadMSAAFromResolve(rpDesc,
                                                          *vulkanResolveTexture,
                                                          renderArea)) {
        SKIA_LOG_E("Failed to load MSAA from resolve");
        this->endRenderPass();
        return false;
    }

    // loadMSAAFromResolve() will have manipulated the viewport, so now that that is done, set it
    // to what the draw passes expect.
    this->setViewport(viewport);

    // Once we have an active render pass, the command buffer should hold on to a frame buffer ref.
    this->trackResource(std::move(framebuffer));
    return true;
}

void VulkanCommandBuffer::endRenderPass() {
    SkASSERT(fActive);
    VULKAN_CALL(fSharedContext->interface(), CmdEndRenderPass(fPrimaryCommandBuffer));
    fActiveRenderPass = false;
    fTargetTexture = nullptr;
}

void VulkanCommandBuffer::addDrawPass(DrawPass* drawPass) {
    // If there is storage buffer data to bind, it must be done prior to draws.
    if (drawPass->storageBufferInfo().fBuffer != nullptr) {
        this->recordBufferBindingInfo(drawPass->storageBufferInfo(),
                                      UniformSlot::kStorage);
    }

    for (auto [type, cmdPtr] : drawPass->commands()) {
        switch (type) {
            case DrawPassCommands::Type::kBindGraphicsPipeline: {
                auto bgp = static_cast<DrawPassCommands::BindGraphicsPipeline*>(cmdPtr);
                this->bindGraphicsPipeline(drawPass->getPipeline(bgp->fPipelineIndex));
                break;
            }
            case DrawPassCommands::Type::kSetBlendConstants: {
                auto sbc = static_cast<DrawPassCommands::SetBlendConstants*>(cmdPtr);
                this->setBlendConstants(sbc->fBlendConstants);
                break;
            }
            case DrawPassCommands::Type::kBindUniformBuffer: {
                auto bub = static_cast<DrawPassCommands::BindUniformBuffer*>(cmdPtr);
                this->recordBufferBindingInfo(bub->fInfo, bub->fSlot);
                break;
            }
            case DrawPassCommands::Type::kBindStaticDataBuffer: {
                auto bdb = static_cast<DrawPassCommands::BindStaticDataBuffer*>(cmdPtr);
                this->bindInputBuffer(bdb->fStaticData.fBuffer, bdb->fStaticData.fOffset,
                                      VulkanGraphicsPipeline::kStaticDataBufferIndex);
                break;
            }
            case DrawPassCommands::Type::kBindAppendDataBuffer: {
                auto bdb = static_cast<DrawPassCommands::BindAppendDataBuffer*>(cmdPtr);
                this->bindInputBuffer(bdb->fAppendData.fBuffer, bdb->fAppendData.fOffset,
                                      VulkanGraphicsPipeline::kAppendDataBufferIndex);
                break;
            }
            case DrawPassCommands::Type::kBindIndexBuffer: {
                auto bdb = static_cast<DrawPassCommands::BindIndexBuffer*>(cmdPtr);
                this->bindIndexBuffer(
                        bdb->fIndices.fBuffer, bdb->fIndices.fOffset);
                break;
            }
            case DrawPassCommands::Type::kBindIndirectBuffer: {
                auto bdb = static_cast<DrawPassCommands::BindIndirectBuffer*>(cmdPtr);
                this->bindIndirectBuffer(
                        bdb->fIndirect.fBuffer, bdb->fIndirect.fOffset);
                break;
            }
            case DrawPassCommands::Type::kBindTexturesAndSamplers: {
                auto bts = static_cast<DrawPassCommands::BindTexturesAndSamplers*>(cmdPtr);
                this->recordTextureAndSamplerDescSet(drawPass, bts);
                break;
            }
            case DrawPassCommands::Type::kSetScissor: {
                auto ss = static_cast<DrawPassCommands::SetScissor*>(cmdPtr);
                this->setScissor(ss->fScissor);
                break;
            }
            case DrawPassCommands::Type::kDraw: {
                auto draw = static_cast<DrawPassCommands::Draw*>(cmdPtr);
                this->draw(draw->fType, draw->fBaseVertex, draw->fVertexCount);
                break;
            }
            case DrawPassCommands::Type::kDrawIndexed: {
                auto draw = static_cast<DrawPassCommands::DrawIndexed*>(cmdPtr);
                this->drawIndexed(
                        draw->fType, draw->fBaseIndex, draw->fIndexCount, draw->fBaseVertex);
                break;
            }
            case DrawPassCommands::Type::kDrawInstanced: {
                auto draw = static_cast<DrawPassCommands::DrawInstanced*>(cmdPtr);
                this->drawInstanced(draw->fType,
                                    draw->fBaseVertex,
                                    draw->fVertexCount,
                                    draw->fBaseInstance,
                                    draw->fInstanceCount);
                break;
            }
            case DrawPassCommands::Type::kDrawIndexedInstanced: {
                auto draw = static_cast<DrawPassCommands::DrawIndexedInstanced*>(cmdPtr);
                this->drawIndexedInstanced(draw->fType,
                                           draw->fBaseIndex,
                                           draw->fIndexCount,
                                           draw->fBaseVertex,
                                           draw->fBaseInstance,
                                           draw->fInstanceCount);
                break;
            }
            case DrawPassCommands::Type::kDrawIndirect: {
                auto draw = static_cast<DrawPassCommands::DrawIndirect*>(cmdPtr);
                this->drawIndirect(draw->fType);
                break;
            }
            case DrawPassCommands::Type::kDrawIndexedIndirect: {
                auto draw = static_cast<DrawPassCommands::DrawIndexedIndirect*>(cmdPtr);
                this->drawIndexedIndirect(draw->fType);
                break;
            }
            case DrawPassCommands::Type::kAddBarrier: {
                auto barrierCmd = static_cast<DrawPassCommands::AddBarrier*>(cmdPtr);
                this->addBarrier(barrierCmd->fType);
                break;
            }
        }
    }
}

void VulkanCommandBuffer::bindGraphicsPipeline(const GraphicsPipeline* graphicsPipeline) {
    SkASSERT(fActiveRenderPass);
    // TODO(b/414645289): Once the front-end is made aware of dynamic state, it could recognize when
    // only dynamic state has changed.  In that case, since the pipeline doesn't change, this call
    // can be avoided.  The logic after this would then have to move to another place; for example
    // setting dynamic states should move to a separate VulkanCommandBuffer call.
    const auto* previousGraphicsPipeline = fActiveGraphicsPipeline;
    fActiveGraphicsPipeline = static_cast<const VulkanGraphicsPipeline*>(graphicsPipeline);
    VULKAN_CALL(fSharedContext->interface(), CmdBindPipeline(fPrimaryCommandBuffer,
                                                             VK_PIPELINE_BIND_POINT_GRAPHICS,
                                                             fActiveGraphicsPipeline->pipeline()));
    // TODO(b/293924877): Compare pipeline layouts. If 2 pipelines have the same pipeline layout,
    // then descriptor sets do not need to be re-bound. For now, simply force a re-binding of
    // descriptor sets with any new bindGraphicsPipeline DrawPassCommand.
    fBindUniformBuffers = true;

    fActiveGraphicsPipeline->updateDynamicState(
            fSharedContext, fPrimaryCommandBuffer, previousGraphicsPipeline);
}

void VulkanCommandBuffer::setBlendConstants(std::array<float, 4> blendConstants) {
    SkASSERT(fActive);
    if (fCachedBlendConstant != blendConstants) {
        VULKAN_CALL(fSharedContext->interface(),
                    CmdSetBlendConstants(fPrimaryCommandBuffer, blendConstants.data()));
        fCachedBlendConstant = blendConstants;
    }
}

void VulkanCommandBuffer::addBarrier(BarrierType type) {
    SkASSERT(fTargetTexture);

    VkPipelineStageFlags dstStage;
    VkAccessFlags dstAccess;
    if (type == BarrierType::kAdvancedNoncoherentBlend) {
        dstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
        dstAccess = VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT;
    } else {
        // If input reads are coherent, no barrier is needed
        if (fSharedContext->vulkanCaps().isInputAttachmentReadCoherent()) {
            return;
        }

        SkASSERT(type == BarrierType::kReadDstFromInput);
        dstStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
        dstAccess = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
    }
    VkImageMemoryBarrier imageMemoryBarrier = {
            VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
            /*pNext=*/nullptr,
            /*srcAccessMask=*/VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
            dstAccess,
            /*oldLayout=*/VK_IMAGE_LAYOUT_GENERAL,
            /*newLayout=*/VK_IMAGE_LAYOUT_GENERAL,
            /*srcQueueFamilyIndex=*/VK_QUEUE_FAMILY_IGNORED,
            /*dstQueueFamilyIndex=*/VK_QUEUE_FAMILY_IGNORED,
            fTargetTexture->vkImage(),
            /*subresourceRange=*/{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }};
    this->addImageMemoryBarrier(fTargetTexture,
                                VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
                                dstStage,
                                /*byRegion=*/true,
                                &imageMemoryBarrier);
}

void VulkanCommandBuffer::recordBufferBindingInfo(const BindBufferInfo& info, UniformSlot slot) {
    unsigned int bufferIndex = 0;
    switch (slot) {
        case UniformSlot::kCombinedUniforms:
            bufferIndex = VulkanGraphicsPipeline::kCombinedUniformIndex;
            break;
        case UniformSlot::kStorage:
            bufferIndex = VulkanGraphicsPipeline::kStorageBufferIndex;
            break;
        default:
            SkASSERT(false);
    }

    fUniformBuffersToBind[bufferIndex] = info;
    fBindUniformBuffers = true;
}

void VulkanCommandBuffer::syncDescriptorSets() {
    if (fBindUniformBuffers) {
        this->bindUniformBuffers();
        // Changes to descriptor sets in lower slot numbers disrupt later set bindings. Currently,
        // the descriptor set which houses uniform buffers is at a lower slot than the texture /
        // sampler set, so rebinding uniform buffers necessitates re-binding any texture/samplers.
        fBindTextureSamplers = true;
    }
    if (fBindTextureSamplers) {
        this->bindTextureSamplers();
    }
}

namespace {
void update_uniform_descriptor_set(SkSpan<DescriptorData> requestedDescriptors,
                                   SkSpan<BindBufferInfo> bindUniformBufferInfo,
                                   VkDescriptorSet descSet,
                                   const VulkanSharedContext* sharedContext) {
    for (size_t i = 0; i < requestedDescriptors.size(); i++) {
        int descriptorBindingIndex = requestedDescriptors[i].fBindingIndex;
        SkASSERT(SkTo<unsigned long>(descriptorBindingIndex) < bindUniformBufferInfo.size());
        const auto& bindInfo = bindUniformBufferInfo[descriptorBindingIndex];
        if (bindInfo.fBuffer) {
#if defined(SK_DEBUG)
            static uint64_t maxBufferRange =
                sharedContext->caps()->storageBufferSupport()
                    ? sharedContext->vulkanCaps().maxStorageBufferRange()
                    : sharedContext->vulkanCaps().maxUniformBufferRange();
            SkASSERT(bindInfo.fSize <= maxBufferRange);
#endif
            VkDescriptorBufferInfo bufferInfo = {};
            auto vulkanBuffer = static_cast<const VulkanBuffer*>(bindInfo.fBuffer);
            bufferInfo.buffer = vulkanBuffer->vkBuffer();
            bufferInfo.offset = 0; // We always use dynamic ubos so we set the base offset to 0
            bufferInfo.range = bindInfo.fSize;

            VkWriteDescriptorSet writeInfo = {};
            writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
            writeInfo.dstSet = descSet;
            writeInfo.dstBinding = descriptorBindingIndex;
            writeInfo.dstArrayElement = 0;
            writeInfo.descriptorCount = requestedDescriptors[i].fCount;
            writeInfo.descriptorType = DsTypeEnumToVkDs(requestedDescriptors[i].fType);
            writeInfo.pBufferInfo = &bufferInfo;

            // TODO(b/293925059): Migrate to updating all the uniform descriptors with one driver
            // call. Calling UpdateDescriptorSets once to encapsulate updates to all uniform
            // descriptors would be ideal, but that led to issues with draws where all the UBOs
            // within that set would unexpectedly be assigned the same offset. Updating them one at
            // a time within this loop works in the meantime but is suboptimal.
            VULKAN_CALL(sharedContext->interface(),
                        UpdateDescriptorSets(sharedContext->device(),
                                             /*descriptorWriteCount=*/1,
                                             &writeInfo,
                                             /*descriptorCopyCount=*/0,
                                             /*pDescriptorCopies=*/nullptr));
        }
    }
}

} // anonymous namespace

void VulkanCommandBuffer::bindUniformBuffers() {
    fBindUniformBuffers = false;
    using Pipeline = VulkanGraphicsPipeline;

    const bool hasCombinedUbo =
            fActiveGraphicsPipeline->hasCombinedUniforms() &&
            fUniformBuffersToBind[Pipeline::kCombinedUniformIndex].fBuffer;
    const bool hasStorageBuffer =
            fActiveGraphicsPipeline->usesStorageBuffer() &&
            fUniformBuffersToBind[Pipeline::kStorageBufferIndex].fBuffer;

    // We should never have a storage buffer without having a combined uniform buffer as well.
    SkASSERT(!hasStorageBuffer || hasCombinedUbo);

    // If no uniforms are used, we can go ahead and return since no descriptors need to be bound.
    if (!hasCombinedUbo) {
        return;
    }

    const auto& combinedUboInfo = fUniformBuffersToBind[Pipeline::kCombinedUniformIndex];
    auto vulkanBuffer = static_cast<const VulkanBuffer*>(combinedUboInfo.fBuffer);

    DescriptorType uniformBufferType =
            fSharedContext->caps()->storageBufferSupport() ? DescriptorType::kStorageBufferDynamic
                                                           : DescriptorType::kUniformBufferDynamic;

    // If we determine that we should use storage buffers, we expect that the actual VkBuffer
    // supports that usage.
    SkASSERT(uniformBufferType != DescriptorType::kStorageBufferDynamic ||
             vulkanBuffer->bufferUsageFlags() | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);

    // We expect to have up to 2 descriptors within this set. Fill out DescriptorData (for
    // interfacing with backend-agnostic graphite calls) and dynamic offset information for each
    // uniform, starting with the combined uniform buffer.
    skia_private::STArray<2, DescriptorData> uniformDescriptorData;
    skia_private::STArray<2, uint32_t> dynamicOffsets;

    uniformDescriptorData.push_back({
            uniformBufferType,
            /*count=*/1,
            Pipeline::kCombinedUniformIndex,
            PipelineStageFlags::kVertexShader | PipelineStageFlags::kFragmentShader });
    dynamicOffsets.push_back(combinedUboInfo.fOffset);

    if (fActiveGraphicsPipeline->usesStorageBuffer()) {
        SkASSERT(fSharedContext->caps()->storageBufferSupport());
        uniformDescriptorData.push_back({DescriptorType::kStorageBufferDynamic,
                                         /*count=*/1,
                                         Pipeline::kStorageBufferIndex,
                                         fActiveGraphicsPipeline->storageBufferStages()});
        dynamicOffsets.push_back(fUniformBuffersToBind[Pipeline::kStorageBufferIndex].fOffset);
    }

    // Now obtain an actual descriptor set. In the case of using only one buffer, we can query
    // the VulkanBuffer for an existing cached set with the appropriate sizing and can avoid
    // performing an update call on the set. Otherwise, obtain a new set and update before binding.
    sk_sp<VulkanDescriptorSet> descSet;
    if (hasStorageBuffer ||
        !(descSet = vulkanBuffer->getCachedSingleBufferDescriptorSet(combinedUboInfo.fSize))) {

        descSet = fResourceProvider->findOrCreateDescriptorSet(uniformDescriptorData);
        if (!descSet) {
            SKIA_LOG_E("Unable to find or create uniform descriptor set");
            return;
        }

        // Update the set before binding.
        update_uniform_descriptor_set(uniformDescriptorData,
                                      fUniformBuffersToBind,
                                      *descSet->descriptorSet(),
                                      fSharedContext);

        // If we ended up creating a new single-buffer descriptor set, cache it on the VulkanBuffer.
        if (!hasStorageBuffer) {
            const_cast<VulkanBuffer*>(vulkanBuffer)->
                    addCachedSingleBufferDescriptorSet(combinedUboInfo.fSize, descSet);
        }
    }

    VULKAN_CALL(fSharedContext->interface(),
                CmdBindDescriptorSets(fPrimaryCommandBuffer,
                                      VK_PIPELINE_BIND_POINT_GRAPHICS,
                                      fActiveGraphicsPipeline->layout(),
                                      Pipeline::kUniformBufferDescSetIndex,
                                      /*setCount=*/1,
                                      descSet->descriptorSet(),
                                      uniformDescriptorData.size(),
                                      dynamicOffsets.data()));

    this->trackResource(std::move(descSet));
}

void VulkanCommandBuffer::bindInputBuffer(const Buffer* inputBuffer, VkDeviceSize offset,
                                          uint32_t binding) {
    if (inputBuffer) {
        SkASSERT(inputBuffer->isProtected() == Protected::kNo);
        VkBuffer vkBuffer = static_cast<const VulkanBuffer*>(inputBuffer)->vkBuffer();
        SkASSERT(vkBuffer != VK_NULL_HANDLE);
        VULKAN_CALL(fSharedContext->interface(), CmdBindVertexBuffers(fPrimaryCommandBuffer,
                                                                      binding,
                                                                      /*bindingCount=*/1,
                                                                      &vkBuffer,
                                                                      &offset));
    }
}

void VulkanCommandBuffer::bindIndexBuffer(const Buffer* indexBuffer, size_t offset) {
    if (indexBuffer) {
        SkASSERT(indexBuffer->isProtected() == Protected::kNo);
        VkBuffer vkBuffer = static_cast<const VulkanBuffer*>(indexBuffer)->vkBuffer();
        SkASSERT(vkBuffer != VK_NULL_HANDLE);
        VULKAN_CALL(fSharedContext->interface(), CmdBindIndexBuffer(fPrimaryCommandBuffer,
                                                                     vkBuffer,
                                                                     offset,
                                                                     VK_INDEX_TYPE_UINT16));
    }
}

void VulkanCommandBuffer::bindIndirectBuffer(const Buffer* indirectBuffer, size_t offset) {
    // Indirect buffers are not bound via the command buffer, but specified in the draw cmd.
    if (indirectBuffer) {
        SkASSERT(indirectBuffer->isProtected() == Protected::kNo);
        fBoundIndirectBuffer = static_cast<const VulkanBuffer*>(indirectBuffer)->vkBuffer();
        fBoundIndirectBufferOffset = offset;
    } else {
        fBoundIndirectBuffer = VK_NULL_HANDLE;
        fBoundIndirectBufferOffset = 0;
    }
}

void VulkanCommandBuffer::recordTextureAndSamplerDescSet(
        const DrawPass* drawPass, const DrawPassCommands::BindTexturesAndSamplers* command) {
    SkASSERT(SkToBool(drawPass) == SkToBool(command));
    SkASSERT(fActiveGraphicsPipeline);
    auto resetTextureAndSamplerState = [&]() {
        fNumTextureSamplers = 0;
        fTextureSamplerDescSetToBind = VK_NULL_HANDLE;
        fBindTextureSamplers = false;
    };

    bool hasDstCopy = fActiveGraphicsPipeline->dstReadStrategy() == DstReadStrategy::kTextureCopy;
    int numTexSamplers = (command ? command->fNumTexSamplers : 0) + hasDstCopy;
    if (numTexSamplers == 0) {
        resetTextureAndSamplerState();
        return;
    }

    sk_sp<VulkanDescriptorSet> set;
    const VulkanTexture* singleTexture = nullptr;
    sk_sp<Sampler> singleSampler = nullptr;
    if (numTexSamplers == 1) {
        SkASSERT(hasDstCopy || command);
        singleTexture = static_cast<const VulkanTexture*>(
                hasDstCopy ? fDstCopy.first : command->fTextures[0]->texture());
        singleSampler = sk_ref_sp<Sampler>(hasDstCopy ? fDstCopy.second : getSampler(command, 0));
        SkASSERT(singleTexture && singleSampler);
        set = singleTexture->getCachedSingleTextureDescriptorSet(singleSampler.get());
    }

    if (!set) {
        TArray<DescriptorData> descriptors(numTexSamplers);
        if (command) {
            for (int i = 0; i < command->fNumTexSamplers; i++) {
                // Embed immutable samplers into the descriptor set directly, which are held on the
                // active graphics pipeline and can be indexed directly with `i`.
                const Sampler* immutableSampler = fActiveGraphicsPipeline->immutableSampler(i);
                SkASSERT(SkToBool(immutableSampler) == command->fSamplers[i].isImmutable());
                descriptors.push_back({DescriptorType::kCombinedTextureSampler,
                                       /*count=*/1,
                                       /*bindingIdx=*/i,
                                       PipelineStageFlags::kFragmentShader,
                                       immutableSampler});
            }
        }
        // If required the dst copy texture+sampler is the last one in the descriptor set
        if (hasDstCopy) {
            descriptors.push_back({DescriptorType::kCombinedTextureSampler,
                                   /*count=*/1,
                                   /*bindingIdx=*/numTexSamplers - 1,
                                   PipelineStageFlags::kFragmentShader,
                                   /*immutableSampler=*/nullptr});
        }
        SkASSERT(descriptors.size() == numTexSamplers);
        // Query resource provider to obtain a descriptor set for the texture/samplers
        set = fResourceProvider->findOrCreateDescriptorSet(
                {&descriptors.front(), (size_t)descriptors.size()});
        if (!set) {
            SKIA_LOG_E("Unable to find or create descriptor set");
            resetTextureAndSamplerState();
            return;
        }

        TArray<VkWriteDescriptorSet> writeDescriptorSets(numTexSamplers);
        TArray<VkDescriptorImageInfo> descriptorImageInfos(numTexSamplers);
        if (command) {
            for (int i = 0; i < command->fNumTexSamplers; ++i) {
                auto texture = static_cast<const VulkanTexture*>(command->fTextures[i]->texture());
                // TODO(b/294198324): Investigate the root cause for null texture or samplers on
                // Ubuntu QuadP400 GPU
                if (!texture) {
                    SKIA_LOG_E("Invalid texture in BindTexturesAndSamplers command.");
                    resetTextureAndSamplerState();
                    return;
                }

                if (command->fSamplers[i].isImmutable()) {
                    populate_write_info(set.get(), descriptorImageInfos, writeDescriptorSets,
                                        texture, /*sampler=*/nullptr, i);
                } else {
                    auto sampler = static_cast<const VulkanSampler*>(
                            fSharedContext->globalCache()->getDynamicSampler(
                                    command->fSamplers[i]));
                    // b/294198324, see above
                    if (!sampler) {
                        SKIA_LOG_E("Invalid dynamic sampler.");
                        resetTextureAndSamplerState();
                        return;
                    }
                    populate_write_info(set.get(), descriptorImageInfos, writeDescriptorSets,
                                        texture, sampler, i);
                }
            }
        }

        if (fActiveGraphicsPipeline->dstReadStrategy() == DstReadStrategy::kTextureCopy) {
            auto texture = static_cast<const VulkanTexture*>(fDstCopy.first);
            auto sampler = static_cast<const VulkanSampler*>(fDstCopy.second);
            // b/294198324, see above
            if (!texture || !sampler) {
                SKIA_LOG_E("Invalid texture or sampler for dst-copy path.");
                resetTextureAndSamplerState();
                return;
            }
            populate_write_info(set.get(), descriptorImageInfos, writeDescriptorSets,
                                        texture, sampler, numTexSamplers - 1);
        }

        SkASSERT(writeDescriptorSets.size() == numTexSamplers);
        VULKAN_CALL(fSharedContext->interface(),
                    UpdateDescriptorSets(fSharedContext->device(),
                                         writeDescriptorSets.size(),
                                         writeDescriptorSets.begin(),
                                         /*descriptorCopyCount=*/0,
                                         /*pDescriptorCopies=*/nullptr));

        if (numTexSamplers == 1) {
            SkASSERT(singleTexture && singleSampler);
            singleTexture->addCachedSingleTextureDescriptorSet(set, singleSampler);
        }
    }

    // Store the updated descriptor set to be actually bound later on. This avoids binding and
    // potentially having to re-bind in cases where earlier descriptor sets change while going
    // through drawpass commands.
    fTextureSamplerDescSetToBind = *set->descriptorSet();
    fBindTextureSamplers = true;
    fNumTextureSamplers = numTexSamplers;
    this->trackResource(std::move(set));
}

void VulkanCommandBuffer::bindTextureSamplers() {
    fBindTextureSamplers = false;
    if (fTextureSamplerDescSetToBind != VK_NULL_HANDLE &&
        fActiveGraphicsPipeline->numFragTexturesAndSamplers() == fNumTextureSamplers) {
        VULKAN_CALL(fSharedContext->interface(),
                    CmdBindDescriptorSets(fPrimaryCommandBuffer,
                                          VK_PIPELINE_BIND_POINT_GRAPHICS,
                                          fActiveGraphicsPipeline->layout(),
                                          VulkanGraphicsPipeline::kTextureBindDescSetIndex,
                                          /*setCount=*/1,
                                          &fTextureSamplerDescSetToBind,
                                          /*dynamicOffsetCount=*/0,
                                          /*dynamicOffsets=*/nullptr));
    }
}

void VulkanCommandBuffer::setScissor(const Scissor& scissor) {
    this->setScissor(scissor.getRect(fReplayTranslation, fRenderAreaBounds));
}

void VulkanCommandBuffer::setScissor(const SkIRect& rect) {
    VkRect2D scissor = {
            {rect.x(), rect.y()},
            {static_cast<unsigned int>(rect.width()), static_cast<unsigned int>(rect.height())}};
    VULKAN_CALL(fSharedContext->interface(),
                CmdSetScissor(fPrimaryCommandBuffer,
                              /*firstScissor=*/0,
                              /*scissorCount=*/1,
                              &scissor));
}

void VulkanCommandBuffer::draw(PrimitiveType,
                               unsigned int baseVertex,
                               unsigned int vertexCount) {
    SkASSERT(fActiveRenderPass);
    this->syncDescriptorSets();
    // TODO: set primitive type via dynamic state if available
    VULKAN_CALL(fSharedContext->interface(),
                CmdDraw(fPrimaryCommandBuffer,
                        vertexCount,
                        /*instanceCount=*/1,
                        baseVertex,
                        /*firstInstance=*/0));
}

void VulkanCommandBuffer::drawIndexed(PrimitiveType,
                                      unsigned int baseIndex,
                                      unsigned int indexCount,
                                      unsigned int baseVertex) {
    SkASSERT(fActiveRenderPass);
    this->syncDescriptorSets();
    // TODO: set primitive type via dynamic state if available
    VULKAN_CALL(fSharedContext->interface(),
                CmdDrawIndexed(fPrimaryCommandBuffer,
                               indexCount,
                               /*instanceCount=*/1,
                               baseIndex,
                               baseVertex,
                               /*firstInstance=*/0));
}

void VulkanCommandBuffer::drawInstanced(PrimitiveType,
                                        unsigned int baseVertex,
                                        unsigned int vertexCount,
                                        unsigned int baseInstance,
                                        unsigned int instanceCount) {
    SkASSERT(fActiveRenderPass);
    this->syncDescriptorSets();
    // TODO: set primitive type via dynamic state if available
    VULKAN_CALL(fSharedContext->interface(),
                CmdDraw(fPrimaryCommandBuffer,
                        vertexCount,
                        instanceCount,
                        baseVertex,
                        baseInstance));
}

void VulkanCommandBuffer::drawIndexedInstanced(PrimitiveType,
                                               unsigned int baseIndex,
                                               unsigned int indexCount,
                                               unsigned int baseVertex,
                                               unsigned int baseInstance,
                                               unsigned int instanceCount) {
    SkASSERT(fActiveRenderPass);
    this->syncDescriptorSets();
    // TODO: set primitive type via dynamic state if available
    VULKAN_CALL(fSharedContext->interface(),
                CmdDrawIndexed(fPrimaryCommandBuffer,
                               indexCount,
                               instanceCount,
                               baseIndex,
                               baseVertex,
                               baseInstance));
}

void VulkanCommandBuffer::drawIndirect(PrimitiveType) {
    SkASSERT(fActiveRenderPass);
    this->syncDescriptorSets();
    // TODO: set primitive type via dynamic state if available
    // Currently we can only support doing one indirect draw operation at a time,
    // so stride is irrelevant.
    VULKAN_CALL(fSharedContext->interface(),
                CmdDrawIndirect(fPrimaryCommandBuffer,
                                fBoundIndirectBuffer,
                                fBoundIndirectBufferOffset,
                                /*drawCount=*/1,
                                /*stride=*/0));
}

void VulkanCommandBuffer::drawIndexedIndirect(PrimitiveType) {
    SkASSERT(fActiveRenderPass);
    this->syncDescriptorSets();
    // TODO: set primitive type via dynamic state if available
    // Currently we can only support doing one indirect draw operation at a time,
    // so stride is irrelevant.
    VULKAN_CALL(fSharedContext->interface(),
                CmdDrawIndexedIndirect(fPrimaryCommandBuffer,
                                       fBoundIndirectBuffer,
                                       fBoundIndirectBufferOffset,
                                       /*drawCount=*/1,
                                       /*stride=*/0));
}

bool VulkanCommandBuffer::bindDispatchResources(const DispatchGroup& group,
                                                const DispatchGroup::Dispatch& dispatch) {
    SkASSERT(fActiveComputePipeline);

    if (dispatch.fBindings.empty()) {
        return true;
    }

    sk_sp<VulkanDescriptorSet> descSet =
            fResourceProvider->findOrCreateDescriptorSet(fActiveComputePipeline->descriptorData());
    if (!descSet) {
        SKIA_LOG_E("Unable to find or create compute descriptor set");
        return false;
    }

    struct BindingWrite {
        VkDescriptorType fType = VK_DESCRIPTOR_TYPE_MAX_ENUM;
        VkDescriptorBufferInfo fBufferInfo = {};
        VkDescriptorImageInfo fImageInfo = {};
        bool fHasBuffer = false;
        bool fHasTexture = false;
        bool fHasSampler = false;
    };

    size_t numBindings = fActiveComputePipeline->descriptorData().size();
    constexpr int kInlineBindings = 8;
    STArray<kInlineBindings, BindingWrite> bindingWrites;
    bindingWrites.resize(numBindings);
    for (size_t i = 0; i < numBindings; ++i) {
        bindingWrites[i].fType = fActiveComputePipeline->bindingType(i);
    }

    for (const ResourceBinding& binding : dispatch.fBindings) {
        SkASSERT(binding.fIndex < SkTo<uint32_t>(bindingWrites.size()));
        BindingWrite& bWrite = bindingWrites[binding.fIndex];

        if (const BindBufferInfo* buffer = std::get_if<BindBufferInfo>(&binding.fResource)) {
            if (!buffer->fBuffer) {
                SKIA_LOG_E("Encountered null buffer binding for compute dispatch");
                return false;
            }
            SkASSERT(buffer->fSize > 0);
#if defined(SK_DEBUG)
            if (bWrite.fType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) {
                SkASSERT(buffer->fSize <= fSharedContext->vulkanCaps().maxUniformBufferRange());
            } else if (bWrite.fType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) {
                SkASSERT(buffer->fSize <= fSharedContext->vulkanCaps().maxStorageBufferRange());
            }
#endif
            const auto* vkBuffer = static_cast<const VulkanBuffer*>(buffer->fBuffer);
            bWrite.fBufferInfo.buffer = vkBuffer->vkBuffer();
            bWrite.fBufferInfo.offset = buffer->fOffset;
            bWrite.fBufferInfo.range = buffer->fSize;
            bWrite.fHasBuffer = true;
            VkAccessFlags accessFlags = fActiveComputePipeline->bufferAccessFlags(binding.fIndex);
            SkASSERT(accessFlags != 0);
            vkBuffer->setBufferAccess(this, accessFlags, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
        } else if (const TextureIndex* texIdx = std::get_if<TextureIndex>(&binding.fResource)) {
            const auto* texture =
                    static_cast<const VulkanTexture*>(group.getTexture(texIdx->fValue));
            SkASSERT(texture);
            if (bWrite.fType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) {
                const_cast<VulkanTexture*>(texture)->setImageLayout(
                        this,
                        VK_IMAGE_LAYOUT_GENERAL,
                        VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
                        VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
                bWrite.fImageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
            } else {
                SkASSERT(bWrite.fType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
                         bWrite.fType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
                const_cast<VulkanTexture*>(texture)->setImageLayout(
                        this,
                        VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
                        VK_ACCESS_SHADER_READ_BIT,
                        VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
                bWrite.fImageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
            }
            bWrite.fImageInfo.imageView =
                    texture->getImageView(VulkanImageView::Usage::kShaderInput)->imageView();
            bWrite.fHasTexture = true;
        } else if (const SamplerIndex* samplerIdx = std::get_if<SamplerIndex>(&binding.fResource)) {
            const auto* sampler =
                    static_cast<const VulkanSampler*>(group.getSampler(samplerIdx->fValue));
            SkASSERT(sampler);
            bWrite.fImageInfo.sampler = sampler->vkSampler();
            bWrite.fHasSampler = true;
        }
    }

    STArray<kInlineBindings, VkWriteDescriptorSet> writes;
    writes.reserve_exact(bindingWrites.size());
    const auto& descData = fActiveComputePipeline->descriptorData();
    for (int i = 0; i < bindingWrites.size(); ++i) {
        BindingWrite& bWrite = bindingWrites[i];
        VkWriteDescriptorSet write = {};
        write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
        write.dstSet = *descSet->descriptorSet();
        write.dstBinding = descData[i].fBindingIndex;
        write.dstArrayElement = 0;
        write.descriptorCount = 1;
        write.descriptorType = bWrite.fType;

        if (bWrite.fHasBuffer) {
            write.pBufferInfo = &bWrite.fBufferInfo;
            writes.push_back(write);
        } else if (bWrite.fHasTexture || bWrite.fHasSampler) {
            SkASSERT(bWrite.fType != VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
                     (bWrite.fHasTexture && bWrite.fHasSampler));
            write.pImageInfo = &bWrite.fImageInfo;
            writes.push_back(write);
        }
    }

    if (!writes.empty()) {
        VULKAN_CALL(fSharedContext->interface(),
                    UpdateDescriptorSets(fSharedContext->device(),
                                         writes.size(),
                                         writes.data(),
                                         0,
                                         nullptr));
    }

    VULKAN_CALL(fSharedContext->interface(),
                CmdBindDescriptorSets(fPrimaryCommandBuffer,
                                      VK_PIPELINE_BIND_POINT_COMPUTE,
                                      fActiveComputePipeline->vkPipelineLayout(),
                                      0,
                                      1,
                                      descSet->descriptorSet(),
                                      0,
                                      nullptr));

    this->trackResource(std::move(descSet));
    return true;
}

bool VulkanCommandBuffer::onAddComputePass(DispatchGroupSpan groups) {
    for (const auto& group : groups) {
        group->addResourceRefs(this);
        for (const auto& dispatch : group->dispatches()) {
            const ComputePipeline* pipeline = group->getPipeline(dispatch.fPipelineIndex);
            if (!pipeline) {
                fActiveComputePipeline = nullptr;
                return false;
            }
            const auto* vkComputePipeline = static_cast<const VulkanComputePipeline*>(pipeline);
            if (fActiveComputePipeline != vkComputePipeline) {
                fActiveComputePipeline = vkComputePipeline;
                VULKAN_CALL(fSharedContext->interface(),
                            CmdBindPipeline(fPrimaryCommandBuffer,
                                            VK_PIPELINE_BIND_POINT_COMPUTE,
                                            vkComputePipeline->vkPipeline()));
            }

            if (!this->bindDispatchResources(*group, dispatch)) {
                fActiveComputePipeline = nullptr;
                return false;
            }

            if (const BindBufferInfo* indirect =
                        std::get_if<BindBufferInfo>(&dispatch.fGlobalSizeOrIndirect)) {
                const auto* indirectBuffer = static_cast<const VulkanBuffer*>(indirect->fBuffer);
                indirectBuffer->setBufferAccess(this,
                                                VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
                                                VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT);
            }

            // TODO: Currently we submit pipeline barriers before each dispatch to ensure safety
            // against RAW/WAW hazards. If a DispatchGroup contains independent dispatches that do
            // not have data dependencies on each other, flushing barriers inside this inner loop
            // could cause slight over-synchronization. We can optimize this in the future by
            // batching barriers across independent dispatches.
            this->submitPipelineBarriers();

            if (const WorkgroupSize* globalSize =
                        std::get_if<WorkgroupSize>(&dispatch.fGlobalSizeOrIndirect)) {
                VULKAN_CALL(fSharedContext->interface(),
                            CmdDispatch(fPrimaryCommandBuffer,
                                        globalSize->fWidth,
                                        globalSize->fHeight,
                                        globalSize->fDepth));
            } else {
                SkASSERT(std::holds_alternative<BindBufferInfo>(dispatch.fGlobalSizeOrIndirect));
                const BindBufferInfo& indirect =
                        *std::get_if<BindBufferInfo>(&dispatch.fGlobalSizeOrIndirect);
                const auto* indirectBuffer = static_cast<const VulkanBuffer*>(indirect.fBuffer);
                VULKAN_CALL(fSharedContext->interface(),
                            CmdDispatchIndirect(fPrimaryCommandBuffer,
                                                indirectBuffer->vkBuffer(),
                                                indirect.fOffset));
            }
        }
    }
    fActiveComputePipeline = nullptr;
    return true;
}

bool VulkanCommandBuffer::onCopyBufferToBuffer(const Buffer* srcBuffer,
                                               size_t srcOffset,
                                               const Buffer* dstBuffer,
                                               size_t dstOffset,
                                               size_t size) {
    auto vkSrcBuffer = static_cast<const VulkanBuffer*>(srcBuffer);
    auto vkDstBuffer = static_cast<const VulkanBuffer*>(dstBuffer);

    SkASSERT(vkSrcBuffer->bufferUsageFlags() & VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
    SkASSERT(vkDstBuffer->bufferUsageFlags() & VK_BUFFER_USAGE_TRANSFER_DST_BIT);

    vkSrcBuffer->setBufferAccess(this, VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
    vkDstBuffer->setBufferAccess(
        this, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);

    VkBufferCopy region = {};
    region.srcOffset = srcOffset;
    region.dstOffset = dstOffset;
    region.size = size;

    this->submitPipelineBarriers();

    VULKAN_CALL(fSharedContext->interface(),
                CmdCopyBuffer(fPrimaryCommandBuffer,
                              vkSrcBuffer->vkBuffer(),
                              vkDstBuffer->vkBuffer(),
                              /*regionCount=*/1,
                              &region));

    // TODO (b/394121386): We don't currently have a list of tracked buffers that are used on a
    // RenderPass in order to put in any needed barriers (like we do for textures). If we did have
    // one, then we would add the needed barriers for the buffers at the start of a render pass.
    // Until we have such a system, we need to do some hackyness here to put in a barrier with the
    // assumption that the buffer will be read after this write from the copy. The only buffer types
    // we allow to be used as the dst of a transfer are vertex and index buffers. So we check the
    // buffers usages for either of those and then set the corresponding access flag.
    VkAccessFlags dstAccess = 0;
    VkPipelineStageFlags dstStageMask = 0;
    VkBufferUsageFlags bufferUsageFlags = vkDstBuffer->bufferUsageFlags();
    if (bufferUsageFlags & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) {
        dstAccess = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
        dstStageMask = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
    } else if (bufferUsageFlags & VK_BUFFER_USAGE_INDEX_BUFFER_BIT) {
        dstAccess = VK_ACCESS_INDEX_READ_BIT;
        dstStageMask = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
    } else if (vkDstBuffer->bufferUsedForCpuRead()) {
        dstAccess = VK_ACCESS_HOST_READ_BIT;
        dstStageMask = VK_PIPELINE_STAGE_HOST_BIT;
    } else {
        SkDEBUGFAIL("Unhandled type of buffer to buffer copy\n");
        return false;
    }
    SkASSERT(dstAccess);
    vkDstBuffer->setBufferAccess(this, dstAccess, dstStageMask);

    return true;
}

bool VulkanCommandBuffer::onCopyTextureToBuffer(const Texture* texture,
                                                SkIRect srcRect,
                                                const Buffer* buffer,
                                                size_t bufferOffset,
                                                size_t bufferRowBytes) {
    const VulkanTexture* srcTexture = static_cast<const VulkanTexture*>(texture);
    auto dstBuffer = static_cast<const VulkanBuffer*>(buffer);
    SkASSERT(dstBuffer->bufferUsageFlags() & VK_BUFFER_USAGE_TRANSFER_DST_BIT);

    const size_t bytesPerBlock = TextureFormatBytesPerBlock(
            TextureInfoPriv::ViewFormat(srcTexture->textureInfo()));

    // Set up copy region
    VkBufferImageCopy region = {};
    region.bufferOffset = bufferOffset;
    // Vulkan expects bufferRowLength in texels, not bytes.
    region.bufferRowLength = (uint32_t)(bufferRowBytes/bytesPerBlock);
    region.bufferImageHeight = 0; // Tightly packed
    region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, /*mipLevel=*/0, 0, 1 };
    region.imageOffset = { srcRect.left(), srcRect.top(), /*z=*/0 };
    region.imageExtent = { (uint32_t)srcRect.width(), (uint32_t)srcRect.height(), /*depth=*/1 };

    // Enable editing of the source texture so we can change its layout so it can be copied from.
    const_cast<VulkanTexture*>(srcTexture)->setImageLayout(this,
                                                           VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
                                                           VK_ACCESS_TRANSFER_READ_BIT,
                                                           VK_PIPELINE_STAGE_TRANSFER_BIT);
    // Set current access mask for buffer
    const_cast<VulkanBuffer*>(dstBuffer)->setBufferAccess(this,
                                                          VK_ACCESS_TRANSFER_WRITE_BIT,
                                                          VK_PIPELINE_STAGE_TRANSFER_BIT);

    this->submitPipelineBarriers();

    VULKAN_CALL(fSharedContext->interface(),
                CmdCopyImageToBuffer(fPrimaryCommandBuffer,
                                     srcTexture->vkImage(),
                                     VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
                                     dstBuffer->vkBuffer(),
                                     /*regionCount=*/1,
                                     &region));
    return true;
}

bool VulkanCommandBuffer::onCopyBufferToTexture(const Buffer* buffer,
                                                const Texture* texture,
                                                const BufferTextureCopyData* copyData,
                                                int count) {
    auto srcBuffer = static_cast<const VulkanBuffer*>(buffer);
    SkASSERT(srcBuffer->bufferUsageFlags() & VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
    const VulkanTexture* dstTexture = static_cast<const VulkanTexture*>(texture);

    TextureFormat format = TextureInfoPriv::ViewFormat(dstTexture->textureInfo());
    int bytesPerBlock = TextureFormatBytesPerBlock(format);
    SkISize oneBlockDims = CompressedDimensions(TextureFormatCompressionType(format), {1, 1});

    // Set up copy regions.
    TArray<VkBufferImageCopy> regions(count);
    for (int i = 0; i < count; ++i) {
        VkBufferImageCopy& region = regions.push_back();
        region = {};
        region.bufferOffset = copyData[i].fBufferOffset;
        // copyData provides row length in bytes, but Vulkan expects bufferRowLength in texels.
        // For compressed this is the number of logical pixels not the number of blocks.
        region.bufferRowLength =
                (uint32_t)((copyData[i].fBufferRowBytes/bytesPerBlock) * oneBlockDims.fWidth);
        region.bufferImageHeight = 0; // Tightly packed
        region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, copyData[i].fMipLevel, 0, 1 };
        region.imageOffset = { copyData[i].fRect.left(),
                               copyData[i].fRect.top(),
                               /*z=*/0 };
        region.imageExtent = { (uint32_t)copyData[i].fRect.width(),
                               (uint32_t)copyData[i].fRect.height(),
                               /*depth=*/1 };
    }

    // Enable editing of the destination texture so we can change its layout so it can be copied to.
    const_cast<VulkanTexture*>(dstTexture)->setImageLayout(this,
                                                           VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
                                                           VK_ACCESS_TRANSFER_WRITE_BIT,
                                                           VK_PIPELINE_STAGE_TRANSFER_BIT);

    this->submitPipelineBarriers();

    VULKAN_CALL(fSharedContext->interface(),
            CmdCopyBufferToImage(fPrimaryCommandBuffer,
                                 srcBuffer->vkBuffer(),
                                 dstTexture->vkImage(),
                                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
                                 regions.size(),
                                 regions.begin()));
    return true;
}

bool VulkanCommandBuffer::onCopyTextureToTexture(const Texture* src,
                                                 SkIRect srcRect,
                                                 const Texture* dst,
                                                 SkIPoint dstPoint,
                                                 int mipLevel) {
    const VulkanTexture* srcTexture = static_cast<const VulkanTexture*>(src);
    const VulkanTexture* dstTexture = static_cast<const VulkanTexture*>(dst);

    VkImageCopy copyRegion = {};
    copyRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
    copyRegion.srcOffset = { srcRect.fLeft, srcRect.fTop, 0 };
    copyRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, (uint32_t)mipLevel, 0, 1 };
    copyRegion.dstOffset = { dstPoint.fX, dstPoint.fY, 0 };
    copyRegion.extent = { (uint32_t)srcRect.width(), (uint32_t)srcRect.height(), 1 };

    // Enable editing of the src texture so we can change its layout so it can be copied from.
    const_cast<VulkanTexture*>(srcTexture)->setImageLayout(this,
                                                           VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
                                                           VK_ACCESS_TRANSFER_READ_BIT,
                                                           VK_PIPELINE_STAGE_TRANSFER_BIT);
    // Enable editing of the destination texture so we can change its layout so it can be copied to.
    const_cast<VulkanTexture*>(dstTexture)->setImageLayout(this,
                                                           VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
                                                           VK_ACCESS_TRANSFER_WRITE_BIT,
                                                           VK_PIPELINE_STAGE_TRANSFER_BIT);

    this->submitPipelineBarriers();

    VULKAN_CALL(fSharedContext->interface(),
                CmdCopyImage(fPrimaryCommandBuffer,
                             srcTexture->vkImage(),
                             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
                             dstTexture->vkImage(),
                             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
                             /*regionCount=*/1,
                             &copyRegion));

    return true;
}

bool VulkanCommandBuffer::onSynchronizeBufferToCpu(const Buffer* buffer, bool* outDidResultInWork) {
    static_cast<const VulkanBuffer*>(buffer)->setBufferAccess(this,
                                                              VK_ACCESS_HOST_READ_BIT,
                                                              VK_PIPELINE_STAGE_HOST_BIT);

    *outDidResultInWork = true;
    return true;
}

bool VulkanCommandBuffer::onClearBuffer(const Buffer* buffer, size_t offset, size_t size) {
    SkASSERT(fActive);
    SkASSERT(!fActiveRenderPass);

    // Note: A requested clear of size 0 is treated as a no-op (matching Dawn and Metal).
    // It must not be passed to vkCmdFillBuffer as VK_WHOLE_SIZE.
    if (size == 0) {
        return true;
    }

    SkASSERT(SkIsAlign4(offset));
    SkASSERT(SkIsAlign4(size));

    const auto* vkBuffer = static_cast<const VulkanBuffer*>(buffer);
    SkASSERT(vkBuffer->bufferUsageFlags() & VK_BUFFER_USAGE_TRANSFER_DST_BIT);
    SkASSERT(offset + size <= vkBuffer->size());

    vkBuffer->setBufferAccess(this, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
    this->submitPipelineBarriers();

    VULKAN_CALL(fSharedContext->interface(),
                CmdFillBuffer(fPrimaryCommandBuffer,
                              vkBuffer->vkBuffer(),
                              offset,
                              size,
                              0));

    return true;
}

void VulkanCommandBuffer::addBufferMemoryBarrier(const Resource* resource,
                                                 VkPipelineStageFlags srcStageMask,
                                                 VkPipelineStageFlags dstStageMask,
                                                 VkBufferMemoryBarrier* barrier) {
    SkASSERT(resource);
    this->pipelineBarrier(resource,
                          srcStageMask,
                          dstStageMask,
                          /*byRegion=*/false,
                          kBufferMemory_BarrierType,
                          barrier);
}

void VulkanCommandBuffer::addBufferMemoryBarrier(VkPipelineStageFlags srcStageMask,
                                                 VkPipelineStageFlags dstStageMask,
                                                 VkBufferMemoryBarrier* barrier) {
    // We don't pass in a resource here to the command buffer. The command buffer only is using it
    // to hold a ref, but every place where we add a buffer memory barrier we are doing some other
    // command with the buffer on the command buffer. Thus those other commands will already cause
    // the command buffer to be holding a ref to the buffer.
    this->pipelineBarrier(/*resource=*/nullptr,
                          srcStageMask,
                          dstStageMask,
                          /*byRegion=*/false,
                          kBufferMemory_BarrierType,
                          barrier);
}

void VulkanCommandBuffer::addImageMemoryBarrier(const Resource* resource,
                                                VkPipelineStageFlags srcStageMask,
                                                VkPipelineStageFlags dstStageMask,
                                                bool byRegion,
                                                VkImageMemoryBarrier* barrier) {
    SkASSERT(resource);
    this->pipelineBarrier(resource,
                          srcStageMask,
                          dstStageMask,
                          byRegion,
                          kImageMemory_BarrierType,
                          barrier);
}

void VulkanCommandBuffer::pipelineBarrier(const Resource* resource,
                                          VkPipelineStageFlags srcStageMask,
                                          VkPipelineStageFlags dstStageMask,
                                          bool byRegion,
                                          PipelineBarrierType barrierType,
                                          void* barrier) {
    // TODO: Do we need to handle wrapped command buffers?
    // SkASSERT(!this->isWrapped());
    SkASSERT(fActive);
#ifdef SK_DEBUG
    // For images we can have barriers inside of render passes but they require us to add more
    // support in subpasses which need self dependencies to have barriers inside them. Also, we can
    // never have buffer barriers inside of a render pass. For now we will just assert that we are
    // not in a render pass.
    bool isValidSubpassBarrier = false;
    if (barrierType == kImageMemory_BarrierType) {
        VkImageMemoryBarrier* imgBarrier = static_cast<VkImageMemoryBarrier*>(barrier);
        isValidSubpassBarrier = (imgBarrier->newLayout == imgBarrier->oldLayout) &&
            (imgBarrier->srcQueueFamilyIndex == VK_QUEUE_FAMILY_IGNORED) &&
            (imgBarrier->dstQueueFamilyIndex == VK_QUEUE_FAMILY_IGNORED) &&
            byRegion;
    }
    SkASSERT(!fActiveRenderPass || isValidSubpassBarrier);
#endif

    if (barrierType == kBufferMemory_BarrierType) {
        const VkBufferMemoryBarrier* barrierPtr = static_cast<VkBufferMemoryBarrier*>(barrier);
        fBufferBarriers.push_back(*barrierPtr);
    } else {
        SkASSERT(barrierType == kImageMemory_BarrierType);
        const VkImageMemoryBarrier* barrierPtr = static_cast<VkImageMemoryBarrier*>(barrier);
        // We need to check if we are adding a pipeline barrier that covers part of the same
        // subresource range as a barrier that is already in current batch. If it does, then we must
        // submit the first batch because the vulkan spec does not define a specific ordering for
        // barriers submitted in the same batch.
        // TODO: Look if we can gain anything by merging barriers together instead of submitting
        // the old ones.
        for (int i = 0; i < fImageBarriers.size(); ++i) {
            VkImageMemoryBarrier& currentBarrier = fImageBarriers[i];
            if (barrierPtr->image == currentBarrier.image) {
                const VkImageSubresourceRange newRange = barrierPtr->subresourceRange;
                const VkImageSubresourceRange oldRange = currentBarrier.subresourceRange;
                SkASSERT(newRange.aspectMask == oldRange.aspectMask);
                SkASSERT(newRange.baseArrayLayer == oldRange.baseArrayLayer);
                SkASSERT(newRange.layerCount == oldRange.layerCount);
                uint32_t newStart = newRange.baseMipLevel;
                uint32_t newEnd = newRange.baseMipLevel + newRange.levelCount - 1;
                uint32_t oldStart = oldRange.baseMipLevel;
                uint32_t oldEnd = oldRange.baseMipLevel + oldRange.levelCount - 1;
                if (std::max(newStart, oldStart) <= std::min(newEnd, oldEnd)) {
                    this->submitPipelineBarriers();
                    break;
                }
            }
        }
        fImageBarriers.push_back(*barrierPtr);
    }
    fBarriersByRegion |= byRegion;
    fSrcStageMask = fSrcStageMask | srcStageMask;
    fDstStageMask = fDstStageMask | dstStageMask;

    if (fActiveRenderPass) {
        this->submitPipelineBarriers(true);
    }
}

void VulkanCommandBuffer::submitPipelineBarriers(bool forSelfDependency) {
    SkASSERT(fActive);

    // TODO: Do we need to handle SecondaryCommandBuffers as well?

    // Currently we never submit a pipeline barrier without at least one buffer or image barrier.
    if (!fBufferBarriers.empty() || !fImageBarriers.empty()) {
        // For images we can have barriers inside of render passes but they require us to add more
        // support in subpasses which need self dependencies to have barriers inside them. Also, we
        // can never have buffer barriers inside of a render pass. For now we will just assert that
        // we are not in a render pass.
        SkASSERT(!fActiveRenderPass || forSelfDependency);
        // TODO: Do we need to handle wrapped CommandBuffers?
        //  SkASSERT(!this->isWrapped());
        SkASSERT(fSrcStageMask && fDstStageMask);

        VkDependencyFlags dependencyFlags = fBarriersByRegion ? VK_DEPENDENCY_BY_REGION_BIT : 0;
        VULKAN_CALL(fSharedContext->interface(),
                    CmdPipelineBarrier(fPrimaryCommandBuffer, fSrcStageMask, fDstStageMask,
                                       dependencyFlags,
                                       /*memoryBarrierCount=*/0, /*pMemoryBarrier=*/nullptr,
                                       fBufferBarriers.size(), fBufferBarriers.begin(),
                                       fImageBarriers.size(), fImageBarriers.begin()));
        fBufferBarriers.clear();
        fImageBarriers.clear();
        fBarriersByRegion = false;
        fSrcStageMask = 0;
        fDstStageMask = 0;
    }
    SkASSERT(fBufferBarriers.empty());
    SkASSERT(fImageBarriers.empty());
    SkASSERT(!fBarriersByRegion);
    SkASSERT(!fSrcStageMask);
    SkASSERT(!fDstStageMask);
}

void VulkanCommandBuffer::nextSubpass() {
    // TODO: Use VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS if we add secondary cmd buffers
    VULKAN_CALL(fSharedContext->interface(),
                CmdNextSubpass(fPrimaryCommandBuffer, VK_SUBPASS_CONTENTS_INLINE));
}

void VulkanCommandBuffer::setViewport(SkIRect viewport) {
    VkViewport vkViewport = {
        (float) viewport.fLeft,
        (float) viewport.fTop,
        (float) viewport.width(),
        (float) viewport.height(),
        0.0f, // minDepth
        1.0f, // maxDepth
    };
    VULKAN_CALL(fSharedContext->interface(),
                CmdSetViewport(fPrimaryCommandBuffer,
                               /*firstViewport=*/0,
                               /*viewportCount=*/1,
                               &vkViewport));
}

}  // namespace skgpu::graphite
