// Copyright 2019 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "src/dawn/native/vulkan/PhysicalDeviceVk.h"

#include <algorithm>
#include <cstdint>
#include <string>
#include <utility>
#include <vector>

#include "dawn/platform/DawnPlatform.h"
#include "src/dawn/common/GPUInfo.h"
#include "src/dawn/native/ChainUtils.h"
#include "src/dawn/native/Error.h"
#include "src/dawn/native/Instance.h"
#include "src/dawn/native/Limits.h"
#include "src/dawn/native/vulkan/BackendVk.h"
#include "src/dawn/native/vulkan/DeviceVk.h"
#include "src/dawn/native/vulkan/ImmediatesLayoutVk.h"
#include "src/dawn/native/vulkan/ResourceMemoryAllocatorVk.h"
#include "src/dawn/native/vulkan/SwapChainVk.h"
#include "src/dawn/native/vulkan/TextureVk.h"
#include "src/dawn/native/vulkan/UtilsVulkan.h"
#include "src/dawn/native/vulkan/VulkanError.h"
#include "src/utils/assert.h"
#include "src/utils/compiler.h"
#include "src/utils/numeric.h"

#if DAWN_PLATFORM_IS(ANDROID)
#include "src/dawn/native/AHBFunctions.h"
#endif  // DAWN_PLATFORM_IS(ANDROID)

