/*
 * 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/VulkanCaps.h"

#include "include/core/SkTextureCompressionType.h"
#include "include/gpu/graphite/ContextOptions.h"
#include "include/gpu/graphite/TextureInfo.h"
#include "include/gpu/graphite/vk/VulkanGraphiteTypes.h"
#include "include/gpu/vk/VulkanExtensions.h"
#include "include/gpu/vk/VulkanTypes.h"
#include "include/private/SkAttributes.h"
#include "include/private/SkMath.h"
#include "src/gpu/SwizzlePriv.h"
#include "src/gpu/graphite/ComputePipelineDesc.h"
#include "src/gpu/graphite/ContextUtils.h"
#include "src/gpu/graphite/GraphicsPipelineDesc.h"
#include "src/gpu/graphite/GraphiteResourceKey.h"
#include "src/gpu/graphite/RenderPassDesc.h"
#include "src/gpu/graphite/RendererProvider.h"
#include "src/gpu/graphite/RuntimeEffectDictionary.h"
#include "src/gpu/graphite/TextureInfoPriv.h"
#include "src/gpu/graphite/vk/VulkanGraphicsPipeline.h"
#include "src/gpu/graphite/vk/VulkanGraphiteUtils.h"
#include "src/gpu/graphite/vk/VulkanRenderPass.h"
#include "src/gpu/graphite/vk/VulkanResourceProvider.h"
#include "src/gpu/graphite/vk/VulkanSharedContext.h"
#include "src/gpu/graphite/vk/VulkanYcbcrConversion.h"
#include "src/gpu/vk/VulkanUtilsPriv.h"
#include "src/sksl/SkSLUtil.h"

#ifdef SK_BUILD_FOR_ANDROID
#include <sys/system_properties.h>
#endif

namespace skgpu::graphite {

namespace {
skgpu::UniqueKey::Domain get_pipeline_domain() {
    static const skgpu::UniqueKey::Domain kVulkanGraphicsPipelineDomain =
            skgpu::UniqueKey::GenerateDomain();

    return kVulkanGraphicsPipelineDomain;
}
}  // namespace

VulkanCaps::VulkanCaps(const ContextOptions& contextOptions,
                       const skgpu::VulkanInterface* vkInterface,
                       VkPhysicalDevice physDev,
                       uint32_t physicalDeviceVersion,
                       const VkPhysicalDeviceFeatures2* features,
                       const skgpu::VulkanExtensions* extensions,
                       Protected isProtected)
        : Caps() {
    this->init(contextOptions, vkInterface, physDev, physicalDeviceVersion, features, extensions,
               isProtected);
}

VulkanCaps::~VulkanCaps() {}

namespace {
void populate_resource_binding_reqs(ResourceBindingRequirements& reqs) {
    reqs.fBackendApi = BackendApi::kVulkan;
    // We can enable std430 and ensure no array stride mismatch in functions because all bound
    // buffers will either be a UBO or SSBO, depending on if storage buffers are enabled or not.
    // Although intrinsic uniforms always use uniform buffers, they do not contain any arrays.
    reqs.fStorageBufferLayout = Layout::kStd430;

    // TODO(b/374997389): Somehow convey & enforce Layout::kStd430 for push constants.
    reqs.fUniformBufferLayout = Layout::kStd140;
    reqs.fSeparateTextureAndSamplerBinding = false;

    // Vulkan uses push constants instead of an intrinsic UBO, so we do not need to assign
    // reqs.fIntrinsicBufferBinding.
    reqs.fUsePushConstantsForIntrinsicConstants = true;

    // Assign uniform buffer binding values for shader generation
    reqs.fCombinedUniformBufferBinding = VulkanGraphicsPipeline::kCombinedUniformIndex;
    reqs.fStorageBufferBinding = VulkanGraphicsPipeline::kStorageBufferIndex;

    // Assign descriptor set indices for shader generation
    reqs.fUniformsSetIdx = VulkanGraphicsPipeline::kUniformBufferDescSetIndex;
    reqs.fTextureSamplerSetIdx = VulkanGraphicsPipeline::kTextureBindDescSetIndex;
    // Note: We use kDstAsInputDescSetIndex as opposed to kLoadMsaaFromResolveInputDescSetIndex
    // because the former is what is needed for SkSL generation purposes at the graphite level. The
    // latter is simply internally referenced when defining bespoke SkSL for loading MSAA from
    // resolve.
    reqs.fInputAttachmentSetIdx = VulkanGraphicsPipeline::kDstAsInputDescSetIndex;
}
} // anonymous

void VulkanCaps::init(const ContextOptions& contextOptions,
                      const skgpu::VulkanInterface* vkInterface,
                      VkPhysicalDevice physDev,
                      uint32_t physicalDeviceVersion,
                      const VkPhysicalDeviceFeatures2* features,
                      const skgpu::VulkanExtensions* extensions,
                      Protected isProtected) {
    const EnabledFeatures enabledFeatures =
            this->getEnabledFeatures(features, physicalDeviceVersion);

    PhysicalDeviceProperties deviceProperties;
    this->getProperties(vkInterface,
                        physDev,
                        physicalDeviceVersion,
                        extensions,
                        enabledFeatures,
                        &deviceProperties);

    const VkPhysicalDeviceLimits& deviceLimits = deviceProperties.fBase.properties.limits;
    const uint32_t vendorID = deviceProperties.fBase.properties.vendorID;

#if defined(GPU_TEST_UTILS)
    this->setDeviceName(deviceProperties.fBase.properties.deviceName);
#endif

    if (isProtected == Protected::kYes && enabledFeatures.fProtectedMemory) {
        fProtectedSupport = true;
        fShouldAlwaysUseDedicatedImageMemory = true;
    }

    fPhysicalDeviceMemoryProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2;
    fPhysicalDeviceMemoryProperties2.pNext = nullptr;
    VULKAN_CALL(vkInterface,
                GetPhysicalDeviceMemoryProperties2(physDev, &fPhysicalDeviceMemoryProperties2));

    // We could actually query and get a max size for each config, however maxImageDimension2D will
    // give the minimum max size across all configs. So for simplicity we will use that for now.
    fMaxTextureSize = std::min(deviceLimits.maxImageDimension2D, (uint32_t)INT_MAX);

    // Assert that our push constant sizes are below the maximum allowed (which is guaranteed to be
    // at least 128 bytes per spec).
    static_assert(VulkanResourceProvider::kIntrinsicConstantSize < 128);

    fRequiredUniformBufferAlignment = deviceLimits.minUniformBufferOffsetAlignment;
    fRequiredStorageBufferAlignment = deviceLimits.minStorageBufferOffsetAlignment;
    fRequiredTransferBufferAlignment = 4;

    // We require a minimum alignment of 4 bytes for CPU memcpy safety when doing memcpys into
    // buffers for upload.
    fTextureDataRowBytesAlignment =
            std::max<size_t>(4, deviceLimits.optimalBufferCopyRowPitchAlignment);

    fMaxVaryings = std::min(deviceLimits.maxVertexOutputComponents,
                            deviceLimits.maxFragmentInputComponents) / 4;

    // Unlike D3D, WebGPU, and Metal, the Vulkan NDC coordinate space is aligned with the top-left
    // Y-down coordinate space of the viewport.
    fNDCYAxisPointsDown = true;

    populate_resource_binding_reqs(fResourceBindingReqs);

    // TODO(b/353983969): Enable storage buffers once perf regressions are addressed.
    fStorageBufferSupport = false;

    // These are guaranteed to be supported on Vulkan 1.0+.
    SkASSERT(deviceLimits.maxComputeWorkGroupInvocations > 0);
    SkASSERT(deviceLimits.maxPerStageDescriptorStorageBuffers > 0);
    fComputeSupport = true;
    fStorageBufferSupportForCompute = true;

    VkPhysicalDeviceMemoryProperties deviceMemoryProperties;
    VULKAN_CALL(vkInterface, GetPhysicalDeviceMemoryProperties(physDev, &deviceMemoryProperties));
    fSupportsMemorylessAttachments = false;
    VkMemoryPropertyFlags requiredLazyFlags = VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT;
    if (fProtectedSupport) {
        // If we have a protected context we can only use memoryless images if they also support
        // being protected. With current devices we don't actually expect this combination to be
        // supported, but this at least covers us for future devices that may allow it.
        requiredLazyFlags |= VK_MEMORY_PROPERTY_PROTECTED_BIT;
    }
    for (uint32_t i = 0; i < deviceMemoryProperties.memoryTypeCount; ++i) {
        const uint32_t& supportedFlags =
                SK_UNSAFE_TODO(deviceMemoryProperties.memoryTypes[i].propertyFlags);
        if ((supportedFlags & requiredLazyFlags) == requiredLazyFlags) {
            fSupportsMemorylessAttachments = true;
        }
    }

#ifdef SK_BUILD_FOR_UNIX
    if (skgpu::kNvidia_VkVendor == vendorID) {
        // On NVIDIA linux we see a big perf regression when not using dedicated image allocations.
        fShouldAlwaysUseDedicatedImageMemory = true;
    }
#endif

    if (vendorID == skgpu::kNvidia_VkVendor || vendorID == skgpu::kAMD_VkVendor) {
        // On discrete GPUs, it can be faster to read gpu-only memory compared to memory that is
        // also mappable on the host.
        fGpuOnlyBuffersMorePerformant = true;

        // On discrete GPUs we try to use special DEVICE_LOCAL and HOST_VISIBLE memory for our
        // cpu write, gpu read buffers. This memory is not ideal to be kept persistently mapped.
        // Some discrete GPUs do not expose this special memory, however we still disable
        // persistently mapped buffers for all of them since most GPUs with updated drivers do
        // expose it. If this becomes an issue we can try to be more fine grained.
        fShouldPersistentlyMapCpuToGpuBuffers = false;
    }

    // AMD advertises support for MAX_UINT vertex attributes but in reality only supports 32.
    fMaxVertexAttributes =
            vendorID == skgpu::kAMD_VkVendor ? 32 : deviceLimits.maxVertexInputAttributes;
    fMaxUniformBufferRange = deviceLimits.maxUniformBufferRange;
    fMaxStorageBufferRange = deviceLimits.maxStorageBufferRange;
    fResourceBindingReqs.fMaxStorageBufferBytes = SkTo<int>(
            std::min<uint64_t>(fMaxStorageBufferRange,
                               ResourceBindingRequirements::kDefaultMaxStorageBufferBytes));

#ifdef SK_BUILD_FOR_ANDROID
    if (extensions->hasExtension(
                VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME, 2) &&
        extensions->hasExtension(VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME, 1)) {
        fSupportsAHardwareBufferImages = true;
    }
#endif

    fSupportsYcbcrConversion = enabledFeatures.fSamplerYcbcrConversion;
    fSupportsDeviceFaultInfo = enabledFeatures.fDeviceFault;
    fSupportsFrameBoundary = enabledFeatures.fFrameBoundary;

    fSupportsPipelineCreationCacheControl = enabledFeatures.fPipelineCreationCacheControl;
    fSupportsPipelineProtectedAccess = enabledFeatures.fPipelineProtectedAccess;

    if (enabledFeatures.fAdvancedBlendModes) {
        fBlendEqSupport = enabledFeatures.fCoherentAdvancedBlendModes
                ? BlendEquationSupport::kAdvancedCoherent
                : BlendEquationSupport::kAdvancedNoncoherent;
        fShaderCaps->fAdvBlendEqInteraction =
                SkSL::ShaderCaps::AdvBlendEqInteraction::kAutomatic_AdvBlendEqInteraction;
    }

    uint32_t queueFamilyCount = 0;
    VULKAN_CALL(vkInterface,
                GetPhysicalDeviceQueueFamilyProperties(physDev, &queueFamilyCount, nullptr));
    if (queueFamilyCount > 0) {
        skia_private::TArray<VkQueueFamilyProperties> queueProps;
        queueProps.resize_back(queueFamilyCount);
        VULKAN_CALL(vkInterface,
                    GetPhysicalDeviceQueueFamilyProperties(
                            physDev, &queueFamilyCount, queueProps.data()));
        fQueueFamilyTimestampValidBits.reserve(queueFamilyCount);
        for (uint32_t i = 0; i < queueFamilyCount; ++i) {
            fQueueFamilyTimestampValidBits.push_back(queueProps[i].timestampValidBits);
        }
    }
    fTimestampPeriod = deviceProperties.fBase.properties.limits.timestampPeriod;

    if (deviceProperties.fBase.properties.limits.timestampComputeAndGraphics &&
        fTimestampPeriod > 0) {
        fSupportedGpuStats |= GpuStatsFlags::kElapsedTime;
    }

    fOcclusionQueryPrecise = enabledFeatures.fOcclusionQueryPrecise;
    if (fOcclusionQueryPrecise) {
        fSupportedGpuStats |= GpuStatsFlags::kOcclusionPassSamples;
    }

    // Note: ARM GPUs have always been coherent, do not add a subpass self-dependency even if the
    // application hasn't enabled this feature as it comes with a performance cost on this GPU.
    //
    // Imagination GPUs are also coherent but only within the same sample when sample-shading.
    // VK_EXT_rasterization_order_attachment_access indicates coherence when input attachment read
    // is done from any samples of the same pixel, which is why Imagination drivers cannot expose
    // this extension. This is not a problem for Graphite however, which does not enable sample
    // shading (nor would it read color from other samples even if it did).
    fSupportsRasterizationOrderColorAttachmentAccess =
            enabledFeatures.fRasterizationOrderColorAttachmentAccess;
    fIsInputAttachmentReadCoherent = fSupportsRasterizationOrderColorAttachmentAccess ||
                                     vendorID == kARM_VkVendor || vendorID == kImagination_VkVendor;

    this->initShaderCaps(enabledFeatures, vendorID);

    // Vulkan 1.0 dynamic state is always supported.  Dynamic state based on features of
    // VK_EXT_extended_dynamic_state and VK_EXT_extended_dynamic_state2 are also considered basic
    // given the extensions' age and the fact that they are core since Vulkan 1.3.
    fUseBasicDynamicState =
            enabledFeatures.fExtendedDynamicState && enabledFeatures.fExtendedDynamicState2;

    // Vertex input dynamic state depends on the main feature of
    // VK_EXT_vertex_input_dynamic_state.
    fUseVertexInputDynamicState = enabledFeatures.fVertexInputDynamicState;

    // Graphics pipeline library usage depends on the main feature of
    // VK_EXT_graphics_pipeline_library.  The graphicsPipelineLibraryFastLinking property indicates
    // whether linking libraries is cheap, without which the extension is not very useful.  However,
    // this property is currently ignored for known vendors that set it to false while link is still
    // fast.
    fUsePipelineLibraries =
            enabledFeatures.fGraphicsPipelineLibrary &&
            (deviceProperties.fGpl.graphicsPipelineLibraryFastLinking || vendorID == kARM_VkVendor);

    // Vulkan allows attachments to be bigger than the VkFramebuffer, which Graphite sizes to the
    // main texture, so using approx-sized dimensions for MSAA and D/S attachments reduces the
    // number of Resources in play (although hopefully they are all transient anyways).
    fAttachmentSizePolicy = AttachmentSizePolicy::kApprox;

    // Multisampled render to single-sampled usage depends on the mandatory feature of
    // VK_EXT_multisampled_render_to_single_sampled.  Per format queries are needed to determine if
    // multisampled->single-sampled rendering is supported, which should in practice always be equal
    // to whether multisampled rendering is supported for that format.
    fMSAARenderToSingleSampledSupport = enabledFeatures.fMultisampledRenderToSingleSampled;

    // Host image copy depends on the main feature of VK_EXT_host_image_copy, which is core since
    // Vulkan 1.4.  The identicalMemoryTypeRequirements property indicates whether host-copyable
    // images require special (limited) memory types.  If that property is not set, use of this
    // extension is avoided to avoid incurring performance penalties or run out of the
    // likely-much-smaller memory available on those devices.  This property is expected to be set
    // on UMA devices.
    //
    // The SHADER_READ_ONLY layout is ubiquitously found in pCopyDstLayouts, so we rely on it.  If
    // that is ever missing (unlikely, given the future direction with
    // VK_KHR_unified_image_layouts), then Recorder::update*BackendTexture should first transition
    // to GENERAL with vkTransitionImageLayout and at the end use a GPU barrier to SHADER_READ_ONLY
    // (as opposed to current code that transitions directly to SHADER_READ_ONLY and uploads to it).
    fSupportsHostImageCopy = enabledFeatures.fHostImageCopy &&
                             deviceProperties.fHic.identicalMemoryTypeRequirements &&
                             deviceProperties.fHicHasShaderReadOnlyDstLayout;

    fShaderReadOnlyLayoutSrcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
    if (fComputeSupport) {
        fShaderReadOnlyLayoutSrcStageMask |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
    }

    // Note: Do not add extension/feature checks after this; driver workarounds should be done last.
    if (!contextOptions.fDisableDriverCorrectnessWorkarounds) {
        this->applyDriverCorrectnessWorkarounds(deviceProperties);
    }

    // Note that format table initialization should be performed at the end of this method to ensure
    // all capability determinations are completed prior to populating the format tables.
    this->initFormatTable(vkInterface, physDev, deviceProperties.fBase.properties, enabledFeatures);

    this->finishInitialization(contextOptions);
}

// Walk the feature chain once and extract any enabled features that Graphite cares about.
VulkanCaps::EnabledFeatures VulkanCaps::getEnabledFeatures(
        const VkPhysicalDeviceFeatures2* features, uint32_t physicalDeviceVersion) {
    EnabledFeatures enabled;
    if (features) {
        // Base features:
        enabled.fDualSrcBlend = features->features.dualSrcBlend;
        enabled.fOcclusionQueryPrecise = features->features.occlusionQueryPrecise;

        if (physicalDeviceVersion >= VK_API_VERSION_1_3) {
            enabled.fExtendedDynamicState = true;
            enabled.fExtendedDynamicState2 = true;
        }

        // Extended features:
        const VkBaseInStructure* pNext = static_cast<const VkBaseInStructure*>(features->pNext);
        while (pNext) {
            switch (pNext->sType) {
                case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES: {
                    const auto* feature =
                            reinterpret_cast<const VkPhysicalDeviceVulkan11Features*>(pNext);
                    enabled.fSamplerYcbcrConversion = feature->samplerYcbcrConversion;
                    break;
                }
                case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES: {
                    const auto* feature =
                            reinterpret_cast<const VkPhysicalDeviceVulkan13Features*>(pNext);
                    enabled.fPipelineCreationCacheControl = feature->pipelineCreationCacheControl;
                    break;
                }
                case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_4_FEATURES: {
                    const auto* feature =
                            reinterpret_cast<const VkPhysicalDeviceVulkan14Features*>(pNext);
                    enabled.fHostImageCopy = feature->hostImageCopy;
                    enabled.fPipelineProtectedAccess = feature->pipelineProtectedAccess;
                    break;
                }
                case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES: {
                    const auto* feature =
                            reinterpret_cast<
                                const VkPhysicalDevicePipelineCreationCacheControlFeatures*>(pNext);
                    enabled.fPipelineCreationCacheControl = feature->pipelineCreationCacheControl;
                    break;
                }
                case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES: {
                    const auto* feature =
                            reinterpret_cast<const VkPhysicalDeviceSamplerYcbcrConversionFeatures*>(
                                    pNext);
                    enabled.fSamplerYcbcrConversion = feature->samplerYcbcrConversion;
                    break;
                }
                case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_FEATURES_EXT: {
                    const auto* feature =
                            reinterpret_cast<const VkPhysicalDeviceFaultFeaturesEXT*>(pNext);
                    enabled.fDeviceFault = feature->deviceFault;
                    break;
                }
                case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT: {
                    const auto* feature = reinterpret_cast<
                            const VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT*>(pNext);
                    // The feature struct being present at all indicated advanced blend mode
                    // support. A member of it indicates whether the device offers coherent or
                    // noncoherent support.
                    enabled.fAdvancedBlendModes = true;
                    enabled.fCoherentAdvancedBlendModes =
                            feature->advancedBlendCoherentOperations == VK_TRUE;
                    break;
                }
                case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT: {
                    const auto* feature = reinterpret_cast<
                            const VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT*>(
                            pNext);
                    enabled.fRasterizationOrderColorAttachmentAccess =
                            feature->rasterizationOrderColorAttachmentAccess;
                    break;
                }
                case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT: {
                    const auto* feature = reinterpret_cast<
                            const VkPhysicalDeviceExtendedDynamicStateFeaturesEXT*>(pNext);
                    enabled.fExtendedDynamicState = feature->extendedDynamicState;
                    break;
                }
                case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT: {
                    const auto* feature = reinterpret_cast<
                            const VkPhysicalDeviceExtendedDynamicState2FeaturesEXT*>(pNext);
                    enabled.fExtendedDynamicState2 = feature->extendedDynamicState2;
                    break;
                }
                case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT: {
                    const auto* feature = reinterpret_cast<
                            const VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT*>(pNext);
                    enabled.fVertexInputDynamicState = feature->vertexInputDynamicState;
                    break;
                }
                case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_FEATURES_EXT: {
                    const auto* feature = reinterpret_cast<
                            const VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT*>(pNext);
                    enabled.fGraphicsPipelineLibrary = feature->graphicsPipelineLibrary;
                    break;
                }
                case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_FEATURES_EXT: {
                    const auto* feature = reinterpret_cast<
                            const VkPhysicalDeviceMultisampledRenderToSingleSampledFeaturesEXT*>(
                            pNext);
                    enabled.fMultisampledRenderToSingleSampled =
                            feature->multisampledRenderToSingleSampled;
                    break;
                }
                case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES: {
                    const auto* feature =
                            reinterpret_cast<const VkPhysicalDeviceHostImageCopyFeatures*>(pNext);
                    enabled.fHostImageCopy = feature->hostImageCopy;
                    break;
                }
                case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAME_BOUNDARY_FEATURES_EXT: {
                    const auto *feature = reinterpret_cast<
                            const VkPhysicalDeviceFrameBoundaryFeaturesEXT*>(pNext);
                    enabled.fFrameBoundary = feature->frameBoundary;
                    break;
                }
                case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RGBA10X6_FORMATS_FEATURES_EXT: {
                    const auto *feature = reinterpret_cast<
                            const VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT*>(pNext);
                    enabled.fFormatRGBA10x6WithoutYCbCrSampler =
                            feature->formatRgba10x6WithoutYCbCrSampler;
                    break;
                }
                case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES: {
                    const auto *feature = reinterpret_cast<
                            const VkPhysicalDeviceProtectedMemoryFeatures*>(pNext);
                    enabled.fProtectedMemory = feature->protectedMemory;
                    break;
                }
                case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES_EXT: {
                    const auto *feature = reinterpret_cast<
                            const VkPhysicalDevicePipelineProtectedAccessFeaturesEXT*>(pNext);
                    enabled.fPipelineProtectedAccess = feature->pipelineProtectedAccess;
                    break;
                }
                default:
                    break;
            }

            pNext = pNext->pNext;
        }
    }
    return enabled;
}

// Query the physical device properties that Graphite cares about.
void VulkanCaps::getProperties(const skgpu::VulkanInterface* vkInterface,
                               VkPhysicalDevice physDev,
                               uint32_t physicalDeviceVersion,
                               const skgpu::VulkanExtensions* extensions,
                               const EnabledFeatures& features,
                               PhysicalDeviceProperties* props) {
    props->fBase = {};
    props->fBase.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;

    props->fDriver = {};
    props->fDriver.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;

    props->fGpl = {};
    props->fGpl.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_PROPERTIES_EXT;

    props->fHic = {};
    props->fHic.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_PROPERTIES;

    constexpr uint32_t kHicCopyDstLayoutMax = 50;
    VkImageLayout hicCopyDstLayoutStorage[kHicCopyDstLayoutMax] = {};
    props->fHic.copyDstLayoutCount = kHicCopyDstLayoutMax;
    props->fHic.pCopyDstLayouts = hicCopyDstLayoutStorage;

    const bool hasDriverProperties =
            physicalDeviceVersion >= VK_API_VERSION_1_2 ||
            extensions->hasExtension(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME, 1);
    if (hasDriverProperties) {
        AddToPNextChain(&props->fBase, &props->fDriver);
    } else {
        SKIA_LOG_W("VK_KHR_driver_properties is not enabled, driver workarounds cannot "
                    "be correctly applied");
    }

    if (features.fGraphicsPipelineLibrary) {
        AddToPNextChain(&props->fBase, &props->fGpl);
    }

    if (features.fHostImageCopy) {
        AddToPNextChain(&props->fBase, &props->fHic);
    }

    // Graphite requires Vulkan version 1.1 or later, so vkGetPhysicalDeviceProperties2 should
    // always be available.
    VULKAN_CALL(vkInterface, GetPhysicalDeviceProperties2(physDev, &props->fBase));

    if (features.fHostImageCopy) {
        // vkTransitionImageLayout from this extension can be used to transition between image
        // layouts on the host, with the allowed old and new layouts found in pCopySrcLayouts and
        // pCopyDstLayouts respectively.  The GENERAL layout is required to be found in both.  Skia
        // has two use cases for this function; initialization (UNDEFINED->GENERAL) and after
        // texture updates (GENERAL->SHADER_READ_ONLY, per Recorder::update*BackendTexture).
        props->fHicHasShaderReadOnlyDstLayout = std::find(
                props->fHic.pCopyDstLayouts,
                SK_UNSAFE_TODO(props->fHic.pCopyDstLayouts + props->fHic.copyDstLayoutCount),
                VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
    }

    // If this field is not filled, driver bug workarounds won't work correctly. It should always
    // be filled, unless filling it itself is a driver bug, or the Vulkan driver is too old. In
    // that case, make a guess of what the driver ID is, but the driver is likely to be too buggy to
    // be used by Graphite either way.
    if (props->fDriver.driverID == 0) {
        switch (props->fBase.properties.vendorID) {
            case kAMD_VkVendor:
                props->fDriver.driverID = VK_DRIVER_ID_AMD_PROPRIETARY;
                break;
            case kARM_VkVendor:
                props->fDriver.driverID = VK_DRIVER_ID_ARM_PROPRIETARY;
                break;
            case kBroadcom_VkVendor:
                props->fDriver.driverID = VK_DRIVER_ID_BROADCOM_PROPRIETARY;
                break;
            case kGoogle_VkVendor:
                props->fDriver.driverID = VK_DRIVER_ID_GOOGLE_SWIFTSHADER;
                break;
            case kImagination_VkVendor:
                props->fDriver.driverID = VK_DRIVER_ID_IMAGINATION_PROPRIETARY;
                break;
            case kIntel_VkVendor:
#ifdef SK_BUILD_FOR_WIN
                props->fDriver.driverID = VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS;
#else
                props->fDriver.driverID = VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA;
#endif
                break;
            case kNvidia_VkVendor:
                props->fDriver.driverID = VK_DRIVER_ID_NVIDIA_PROPRIETARY;
                break;
            case kQualcomm_VkVendor:
                props->fDriver.driverID = VK_DRIVER_ID_QUALCOMM_PROPRIETARY;
                break;
            case kSamsung_VkVendor:
                props->fDriver.driverID = VK_DRIVER_ID_SAMSUNG_PROPRIETARY;
                break;
            case kVeriSilicon_VkVendor:
                props->fDriver.driverID = VK_DRIVER_ID_VERISILICON_PROPRIETARY;
                break;
            default:
                // Unknown device, but this means no driver workarounds are provisioned for it so
                // driver ID remaining 0 is not going to change anything.
                break;
        }
    }
}

namespace {

bool is_adreno_6xx_proprietary(uint32_t deviceID) {
    // According to Gemini (with poor citations), the format follows this pattern:
    //     0x0 + [Series Core] + [Major Tier] + [Minor Revision/Patch]
    // For the Adreno660, it maps series 6, tier 60, revision 01 -> 0x06060001.
    // For the Adreno640, it maps series 6, tier 40, revision 01 -> 0x06040001.
    // For the Adreno620, it maps series 6, tier 20, revision 00 -> 0x06020000.
    // For the Adreno610, it maps series 6, tier 10, revision 01 -> 0x06010000.
    //
    // NOTE: This applies to the proprietary QC driver. Turnip supposedly just reports the GPU
    // number directly, e.g. 640.
    static constexpr uint32_t kAdreno6xxMask = 0xFFF00000; // Selects what should be 0x060
    static constexpr uint32_t kAdreno6xxId   = 0x06000000;
    return (deviceID & kAdreno6xxMask) == kAdreno6xxId;
}

} // anonymous namespace

void VulkanCaps::applyDriverCorrectnessWorkarounds(const PhysicalDeviceProperties& properties) {
    // By default, we initialize the Android API version to 0 since we consider certain things
    // "fixed" only once above a certain version. This way, we default to enabling the workarounds.
    int androidAPIVersion = 0;
#if defined(SK_BUILD_FOR_ANDROID)
    char androidAPIVersionStr[PROP_VALUE_MAX];
    int strLength = __system_property_get("ro.build.version.sdk", androidAPIVersionStr);
    // Defaults to zero since most checks care if it is greater than a specific value. So this will
    // just default to it being less.
    androidAPIVersion = (strLength == 0) ? 0 : atoi(androidAPIVersionStr);
#endif

    const uint32_t vendorID = properties.fBase.properties.vendorID;
    const uint32_t deviceID = properties.fBase.properties.deviceID;
    const VkDriverId driverID = properties.fDriver.driverID;
    const skgpu::DriverVersion driverVersion =
            skgpu::ParseVulkanDriverVersion(driverID, properties.fBase.properties.driverVersion);

    const bool isARM = skgpu::kARM_VkVendor == vendorID;
    const bool isIntel = skgpu::kIntel_VkVendor == vendorID;
    const bool isQualcomm = skgpu::kQualcomm_VkVendor == vendorID;
    const bool isImagination = skgpu::kImagination_VkVendor == vendorID;

    const bool isSwiftshader = skgpu::kGoogle_VkVendor == vendorID && 0xC0DE == deviceID;

    const bool isARMProprietary = isARM && VK_DRIVER_ID_ARM_PROPRIETARY == driverID;
    const bool isIntelWindowsProprietary =
            isIntel && VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS == driverID;
    const bool isQualcommProprietary = isQualcomm && VK_DRIVER_ID_QUALCOMM_PROPRIETARY == driverID;

    // All Mali Job-Manager based GPUs have maxDrawIndirectCount==1 and all Commans-Stream Front
    // GPUs have maxDrawIndirectCount>1.  This is used as proxy to detect JM GPUs.
    const bool isMaliJobManagerArch =
            isARM && properties.fBase.properties.limits.maxDrawIndirectCount <= 1;

    // On Mali galaxy s7 we see lots of rendering issues when we suballocate VkImages.
    if (isARMProprietary && androidAPIVersion <= 28) {
        fShouldAlwaysUseDedicatedImageMemory = true;
    }

    // On Qualcomm the gpu resolves an area larger than the render pass bounds when using
    // discardable msaa attachments. This causes the resolve to resolve uninitialized data from the
    // msaa image into the resolve image. This was reproed on a Pixel4 using the DstReadShuffle GM
    // where the top half of the GM would drop out. In Ganesh we had also seen this on Arm devices,
    // but the issue hasn't appeared yet in Graphite. It may just have occurred on older Arm drivers
    // that we don't even test any more.
    // On Imagination (PowerVR) GPUs, using discardable MSAA attachments and loading from resolve in
    // DMSAA subpasses causes 3D MMU page faults and GPU lockups.
    // This also occurs on swiftshader, see b/303705884.
    if (isQualcommProprietary || isImagination || isSwiftshader) {
        fMustLoadFullImageForMSAA = true;
    }

    // Adreno 620s render garbage when attachment sizes aren't identical; likely an issue with
    // how the subpass load coordinates are calculated, or how the resolve addresses are handled.
    // Conservatively disable for all 6xx using QC's driver (not tested on Turnip).
    //
    // Swiftshader segfaults when using attachments larger than the framebuffer.
    if ((isQualcommProprietary && is_adreno_6xx_proprietary(deviceID)) ||
        driverID == VK_DRIVER_ID_GOOGLE_SWIFTSHADER) {
        fAttachmentSizePolicy = AttachmentSizePolicy::kExact;
    }

    // MSAA doesn't work well on Intel GPUs crbug.com/40434119, crbug.com/41470715
    if (isIntel) {
        fAvoidMSAA = true;
    }

    // Too many bugs on older ARM drivers with CSF architecture.  On JM GPUs, more bugs were
    // encountered with newer drivers, unknown if ever fixed.
    const bool avoidExtendedDynamicState =
            (isARMProprietary && driverVersion < skgpu::DriverVersion(44, 1)) ||
            isMaliJobManagerArch;

    // Known bugs in addition to ARM bugs above:
    //
    // - Cull mode dynamic state on ARM drivers prior to r52; vkCmdSetCullMode incorrectly culls
    //   non-triangle topologies, according to the errata:
    //   https://developer.arm.com/documentation/SDEN-3735689/0100/?lang=en.  However,
    //   Graphite only uses triangles and cull mode is always disabled so this driver bug is not
    //   relevant.
    if (avoidExtendedDynamicState) {
        fUseBasicDynamicState = false;
    }

    // Known bugs in vertex input dynamic state:
    //
    // - Intel windows driver, unknown if fixed: http://anglebug.com/42265637#comment9
    // - Qualcomm drivers prior to 777:  http://anglebug.com/381384988
    // - In ARM drivers prior to r48, vkCmdBindVertexBuffers2 applies strides to the wrong index
    //   when the state is dynamic, according to the errata:
    //   https://developer.arm.com/documentation/SDEN-3735689/0100/?lang=en
    if (isIntelWindowsProprietary ||
        (isARMProprietary && driverVersion < skgpu::DriverVersion(48, 0)) ||
        (isQualcommProprietary && driverVersion < skgpu::DriverVersion(512, 777))) {
        fUseVertexInputDynamicState = false;
    }

    // Qualcomm driver 512.821 is known to have rendering bugs with
    // VK_EXT_multisampled_render_to_single_sampled.
    // http://crbug.com/413427770
    if (isQualcommProprietary && driverVersion < skgpu::DriverVersion(512, 822)) {
        fMSAARenderToSingleSampledSupport = false;
    }
}

void VulkanCaps::initShaderCaps(const EnabledFeatures enabledFeatures, const uint32_t vendorID) {
    // TODO(skbug.com/40045541): We must force std430 array stride when using SSBOs since SPIR-V
    // generation cannot handle mixed array strides being passed into functions.
    fShaderCaps->fForceStd430ArrayLayout =
            fStorageBufferSupport && fResourceBindingReqs.fStorageBufferLayout == Layout::kStd430;

    // Avoid RelaxedPrecision with OpImageSampleImplicitLod due to driver bug with YCbCr sampling.
    // (skbug.com/421927604)
    fShaderCaps->fCannotUseRelaxedPrecisionOnImageSample = vendorID == kNvidia_VkVendor;
    fShaderCaps->fDualSourceBlendingSupport = enabledFeatures.fDualSrcBlend;
}

void VulkanCaps::initFormatTable(const skgpu::VulkanInterface* interface,
                                 VkPhysicalDevice physDev,
                                 const VkPhysicalDeviceProperties& properties,
                                 const EnabledFeatures& enabledFeatures) {
    // Technically without this extension and enabled feature we could still use this format to
    // sample with a ycbcr sampler. But for simplicity until we have clients requesting that, we
    // limit the use of this format to cases where we have the extension supported.
    const bool disableRGBA10x6 = !enabledFeatures.fFormatRGBA10x6WithoutYCbCrSampler;

    // Qualcomm drivers will report OUT_OF_HOST_MEMORY when binding memory to a VkImage with
    // D16_UNORM in a protected context. Using D32_SFLOAT succeeds, so clearly it's not actually
    // out of memory. D16_UNORM appears to function correctly in unprotected contexts.
    const bool disableD16InProtected =
            this->protectedSupport() && skgpu::kQualcomm_VkVendor == properties.vendorID;

    for (int i = 0; i < kTextureFormatCount; ++i) {
        SkASSERT(!SkToBool(fFormatSupport[0][i].first) && !SkToBool(fFormatSupport[0][i].second));
        SkASSERT(!SkToBool(fFormatSupport[1][i].first) && !SkToBool(fFormatSupport[1][i].second));

        TextureFormat format = static_cast<TextureFormat>(i);

        // Driver workarounds and extensions checks to keep treat a format as disabled
        if (format == TextureFormat::kD16 && disableD16InProtected) {
            continue;
        }
        if (format == TextureFormat::kRGBA10x6 && disableRGBA10x6) {
            continue;
        }

        VkFormatProperties formatProperties;
        if (format == TextureFormat::kExternal) {
            // kExternal maps to VK_FORMAT_UNDEFINED and then a specific external format is held
            // in another field of the VulkanTextureInfo. This means vkFormat can't be used to query
            // format properties, but we can also assume all external foramts are the same.
            formatProperties = { /*linearTilingFeatures=*/0,
                                 /*optimalTilingFeatures=*/VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT,
                                 /*bufferFeatures=*/0};
        } else {
            VULKAN_CALL(interface, GetPhysicalDeviceFormatProperties(
                    physDev, TextureFormatToVkFormat(format), &formatProperties));
        }

        for (Tiling tiling : {Tiling::kOptimal, Tiling::kLinear}) {
            fFormatSupport[(int) tiling][i] = this->getTextureSupport(
                    interface, physDev, format, tiling, formatProperties);
        }
    }
}

std::pair<SkEnumBitMask<TextureUsage>, SkEnumBitMask<SampleCount>> VulkanCaps::getTextureSupport(
        const skgpu::VulkanInterface* interface,
        VkPhysicalDevice physDev,
        TextureFormat format,
        Tiling tiling,
        const VkFormatProperties& props) const {
    const VkFormat vkFormat = TextureFormatToVkFormat(format);

    bool isEfficientWithHostImageCopy;
    VkImageUsageFlags renderUsageFlags;
    VkFormatFeatureFlags renderBits;
    if (TextureFormatIsDepthOrStencil(format)) {
        isEfficientWithHostImageCopy = false;
        renderBits = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
        renderUsageFlags = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
    } else {
        // Assume linear tiling is always efficient for copying directly.
        isEfficientWithHostImageCopy = tiling == Tiling::kLinear ||
                                       this->isEfficientWithHostCopy(interface, physDev, vkFormat);

        renderBits = VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
                     VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;
        // We make all renderable images support being used as input attachment
        renderUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
                           VK_IMAGE_USAGE_TRANSFER_DST_BIT |
                           VK_IMAGE_USAGE_SAMPLED_BIT |
                           VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
                           VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
    }

    SkEnumBitMask<TextureUsage> supports;
    SkEnumBitMask<SampleCount> sampleCounts;
    VkFormatFeatureFlags featureFlags = tiling == Tiling::kOptimal ? props.optimalTilingFeatures
                                                                   : props.linearTilingFeatures;

    if ((featureFlags & renderBits) == renderBits) {
        supports |= TextureUsage::kRender;

        // At least 1x sample count should be supported (the limit for linear tiling).
        sampleCounts = tiling == Tiling::kOptimal
                ? this->getSupportedSampleCounts(interface, physDev, vkFormat, renderUsageFlags)
                : SampleCount::k1;

        if (this->msaaRenderToSingleSampledSupport() &&
            SkToBool(sampleCounts) &&
            sampleCounts != SampleCount::k1) {
            // SupportedSampleCounts' initialization validates the sample counts that are
            // available when using VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT
            // so if it is more than just 1x, we can assume MSRTSS is supported for this format.
            supports |= TextureUsage::kMSRTSS;
        }
    }

    if (VkFormatNeedsYcbcrSampler(vkFormat) || format == TextureFormat::kExternal) {
        // Assume all external formats are sampleable, since we support adjusting the filtering on
        // a per-immutable sampler basis.
        supports |= TextureUsage::kSample | TextureUsage::kRead;
    } else if (featureFlags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) {
        // VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT guarantees point/nearest sampling, VK_FILTER_NEAREST,
        // and texelFetch. Linear filtering, VK_FILTER_LINEAR, requires
        // VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT.
        // See https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkFormatFeatureFlagBits.html
        supports |= TextureUsage::kRead;
        if (featureFlags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT) {
            supports |= TextureUsage::kSample;
        }
    }

    // NOTE: We don't check the protected-ness of the Context for format support. It is handled on
    // a per-texture basis if that texture ends up being allocated with protected memory. We
    // intentionally skip adding CopySrc for compressed formats since there is no current support
    // for read back in higher-level Graphite code.
    if ((featureFlags & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) &&
        TextureFormatCompressionType(format) == SkTextureCompressionType::kNone) {
        supports |= TextureUsage::kCopySrc;
    }

    if (featureFlags & VK_FORMAT_FEATURE_TRANSFER_DST_BIT) {
        // Unlike CopySrc, we include CopyDst for compressed formats since there are specialized
        // upload code paths.
        supports |= TextureUsage::kCopyDst;

        if (isEfficientWithHostImageCopy) {
            // NOTE: We will check protectedness on a texture-by-texture basis.
            supports |= TextureUsage::kHostCopy;
        }
    }

    if (featureFlags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) {
        supports |= TextureUsage::kStorage;
    }

    // Some drivers report no sample counts for multiplanar or compressed formats, even when they
    // can be sampled. There is a pedantic argument that this is valid since neither of these types
    // of textures have conventional texels to begin with, but in practice, sampling acts as though
    // its 1x. Include 1x to simplify higher-level support checks.
    if (!SkToBool(sampleCounts & SampleCount::k1) &&
        SkToBool(supports & (TextureUsage::kSample | TextureUsage::kRead))) {
        sampleCounts |= SampleCount::k1;
    }

    return {supports, sampleCounts};
}