namespace dawn::native::vulkan {

namespace {

gpu_info::DriverVersion DecodeVulkanDriverVersion(uint32_t vendorID, uint32_t versionRaw) {
    gpu_info::DriverVersion driverVersion;
    switch (vendorID) {
        case gpu_info::kVendorID_Nvidia:
            driverVersion = {static_cast<uint16_t>((versionRaw >> 22) & 0x3FF),
                             static_cast<uint16_t>((versionRaw >> 14) & 0x0FF),
                             static_cast<uint16_t>((versionRaw >> 6) & 0x0FF),
                             static_cast<uint16_t>(versionRaw & 0x003F)};
            break;
        case gpu_info::kVendorID_Intel:
            if (PhysicalDevice::IsWindows()) {
                // Windows Vulkan driver releases together with D3D driver, so they share the same
                // version. But only CCC.DDDD is encoded in 32-bit driverVersion.
                driverVersion = {static_cast<uint16_t>(versionRaw >> 14),
                                 static_cast<uint16_t>(versionRaw & 0x3FFF)};
                break;
            }
            [[fallthrough]];
        default:
            // Use Vulkan driver conversions for other vendors
            driverVersion = {static_cast<uint16_t>(versionRaw >> 22),
                             static_cast<uint16_t>((versionRaw >> 12) & 0x3FF),
                             static_cast<uint16_t>(versionRaw & 0xFFF)};
            break;
    }

    return driverVersion;
}

bool VKComponentTypeToWGPUSubgroupMatrixComponentType(
    wgpu::SubgroupMatrixComponentType* wgpuComponentType,
    VkComponentTypeKHR vkComponentType) {
    DAWN_ASSERT(wgpuComponentType != nullptr);

    switch (vkComponentType) {
        case VK_COMPONENT_TYPE_FLOAT32_KHR:
            *wgpuComponentType = wgpu::SubgroupMatrixComponentType::F32;
            return true;
        case VK_COMPONENT_TYPE_FLOAT16_KHR:
            *wgpuComponentType = wgpu::SubgroupMatrixComponentType::F16;
            return true;
        case VK_COMPONENT_TYPE_UINT32_KHR:
            *wgpuComponentType = wgpu::SubgroupMatrixComponentType::U32;
            return true;
        case VK_COMPONENT_TYPE_SINT32_KHR:
            *wgpuComponentType = wgpu::SubgroupMatrixComponentType::I32;
            return true;
        case VK_COMPONENT_TYPE_UINT8_KHR:
            *wgpuComponentType = wgpu::SubgroupMatrixComponentType::U8;
            return true;
        case VK_COMPONENT_TYPE_SINT8_KHR:
            *wgpuComponentType = wgpu::SubgroupMatrixComponentType::I8;
            return true;
        default:
            return false;
    }
}

}  // anonymous namespace

PhysicalDevice::PhysicalDevice(VulkanInstance* vulkanInstance, VkPhysicalDevice physicalDevice)
    : PhysicalDeviceBase(wgpu::BackendType::Vulkan),
      mVkPhysicalDevice(physicalDevice),
      mVulkanInstance(vulkanInstance) {}

PhysicalDevice::~PhysicalDevice() = default;

const VulkanDeviceInfo& PhysicalDevice::GetDeviceInfo() const {
    return mDeviceInfo;
}

VkPhysicalDevice PhysicalDevice::GetVkPhysicalDevice() const {
    return mVkPhysicalDevice;
}

VulkanInstance* PhysicalDevice::GetVulkanInstance() const {
    return mVulkanInstance.Get();
}

bool PhysicalDevice::IsDepthStencilFormatSupported(VkFormat format) const {
    DAWN_ASSERT(format == VK_FORMAT_D16_UNORM_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT ||
                format == VK_FORMAT_D32_SFLOAT_S8_UINT || format == VK_FORMAT_S8_UINT);

    VkFormatProperties properties;
    mVulkanInstance->GetFunctions().GetPhysicalDeviceFormatProperties(mVkPhysicalDevice, format,
                                                                      &properties);
    return (properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
}

bool PhysicalDevice::IsTextureCompressionASTCSliced3DSupported(VkFormat format) const {
    VkImageFormatProperties properties;
    VkResult result =
        VkResult::WrapUnsafe(mVulkanInstance->GetFunctions().GetPhysicalDeviceImageFormatProperties(
            mVkPhysicalDevice, format, VK_IMAGE_TYPE_3D, VK_IMAGE_TILING_OPTIMAL,
            VK_IMAGE_USAGE_SAMPLED_BIT, {}, &properties));
    return (result == VK_SUCCESS);
}

MaybeError PhysicalDevice::InitializeImpl() {
    DAWN_TRY_ASSIGN(mDeviceInfo, GatherDeviceInfo(*this));

    mDriverVersion = DecodeVulkanDriverVersion(mDeviceInfo.properties.vendorID,
                                               mDeviceInfo.properties.driverVersion);
    const std::string driverVersionStr = mDriverVersion.ToString();

    // Disable Vulkan adapter on Windows Intel driver < 30.0.101.2111 due to flaky
    // issues.
    const gpu_info::IntelWindowsDriverVersion kDriverVersion({30, 0, 101, 2111});
    if (IsWindows() && gpu_info::IsIntel(mDeviceInfo.properties.vendorID) &&
        gpu_info::IntelWindowsDriverVersion(mDriverVersion) < kDriverVersion) {
        return DAWN_FORMAT_INTERNAL_ERROR(
            "Disable Intel Vulkan adapter on Windows driver version %s. See "
            "https://crbug.com/1338622.",
            driverVersionStr);
    }

    if (mDeviceInfo.HasExt(DeviceExt::DriverProperties)) {
        mDriverDescription = mDeviceInfo.driverProperties.driverName;
        if (mDeviceInfo.driverProperties.driverInfo[0] != '\0') {
            mDriverDescription += std::string(": ") + mDeviceInfo.driverProperties.driverInfo;
        }
        // There may be no driver version in driverInfo.
        if (mDriverDescription.find(driverVersionStr) == std::string::npos) {
            mDriverDescription += std::string(" ") + driverVersionStr;
        }
    } else {
        mDriverDescription = std::string("Vulkan driver version ") + driverVersionStr;
    }

    mDeviceId = mDeviceInfo.properties.deviceID;
    mVendorId = mDeviceInfo.properties.vendorID;
    mName = mDeviceInfo.properties.deviceName;

    switch (mDeviceInfo.properties.deviceType) {
        case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
            mAdapterType = wgpu::AdapterType::IntegratedGPU;
            break;
        case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
            mAdapterType = wgpu::AdapterType::DiscreteGPU;
            break;
        case VK_PHYSICAL_DEVICE_TYPE_CPU:
            mAdapterType = wgpu::AdapterType::CPU;
            break;
        default:
            mAdapterType = wgpu::AdapterType::Unknown;
            break;
    }

    mSubgroupMinSize = mDeviceInfo.subgroupSizeControlProperties.minSubgroupSize;
    mSubgroupMaxSize = mDeviceInfo.subgroupSizeControlProperties.maxSubgroupSize;

    // Check for essential Vulkan extensions and features

    // Dawn requires at least Vulkan 1.1
    DAWN_ASSERT(mDeviceInfo.properties.apiVersion >= VK_API_VERSION_1_1);

    // Needed for security
    if (!mDeviceInfo.features.robustBufferAccess) {
        return DAWN_INTERNAL_ERROR("Vulkan robustBufferAccess feature required.");
    }

    if (!mDeviceInfo.features.textureCompressionBC &&
        !(mDeviceInfo.features.textureCompressionETC2 &&
          mDeviceInfo.features.textureCompressionASTC_LDR)) {
        return DAWN_INTERNAL_ERROR(
            "Vulkan textureCompressionBC feature required or both textureCompressionETC2 and "
            "textureCompressionASTC required.");
    }

    // Needed for binding_array support.
    if (!mDeviceInfo.features.shaderUniformBufferArrayDynamicIndexing ||
        !mDeviceInfo.features.shaderStorageBufferArrayDynamicIndexing ||
        !mDeviceInfo.features.shaderSampledImageArrayDynamicIndexing ||
        !mDeviceInfo.features.shaderStorageImageArrayDynamicIndexing) {
        return DAWN_INTERNAL_ERROR("Vulkan shaderUniform*ArrayDynamicIndexing required.");
    }

    // Needed for the respective WebGPU features.
    if (mSupportsCoreFeatureLevel && !mDeviceInfo.features.depthBiasClamp) {
        SetCoreNotSupported(DAWN_INTERNAL_ERROR("Vulkan depthBiasClamp feature required."));
    }
    if (!mDeviceInfo.features.fragmentStoresAndAtomics) {
        // Technically `fragmentStoresAndAtomics` isn't needed for compat mode. It's essentially
        // always supported on Vulkan 1.1 devices so just leave it as required.
        return DAWN_INTERNAL_ERROR("Vulkan fragmentStoresAndAtomics feature required.");
    }
    if (!mDeviceInfo.features.fullDrawIndexUint32) {
        return DAWN_INTERNAL_ERROR("Vulkan fullDrawIndexUint32 feature required.");
    }
    if (mSupportsCoreFeatureLevel && !mDeviceInfo.features.imageCubeArray) {
        SetCoreNotSupported(DAWN_INTERNAL_ERROR("Vulkan imageCubeArray feature required."));
    }
    if (mSupportsCoreFeatureLevel && !mDeviceInfo.features.independentBlend) {
        SetCoreNotSupported(DAWN_INTERNAL_ERROR("Vulkan independentBlend feature required."));
    }
    if (mSupportsCoreFeatureLevel && !mDeviceInfo.features.sampleRateShading) {
        SetCoreNotSupported(DAWN_INTERNAL_ERROR("Vulkan sampleRateShading feature required."));
    }

    return {};
}

void PhysicalDevice::InitializeSupportedFeaturesImpl() {
    EnableFeature(Feature::AdapterPropertiesMemoryHeaps);
    EnableFeature(Feature::StaticSamplers);
    EnableFeature(Feature::FlexibleTextureViews);
    EnableFeature(Feature::DawnDeviceAllocatorControl);
    EnableFeature(Feature::TextureCompressionUnaligned);

    // Initialize supported extensions
    if (mDeviceInfo.features.textureCompressionBC == VK_TRUE) {
        EnableFeature(Feature::TextureCompressionBC);
        EnableFeature(Feature::TextureCompressionBCSliced3D);
    }

    if (mDeviceInfo.features.textureCompressionETC2 == VK_TRUE) {
        EnableFeature(Feature::TextureCompressionETC2);
    }

    if (mDeviceInfo.features.textureCompressionASTC_LDR == VK_TRUE) {
        EnableFeature(Feature::TextureCompressionASTC);

        bool textureCompressionASTCSliced3DSupported = true;
        for (const auto& astcFormat :
             {VK_FORMAT_ASTC_4x4_UNORM_BLOCK,   VK_FORMAT_ASTC_4x4_SRGB_BLOCK,
              VK_FORMAT_ASTC_5x4_UNORM_BLOCK,   VK_FORMAT_ASTC_5x4_SRGB_BLOCK,
              VK_FORMAT_ASTC_5x5_UNORM_BLOCK,   VK_FORMAT_ASTC_5x5_SRGB_BLOCK,
              VK_FORMAT_ASTC_6x5_UNORM_BLOCK,   VK_FORMAT_ASTC_6x5_SRGB_BLOCK,
              VK_FORMAT_ASTC_6x6_UNORM_BLOCK,   VK_FORMAT_ASTC_6x6_SRGB_BLOCK,
              VK_FORMAT_ASTC_8x5_UNORM_BLOCK,   VK_FORMAT_ASTC_8x5_SRGB_BLOCK,
              VK_FORMAT_ASTC_8x6_UNORM_BLOCK,   VK_FORMAT_ASTC_8x6_SRGB_BLOCK,
              VK_FORMAT_ASTC_8x8_UNORM_BLOCK,   VK_FORMAT_ASTC_8x8_SRGB_BLOCK,
              VK_FORMAT_ASTC_10x5_UNORM_BLOCK,  VK_FORMAT_ASTC_10x5_SRGB_BLOCK,
              VK_FORMAT_ASTC_10x6_UNORM_BLOCK,  VK_FORMAT_ASTC_10x6_SRGB_BLOCK,
              VK_FORMAT_ASTC_10x8_UNORM_BLOCK,  VK_FORMAT_ASTC_10x8_SRGB_BLOCK,
              VK_FORMAT_ASTC_10x10_UNORM_BLOCK, VK_FORMAT_ASTC_10x10_SRGB_BLOCK,
              VK_FORMAT_ASTC_12x10_UNORM_BLOCK, VK_FORMAT_ASTC_12x10_SRGB_BLOCK,
              VK_FORMAT_ASTC_12x12_UNORM_BLOCK, VK_FORMAT_ASTC_12x12_SRGB_BLOCK}) {
            textureCompressionASTCSliced3DSupported &=
                IsTextureCompressionASTCSliced3DSupported(astcFormat);
        }
        if (textureCompressionASTCSliced3DSupported) {
            EnableFeature(Feature::TextureCompressionASTCSliced3D);
        }
    }

    if (mDeviceInfo.properties.limits.timestampComputeAndGraphics == VK_TRUE) {
        EnableFeature(Feature::TimestampQuery);
        EnableFeature(Feature::ChromiumExperimentalTimestampQueryInsidePasses);
    }

    if (IsDepthStencilFormatSupported(VK_FORMAT_D32_SFLOAT_S8_UINT)) {
        EnableFeature(Feature::Depth32FloatStencil8);
    }

    if (mDeviceInfo.features.drawIndirectFirstInstance == VK_TRUE) {
        EnableFeature(Feature::IndirectFirstInstance);
    }

    if (mDeviceInfo.features.dualSrcBlend == VK_TRUE) {
        EnableFeature(Feature::DualSourceBlending);
    }

    if (mDeviceInfo.HasExt(DeviceExt::RasterizationOrderAttachmentAccess) &&
        mDeviceInfo.rasterizationOrderAttachmentAccessFeatures
                .rasterizationOrderColorAttachmentAccess == VK_TRUE) {
        // There are four possible ways FramebufferFetch can be supported. Currently only #1 is
        // implemented.
        //
        // 1. Coherent with rasterization order extension.
        // 2. Coherent without rasterization order extension but when GPU architecture supports
        //    coherent input attachment reads. This needs a subpass self dependency to be added.
        // 3. Non-coherent. This needs both a subpass self dependency and barriers to be
        //    inserted before draws that use FramebufferFetch.
        // 4. When dynamic rendering is used FramebufferFetch requires the dynamic rendering local
        //    storage extension and barriers to be inserted before draws that use FramebufferFetch.
        EnableFeature(Feature::FramebufferFetch);
    }

    if (mDeviceInfo.features.shaderClipDistance == VK_TRUE) {
        EnableFeature(Feature::ClipDistances);
    }

    // primitive_index is currently exposed if we support geometry shaders.
    // TODO(342172182): We could also potentially use tessellation or mesh shaders.
    if (mDeviceInfo.features.geometryShader == VK_TRUE) {
        EnableFeature(Feature::PrimitiveIndex);
    }

    // buffer_view decompositions may use u16 if the smallest access is 16-bit, so require
    // shaderInt16 as well.
    bool shaderF16Enabled = false;
    // crbug.com/519984285: Huawei Maleoon GPUs mis-compile 16-bit values in the
    // private/function storage classes.
    const bool isHuaweiMaleoon = gpu_info::IsHuaweiMaleoon(GetVendorId(), GetDeviceId());
    if (mDeviceInfo.HasExt(DeviceExt::ShaderFloat16Int8) &&
        mDeviceInfo.shaderFloat16Int8Features.shaderFloat16 == VK_TRUE &&
        mDeviceInfo.features.shaderInt16 == VK_TRUE &&
        mDeviceInfo._16BitStorageFeatures.storageBuffer16BitAccess == VK_TRUE && !isHuaweiMaleoon) {
        EnableFeature(Feature::ShaderF16);
        shaderF16Enabled = true;
    }

    if (mDeviceInfo.HasExt(DeviceExt::DrawIndirectCount) &&
        mDeviceInfo.features.multiDrawIndirect == VK_TRUE) {
        EnableFeature(Feature::MultiDrawIndirect);
    }

    // unclippedDepth=true translates to depthClamp=true, which implicitly disables clipping.
    if (mDeviceInfo.features.depthClamp == VK_TRUE) {
        EnableFeature(Feature::DepthClipControl);
    }

    if (mDeviceInfo.HasExt(DeviceExt::MultisampledRenderToSingleSampled) &&
        mDeviceInfo.multisampledRenderToSingleSampledFeatures.multisampledRenderToSingleSampled ==
            VK_TRUE) {
        EnableFeature(Feature::MSAARenderToSingleSampled);
    }

    if (mDeviceInfo.HasExt(DeviceExt::ExternalMemoryAndroidHardwareBuffer) &&
        mDeviceInfo.samplerYCbCrConversionFeatures.samplerYcbcrConversion == VK_TRUE) {
        EnableFeature(Feature::YCbCrVulkanSamplers);
        EnableFeature(Feature::OpaqueYCbCrAndroidForExternalTexture);
    }

    VkFormatProperties rg11b10Properties;
    mVulkanInstance->GetFunctions().GetPhysicalDeviceFormatProperties(
        mVkPhysicalDevice, VK_FORMAT_B10G11R11_UFLOAT_PACK32, &rg11b10Properties);

    if (IsSubset(static_cast<VkFormatFeatureFlags>(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
                                                   VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT),
                 rg11b10Properties.optimalTilingFeatures)) {
        EnableFeature(Feature::RG11B10UfloatRenderable);
    }

    VkFormatProperties bgra8unormProperties;
    mVulkanInstance->GetFunctions().GetPhysicalDeviceFormatProperties(
        mVkPhysicalDevice, VK_FORMAT_B8G8R8A8_UNORM, &bgra8unormProperties);
    if (bgra8unormProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) {
        EnableFeature(Feature::BGRA8UnormStorage);
    }

    bool unorm16TextureFormatsSupported = true;
    bool unorm16FormatsFilterabilitySupported = true;
    for (const auto& unorm16Format :
         {VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM, VK_FORMAT_R16G16B16A16_UNORM}) {
        VkFormatProperties unorm16Properties;
        mVulkanInstance->GetFunctions().GetPhysicalDeviceFormatProperties(
            mVkPhysicalDevice, unorm16Format, &unorm16Properties);
        unorm16TextureFormatsSupported &= IsSubset(
            static_cast<VkFormatFeatureFlags>(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
                                              VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
                                              VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT),
            unorm16Properties.optimalTilingFeatures);
        unorm16FormatsFilterabilitySupported &= IsSubset(
            static_cast<VkFormatFeatureFlags>(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
                                              VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT),
            unorm16Properties.optimalTilingFeatures);
    }
    if (unorm16TextureFormatsSupported) {
        EnableFeature(Feature::Unorm16TextureFormats);
    }
    if (unorm16FormatsFilterabilitySupported) {
        EnableFeature(Feature::Unorm16Filterable);
        EnableFeature(Feature::Unorm16FormatsForExternalTexture);
    }

    // 32 bit float channel formats.
    VkFormatProperties r32Properties;
    VkFormatProperties rg32Properties;
    VkFormatProperties rgba32Properties;
    mVulkanInstance->GetFunctions().GetPhysicalDeviceFormatProperties(
        mVkPhysicalDevice, VK_FORMAT_R32_SFLOAT, &r32Properties);
    mVulkanInstance->GetFunctions().GetPhysicalDeviceFormatProperties(
        mVkPhysicalDevice, VK_FORMAT_R32G32_SFLOAT, &rg32Properties);
    mVulkanInstance->GetFunctions().GetPhysicalDeviceFormatProperties(
        mVkPhysicalDevice, VK_FORMAT_R32G32B32A32_SFLOAT, &rgba32Properties);
    if ((r32Properties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT) &&
        (rg32Properties.optimalTilingFeatures &
         VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT) &&
        (rgba32Properties.optimalTilingFeatures &
         VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)) {
        EnableFeature(Feature::Float32Filterable);
    }
    if ((r32Properties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT) &&
        (rg32Properties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT) &&
        (rgba32Properties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT)) {
        EnableFeature(Feature::Float32Blendable);
    }

    // Multiplanar formats.
    constexpr VkFormat multiplanarFormats[] = {
        VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,
    };

    bool allMultiplanarFormatsSupported = true;
    for (const auto multiplanarFormat : multiplanarFormats) {
        VkFormatProperties multiplanarProps;
        mVulkanInstance->GetFunctions().GetPhysicalDeviceFormatProperties(
            mVkPhysicalDevice, multiplanarFormat, &multiplanarProps);

        if (!IsSubset(static_cast<VkFormatFeatureFlagBits>(
                          VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
                          VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT |
                          VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT),
                      multiplanarProps.optimalTilingFeatures)) {
            allMultiplanarFormatsSupported = false;
        }
    }

    if (allMultiplanarFormatsSupported) {
        EnableFeature(Feature::DawnMultiPlanarFormats);
        EnableFeature(Feature::MultiPlanarFormatExtendedUsages);
    }

    EnableFeature(Feature::TransientAttachments);
    EnableFeature(Feature::AdapterPropertiesVk);
    EnableFeature(Feature::DawnLoadResolveTexture);
    EnableFeature(Feature::RenderPassRenderArea);

    // Enable Subgroups feature if:
    // 1. Vulkan API version is 1.1 or later, and
    // 2. subgroupSupportedStages includes compute and fragment stage bit, and
    // 3. subgroupSupportedOperations includes vote, ballot, shuffle, shuffle relative, arithmetic,
    //    and quad bits, and
    // 4. VK_EXT_subgroup_size_control extension is valid, and subgroupSizeControl
    //    is TRUE in VkPhysicalDeviceSubgroupSizeControlFeaturesEXT. This is required
    //    to support VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT.
    const bool hasBaseSubgroupSupport =
        (mDeviceInfo.properties.apiVersion >= VK_API_VERSION_1_1) &&
        (mDeviceInfo.subgroupProperties.supportedStages & VK_SHADER_STAGE_COMPUTE_BIT) &&
        (mDeviceInfo.subgroupProperties.supportedStages & VK_SHADER_STAGE_FRAGMENT_BIT) &&
        (mDeviceInfo.subgroupProperties.supportedOperations & VK_SUBGROUP_FEATURE_BASIC_BIT) &&
        (mDeviceInfo.subgroupProperties.supportedOperations & VK_SUBGROUP_FEATURE_BALLOT_BIT) &&
        (mDeviceInfo.subgroupProperties.supportedOperations & VK_SUBGROUP_FEATURE_SHUFFLE_BIT) &&
        (mDeviceInfo.subgroupProperties.supportedOperations &
         VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT) &&
        (mDeviceInfo.subgroupProperties.supportedOperations & VK_SUBGROUP_FEATURE_ARITHMETIC_BIT) &&
        (mDeviceInfo.subgroupProperties.supportedOperations & VK_SUBGROUP_FEATURE_QUAD_BIT) &&
        (mDeviceInfo.HasExt(DeviceExt::SubgroupSizeControl)) &&
        (mDeviceInfo.subgroupSizeControlFeatures.subgroupSizeControl == VK_TRUE);

    // If shader f16 is enabled we only enable subgroups if we extended subgroup support.
    // This means there is a vary narrow number of devices (~4%) will not get subgroup
    // support due to the fact that they support shader f16 but not actually f16
    // operations in subgroups.
    const bool hasRequiredF16Support =
        !shaderF16Enabled ||
        (mDeviceInfo.shaderSubgroupExtendedTypes.shaderSubgroupExtendedTypes == VK_TRUE);

    const bool hasAtomic64Support = mDeviceInfo.HasExt(DeviceExt::ShaderBufferInt64Atomics) &&
                                    mDeviceInfo.shaderAtomicInt64Features.shaderBufferInt64Atomics;

    if (hasAtomic64Support) {
        EnableFeature(Feature::AtomicVec2uMinMax);
    }
    // Some devices (PowerVR GE8320) can apparently report subgroup size of 1.
    const bool allowSubgroupSizeRanges =
        mSubgroupMinSize >= kDefaultSubgroupMinSize && mSubgroupMaxSize <= kDefaultSubgroupMaxSize;

    const bool supportsSubgroupsFeature =
        hasBaseSubgroupSupport && hasRequiredF16Support && allowSubgroupSizeRanges;
    if (supportsSubgroupsFeature) {
        EnableFeature(Feature::Subgroups);
    }

    // Enable subgroup matrix if all of the following are true:
    //   1. Cooperative Matrix is supported in compute shaders.
    //   2. Vulkan Memory Model is supported at device scope.
    //   3. Subgroup Size Control is supported along with the full subgroups feature bit.
    //   4. There is at least one supported matrix configuration.
    const bool hasCooperativeMatrix =
        mDeviceInfo.HasExt(DeviceExt::CooperativeMatrix) &&
        mDeviceInfo.cooperativeMatrixFeatures.cooperativeMatrix == VK_TRUE &&
        (mDeviceInfo.cooperativeMatrixProperties.cooperativeMatrixSupportedStages &
         VK_SHADER_STAGE_COMPUTE_BIT) != 0;
    const bool hasVulkanMemoryModel =
        mDeviceInfo.HasExt(DeviceExt::VulkanMemoryModel) &&
        mDeviceInfo.vulkanMemoryModelFeatures.vulkanMemoryModel == VK_TRUE &&
        mDeviceInfo.vulkanMemoryModelFeatures.vulkanMemoryModelDeviceScope == VK_TRUE;
    const bool hasComputeFullSubgroups =
        mDeviceInfo.HasExt(DeviceExt::SubgroupSizeControl) &&
        (mDeviceInfo.subgroupSizeControlFeatures.subgroupSizeControl == VK_TRUE) &&
        (mDeviceInfo.subgroupSizeControlFeatures.computeFullSubgroups == VK_TRUE);
    if (hasCooperativeMatrix && hasVulkanMemoryModel && hasComputeFullSubgroups) {
        // crbug.com/415828149: Older Mesa drivers have bugs around subgroup matrix initialization,
        // so we blocklist SubgroupMatrix for Mesa drivers older than 25.2.
        const gpu_info::DriverVersion kGoodMesaDriver = {25, 2, 0, 0};
        const bool badDriver = IsIntelMesa() && GetDriverVersion() < kGoodMesaDriver;
        if (!badDriver) {
            EnableFeature(Feature::ChromiumExperimentalSubgroupMatrix);
        }
    }

    if (supportsSubgroupsFeature && hasComputeFullSubgroups) {
        EnableFeature(Feature::SubgroupSizeControl);
    }

    // HostMappedPointer is not supported on AMD (see: crbug.com/494566064)
    if (!gpu_info::IsAMD(GetVendorId()) && mDeviceInfo.HasExt(DeviceExt::ExternalMemoryHost) &&
        mDeviceInfo.externalMemoryHostProperties.minImportedHostPointerAlignment <=
            kMinimumHostMappedPointerAlignment) {
        EnableFeature(Feature::HostMappedPointer);
    }

    if (mDeviceInfo.HasExt(DeviceExt::ExternalMemoryDmaBuf) &&
        mDeviceInfo.HasExt(DeviceExt::ImageDrmFormatModifier)) {
        EnableFeature(Feature::SharedTextureMemoryDmaBuf);
    }
    if (mDeviceInfo.HasExt(DeviceExt::ExternalMemoryFD)) {
        EnableFeature(Feature::SharedTextureMemoryOpaqueFD);
    }

    if (mDeviceInfo.HasExt(DeviceExt::PhysicalDeviceDrm)) {
        EnableFeature(Feature::AdapterPropertiesDrm);
    }

    // Using mappable buffers on NVIDIA was found to be significantly slower in some tests. The
    // memory heap size is also small (~250MB) on many devices which leads to OOMs when allocating
    // large mappable buffers, see https://crbug.com/432044227 for details.
    if (!gpu_info::IsNvidia(GetVendorId()) && SupportsBufferMapExtendedUsages(mDeviceInfo)) {
        EnableFeature(Feature::BufferMapExtendedUsages);
    }

    if (mDeviceInfo.features.shaderStorageImageExtendedFormats == VK_TRUE) {
        bool supportTier1AndTier2 = true;

        for (const auto& format :
             {VK_FORMAT_R16_UNORM, VK_FORMAT_R16_SNORM, VK_FORMAT_R16G16_UNORM,
              VK_FORMAT_R16G16_SNORM, VK_FORMAT_R16G16B16A16_UNORM, VK_FORMAT_R16G16B16A16_SNORM,
              VK_FORMAT_R8_SNORM, VK_FORMAT_R8G8_SNORM, VK_FORMAT_R8G8B8A8_SNORM,
              VK_FORMAT_B10G11R11_UFLOAT_PACK32}) {
            VkFormatProperties properties;
            mVulkanInstance->GetFunctions().GetPhysicalDeviceFormatProperties(mVkPhysicalDevice,
                                                                              format, &properties);
            if (!IsSubset(
                    static_cast<VkFormatFeatureFlags>(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
                                                      VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT),
                    properties.optimalTilingFeatures)) {
                supportTier1AndTier2 = false;
                break;
            }
        }

        // We cannot enable TextureFormatsTier2 if TextureFormatsTier1 is not enabled.
        // TextureFormatsTier2 only requires shaderStorageImageExtendedFormats from Vulkan
        // so we don't have to check anything else.
        if (supportTier1AndTier2) {
            EnableFeature(Feature::TextureFormatsTier1);
            EnableFeature(Feature::TextureFormatsTier2);
        }
    }

#if DAWN_PLATFORM_IS(ANDROID)
    if (mDeviceInfo.HasExt(DeviceExt::ExternalMemoryAndroidHardwareBuffer)) {
        if (GetOrLoadAHBFunctions()->IsValid()) {
            EnableFeature(Feature::SharedTextureMemoryAHardwareBuffer);
        }
    }
#endif  // DAWN_PLATFORM_IS(ANDROID)

    if (CheckSemaphoreSupport(DeviceExt::ExternalSemaphoreZirconHandle,
                              VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA)) {
        EnableFeature(Feature::SharedFenceVkSemaphoreZirconHandle);
    }
    if (CheckSemaphoreSupport(DeviceExt::ExternalSemaphoreFD,
                              VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR)) {
        EnableFeature(Feature::SharedFenceSyncFD);
    }
    if (CheckSemaphoreSupport(DeviceExt::ExternalSemaphoreFD,
                              VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR)) {
        EnableFeature(Feature::SharedFenceVkSemaphoreOpaqueFD);
    }

    if (mDeviceInfo.HasExt(DeviceExt::ImageDrmFormatModifier)) {
        EnableFeature(Feature::DawnDrmFormatCapabilities);
    }

    EnableFeature(Feature::TextureComponentSwizzle);

    // Enable support for bindless if WebGPU semantics are supported:
    //  - We can update descriptor sets while pending.
    //  - Descriptor set may have variable size and be partially bound.
    //  - We can declare runtime-sized arrays of resources in SPIRV.
    //  - Limits are large enough for WebGPU.
    // Bindless support for WebGPU requires checking a LOT of things, use runtimeDescriptorArray as
    // good proxy to whether bindless will be available, and do the proper check using separate
    // boolean variables instead of a giant if-statement. runtimeDescriptorArray checks if we can
    // declare runtime-sized arrays of resources in SPIRV.
    if (mDeviceInfo.HasExt(DeviceExt::DescriptorIndexing) &&
        mDeviceInfo.descriptorIndexingFeatures.runtimeDescriptorArray) {
        const auto& vkFeatures = mDeviceInfo.descriptorIndexingFeatures;
        const auto& vkProperties = mDeviceInfo.descriptorIndexingProperties;

        // All shader resource types support update-after-bind, except uniform buffers and input
        // attachments that are not supported in WebGPU"s bindless.
        bool hasUpdateAfterBind = vkFeatures.descriptorBindingSampledImageUpdateAfterBind &&
                                  vkFeatures.descriptorBindingStorageImageUpdateAfterBind &&
                                  vkFeatures.descriptorBindingStorageBufferUpdateAfterBind &&
                                  vkFeatures.descriptorBindingStorageTexelBufferUpdateAfterBind;

        // We can modify descriptor sets after binding them, they can have variable size and be
        // sparse.
        bool hasOtherFeatures = vkFeatures.descriptorBindingUpdateUnusedWhilePending &&
                                vkFeatures.descriptorBindingPartiallyBound &&
                                vkFeatures.descriptorBindingVariableDescriptorCount;

        // We need to check all the limits for numbers of bindings related to bindless.
        constexpr uint32_t kRequiredLimit = kMaxResourceTableSize + kReservedResourceTableSlots;
        bool hasLimit =
            vkProperties.maxPerStageDescriptorUpdateAfterBindSamplers >= kRequiredLimit &&
            vkProperties.maxPerStageDescriptorUpdateAfterBindSampledImages >= kRequiredLimit &&
            vkProperties.maxPerStageUpdateAfterBindResources >= kRequiredLimit &&
            vkProperties.maxDescriptorSetUpdateAfterBindSamplers >= kRequiredLimit &&
            vkProperties.maxDescriptorSetUpdateAfterBindSampledImages >= kRequiredLimit &&
            vkProperties.maxUpdateAfterBindDescriptorsInAllPools >= kRequiredLimit;

        // Drivers may not support robust buffer access with UpdateAfterBind (presumably because
        // they only pass a GPU virtual memory address in the descriptor and not the size of the
        // binding). This is denoted with robustBufferAccessUpdateAfterBind and when this is false
        // Vulkan 1.0 robustness and the later robustness2 feature must not be used at all. While
        // Dawn can emulate most robustness, doing it for vertex inputs would be too onerous.
        //
        // Luckily, the extension VK_EXT_pipeline_robustness (promoted to 1.4, made originally for
        // ANGLE) allows enabling robustness per-pipeline and more importantly per buffer type.
        // Without robustBufferAccessUpdateAfterBind, all the buffer robustness is disallowed,
        // except vertexInputs, the one we actually care about.
        //
        // Note that we could add this requirement only when robustness is enabled, but doing so
        // would make some GPUAdapter potentially advertise bindless support but fail to create a
        // GPUDevice with it (because it cannot be supported with robustness).
        bool canSupportRobustness = vkProperties.robustBufferAccessUpdateAfterBind ||
                                    (mDeviceInfo.HasExt(DeviceExt::PipelineRobustness) &&
                                     mDeviceInfo.pipelineRobustnessFeatures.pipelineRobustness);

        if (hasUpdateAfterBind && hasOtherFeatures && hasLimit && canSupportRobustness) {
            EnableFeature(Feature::ChromiumExperimentalSamplingResourceTable);
        }

        // TODO(https://issues.chromium.org/473444515): add support for heterogeneous bindless by
        // checking both for storage buffers/images limits and some support for heterogeneous
        // bindings via VK_EXT_mutable_descriptor_type, VK_EXT_descriptor_buffer or descriptor
        // heaps.
    }
}

MaybeError PhysicalDevice::InitializeSupportedLimitsImpl(CombinedLimits* limits) {
    if (mSupportsCoreFeatureLevel) {
        MaybeError result = InitializeSupportedLimitsInternal(wgpu::FeatureLevel::Core, limits);
        if (result.IsSuccess()) {
            return result;
        }

        // Log a warning why core isn't supported and retry checking lower compat limits.
        SetCoreNotSupported(result.AcquireError());
    }

    return InitializeSupportedLimitsInternal(wgpu::FeatureLevel::Compatibility, limits);
}

MaybeError PhysicalDevice::InitializeSupportedLimitsInternal(wgpu::FeatureLevel featureLevel,
                                                             CombinedLimits* limits) {
    GetDefaultLimits(limits, featureLevel);
    CombinedLimits baseLimits = *limits;

    const VkPhysicalDeviceLimits& vkLimits = mDeviceInfo.properties.limits;

#define CHECK_V1_LIMIT_IMPL(vulkanName, webgpuName, compareOp, msgSegment)           \
    do {                                                                             \
        if (vkLimits.vulkanName compareOp baseLimits.v1.webgpuName) {                \
            return DAWN_INTERNAL_ERROR("Insufficient Vulkan limits for " #webgpuName \
                                       "."                                           \
                                       " VkPhysicalDeviceLimits::" #vulkanName       \
                                       " must be at " msgSegment " " +               \
                                       std::to_string(baseLimits.v1.webgpuName));    \
        }                                                                            \
    } while (false)

#define CHECK_AND_SET_V1_LIMIT_IMPL(vulkanName, webgpuName, compareOp, msgSegment) \
    do {                                                                           \
        CHECK_V1_LIMIT_IMPL(vulkanName, webgpuName, compareOp, msgSegment);        \
        limits->v1.webgpuName = dchecked_cast<uint32_t>(vkLimits.vulkanName);      \
    } while (false)

#define CHECK_V1_MAX_LIMIT(vulkanName, webgpuName) \
    CHECK_V1_LIMIT_IMPL(vulkanName, webgpuName, <, "least")
#define CHECK_AND_SET_V1_MAX_LIMIT(vulkanName, webgpuName) \
    CHECK_AND_SET_V1_LIMIT_IMPL(vulkanName, webgpuName, <, "least")
#define CHECK_AND_SET_V1_MIN_LIMIT(vulkanName, webgpuName) \
    CHECK_AND_SET_V1_LIMIT_IMPL(vulkanName, webgpuName, >, "most")

    CHECK_AND_SET_V1_MAX_LIMIT(maxImageDimension1D, maxTextureDimension1D);

    CHECK_V1_MAX_LIMIT(maxImageDimension2D, maxTextureDimension2D);
    CHECK_V1_MAX_LIMIT(maxImageDimensionCube, maxTextureDimension2D);
    CHECK_V1_MAX_LIMIT(maxFramebufferWidth, maxTextureDimension2D);
    CHECK_V1_MAX_LIMIT(maxFramebufferHeight, maxTextureDimension2D);
    CHECK_V1_MAX_LIMIT(maxViewportDimensions[0], maxTextureDimension2D);
    CHECK_V1_MAX_LIMIT(maxViewportDimensions[1], maxTextureDimension2D);
    CHECK_V1_MAX_LIMIT(viewportBoundsRange[1], maxTextureDimension2D);
    limits->v1.maxTextureDimension2D = std::min({
        vkLimits.maxImageDimension2D,
        vkLimits.maxImageDimensionCube,
        vkLimits.maxFramebufferWidth,
        vkLimits.maxFramebufferHeight,
        vkLimits.maxViewportDimensions[0],
        vkLimits.maxViewportDimensions[1],
        static_cast<uint32_t>(vkLimits.viewportBoundsRange[1]),
    });

    CHECK_AND_SET_V1_MAX_LIMIT(maxImageDimension3D, maxTextureDimension3D);
    CHECK_AND_SET_V1_MAX_LIMIT(maxImageArrayLayers, maxTextureArrayLayers);
    CHECK_AND_SET_V1_MAX_LIMIT(maxBoundDescriptorSets, maxBindGroups);
    CHECK_AND_SET_V1_MAX_LIMIT(maxDescriptorSetUniformBuffersDynamic,
                               maxDynamicUniformBuffersPerPipelineLayout);
    CHECK_AND_SET_V1_MAX_LIMIT(maxDescriptorSetStorageBuffersDynamic,
                               maxDynamicStorageBuffersPerPipelineLayout);

    CHECK_AND_SET_V1_MAX_LIMIT(maxPerStageDescriptorSampledImages,
                               maxSampledTexturesPerShaderStage);
    CHECK_AND_SET_V1_MAX_LIMIT(maxPerStageDescriptorSamplers, maxSamplersPerShaderStage);
    CHECK_AND_SET_V1_MAX_LIMIT(maxPerStageDescriptorStorageBuffers,
                               maxStorageBuffersPerShaderStage);
    CHECK_AND_SET_V1_MAX_LIMIT(maxPerStageDescriptorStorageImages,
                               maxStorageTexturesPerShaderStage);
    CHECK_AND_SET_V1_MAX_LIMIT(maxPerStageDescriptorUniformBuffers,
                               maxUniformBuffersPerShaderStage);
    CHECK_AND_SET_V1_MAX_LIMIT(maxStorageBufferRange, maxStorageBufferBindingSize);
    CHECK_AND_SET_V1_MAX_LIMIT(maxColorAttachments, maxColorAttachments);

    // Round max uniform buffer size down to a multiple of 16 bytes since Tint will polyfill them as
    // array<vec4u, ...>.
    uint32_t maxUniformBufferSize = vkLimits.maxUniformBufferRange;
    maxUniformBufferSize = maxUniformBufferSize - (maxUniformBufferSize % 16);
    if (maxUniformBufferSize < baseLimits.v1.maxUniformBufferBindingSize) {
        return DAWN_INTERNAL_ERROR("Insufficient Vulkan limits for maxUniformBufferBindingSize");
    }
    limits->v1.maxUniformBufferBindingSize = maxUniformBufferSize;

    // Vulkan has no such limit; set it to 32 (the byte width of the largest format) multiplied by
    // the maximum number of attachments in order to make it a no-op.
    limits->v1.maxColorAttachmentBytesPerSample = 32 * vkLimits.maxColorAttachments;

    // Validate against maxFragmentCombinedOutputResources, tightening the limits when necessary.
    const uint32_t minFragmentCombinedOutputResources =
        baseLimits.v1.maxStorageBuffersPerShaderStage +
        baseLimits.v1.maxStorageTexturesPerShaderStage + baseLimits.v1.maxColorAttachments;
    const uint64_t maxFragmentCombinedOutputResources =
        limits->v1.maxStorageBuffersPerShaderStage + limits->v1.maxStorageTexturesPerShaderStage +
        limits->v1.maxColorAttachments;
    // Only re-adjust the limits when the limit makes sense w.r.t to the required WebGPU limits.
    // Otherwise, we ignore the maxFragmentCombinedOutputResources since it is known to yield
    // incorrect values on desktop drivers.
    bool readjustFragmentCombinedOutputResources =
        vkLimits.maxFragmentCombinedOutputResources > minFragmentCombinedOutputResources &&
        uint64_t(vkLimits.maxFragmentCombinedOutputResources) < maxFragmentCombinedOutputResources;
    if (readjustFragmentCombinedOutputResources) {
        // Split extra resources across the three other limits instead of using the default values
        // since it would overflow.
        uint32_t extraResources =
            vkLimits.maxFragmentCombinedOutputResources - minFragmentCombinedOutputResources;
        limits->v1.maxColorAttachments = std::min(
            baseLimits.v1.maxColorAttachments + (extraResources / 3), vkLimits.maxColorAttachments);
        extraResources -= limits->v1.maxColorAttachments - baseLimits.v1.maxColorAttachments;
        limits->v1.maxStorageTexturesPerShaderStage =
            std::min(baseLimits.v1.maxStorageTexturesPerShaderStage + (extraResources / 2),
                     vkLimits.maxPerStageDescriptorStorageImages);
        extraResources -= limits->v1.maxStorageTexturesPerShaderStage -
                          baseLimits.v1.maxStorageTexturesPerShaderStage;
        limits->v1.maxStorageBuffersPerShaderStage =
            std::min(baseLimits.v1.maxStorageBuffersPerShaderStage + extraResources,
                     vkLimits.maxPerStageDescriptorStorageBuffers);
    }
    limits->compat.maxStorageTexturesInFragmentStage = limits->v1.maxStorageTexturesPerShaderStage;
    limits->compat.maxStorageBuffersInFragmentStage = limits->v1.maxStorageBuffersPerShaderStage;
    limits->compat.maxStorageTexturesInVertexStage = limits->v1.maxStorageTexturesPerShaderStage;
    limits->compat.maxStorageBuffersInVertexStage = limits->v1.maxStorageBuffersPerShaderStage;

    CHECK_AND_SET_V1_MIN_LIMIT(minUniformBufferOffsetAlignment, minUniformBufferOffsetAlignment);
    CHECK_AND_SET_V1_MIN_LIMIT(minStorageBufferOffsetAlignment, minStorageBufferOffsetAlignment);

    CHECK_AND_SET_V1_MAX_LIMIT(maxVertexInputBindings, maxVertexBuffers);
    CHECK_AND_SET_V1_MAX_LIMIT(maxVertexInputAttributes, maxVertexAttributes);

    if (vkLimits.maxVertexInputBindingStride < baseLimits.v1.maxVertexBufferArrayStride ||
        vkLimits.maxVertexInputAttributeOffset < baseLimits.v1.maxVertexBufferArrayStride - 1) {
        return DAWN_INTERNAL_ERROR("Insufficient Vulkan limits for maxVertexBufferArrayStride");
    }
    // Note that some drivers have UINT32_MAX as maxVertexInputAttributeOffset so we do that +1 only
    // after the std::min.
    limits->v1.maxVertexBufferArrayStride =
        std::min(vkLimits.maxVertexInputBindingStride - 1, vkLimits.maxVertexInputAttributeOffset) +
        1;

    // Reserve 4 components for the SPIR-V builtin `position`. WebGPU SPEC requires the minimum
    // value of `maxInterStageShaderVariables` be 16. According to Vulkan SPEC, "the Location value
    // specifies an interface slot comprised of a 32-bit four-component vector conveyed between
    // stages". The WebGPU SPEC also requires position at pixel centers even in the case of
    // multisampling. Vulkan does not provide a reliable way of enforcing this so must potentially
    // use another vec4f slot to emulate this behavior. So on any WebGPU Vulkan backend
    // `maxVertexOutputComponents` must be no less than 72 = (16 * 4 + 8).
    if (vkLimits.maxVertexOutputComponents < baseLimits.v1.maxInterStageShaderVariables * 4 + 8 ||
        vkLimits.maxFragmentInputComponents < baseLimits.v1.maxInterStageShaderVariables * 4 + 8) {
        return DAWN_INTERNAL_ERROR("Insufficient Vulkan limits for maxInterStageShaderVariables");
    }
    // Reserve 1 for position and 1 for emulated fragment pixel center.
    auto constexpr kNumReservedVariables = 1 + 1;
    limits->v1.maxInterStageShaderVariables =
        std::min(vkLimits.maxVertexOutputComponents, vkLimits.maxFragmentInputComponents) / 4 -
        kNumReservedVariables;

    CHECK_AND_SET_V1_MAX_LIMIT(maxComputeSharedMemorySize, maxComputeWorkgroupStorageSize);
    CHECK_AND_SET_V1_MAX_LIMIT(maxComputeWorkGroupInvocations, maxComputeInvocationsPerWorkgroup);
    CHECK_AND_SET_V1_MAX_LIMIT(maxComputeWorkGroupSize[0], maxComputeWorkgroupSizeX);
    CHECK_AND_SET_V1_MAX_LIMIT(maxComputeWorkGroupSize[1], maxComputeWorkgroupSizeY);
    CHECK_AND_SET_V1_MAX_LIMIT(maxComputeWorkGroupSize[2], maxComputeWorkgroupSizeZ);

    CHECK_AND_SET_V1_MAX_LIMIT(maxComputeWorkGroupCount[0], maxComputeWorkgroupsPerDimension);
    CHECK_AND_SET_V1_MAX_LIMIT(maxComputeWorkGroupCount[1], maxComputeWorkgroupsPerDimension);
    CHECK_AND_SET_V1_MAX_LIMIT(maxComputeWorkGroupCount[2], maxComputeWorkgroupsPerDimension);
    limits->v1.maxComputeWorkgroupsPerDimension = std::min({
        vkLimits.maxComputeWorkGroupCount[0],
        vkLimits.maxComputeWorkGroupCount[1],
        vkLimits.maxComputeWorkGroupCount[2],
    });

    if (!IsSubset(VkSampleCountFlags(VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT),
                  vkLimits.framebufferColorSampleCounts)) {
        return DAWN_INTERNAL_ERROR("Insufficient Vulkan limits for framebufferColorSampleCounts");
    }
    if (!IsSubset(VkSampleCountFlags(VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT),
                  vkLimits.framebufferDepthSampleCounts)) {
        return DAWN_INTERNAL_ERROR("Insufficient Vulkan limits for framebufferDepthSampleCounts");
    }

    limits->v1.maxBufferSize = kAssumedMaxBufferSize;
    if (mDeviceInfo.HasExt(DeviceExt::Maintenance4)) {
        limits->v1.maxBufferSize = mDeviceInfo.propertiesMaintenance4.maxBufferSize;
    } else {
        limits->v1.maxBufferSize = mDeviceInfo.propertiesMaintenance3.maxMemoryAllocationSize;
    }

    // OpArrayLength returns 0 for buffers >= 2GB for some NVIDIA devices.
    // There is an open bug with NVIDIA to resolve. Likely some issue with the sign bit.
    // See: crbug.com/435684920
    if (gpu_info::IsNvidia(GetVendorId())) {
        // 2GB limits will actually be capped to 2GB - 4 by Chrome tier limits but we do so
        // explicitly here to avoid failures in Dawn native.
        const uint64_t k2GbMinus4 = 0x80000000 - 4;
        limits->v1.maxStorageBufferBindingSize = std::min(limits->v1.maxBufferSize, k2GbMinus4);
    }

    if (limits->v1.maxBufferSize < baseLimits.v1.maxBufferSize) {
        return DAWN_INTERNAL_ERROR("Insufficient Vulkan maxBufferSize limit");
    }

    if (mDeviceInfo.HasExt(DeviceExt::SubgroupSizeControl)) {
        mDefaultComputeSubgroupSize = FindDefaultComputeSubgroupSize();
        if (mDefaultComputeSubgroupSize.has_value()) {
            // According to VK_EXT_subgroup_size_control, for compute shaders we must ensure
            // computeInvocationsPerWorkgroup <= maxComputeWorkgroupSubgroups x computeSubgroupSize
            limits->v1.maxComputeInvocationsPerWorkgroup =
                std::min(limits->v1.maxComputeInvocationsPerWorkgroup,
                         mDeviceInfo.subgroupSizeControlProperties.maxComputeWorkgroupSubgroups *
                             mDefaultComputeSubgroupSize.value());
        }
    }

    // Vulkan needs to have enough push constant range size for all
    // internal and external immediate data usages.
    constexpr uint32_t kVkGuaranteedMaxPushConstantsSize = 128;  // from Vulkan spec
    constexpr uint32_t kMaxInternalConstants = sizeof(RenderImmediates) - sizeof(UserImmediates);
    static_assert(kVkGuaranteedMaxPushConstantsSize >=
                  kMaxImmediateDataBytes + kMaxInternalConstants);
    DAWN_ASSERT(vkLimits.maxPushConstantsSize >= kVkGuaranteedMaxPushConstantsSize);
    limits->v1.maxImmediateSize = kMaxImmediateDataBytes;

    if (mDeviceInfo.HasExt(DeviceExt::ExternalMemoryHost) &&
        mDeviceInfo.externalMemoryHostProperties.minImportedHostPointerAlignment <=
            kMinimumHostMappedPointerAlignment) {
        limits->hostMappedPointerLimits.hostMappedPointerAlignment =
            kMinimumHostMappedPointerAlignment;
    }

    return {};
}

bool PhysicalDevice::SupportsExternalImages() const {
    // Via dawn::native::vulkan::WrapVulkanImage
    return external_memory::Service::CheckSupport(mDeviceInfo) &&
           external_semaphore::Service::CheckSupport(mDeviceInfo, mVkPhysicalDevice,
                                                     mVulkanInstance->GetFunctions());
}

bool PhysicalDevice::SupportsFeatureLevel(wgpu::FeatureLevel featureLevel,
                                          InstanceBase* instance) const {
    if (featureLevel == wgpu::FeatureLevel::Core && !mSupportsCoreFeatureLevel) {
        if (mCoreError && instance) {
            // Log a warning explaining why this device doesn't support core the first time a core
            // adapter is requested.
            mCoreError->AppendContext(
                absl::StrFormat("checking core feature level support on \"%s\"", GetName()));
            instance->ConsumedErrorAndWarnOnce(std::move(mCoreError));
        }
        return false;
    }
    return true;
}

void PhysicalDevice::SetupBackendAdapterToggles(dawn::platform::Platform* platform,
                                                TogglesState* adapterToggles) const {
    // The environment can only request to use the Vulkan Memory Model when the extension is present
    // and the capabilities are available. Override the decision if they are not supported.
    if (!GetDeviceInfo().HasExt(DeviceExt::VulkanMemoryModel) ||
        GetDeviceInfo().vulkanMemoryModelFeatures.vulkanMemoryModel == VK_FALSE ||
        GetDeviceInfo().vulkanMemoryModelFeatures.vulkanMemoryModelDeviceScope == VK_FALSE) {
        adapterToggles->ForceSet(Toggle::UseVulkanMemoryModel, false);
    }
    adapterToggles->Default(Toggle::UseVulkanMemoryModel, true);

    adapterToggles->Default(
        Toggle::DecomposeUniformBuffers,
        platform->IsFeatureEnabled(platform::Features::kWebGPUDecomposeUniformBuffers));

    // VulkanUseDynamicRendering and VulkanUseCreateRenderPass2 are treated as Adapter toggles
    // because they affect whether or not the MSAARenderToSingleSampled feature is available.

    // Use dynamic rendering by default if the corresponding extension is available.
    // Also disable on older Intel devices, ARM Mali-G68 devices, and PowerVR devices, all of which
    // have been observed to have driver issues with the dynamic rendering path.
    if (!GetDeviceInfo().HasExt(DeviceExt::DynamicRendering) ||
        GetDeviceInfo().dynamicRenderingFeatures.dynamicRendering == VK_FALSE ||
        (gpu_info::IsIntel(GetVendorId()) &&
         gpu_info::GetIntelGen(GetVendorId(), GetDeviceId()) <= gpu_info::IntelGen::Gen9) ||
        (gpu_info::IsARM(GetVendorId()) && gpu_info::IsMaliG68(GetDeviceId())) ||
        gpu_info::IsImgTec(GetVendorId())) {
        adapterToggles->ForceSet(Toggle::VulkanUseDynamicRendering, false);
    } else {
        adapterToggles->Default(Toggle::VulkanUseDynamicRendering, true);
    }

    // Use CreateRenderPass2KHR by default if the corresponding extension is available.
    if (!GetDeviceInfo().HasExt(DeviceExt::CreateRenderPass2)) {
        adapterToggles->ForceSet(Toggle::VulkanUseCreateRenderPass2, false);
    } else {
        adapterToggles->Default(Toggle::VulkanUseCreateRenderPass2, true);
    }
}

void PhysicalDevice::SetupBackendDeviceToggles(dawn::platform::Platform* platform,
                                               TogglesState* deviceToggles) const {
    // TODO(crbug.com/dawn/857): tighten this workaround when this issue is fixed in both
    // Vulkan SPEC and drivers.
    deviceToggles->Default(Toggle::UseTemporaryBufferInCompressedTextureToTextureCopy, true);

    if (MayBeQualcommProprietary()) {
        // dawn:1564, dawn:1897: Recording a compute pass after a render pass in the same command
        // buffer frequently causes a crash on Qualcomm GPUs. To work around that bug, split the
        // command buffer any time we are about to record a compute pass when a render pass has
        // already been recorded.
        deviceToggles->Default(Toggle::VulkanSplitCommandBufferOnComputePassAfterRenderPass, true);

        // dawn:1569: Qualcomm devices have a bug resolving into a non-zero level of an array
        // texture. Work around it by resolving into a single level texture and then copying into
        // the intended layer.
        deviceToggles->Default(Toggle::AlwaysResolveIntoZeroLevelAndLayer, true);

        // chromium:411656647: Qualcomm devices have a bug where an empty render pass that has a
        // resolve target doesn't perform the resolve. To work around it, add a small amount of work
        // to the pass to force it to execute.
        deviceToggles->Default(Toggle::VulkanAddWorkToEmptyResolvePass, true);

        // chromium:407109052: Qualcomm devices have a bug where the spirv extended op NClamp
        // modifies other components of a vector when one of the components is nan.
        deviceToggles->Default(Toggle::ScalarizeMaxMinClamp, true);

        // Qualcomm's shader compiler returns an internal error when binding_array<texture*> is
        // passed by argument to functions.
        deviceToggles->Default(Toggle::VulkanDirectVariableAccessTransformHandle, true);

        // Qualcomm has compiler error only in 32 bit. Modern devices (64 bit, adreno 8xx) do not
        // exhibit this compiler error.
#if DAWN_PLATFORM_IS(32_BIT)
        deviceToggles->Default(Toggle::VulkanSampleCompareDepthCubeArrayWorkaround, true);
#endif
        // crbug.com/469328925
        deviceToggles->Default(Toggle::VulkanSampleCompare2DWorkaround, true);
    }

    if (IsPixel10() || IsAndroidSamsung()) {
        // Pixel 10 has a bug in vkGetPipelineCacheData(), see https://crbug.com/437807243.
        // Samsung Xclipse GPUs appear to have the same problem, see https://crbug.com/487613497.
        // TODO(crbug.com/437807243): If newer driver version without bug is released then we can
        // gate this on driver version.
        deviceToggles->Default(Toggle::VulkanIncompletePipelineCacheWorkaround, true);
    }

    if (MayBeImaginationProprietary()) {
        // crbug.com/443906252: Polyfill for case switch with large ranges.
        deviceToggles->Default(Toggle::VulkanPolyfillSwitchWithIf, true);
    }

    // AMD Mesa front end optimizer bug for unary negation and abs.
    // Fixed in 25.3 - See crbug.com/448294721 and crbug.com/500099471
    // See crbug.com/93692702 for variations of this bug.
    if (IsAmdMesa()) {
        const gpu_info::DriverVersion kGoodMesaDriver = {25, 3, 0, 0};
        const bool badDriver = GetDriverVersion() < kGoodMesaDriver;
        if (badDriver) {
            deviceToggles->Default(Toggle::VulkanPolyfillFloatAbs, true);
            deviceToggles->Default(Toggle::VulkanPolyfillFloatNegation, true);
        }
    }

    if (MayBeArmProprietary()) {
        // dawn:1550: Resolving multiple color targets in a single pass fails on ARM GPUs. To
        // work around the issue, passes that resolve to multiple color targets will instead be
        // forced to store the multisampled targets and do the resolves as separate passes injected
        // after the original one.
        deviceToggles->Default(Toggle::ResolveMultipleAttachmentInSeparatePasses, true);

        // dawn:379551588: Using the `pack4x8snorm`, `pack4x8unorm`, `unpack4x8snorm` and
        // `unpack4x8unorm` methods can have issues on ARM. To work around the issue we re-write the
        // pack/unpack calls and do the packing manually.
        deviceToggles->Default(Toggle::PolyfillPackUnpack4x8Norm, true);

        // chromium:387000529: Arm devices have issues passing texture handles as parameters to
        // functions for accesses without a sampler (TextureLoad).
        deviceToggles->Default(Toggle::VulkanDirectVariableAccessTransformHandle, true);

        // Mali drivers incorrectly treat the stride operand to cooperative matrix load and store
        // instructions as matrix elements instead of a source/dest pointee elements.
        // See crbug.com/460209126
        deviceToggles->Default(Toggle::VulkanCooperativeMatrixStrideIsMatrixElements, true);

        // dawn:500417361
        // TODO: Add details once available.
        deviceToggles->Default(Toggle::VulkanSleepAfterLostDeviceWait, true);
    }

    if (IsAndroidSamsung() || IsAndroidQualcomm() || IsAndroidHuawei()) {
        deviceToggles->Default(Toggle::IgnoreImportedAHardwareBufferVulkanImageSize, true);
    }

    if (gpu_info::IsHuaweiMaleoon(GetVendorId(), GetDeviceId())) {
        // crbug.com/520126486: Huawei Maleoon drivers mis-stride multi-layer
        // buffer<->image copies: only the first array layer / depth slice lands at
        // the correct buffer offset when a copy region has layerCount > 1.
        // Split such copies into one region per layer.
        deviceToggles->Default(Toggle::VulkanSplitBufferTextureCopyForArrayLayers, true);
    }

    // Collapse redundant subgroup min and max operations to workaround a driver crash on some AMD
    // GPUs.  Should only affect AMD Windows Driver versions < 31.0.22000.0, but because this is a
    // harmless "optimizing" workaround go ahead enable for all versions. See:
    // https://crbug.com/508265321.
    if (IsWindowsAMD()) {
        deviceToggles->Default(Toggle::CollapseSubgroupMinMax, true);
    }

    if (IsSwiftshader()) {
        // Swiftshader doesn't handle propagating decorations for descriptors through
        // OpCompositeExtract which happens when a binding_array is indexed "by value" instead of
        // through a pointer.
        deviceToggles->Default(Toggle::VulkanDirectVariableAccessTransformHandle, true);

        // Disable use of ExtendedDynamicState on SwitfShader. It doesn't appear to be handling all
        // dynamic states properly, specifically some stencil ops.
        //
        // Only force-disable when the extension is actually advertised. When it isn't, the generic
        // availability check below already force-disables the toggle, and force-setting the same
        // toggle twice trips the DAWN_CHECK(!mForcedToggles.Has(toggle)) in TogglesState::ForceSet.
        if (GetDeviceInfo().HasExt(DeviceExt::ExtendedDynamicState) &&
            GetDeviceInfo().extendedDynamicStateFeatures.extendedDynamicState == VK_TRUE) {
            deviceToggles->ForceSet(Toggle::VulkanUseExtendedDynamicState, false);
        }
    }

    if (IsIntelMesa()) {
        // chromium:448873316: Non-scalar (vector) saturate from uniform fails.
        deviceToggles->Default(Toggle::SaturateAsMinMaxF16, true);

        if (gpu_info::IsIntelGen12LP(GetVendorId(), GetDeviceId())) {
            // dawn:1688: Intel Mesa driver has a bug about reusing the VkDeviceMemory that was
            // previously bound to a 2D VkImage. To work around that bug we have to disable the
            // resource sub-allocation for 2D textures with CopyDst or RenderAttachment usage.
            const gpu_info::DriverVersion kBuggyDriverVersion = {21, 3, 6, 0};
            if (GetDriverVersion() >= kBuggyDriverVersion) {
                deviceToggles->Default(
                    Toggle::DisableSubAllocationFor2DTextureWithCopyDstOrRenderAttachment, true);
            }

            // chromium:1361662: Mesa driver has a bug clearing R8 mip-leveled textures on Intel
            // Gen12 GPUs. Work around it by clearing the whole texture as soon as they are created.
            const gpu_info::DriverVersion kFixedDriverVersion = {23, 1, 0, 0};
            if (GetDriverVersion() < kFixedDriverVersion) {
                deviceToggles->Default(Toggle::VulkanClearGen12TextureWithCCSAmbiguateOnCreation,
                                       true);
            }
        }

        if (gpu_info::IsIntelGen12LP(GetVendorId(), GetDeviceId()) ||
            gpu_info::IsIntelGen12HP(GetVendorId(), GetDeviceId())) {
            // Intel Mesa driver has a bug where vkCmdCopyQueryPoolResults fails to write
            // overlapping queries to a same buffer after the buffer is accessed by a compute shader
            // with correct resource barriers, which may caused by flush and memory coherency issue
            // on Intel Gen12 GPUs. Workaround for it to clear the buffer before
            // vkCmdCopyQueryPoolResults on Mesa driver version < 23.1.3.
            const gpu_info::DriverVersion kBuggyDriverVersion = {21, 2, 0, 0};
            const gpu_info::DriverVersion kFixedDriverVersion = {23, 1, 3, 0};
            if (GetDriverVersion() >= kBuggyDriverVersion &&
                GetDriverVersion() < kFixedDriverVersion) {
                deviceToggles->Default(Toggle::ClearBufferBeforeResolveQueries, true);
            }
        }
    }

    // The environment can request to various options for depth-stencil formats that could be
    // unavailable. Override the decision if it is not applicable.
    bool supportsD32s8 = IsDepthStencilFormatSupported(VK_FORMAT_D32_SFLOAT_S8_UINT);
    bool supportsD24s8 = IsDepthStencilFormatSupported(VK_FORMAT_D24_UNORM_S8_UINT);
    bool supportsS8 = IsDepthStencilFormatSupported(VK_FORMAT_S8_UINT);

    DAWN_ASSERT(supportsD32s8 || supportsD24s8);

    if (!supportsD24s8) {
        deviceToggles->ForceSet(Toggle::VulkanUseD32S8, true);
    }
    if (!supportsD32s8) {
        deviceToggles->ForceSet(Toggle::VulkanUseD32S8, false);
    }
    // By default try to use D32S8 for Depth24PlusStencil8
    deviceToggles->Default(Toggle::VulkanUseD32S8, true);

    if (!supportsS8) {
        deviceToggles->ForceSet(Toggle::VulkanUseS8, false);
    }
    // By default try to use S8 if available.
    deviceToggles->Default(Toggle::VulkanUseS8, true);

    // The environment can only request to use VK_KHR_zero_initialize_workgroup_memory when the
    // extension is available. Override the decision if it is not applicable or
    // zeroInitializeWorkgroupMemoryFeatures.shaderZeroInitializeWorkgroupMemory == VK_FALSE.
    // Never use the extension on Mali devices due to a known bug (see crbug.com/tint/2101).
    // Pixel 10 workgroup zero init does not always work as expected (see crbug.com/479242793). We
    // have conservatively enabled this for all of imagination.
    if (!GetDeviceInfo().HasExt(DeviceExt::ZeroInitializeWorkgroupMemory) ||
        GetDeviceInfo().zeroInitializeWorkgroupMemoryFeatures.shaderZeroInitializeWorkgroupMemory ==
            VK_FALSE ||
        gpu_info::IsARM(GetVendorId()) || gpu_info::IsImgTec(GetVendorId())) {
        deviceToggles->ForceSet(Toggle::VulkanUseZeroInitializeWorkgroupMemoryExtension, false);
    }
    // By default try to initialize workgroup memory with OpConstantNull according to the Vulkan
    // extension VK_KHR_zero_initialize_workgroup_memory.
    deviceToggles->Default(Toggle::VulkanUseZeroInitializeWorkgroupMemoryExtension, true);

    // Spirv OpKill does not do demote to helper and has also been deprecated. Use
    // OpDemoteToHelperInvocation where the extension is available to get correct platform demote to
    // helper for "discard".
    if (!GetDeviceInfo().HasExt(DeviceExt::DemoteToHelperInvocation) ||
        GetDeviceInfo().demoteToHelperInvocationFeatures.shaderDemoteToHelperInvocation ==
            VK_FALSE) {
        deviceToggles->ForceSet(Toggle::VulkanUseDemoteToHelperInvocationExtension, false);
    }

    // By default we will use the vulkan demote to helper extension if it is available. This gives
    // us correct fragment shader discard semantics.
    deviceToggles->Default(Toggle::VulkanUseDemoteToHelperInvocationExtension, true);

    // The environment can only request to use StorageInputOutput16 when the capability is
    // available.
    if (GetDeviceInfo()._16BitStorageFeatures.storageInputOutput16 == VK_FALSE) {
        deviceToggles->ForceSet(Toggle::VulkanUseStorageInputOutput16, false);
    }
    // By default try to use the StorageInputOutput16 capability.
    deviceToggles->Default(Toggle::VulkanUseStorageInputOutput16, true);

    // Inject fragment shaders in all vertex-only pipelines.
    // TODO(crbug.com/dawn/1698): relax this requirement where the Vulkan spec allows.
    // In particular, enable rasterizer discard if the depth-stencil stage is a no-op, and skip
    // insertion of the placeholder fragment shader.
    deviceToggles->Default(Toggle::UsePlaceholderFragmentInVertexOnlyPipeline, true);

    // By default try to skip injecting robustness checks on textures using VK_EXT_robustness2. But
    // disable that optimization when the feature is not available.
    if (!GetDeviceInfo().HasExt(DeviceExt::Robustness2) ||
        GetDeviceInfo().robustness2Features.robustImageAccess2 == VK_FALSE) {
        deviceToggles->ForceSet(Toggle::VulkanUseImageRobustAccess2, false);
    } else {
        deviceToggles->Default(Toggle::VulkanUseImageRobustAccess2, true);
    }

    // By default try to skip injecting robustness checks on buffers using VK_EXT_robustness2. But
    // disable that optimization when the feature is not available or if it conflicts with bindless
    // support (see comment in the detection of bindless support for more details).
    if (!GetDeviceInfo().HasExt(DeviceExt::Robustness2) ||
        GetDeviceInfo().robustness2Features.robustBufferAccess2 == VK_FALSE) {
        deviceToggles->ForceSet(Toggle::VulkanUseBufferRobustAccess2, false);
    } else if (GetDeviceInfo().HasExt(DeviceExt::DescriptorIndexing) &&
               !GetDeviceInfo().descriptorIndexingProperties.robustBufferAccessUpdateAfterBind) {
        // TODO(https://issues.chromium.org/435317394): Only disable the toggle if the bindless
        // extension is actually requested.
        deviceToggles->ForceSet(Toggle::VulkanUseBufferRobustAccess2, false);
    } else {
        deviceToggles->Default(Toggle::VulkanUseBufferRobustAccess2, true);
    }

    // Enable the polyfill versions of dot4I8Packed() and dot4U8Packed() when the SPIR-V capability
    // `DotProductInput4x8BitPackedKHR` is not supported.
    if (!GetDeviceInfo().HasExt(DeviceExt::ShaderIntegerDotProduct) ||
        GetDeviceInfo().shaderIntegerDotProductFeatures.shaderIntegerDotProduct == VK_FALSE) {
        deviceToggles->ForceSet(Toggle::PolyFillPacked4x8DotProduct, true);
    }

    // Enable the integer range analysis for shader robustness by default if the corresponding
    // platform feature is enabled.
    deviceToggles->Default(
        Toggle::EnableIntegerRangeAnalysisInRobustness,
        platform->IsFeatureEnabled(platform::Features::kWebGPUEnableRangeAnalysisForRobustness));

    // TODO(https://issues.chromium.org/498659375): Re-enable on Android ARM.
    if (GetDeviceInfo().HasExt(DeviceExt::Spirv14)) {
        deviceToggles->Default(
            Toggle::UseSpirv14,
            platform->IsFeatureEnabled(platform::Features::kWebGPUUseSpirv14) && !IsAndroidARM());
    } else {
        deviceToggles->ForceSet(Toggle::UseSpirv14, false);
    }

    // TODO(b/379673383): Disabled on Pixel10 devices.
    if (GetDeviceInfo().HasExt(DeviceExt::MaximalReconvergence) &&
        GetDeviceInfo().shaderMaximalReconvergenceFeatures.shaderMaximalReconvergence == VK_TRUE &&
        !IsAndroidImgTec()) {
        deviceToggles->Default(
            Toggle::UseSpirvReconvergenceMode,
            platform->IsFeatureEnabled(platform::Features::kWebGPUUseSpirvReconvergenceMode));
    } else if (GetDeviceInfo().HasExt(DeviceExt::SubgroupUniformControlFlow) &&
               GetDeviceInfo()
                       .shaderSubgroupUniformControlFlowFeatures.shaderSubgroupUniformControlFlow ==
                   VK_TRUE &&
               (mDeviceInfo.subgroupProperties.supportedStages & VK_SHADER_STAGE_COMPUTE_BIT) &&
               (mDeviceInfo.subgroupProperties.supportedStages & VK_SHADER_STAGE_FRAGMENT_BIT) &&
               !IsAndroidImgTec()) {
        deviceToggles->Default(
            Toggle::UseSpirvReconvergenceMode,
            platform->IsFeatureEnabled(platform::Features::kWebGPUUseSpirvReconvergenceMode));
    } else {
        deviceToggles->ForceSet(Toggle::UseSpirvReconvergenceMode, false);
    }

    // Vulkan waiting is already thread safe.
    deviceToggles->Default(Toggle::WaitIsThreadSafe, true);

    // Enable validation of generated SPIR-V by default.
    // Graphite and other native clients may turn this off.
    deviceToggles->Default(Toggle::EnableSpirvValidation, true);

    // Use ExtendedDynamicState by default if the corresponding extension is available.
    if (!GetDeviceInfo().HasExt(DeviceExt::ExtendedDynamicState) ||
        GetDeviceInfo().extendedDynamicStateFeatures.extendedDynamicState == VK_FALSE) {
        deviceToggles->ForceSet(Toggle::VulkanUseExtendedDynamicState, false);
    } else {
        deviceToggles->Default(Toggle::VulkanUseExtendedDynamicState, false);
    }
}

ResultOrError<Ref<DeviceBase>> PhysicalDevice::CreateDeviceImpl(
    AdapterBase* adapter,
    const UnpackedPtr<DeviceDescriptor>& descriptor,
    const TogglesState& deviceToggles,
    Ref<DeviceBase::DeviceLostEvent>&& lostEvent) {
    return Device::Create(adapter, descriptor, deviceToggles, std::move(lostEvent));
}

FeatureValidationResult PhysicalDevice::ValidateFeatureSupportedWithTogglesImpl(
    wgpu::FeatureName feature,
    const TogglesState& toggles) const {
    switch (feature) {
        // Subgroup matrices require the vulkan memory model to be used.
        case wgpu::FeatureName::ChromiumExperimentalSubgroupMatrix:
            if (!toggles.IsEnabled(Toggle::UseVulkanMemoryModel)) {
                return FeatureValidationResult(absl::StrFormat(
                    "Feature %s requires VulkanMemoryModel toggle on Vulkan.", feature));
            }
            break;

        // The function subgroupBroadcast(f16) fails for some edge cases on Intel Gen-9 devices.
        // See crbug.com/391680973. We disable subgroups on this device unless the user has
        // explicitly enabled the 'enable_subgroups_intel_gen9' toggle.
        case wgpu::FeatureName::Subgroups:
        case wgpu::FeatureName::SubgroupSizeControl:
            if (gpu_info::IsIntelGen9(GetVendorId(), GetDeviceId()) &&
                !toggles.IsEnabled(Toggle::EnableSubgroupsIntelGen9)) {
                return FeatureValidationResult(
                    absl::StrFormat("Intel Gen-9 devices require `enable_subgroups_intel_gen9`"
                                    " to enable %s.",
                                    feature));
            }
            break;

        case wgpu::FeatureName::ShaderF16:
            if (!toggles.IsEnabled(Toggle::DecomposeUniformBuffers) &&
                mDeviceInfo._16BitStorageFeatures.uniformAndStorageBuffer16BitAccess == VK_FALSE) {
                return FeatureValidationResult(
                    absl::StrFormat("uniformAndStorageBuffer16BitAccess is required to enable %s "
                                    "if `decompose_uniform_buffers` is not used",
                                    feature));
            }
            // TODO(crbug.com/42251215): Investigate f16 CTS test failures to enable on Nvidia.
            if (gpu_info::IsNvidia(mVendorId) &&
                !toggles.IsEnabled(Toggle::VulkanEnableF16OnNvidia)) {
                return FeatureValidationResult(
                    absl::StrFormat("Feature %s is not yet supported on Nvidia GPUs", feature));
            }
            break;

        case wgpu::FeatureName::MSAARenderToSingleSampled:
            // Must be using either Dynamic Rendering or CreateRenderPass2 for this feature to be
            // available.
            if (!toggles.IsEnabled(Toggle::VulkanUseDynamicRendering) &&
                !toggles.IsEnabled(Toggle::VulkanUseCreateRenderPass2)) {
                return FeatureValidationResult(
                    absl::StrFormat("Feature %s requires either the VulkanUseDynamicRendering or "
                                    "VulkanUseCreateRenderPass2 toggle on Vulkan",
                                    feature));
            }
            break;

        // HostMappedPointer is not supported on AMD (see: crbug.com/494566064)
        case wgpu::FeatureName::HostMappedPointer:
            if (gpu_info::IsAMD(GetVendorId())) {
                return FeatureValidationResult(
                    absl::StrFormat("Feature %s is not yet supported on AMD GPUs", feature));
            }
            break;

        default:
            break;
    }

    return {};
}

bool PhysicalDevice::IsAndroid() {
#if DAWN_PLATFORM_IS(ANDROID)
    return true;
#else
    return false;
#endif
}

// Android devices with Qualcomm GPUs have a myriad of known issues. (dawn:1549)
bool PhysicalDevice::IsAndroidQualcomm() const {
    return IsAndroid() && gpu_info::IsQualcommPCI(GetVendorId());
}

// Android devices with ARM GPUs have known issues. (dawn:1550)
bool PhysicalDevice::IsAndroidARM() const {
    return IsAndroid() && gpu_info::IsARM(GetVendorId());
}

bool PhysicalDevice::IsAndroidSamsung() const {
    return IsAndroid() && gpu_info::IsSamsung(GetVendorId());
}

bool PhysicalDevice::IsAndroidHuawei() const {
    return IsAndroid() && gpu_info::IsHuawei(GetVendorId());
}

bool PhysicalDevice::IsAndroidImgTec() const {
    return IsAndroid() && gpu_info::IsImgTec(GetVendorId());
}

bool PhysicalDevice::IsPixel10() const {
    // Pixel 10 is the only device seen with PowerVR D-Series DXT-48-1536 so far.
    return IsAndroidImgTec() && GetDeviceId() == 0x71061212;
}

bool PhysicalDevice::IsIntelMesa() const {
    if (mDeviceInfo.HasExt(DeviceExt::DriverProperties)) {
        return mDeviceInfo.driverProperties.driverID == VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA_KHR;
    }
    return false;
}

bool PhysicalDevice::IsAmdMesa() const {
    if (mDeviceInfo.HasExt(DeviceExt::DriverProperties)) {
        return mDeviceInfo.driverProperties.driverID == VK_DRIVER_ID_MESA_RADV_KHR;
    }
    return false;
}

bool PhysicalDevice::IsSwiftshader() const {
    return gpu_info::IsGoogleSwiftshader(GetVendorId(), GetDeviceId());
}

bool PhysicalDevice::IsWindows() {
#if DAWN_PLATFORM_IS(WINDOWS)
    return true;
#else
    return false;
#endif
}

bool PhysicalDevice::IsWindowsAMD() const {
    return IsWindows() && gpu_info::IsAMD(GetVendorId());
}

bool PhysicalDevice::MayBeArmProprietary() const {
    if (!gpu_info::IsARM(GetVendorId())) {
        return false;
    }

    return !mDeviceInfo.HasExt(DeviceExt::DriverProperties) ||
           mDeviceInfo.driverProperties.driverID == VK_DRIVER_ID_ARM_PROPRIETARY;
}

bool PhysicalDevice::MayBeQualcommProprietary() const {
    if (!gpu_info::IsQualcommPCI(GetVendorId())) {
        return false;
    }

    return !mDeviceInfo.HasExt(DeviceExt::DriverProperties) ||
           mDeviceInfo.driverProperties.driverID == VK_DRIVER_ID_QUALCOMM_PROPRIETARY;
}

bool PhysicalDevice::MayBeImaginationProprietary() const {
    if (!gpu_info::IsImgTec(GetVendorId())) {
        return false;
    }

    return !mDeviceInfo.HasExt(DeviceExt::DriverProperties) ||
           mDeviceInfo.driverProperties.driverID == VK_DRIVER_ID_IMAGINATION_PROPRIETARY;
}

std::optional<uint32_t> PhysicalDevice::FindDefaultComputeSubgroupSize() const {
    if (!mDeviceInfo.HasExt(DeviceExt::SubgroupSizeControl)) {
        return std::nullopt;
    }

    const VkPhysicalDeviceSubgroupSizeControlPropertiesEXT& ext =
        mDeviceInfo.subgroupSizeControlProperties;

    if (ext.minSubgroupSize == ext.maxSubgroupSize) {
        return std::nullopt;
    }

    // At the moment, only Intel devices support varying subgroup sizes and 16, which is the
    // next value after the minimum of 8, is the sweet spot according to [1]. Hence the
    // following heuristics, which may need to be adjusted in the future for other
    // architectures, or if a specific API is added to let client code select the size.
    //
    // [1] https://bugs.freedesktop.org/show_bug.cgi?id=108875
    uint32_t subgroupSize = ext.minSubgroupSize * 2;
    if (subgroupSize <= ext.maxSubgroupSize) {
        return subgroupSize;
    } else {
        return ext.minSubgroupSize;
    }
}

bool PhysicalDevice::CheckSemaphoreSupport(DeviceExt deviceExt,
                                           VkExternalSemaphoreHandleTypeFlagBits handleType) const {
    if (!mDeviceInfo.HasExt(deviceExt)) {
        return false;
    }

    constexpr VkFlags kRequiredSemaphoreFlags = VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR |
                                                VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR;

    VkPhysicalDeviceExternalSemaphoreInfoKHR semaphoreInfo;
    semaphoreInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR;
    semaphoreInfo.pNext = nullptr;

    VkExternalSemaphorePropertiesKHR semaphoreProperties;
    semaphoreProperties.sType = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR;
    semaphoreProperties.pNext = nullptr;

    semaphoreInfo.handleType = handleType;
    mVulkanInstance->GetFunctions().GetPhysicalDeviceExternalSemaphoreProperties(
        mVkPhysicalDevice, &semaphoreInfo, &semaphoreProperties);

    return IsSubset(kRequiredSemaphoreFlags, semaphoreProperties.externalSemaphoreFeatures);
}

std::optional<uint32_t> PhysicalDevice::GetDefaultComputeSubgroupSize() const {
    return mDefaultComputeSubgroupSize;
}

ResultOrError<PhysicalDeviceSurfaceCapabilities> PhysicalDevice::GetSurfaceCapabilities(
    InstanceBase* instance,
    const Surface* surface) const {
    // Gather the Vulkan surface capabilities.
    VulkanSurfaceInfo vkCaps;
    {
        const VulkanFunctions& fn = GetVulkanInstance()->GetFunctions();
        VkInstance vkInstance = GetVulkanInstance()->GetVkInstance();

        VkSurfaceKHR vkSurface;
        DAWN_TRY_ASSIGN(vkSurface, CreateVulkanSurface(instance, this, surface));
        DAWN_TRY_ASSIGN_WITH_CLEANUP(vkCaps, GatherSurfaceInfo(*this, vkSurface),
                                     { fn.DestroySurfaceKHR(vkInstance, vkSurface, nullptr); });

        fn.DestroySurfaceKHR(vkInstance, vkSurface, nullptr);
    }

    PhysicalDeviceSurfaceCapabilities capabilities;

    // Convert the known swapchain usages.
    capabilities.usages = wgpu::TextureUsage::None;
    if (vkCaps.capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) {
        capabilities.usages |= wgpu::TextureUsage::CopySrc;
    }
    if (vkCaps.capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) {
        capabilities.usages |= wgpu::TextureUsage::CopyDst;
    }
    if (vkCaps.capabilities.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
        capabilities.usages |= wgpu::TextureUsage::RenderAttachment;
    }
    if (vkCaps.capabilities.supportedUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) {
        capabilities.usages |= wgpu::TextureUsage::TextureBinding;
    }
    if (vkCaps.capabilities.supportedUsageFlags & VK_IMAGE_USAGE_STORAGE_BIT) {
        capabilities.usages |= wgpu::TextureUsage::StorageBinding;
    }

    // Convert known swapchain formats
    auto ToWGPUSwapChainFormat = [](VkFormat format) -> wgpu::TextureFormat {
        switch (format) {
            case VK_FORMAT_R8G8B8A8_UNORM:
                return wgpu::TextureFormat::RGBA8Unorm;
            case VK_FORMAT_R8G8B8A8_SRGB:
                return wgpu::TextureFormat::RGBA8UnormSrgb;
            case VK_FORMAT_B8G8R8A8_UNORM:
                return wgpu::TextureFormat::BGRA8Unorm;
            case VK_FORMAT_B8G8R8A8_SRGB:
                return wgpu::TextureFormat::BGRA8UnormSrgb;
            case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
                return wgpu::TextureFormat::RGB10A2Unorm;
            case VK_FORMAT_R16G16B16A16_SFLOAT:
                return wgpu::TextureFormat::RGBA16Float;
            default:
                return wgpu::TextureFormat::Undefined;
        }
    };
    for (VkSurfaceFormatKHR surfaceFormat : vkCaps.formats) {
        wgpu::TextureFormat format = ToWGPUSwapChainFormat(surfaceFormat.format);
        if (format != wgpu::TextureFormat::Undefined) {
            capabilities.formats.push_back(format);
        }
    }

    // Convert known present modes
    auto ToWGPUPresentMode = [](VkPresentModeKHR mode) -> std::optional<wgpu::PresentMode> {
        switch (mode) {
            case VK_PRESENT_MODE_FIFO_KHR:
                return wgpu::PresentMode::Fifo;
            case VK_PRESENT_MODE_FIFO_RELAXED_KHR:
                return wgpu::PresentMode::FifoRelaxed;
            case VK_PRESENT_MODE_MAILBOX_KHR:
                return wgpu::PresentMode::Mailbox;
            case VK_PRESENT_MODE_IMMEDIATE_KHR:
                return wgpu::PresentMode::Immediate;
            default:
                return {};
        }
    };
    for (VkPresentModeKHR vkMode : vkCaps.presentModes) {
        std::optional<wgpu::PresentMode> wgpuMode = ToWGPUPresentMode(vkMode);
        if (wgpuMode) {
            capabilities.presentModes.push_back(*wgpuMode);
        }
    }

    // Compute supported alpha modes
    struct AlphaModePairs {
        VkCompositeAlphaFlagBitsKHR vkBit;
        wgpu::CompositeAlphaMode webgpuEnum;
    };
    AlphaModePairs alphaModePairs[] = {
        {VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, wgpu::CompositeAlphaMode::Opaque},
        {VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR, wgpu::CompositeAlphaMode::Premultiplied},
        {VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR, wgpu::CompositeAlphaMode::Unpremultiplied},
        {VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR, wgpu::CompositeAlphaMode::Inherit},
    };

    for (auto mode : alphaModePairs) {
        if (vkCaps.capabilities.supportedCompositeAlpha & mode.vkBit) {
            capabilities.alphaModes.push_back(mode.webgpuEnum);
        }
    }

    return capabilities;
}

const AHBFunctions* PhysicalDevice::GetOrLoadAHBFunctions() {
#if DAWN_PLATFORM_IS(ANDROID)
    if (mAHBFunctions == nullptr) {
        mAHBFunctions = std::make_unique<AHBFunctions>();
    }
    return mAHBFunctions.get();
#else
    DAWN_UNREACHABLE();
#endif  // DAWN_PLATFORM_IS(ANDROID)
}

void PhysicalDevice::PopulateBackendProperties(UnpackedPtr<AdapterInfo>& info,
                                               const TogglesState& toggles) const {
    if (auto* memoryHeapProperties = info.Get<AdapterPropertiesMemoryHeaps>()) {
        // TODO(https://crbug.com/512465980): Use dawn::HeapArray and Enumerate to loop over it.
        size_t count = mDeviceInfo.memoryHeaps.size();
        auto* heapInfo = new MemoryHeapInfo[count];
        memoryHeapProperties->heapInfo = DAWN_UNSAFE_TODO({heapInfo, count});

        for (size_t i = 0; i < count; ++i) {
            DAWN_UNSAFE_TODO(heapInfo[i]).size = mDeviceInfo.memoryHeaps[i].size;
            DAWN_UNSAFE_TODO(heapInfo[i]).properties = {};
            if (mDeviceInfo.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) {
                DAWN_UNSAFE_TODO(heapInfo[i]).properties |= wgpu::HeapProperty::DeviceLocal;
            }
        }
        for (const auto& memoryType : mDeviceInfo.memoryTypes) {
            if (memoryType.propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
                DAWN_UNSAFE_TODO(heapInfo[memoryType.heapIndex]).properties |=
                    wgpu::HeapProperty::HostVisible;
            }
            if (memoryType.propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) {
                DAWN_UNSAFE_TODO(heapInfo[memoryType.heapIndex]).properties |=
                    wgpu::HeapProperty::HostCoherent;
            }
            if (memoryType.propertyFlags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) {
                DAWN_UNSAFE_TODO(heapInfo[memoryType.heapIndex]).properties |=
                    wgpu::HeapProperty::HostCached;
            } else {
                DAWN_UNSAFE_TODO(heapInfo[memoryType.heapIndex]).properties |=
                    wgpu::HeapProperty::HostUncached;
            }
        }
    }
    if (auto* vkProperties = info.Get<AdapterPropertiesVk>()) {
        vkProperties->driverVersion = mDeviceInfo.properties.driverVersion;
    }
    if (auto* drmProperties = info.Get<AdapterPropertiesDrm>()) {
        drmProperties->hasPrimary = mDeviceInfo.drmProperties.hasPrimary;
        drmProperties->hasRender = mDeviceInfo.drmProperties.hasRender;
        // TODO(crbug.com/42240462): Ideally these would be declared as int64_t in dawn.json to
        // match the Vulkan structs, but at the time of this comment that wasn't supported yet.
        drmProperties->primaryMajor = sign_dcast(mDeviceInfo.drmProperties.primaryMajor);
        drmProperties->primaryMinor = sign_dcast(mDeviceInfo.drmProperties.primaryMinor);
        drmProperties->renderMajor = sign_dcast(mDeviceInfo.drmProperties.renderMajor);
        drmProperties->renderMinor = sign_dcast(mDeviceInfo.drmProperties.renderMinor);
    }
    if (auto* subgroupMatrixConfigs = info.Get<AdapterPropertiesSubgroupMatrixConfigs>()) {
        std::vector<SubgroupMatrixConfig> supportedConfigs =
            EnumerateSubgroupMatrixConfigs(toggles);
        size_t count = supportedConfigs.size();
        // TODO(https://crbug.com/512465980): Use dawn::HeapArray
        SubgroupMatrixConfig* configs = new SubgroupMatrixConfig[count];
        subgroupMatrixConfigs->configs = DAWN_UNSAFE_TODO({configs, supportedConfigs.size()});
        // TODO(https://crbug.com/524406299): use dawn::Span::CopyFrom.
        DAWN_UNSAFE_TODO(
            memcpy(configs, supportedConfigs.data(), count * sizeof(SubgroupMatrixConfig)));
    }
}

void PhysicalDevice::PopulateBackendFormatCapabilities(
    wgpu::TextureFormat format,
    UnpackedPtr<DawnFormatCapabilities>& capabilities) const {
    if (auto* drmCapabilities = capabilities.Get<DawnDrmFormatCapabilities>()) {
        auto vk_format = ColorVulkanImageFormat(format);
        if (vk_format == VK_FORMAT_UNDEFINED) {
            drmCapabilities->properties = {};
        }
        auto drmFormatModifiers =
            GetFormatModifierProps(mVulkanInstance->GetFunctions(), mVkPhysicalDevice, vk_format);
        if (!drmFormatModifiers.empty()) {
            size_t count = drmFormatModifiers.size();
            // TODO(https://crbug.com/512465980): Use dawn::HeapArray
            auto* properties = new DawnDrmFormatProperties[count];
            drmCapabilities->properties = DAWN_UNSAFE_TODO({properties, count});

            for (size_t i = 0; i < count; i++) {
                DAWN_UNSAFE_TODO(properties[i]).modifier = drmFormatModifiers[i].drmFormatModifier;
                DAWN_UNSAFE_TODO(properties[i]).modifierPlaneCount =
                    drmFormatModifiers[i].drmFormatModifierPlaneCount;
            }
        }
    }
}

std::vector<SubgroupMatrixConfig> PhysicalDevice::EnumerateSubgroupMatrixConfigs(
    const TogglesState& toggles) const {
    size_t configCount = mDeviceInfo.cooperativeMatrixConfigs.size();
    std::vector<SubgroupMatrixConfig> subgroupMatrixConfigs;
    subgroupMatrixConfigs.reserve(configCount);

    auto SupportComponentType = [&](wgpu::SubgroupMatrixComponentType componentType) {
        if (componentType == wgpu::SubgroupMatrixComponentType::F16) {
            return IsFeatureSupportedWithToggles(wgpu::FeatureName::ShaderF16, toggles);
        }
        return true;
    };

    for (uint32_t i = 0; i < configCount; i++) {
        const VkCooperativeMatrixPropertiesKHR& p = mDeviceInfo.cooperativeMatrixConfigs[i];

        // Filter out configurations that WebGPU does not support.
        if (p.AType != p.BType || p.CType != p.ResultType || p.scope != VK_SCOPE_SUBGROUP_KHR ||
            p.saturatingAccumulation) {
            continue;
        }

        SubgroupMatrixConfig config;
        config.M = p.MSize;
        config.N = p.NSize;
        config.K = p.KSize;

        // Filter out the component types that WebGPU does not support.
        if (!VKComponentTypeToWGPUSubgroupMatrixComponentType(&config.componentType, p.AType)) {
            continue;
        }
        if (!SupportComponentType(config.componentType)) {
            continue;
        }
        if (!VKComponentTypeToWGPUSubgroupMatrixComponentType(&config.resultComponentType,
                                                              p.ResultType)) {
            continue;
        }
        if (!SupportComponentType(config.resultComponentType)) {
            continue;
        }

        subgroupMatrixConfigs.push_back(config);
    }

    return subgroupMatrixConfigs;
}

void PhysicalDevice::SetCoreNotSupported(std::unique_ptr<ErrorData> error) {
    DAWN_ASSERT(mSupportsCoreFeatureLevel);
    mSupportsCoreFeatureLevel = false;
    DAWN_ASSERT(error);
    mCoreError = std::move(error);
}

}  // namespace dawn::native::vulkan