std::pair<SkEnumBitMask<TextureUsage>, Tiling> VulkanCaps::getTextureUsage(
        const TextureInfo& info) const {
    const auto& vkInfo = TextureInfoPriv::Get<VulkanTextureInfo>(info);

    SkEnumBitMask<TextureUsage> usage;

    if (TextureFormatIsDepthOrStencil(TextureInfoPriv::ViewFormat(info))) {
        if (SkToBool(vkInfo.fImageUsageFlags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
            usage |= TextureUsage::kRender;
        }
    } else {
        // All color renderable vulkan textures within graphite must have input attachment usage
        if (SkToBool(vkInfo.fImageUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) &&
            SkToBool(vkInfo.fImageUsageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) {
            usage |= TextureUsage::kRender;

            // And flag MSRTSS if the creation flag was set on the texture
            if (this->msaaRenderToSingleSampledSupport() && SkToBool(vkInfo.fFlags &
                        VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT)) {
                usage |= TextureUsage::kMSRTSS;
            }
        }
    }

    // All images using external formats are required to be able to be sampled per Vulkan spec.
    // https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkAndroidHardwareBufferFormatPropertiesANDROID.html#_description
    if (vkInfo.fFormat == VK_FORMAT_UNDEFINED && vkInfo.fYcbcrConversionInfo.isValid()) {
        usage |= TextureUsage::kSample | TextureUsage::kRead;
    } else if (SkToBool(vkInfo.fImageUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT)) {
        usage |= TextureUsage::kSample | TextureUsage::kRead;
    }

    // We include CopyDst/CopySrc without worrying about format support since that is masked out
    // automatically with getTextureSupport()'s handling of compressed and external formats.
    if (info.isProtected() == Protected::kNo &&
        SkToBool(vkInfo.fImageUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT)) {
        usage |= TextureUsage::kCopySrc;
    }

    if (SkToBool(vkInfo.fImageUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT)) {
        usage |= TextureUsage::kCopyDst;

        if (info.isProtected() == Protected::kNo &&
            SkToBool(vkInfo.fImageUsageFlags & VK_IMAGE_USAGE_HOST_TRANSFER_BIT)) {
            usage |= TextureUsage::kHostCopy;
        }
    }

    if (SkToBool(vkInfo.fImageUsageFlags & VK_IMAGE_USAGE_STORAGE_BIT)) {
        usage |= TextureUsage::kStorage;
    }

    const Tiling tiling = vkInfo.fImageTiling == VK_IMAGE_TILING_OPTIMAL ? Tiling::kOptimal
                                                                         : Tiling::kLinear;
    return {usage, tiling};
}

TextureInfo VulkanCaps::onGetDefaultTextureInfo(SkEnumBitMask<TextureUsage> usage,
                                                TextureFormat format,
                                                SampleCount sampleCount,
                                                Mipmapped mipmapped,
                                                Protected isProtected,
                                                Discardable discardable) const {
    VkFormat vkFormat = TextureFormatToVkFormat(format);
    SkASSERT(vkFormat != VK_FORMAT_UNDEFINED); // should have been caught by Caps first

    VkImageUsageFlags vkUsage = 0;
    VkImageCreateFlags createFlags =
            isProtected == Protected::kYes ? VK_IMAGE_CREATE_PROTECTED_BIT : 0;

    if (usage & (TextureUsage::kSample | TextureUsage::kRead)) {
        vkUsage |= VK_IMAGE_USAGE_SAMPLED_BIT;
    }
    if (usage & TextureUsage::kStorage) {
        vkUsage |= VK_IMAGE_USAGE_STORAGE_BIT;
    }
    if (usage & TextureUsage::kCopySrc) {
        vkUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
    }
    if (usage & TextureUsage::kCopyDst) {
        vkUsage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
        if (usage & TextureUsage::kHostCopy) {
            SkASSERT(this->supportsHostImageCopy());
            vkUsage |= VK_IMAGE_USAGE_HOST_TRANSFER_BIT;
        }
    }
    if (usage & TextureUsage::kRender) {
        if (TextureFormatIsDepthOrStencil(format)) {
            vkUsage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
        } else {
            // We make all renderable color images support being used as input attachment
            vkUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
                       VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
        }

        if (usage & TextureUsage::kMSRTSS) {
            SkASSERT(this->msaaRenderToSingleSampledSupport());
            createFlags |= VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT;
        }
        if (discardable == Discardable::kYes && fSupportsMemorylessAttachments) {
            vkUsage |= VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT;
        }
    }

    VkImageAspectFlags vkAspectMask = 0;
    if (TextureFormatIsDepthOrStencil(format)) {
        if (TextureFormatHasDepth(format)) {
            vkAspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
        }
        if (TextureFormatHasStencil(format)) {
            vkAspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
        }
    } else {
        vkAspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    }

    VulkanTextureInfo info;
    info.fSampleCount = sampleCount;
    info.fMipmapped = mipmapped;
    info.fFlags = createFlags;
    info.fFormat = vkFormat;
    info.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
    info.fImageUsageFlags = vkUsage;
    info.fSharingMode = VK_SHARING_MODE_EXCLUSIVE;
    info.fAspectMask = vkAspectMask;

    return TextureInfos::MakeVulkan(info);
}

SkEnumBitMask<SampleCount> VulkanCaps::getSupportedSampleCounts(
        const skgpu::VulkanInterface* interface,
        VkPhysicalDevice physDev,
        VkFormat format,
        VkImageUsageFlags usage) const {
    VkImageFormatProperties properties;

    VkResult result;
    // VULKAN_CALL_RESULT requires a VulkanSharedContext for tracking DEVICE_LOST, but VulkanCaps
    // are initialized before a VulkanSharedContext is available. The _NOCHECK variant only requires
    // a VulkanInterface, so we can use that and log failures manually.
    VULKAN_CALL_RESULT_NOCHECK(interface,
                               result,
                               GetPhysicalDeviceImageFormatProperties(physDev,
                                                                      format,
                                                                      VK_IMAGE_TYPE_2D,
                                                                      VK_IMAGE_TILING_OPTIMAL,
                                                                      usage,
                                                                      0,  // createFlags
                                                                      &properties));
    if (result != VK_SUCCESS) {
        SKIA_LOG_W("Vulkan call GetPhysicalDeviceImageFormatProperties failed: %d", result);
        return {};
    }

    // Standard sample locations are not defined for more than 16 samples, and we don't need more
    // than 16. Omit 32 and 64.
    VkSampleCountFlags sampleCounts = properties.sampleCounts &
                    (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_2_BIT | VK_SAMPLE_COUNT_4_BIT |
                     VK_SAMPLE_COUNT_8_BIT | VK_SAMPLE_COUNT_16_BIT);

    // Disable MSAA if driver workaround requires it, by pretending the format does not support any
    // sample count other than 1.
    if (this->avoidMSAA()) {
        sampleCounts &= VK_SAMPLE_COUNT_1_BIT;
    }

    // If VK_EXT_multisampled_render_to_single_sampled is used, verify that the
    // VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT flag does not alter the
    // supported sample counts. If it does, it's not against the spec but it also doesn't make
    // practical sense (the extension is all about load (unresolve) and store (resolve) ops, it
    // shouldn't affect multisampled rendering itself). In that case, issue a warning and mask out
    // unsupported bits.
    if (this->msaaRenderToSingleSampledSupport() && sampleCounts > VK_SAMPLE_COUNT_1_BIT) {
        properties.sampleCounts = VK_SAMPLE_COUNT_1_BIT;
        VULKAN_CALL_RESULT_NOCHECK(
                interface,
                result,
                GetPhysicalDeviceImageFormatProperties(
                        physDev,
                        format,
                        VK_IMAGE_TYPE_2D,
                        VK_IMAGE_TILING_OPTIMAL,
                        usage,
                        VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT,
                        &properties));
        if (result != VK_SUCCESS && result != VK_ERROR_FORMAT_NOT_SUPPORTED) {
            SKIA_LOG_W("Vulkan call GetPhysicalDeviceImageFormatProperties failed for msaa: %d",
                       result);
            return {};
        }
        if (result == VK_ERROR_FORMAT_NOT_SUPPORTED ||
            properties.sampleCounts <= VK_SAMPLE_COUNT_1_BIT ||
            (sampleCounts & properties.sampleCounts) != sampleCounts) {
            SKIA_LOG_W("Inconsistent MSAA rendering support in the presence of "
                        "VK_EXT_multisampled_render_to_single_sampled (Supported MSAA bits: %#X vs "
                        "with MSRTSS: %#X)",
                        sampleCounts,
                        result == VK_ERROR_FORMAT_NOT_SUPPORTED ? 0 : properties.sampleCounts);

            // Mask out the unsupported bits
            if (result == VK_SUCCESS) {
                sampleCounts &= (properties.sampleCounts | VK_SAMPLE_COUNT_1_BIT);
            } else {
                sampleCounts &= VK_SAMPLE_COUNT_1_BIT;
            }
        }
    }

    // VkSampleCount is bit equal to SampleCount, so VkSampleCountFlags will be bit-equal to
    // SkEnumBitMask<SampleCount>, but given the type wrapping we have to cast to SampleCount.
    return static_cast<SampleCount>(sampleCounts);
}

/*
 * The VK_IMAGE_USAGE_HOST_TRANSFER_BIT flag may cause the image to be put in a suboptimal physical
 * layout.  In practice, images that could have had framebuffer compression end up with framebuffer
 * compression disabled.  Using `VkHostImageCopyDevicePerformanceQuery`, we can determine if the
 * layout is going to be suboptimal and avoid this flag.
 *
 * `fIsEfficientWithHostImageCopy` indicates whether the VK_IMAGE_USAGE_HOST_TRANSFER_BIT is
 * efficient for this format with the following assumptions:
 *
 * - Image tiling is VK_IMAGE_TILING_OPTIMAL (note that VK_IMAGE_TILING_LINEAR is always
 *   efficient for host image copy).
 * - Image type is 2D.
 * - Image create flags is 0.
 * - Image usage flags is a subset of VK_IMAGE_USAGE_SAMPLED_BIT |
 *                                    VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
 *                                    VK_IMAGE_USAGE_TRANSFER_DST_BIT
 */
bool VulkanCaps::isEfficientWithHostCopy(const skgpu::VulkanInterface* interface,
                                         VkPhysicalDevice physDev,
                                         VkFormat format) const {
    if (!this->supportsHostImageCopy() || format == VK_FORMAT_UNDEFINED) {
        return false;
    }

    VkHostImageCopyDevicePerformanceQuery perfQuery = {};
    perfQuery.sType = VK_STRUCTURE_TYPE_HOST_IMAGE_COPY_DEVICE_PERFORMANCE_QUERY_EXT;

    VkPhysicalDeviceImageFormatInfo2 imageFormatInfo = {};
    imageFormatInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2;
    imageFormatInfo.format = format;
    imageFormatInfo.type = VK_IMAGE_TYPE_2D;
    imageFormatInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
    imageFormatInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
                            VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_HOST_TRANSFER_BIT;
    imageFormatInfo.flags = 0;

    VkImageFormatProperties2 imageFormatProperties2 = {};
    imageFormatProperties2.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
    imageFormatProperties2.pNext = &perfQuery;

    bool isEfficient = false;
    if (VULKAN_CALL(interface,
                    GetPhysicalDeviceImageFormatProperties2(
                            physDev, &imageFormatInfo, &imageFormatProperties2)) == VK_SUCCESS) {
        // There are two results returned in `perfQuery`:
        //
        // * `identicalMemoryLayout` indicates that the added flag does not affect the physical
        //   layout of the image. We can definitely add the flag in this case.
        // * `optimalDeviceAccess` indicates that the added flag _does_ change the physical layout
        //   of the image, but that according to the driver authors the fallback layout is still
        //   "pretty good, you won't know the difference".
        //
        // For now, host image copy is only used if `identicalMemoryLayout` is true, but we could
        // consider enabling it when only `optimalDeviceAccess` is true based on experimenting on
        // different vendors.
        isEfficient = perfQuery.identicalMemoryLayout;
    }
    return isEfficient;
}

// 4 uint32s for the render step id, paint id, compatible render pass description, and write
// swizzle.
static constexpr uint16_t kPipelineKeyData32Count = 4;

static constexpr int kPipelineKeyRenderStepIDIndex = 0;
static constexpr int kPipelineKeyPaintParamsIDIndex = 1;
static constexpr int kPipelineKeyRenderPassDescIndex = 2;
static constexpr int kPipelineKeyWriteSwizzleIndex = 3;

UniqueKey VulkanCaps::makeGraphicsPipelineKey(const GraphicsPipelineDesc& pipelineDesc,
                                              const RenderPassDesc& renderPassDesc) const {
    UniqueKey pipelineKey;
    {
        UniqueKey::Builder builder(
                &pipelineKey, get_pipeline_domain(), kPipelineKeyData32Count, "GraphicsPipeline");

        // Add GraphicsPipelineDesc information
        builder[kPipelineKeyRenderStepIDIndex] = static_cast<uint32_t>(pipelineDesc.renderStepID());
        builder[kPipelineKeyPaintParamsIDIndex] = pipelineDesc.paintParamsID().asUInt();
        // Add RenderPassDesc information
        builder[kPipelineKeyRenderPassDescIndex] = VulkanRenderPass::GetRenderPassKey(
                renderPassDesc, /*compatibleForPipelineKey=*/true);
        // Add RenderPass info relevant for pipeline creation that's not captured in RenderPass keys
        builder[kPipelineKeyWriteSwizzleIndex] = renderPassDesc.fWriteSwizzle.asKey();

        builder.finish();
    }

    return pipelineKey;
}

bool VulkanCaps::extractGraphicsDescs(const UniqueKey& key,
                                      GraphicsPipelineDesc* pipelineDesc,
                                      RenderPassDesc* renderPassDesc,
                                      const RendererProvider* rendererProvider) const {
    SkASSERT(key.domain() == get_pipeline_domain());
    SkASSERT(key.dataSize() == 4 * kPipelineKeyData32Count);

    const uint32_t* rawKeyData = key.data();

    SkASSERT(RenderStep::IsValidRenderStepID(
            SK_UNSAFE_TODO(rawKeyData[kPipelineKeyRenderStepIDIndex])));
    RenderStep::RenderStepID renderStepID = static_cast<RenderStep::RenderStepID>(
            SK_UNSAFE_TODO(rawKeyData[kPipelineKeyRenderStepIDIndex]));

    *pipelineDesc = GraphicsPipelineDesc(
            renderStepID,
            UniquePaintParamsID(SK_UNSAFE_TODO(rawKeyData[kPipelineKeyPaintParamsIDIndex])));

    const uint32_t rpDescBits = SK_UNSAFE_TODO(rawKeyData[kPipelineKeyRenderPassDescIndex]);
    VulkanRenderPass::ExtractRenderPassDesc(
            rpDescBits,
            SwizzleCtorAccessor::Make(SK_UNSAFE_TODO(rawKeyData[kPipelineKeyWriteSwizzleIndex])),
            this->getDstReadStrategy(),
            renderPassDesc);

    if ((renderPassDesc->fColorAttachment.fSampleCount > SampleCount::k1 && this->avoidMSAA()) ||
        (renderPassDesc->fDepthStencilAttachment.fFormat != TextureFormat::kUnsupported &&
         this->avoidDepthMode())) {
        *renderPassDesc = {};
        return false;
    }
    if (this->avoidDepthMode()) {
        renderPassDesc->fDepthStencilAttachment = {};
    }

    return true;
}

UniqueKey VulkanCaps::makeComputePipelineKey(const ComputePipelineDesc& pipelineDesc) const {
    UniqueKey pipelineKey;
    {
        static const skgpu::UniqueKey::Domain kComputePipelineDomain = UniqueKey::GenerateDomain();
        // The key is made up of a single uint32_t corresponding to the compute step ID.
        UniqueKey::Builder builder(&pipelineKey, kComputePipelineDomain, 1, "ComputePipeline");
        builder[0] = pipelineDesc.computeStep()->uniqueID();

        // TODO(b/240615224): The local work group size should factor into the key here since it is
        // specified in the shader text on Vulkan/SPIR-V. This is not a problem right now since
        // ComputeSteps don't vary their workgroup size dynamically.

        builder.finish();
    }
    return pipelineKey;
}

void VulkanCaps::buildKeyForTexture(SkISize dimensions,
                                    const TextureInfo& info,
                                    ResourceType type,
                                    GraphiteResourceKey* key) const {
    SkASSERT(!dimensions.isEmpty());

    const auto& vkInfo = TextureInfoPriv::Get<VulkanTextureInfo>(info);
    // We expect that the VkFormat enum is at most a 32-bit value.
    static_assert(VK_FORMAT_MAX_ENUM == 0x7FFFFFFF);
    // We should either be using a known VkFormat or have a valid ycbcr conversion.
    SkASSERT(vkInfo.fFormat != VK_FORMAT_UNDEFINED || vkInfo.fYcbcrConversionInfo.isValid());

    uint32_t format = static_cast<uint32_t>(vkInfo.fFormat);
    uint32_t samples = SamplesToKey(info.sampleCount());
    // We don't have to key the number of mip levels because it is inherit in the combination of
    // isMipped and dimensions.
    bool isMipped = info.mipmapped() == Mipmapped::kYes;
    Protected isProtected = info.isProtected();

    // Confirm all the below parts of the key can fit in a single uint32_t. The sum of the shift
    // amounts in the asserts must be less than or equal to 32. vkInfo.fFlags and
    // vkInfo.fImageUsageFlags will go into their own 32-bit block.
    SkASSERT(samples                            < (1u << 3));  // sample key is first 3 bits
    SkASSERT(static_cast<uint32_t>(isMipped)    < (1u << 1));  // isMapped is 4th bit
    SkASSERT(static_cast<uint32_t>(isProtected) < (1u << 1));  // isProtected is 5th bit
    SkASSERT(vkInfo.fImageTiling                < (1u << 1));  // imageTiling is 6th bit
    SkASSERT(vkInfo.fSharingMode                < (1u << 1));  // sharingMode is 7th bit
    SkASSERT(vkInfo.fAspectMask                 < (1u << 11)); // aspectMask is bits 8 - 19

    // We need two uint32_ts for dimensions and 3 for miscellaneous information.
    static constexpr uint16_t kNum32DimensionDataCnt = 2;
    static constexpr uint16_t kNum32MiscDataCnt = 3;
    // Non-YCbCr formats need 1 int for format.
    // YCbCr conversion needs 1 int for non-format flags, and a 64-bit format (external or regular).
    static constexpr uint16_t kNum32FormatDataCntNoYcbcr = 1;
    static constexpr uint16_t kNum32FormatDataCntYcbcr = 3;

    const VulkanYcbcrConversionInfo& ycbcrInfo = vkInfo.fYcbcrConversionInfo;
    const uint16_t num32DataCnt =
            kNum32DimensionDataCnt + kNum32MiscDataCnt +
            (ycbcrInfo.isValid() ? kNum32FormatDataCntYcbcr : kNum32FormatDataCntNoYcbcr);

    GraphiteResourceKey::Builder builder(key, type, num32DataCnt);

    int i = 0;
    builder[i++] = dimensions.width();
    builder[i++] = dimensions.height();

    if (ycbcrInfo.isValid()) {
        SkASSERT(ycbcrInfo.format() != VK_FORMAT_UNDEFINED || ycbcrInfo.hasExternalFormat());
        ImmutableSamplerInfo packedInfo = VulkanYcbcrConversion::ToImmutableSamplerInfo(ycbcrInfo);

        builder[i++] = packedInfo.fNonFormatYcbcrConversionInfo;
        builder[i++] = (uint32_t) packedInfo.fFormat;
        builder[i++] = (uint32_t) (packedInfo.fFormat >> 32);
    } else {
        builder[i++] = format;
    }

    builder[i++] = static_cast<uint32_t>(vkInfo.fFlags);
    builder[i++] = static_cast<uint32_t>(vkInfo.fImageUsageFlags);
    builder[i++] = (samples                                    << 0) |
                   (static_cast<uint32_t>(isMipped)            << kNumSampleKeyBits) |
                   (static_cast<uint32_t>(isProtected)         << 4) |
                   (static_cast<uint32_t>(vkInfo.fImageTiling) << 5) |
                   (static_cast<uint32_t>(vkInfo.fSharingMode) << 6) |
                   (static_cast<uint32_t>(vkInfo.fAspectMask)  << 7);
    SkASSERT(i == num32DataCnt);
}

DstReadStrategy VulkanCaps::getDstReadStrategy() const {
    // We know the graphite Vulkan backend does not support frame buffer fetch, so make sure it is
    // not marked as supported and skip checking for it.
    SkASSERT(!this->shaderCaps()->fFBFetchSupport);

    // All render target textures are expected to have VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT.
    return DstReadStrategy::kReadFromInput;
}

ImmutableSamplerInfo VulkanCaps::getImmutableSamplerInfo(const TextureInfo& textureInfo) const {
    const skgpu::VulkanYcbcrConversionInfo& ycbcrConversionInfo =
            TextureInfoPriv::Get<VulkanTextureInfo>(textureInfo).fYcbcrConversionInfo;

    if (ycbcrConversionInfo.isValid()) {
        return VulkanYcbcrConversion::ToImmutableSamplerInfo(ycbcrConversionInfo);
    }

    // If the YCbCr conversion for the TextureInfo is invalid, then return a default
    // ImmutableSamplerInfo struct.
    return {};
}

std::string VulkanCaps::toString(const ImmutableSamplerInfo& immutableSamplerInfo) const {
    return VulkanYcbcrConversion::InfoToString(
            VulkanYcbcrConversion::FromImmutableSamplerInfo(immutableSamplerInfo));
}

} // namespace skgpu::graphite
