// Copyright 2023 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/Adapter.h"

#include <algorithm>
#include <memory>
#include <string>
#include <tuple>
#include <unordered_set>
#include <utility>
#include <vector>

#include "partition_alloc/pointers/raw_ptr.h"
#include "src/dawn/common/Math.h"
#include "src/dawn/common/StringViewUtils.h"
#include "src/dawn/native/ChainUtils.h"
#include "src/dawn/native/Device.h"
#include "src/dawn/native/Error.h"
#include "src/dawn/native/Instance.h"
#include "src/dawn/native/PhysicalDevice.h"
#include "src/utils/compiler.h"
#include "src/utils/heap_array.h"

namespace dawn::native {
namespace {
static constexpr DeviceDescriptor kDefaultDeviceDesc = {};
}  // anonymous namespace

AdapterBase::AdapterBase(InstanceBase* instance,
                         Ref<PhysicalDeviceBase> physicalDevice,
                         wgpu::FeatureLevel featureLevel,
                         const TogglesState& requiredAdapterToggles,
                         wgpu::PowerPreference powerPreference)
    : mInstance(instance),
      mPhysicalDevice(std::move(physicalDevice)),
      mFeatureLevel(featureLevel),
      mTogglesState(requiredAdapterToggles),
      mPowerPreference(powerPreference) {
    DAWN_CHECK(mPhysicalDevice->SupportsFeatureLevel(featureLevel));
    DAWN_CHECK(mTogglesState.GetStage() == ToggleStage::Adapter);
    // Cache the supported features of this adapter. Note that with device toggles overriding, a
    // device created by this adapter may support features not in this set and vice versa.
    mSupportedFeatures = mPhysicalDevice->GetSupportedFeatures(mTogglesState);
    // Cache the limits of this adapter. UpdateLimits should be called when the adapter's
    // limits-related status changes, e.g. SetUseTieredLimits.
    UpdateLimits();
}

AdapterBase::~AdapterBase() = default;

void AdapterBase::SetUseTieredLimits(bool useTieredLimits) {
    mUseTieredLimits = useTieredLimits;
    UpdateLimits();
}

PhysicalDeviceBase* AdapterBase::GetPhysicalDevice() {
    return mPhysicalDevice.Get();
}

const PhysicalDeviceBase* AdapterBase::GetPhysicalDevice() const {
    return mPhysicalDevice.Get();
}

InstanceBase* AdapterBase::GetInstance() const {
    return mInstance.Get();
}

InstanceBase* AdapterBase::APIGetInstance() const {
    InstanceBase* instance = mInstance.Get();
    DAWN_ASSERT(instance != nullptr);
    instance->APIAddRef();
    return instance;
}

void AdapterBase::UpdateLimits() {
    mLimits = mPhysicalDevice->GetLimits();

    // Apply the tiered limits if needed.
    if (mUseTieredLimits) {
        ApplyLimitTiers(&mLimits);
    }
}

const CombinedLimits& AdapterBase::GetLimits() const {
    return mLimits;
}

wgpu::Status AdapterBase::APIGetLimits(Limits* limits) const {
    if (mInstance->ConsumedError(
            ValidateAndFillLimits(limits, mSupportedFeatures, mLimits,
                                  mTogglesState.IsEnabled(Toggle::AllowExperimentalAPIs)))) {
        return wgpu::Status::Error;
    }
    return wgpu::Status::Success;
}

wgpu::Status AdapterBase::APIGetInfo(AdapterInfo* info) const {
    DAWN_CHECK(info != nullptr);

    UnpackedPtr<AdapterInfo> unpacked;
    if (mInstance->ConsumedError(ValidateGetInfo(info), &unpacked)) {
        return wgpu::Status::Error;
    }

    if (auto* powerPreferenceDesc = unpacked.Get<DawnAdapterPropertiesPowerPreference>()) {
        powerPreferenceDesc->powerPreference = mPowerPreference;
    }

    mPhysicalDevice->PopulateBackendProperties(unpacked, mTogglesState);

    auto AllocateStringView = [&](const std::string& in) -> StringView {
        Span<char> copy = HeapArrayFrom(in).MoveToSpan();
        return {copy.data(), copy.size()};
    };

    info->vendor = AllocateStringView(mPhysicalDevice->GetVendorName());
    info->architecture = AllocateStringView(mPhysicalDevice->GetArchitectureName());
    info->device = AllocateStringView(mPhysicalDevice->GetName());
    info->description = AllocateStringView(mPhysicalDevice->GetDriverDescription());
    info->backendType = mPhysicalDevice->GetBackendType();
    info->adapterType = mPhysicalDevice->GetAdapterType();
    info->vendorID = mPhysicalDevice->GetVendorId();
    info->deviceID = mPhysicalDevice->GetDeviceId();
    info->subgroupMinSize = mPhysicalDevice->GetSubgroupMinSize();
    info->subgroupMaxSize = mPhysicalDevice->GetSubgroupMaxSize();

    if (mPhysicalDevice->GetBackendType() == wgpu::BackendType::D3D12 &&
        mTogglesState.IsEnabled(Toggle::D3D12RelaxMinSubgroupSizeTo8)) {
        info->subgroupMinSize = std::min(info->subgroupMinSize, 8u);
    }

    DAWN_CHECK(info->subgroupMaxSize == 0 || IsPowerOfTwo(info->subgroupMaxSize));
    DAWN_CHECK(info->subgroupMinSize == 0 || IsPowerOfTwo(info->subgroupMinSize));

    return wgpu::Status::Success;
}

ResultOrValError<UnpackedPtr<AdapterInfo>> AdapterBase::ValidateGetInfo(AdapterInfo* info) const {
    UnpackedPtr<AdapterInfo> unpacked;
    DAWN_TRY_ASSIGN(unpacked, ValidateAndUnpack(info));
    if (!mTogglesState.IsEnabled(Toggle::AllowExperimentalAPIs)) {
        // Only the chained structs that are part of the stable ABI may be requested.
        DAWN_TRY_CONTEXT(unpacked.ValidateStable(),
                         "validating AdapterInfo chain with allow_experimental_apis disabled");
    }

    DAWN_INVALID_IF(
        unpacked.Has<AdapterPropertiesMemoryHeaps>() &&
            !mSupportedFeatures.IsEnabled(wgpu::FeatureName::AdapterPropertiesMemoryHeaps),
        "Feature AdapterPropertiesMemoryHeaps is not available.");
    DAWN_INVALID_IF(unpacked.Has<AdapterPropertiesD3D>() &&
                        !mSupportedFeatures.IsEnabled(wgpu::FeatureName::AdapterPropertiesD3D),
                    "Feature AdapterPropertiesD3D is not available.");
    DAWN_INVALID_IF(unpacked.Has<AdapterPropertiesVk>() &&
                        !mSupportedFeatures.IsEnabled(wgpu::FeatureName::AdapterPropertiesVk),
                    "Feature AdapterPropertiesVk is not available.");
    DAWN_INVALID_IF(unpacked.Has<vulkan::AdapterPropertiesVulkanUUIDs>() &&
                        !mSupportedFeatures.IsEnabled(wgpu::FeatureName::AdapterPropertiesVk),
                    "Feature AdapterPropertiesVk is not available.");
    DAWN_INVALID_IF(unpacked.Has<AdapterPropertiesDrm>() &&
                        !mSupportedFeatures.IsEnabled(wgpu::FeatureName::AdapterPropertiesDrm),
                    "Feature AdapterPropertiesDrm is not available.");
    DAWN_INVALID_IF(
        unpacked.Has<AdapterPropertiesSubgroupMatrixConfigs>() &&
            !mSupportedFeatures.IsEnabled(wgpu::FeatureName::ChromiumExperimentalSubgroupMatrix),
        "Feature ChromiumExperimentalSubgroupMatrix is not available.");

    return unpacked;
}

void APIAdapterInfoFreeMembers(WGPUAdapterInfo info) {
    DeleteAllocationFromHeapArray(info.vendor.data);
    DeleteAllocationFromHeapArray(info.architecture.data);
    DeleteAllocationFromHeapArray(info.device.data);
    DeleteAllocationFromHeapArray(info.description.data);
}

void APIAdapterPropertiesMemoryHeapsFreeMembers(
    WGPUAdapterPropertiesMemoryHeaps memoryHeapProperties) {
    DeleteAllocationFromHeapArray(memoryHeapProperties.heapInfo);
}

void APIDawnDrmFormatCapabilitiesFreeMembers(WGPUDawnDrmFormatCapabilities capabilities) {
    DeleteAllocationFromHeapArray(capabilities.properties);
}

void APIAdapterPropertiesSubgroupMatrixConfigsFreeMembers(
    WGPUAdapterPropertiesSubgroupMatrixConfigs subgroupMatrixConfigs) {
    DeleteAllocationFromHeapArray(subgroupMatrixConfigs.configs);
}

bool AdapterBase::APIHasFeature(wgpu::FeatureName feature) const {
    return mSupportedFeatures.IsEnabled(feature);
}

void AdapterBase::APIGetFeatures(wgpu::SupportedFeatures* features) const {
    this->APIGetFeatures(reinterpret_cast<SupportedFeatures*>(features));
}

void AdapterBase::APIGetFeatures(SupportedFeatures* features) const {
    mSupportedFeatures.ToSupportedFeatures(features);
}

void APISupportedFeaturesFreeMembers(WGPUSupportedFeatures supportedFeatures) {
    DeleteAllocationFromHeapArray(supportedFeatures.features);
}

// TODO(https://crbug.com/dawn/2465) Could potentially re-implement via AllowSpontaneous async mode.
DeviceBase* AdapterBase::APICreateDevice(const DeviceDescriptor* descriptor) {
    if (descriptor == nullptr) {
        descriptor = &kDefaultDeviceDesc;
    }

    auto [lostEvent, result] = CreateDevice(descriptor);
    mInstance->GetEventManager()->TrackEvent(lostEvent);
    Ref<DeviceBase> device;
    if (mInstance->ConsumedError(std::move(result), &device)) {
        return nullptr;
    }
    return ReturnToAPI(std::move(device));
}

TogglesState AdapterBase::CreateDeviceToggles(
    const DawnTogglesDescriptor* deviceTogglesDesc) const {
    TogglesState deviceToggles =
        TogglesState::CreateFromTogglesDescriptor(deviceTogglesDesc, ToggleStage::Device);
    deviceToggles.InheritFrom(mTogglesState);
    // Default toggles for all backend
    deviceToggles.Default(Toggle::LazyClearResourceOnFirstUse, true);
    deviceToggles.Default(Toggle::TimestampQuantization, true);
    if (mInstance->IsBackendValidationEnabled()) {
        deviceToggles.Default(Toggle::UseUserDefinedLabelsInBackend, true);
    }
    // Currently enable the blob cache hash validation by default to catch possible collapse.
    // TODO(crbug.com/429938352): Disable default hash validation to prevent performance cost when
    // no longer necessary.
    deviceToggles.Default(Toggle::BlobCacheHashValidation, true);

#if defined(DAWN_ENABLE_ASSERTS)
    deviceToggles.Default(Toggle::EnableTintIRValidationAsserts, true);
#endif

    // Backend-specific forced and default device toggles
    mPhysicalDevice->SetupBackendDeviceToggles(mInstance->GetPlatform(), &deviceToggles);
    return deviceToggles;
}

ResultOrUnknownError<Ref<DeviceBase>> AdapterBase::CreateDeviceInternal(
    const DeviceDescriptor* rawDescriptor,
    Ref<DeviceBase::DeviceLostEvent> lostEvent) {
    DAWN_CHECK(rawDescriptor != nullptr);

    // Create device toggles state from required toggles descriptor and inherited adapter toggles
    // state.
    UnpackedPtr<DeviceDescriptor> descriptor;
    DAWN_TRY_ASSIGN(descriptor, ValidateAndUnpack(rawDescriptor));
    if (!mTogglesState.IsEnabled(Toggle::AllowExperimentalAPIs)) {
        // Only the chained structs that are part of the stable ABI may be used. This also rejects
        // DawnTogglesDescriptor, so allow_experimental_apis cannot be turned back on here.
        DAWN_TRY_CONTEXT(descriptor.ValidateStable(),
                         "validating %s with allow_experimental_apis disabled", rawDescriptor);
    }
    auto* deviceTogglesDesc = descriptor.Get<DawnTogglesDescriptor>();

    // Create device toggles state.
    TogglesState deviceToggles = CreateDeviceToggles(deviceTogglesDesc);

    std::unordered_set<wgpu::FeatureName> requiredFeatureSet{descriptor->requiredFeatures.begin(),
                                                             descriptor->requiredFeatures.end()};

    // Validate all required features are supported by the adapter and suitable under device
    // toggles. Note that certain toggles in device toggles state may be overridden by user and
    // different from the adapter toggles state, and in this case a device may support features
    // that not supported by the adapter. We allow such toggles overriding for the convenience e.g.
    // creating a device for internal usage with AllowUnsafeAPIs enabled from an adapter that
    // disabled AllowUnsafeAPIs.
    for (wgpu::FeatureName requiredFeature : requiredFeatureSet) {
        FeatureValidationResult result =
            mPhysicalDevice->ValidateFeatureSupportedWithToggles(requiredFeature, deviceToggles);
        DAWN_INVALID_IF(!result.success, "Invalid feature required: %s",
                        result.errorMessage.c_str());
    }

    if (descriptor->requiredLimits != nullptr) {
        CombinedLimits requiredLimits;
        DAWN_TRY_CONTEXT(ValidateAndUnpackLimitsIn(
                             descriptor->requiredLimits, requiredFeatureSet, &requiredLimits,
                             deviceToggles.IsEnabled(Toggle::AllowExperimentalAPIs)),
                         "Validating and unpacking descriptor->requiredLimits");

        DAWN_TRY_CONTEXT(ValidateLimits(GetLimits(), requiredLimits), "validating required limits");
    }

    if (auto* allocatorDesc = descriptor.Get<DawnDeviceAllocatorControl>()) {
        DAWN_INVALID_IF(!requiredFeatureSet.contains(wgpu::FeatureName::DawnDeviceAllocatorControl),
                        "%s is not enabled.", wgpu::FeatureName::DawnDeviceAllocatorControl);

        DAWN_INVALID_IF(!IsPowerOfTwo(allocatorDesc->allocatorHeapBlockSize),
                        "allocator heap block size (%d) isn't a power of two.",
                        allocatorDesc->allocatorHeapBlockSize);
    }

    DAWN_INVALID_IF(mAdapterIsConsumed,
                    "adapter is \"consumed\": it has already been used to create a device");

    ResultOrError<Ref<DeviceBase>> result =
        mPhysicalDevice->CreateDevice(this, descriptor, deviceToggles, std::move(lostEvent));

    // The adapter should be consumed only upon successful device creation if the instance doesn't
    // allow multiple devices per adapter, or if the descriptor explicitly requests consumption.
    auto* consumeAdapterDesc = descriptor.Get<DawnConsumeAdapterDescriptor>();
    const bool consumeOnSuccess =
        !mInstance->HasFeature(wgpu::InstanceFeatureName::MultipleDevicesPerAdapter) ||
        (consumeAdapterDesc && consumeAdapterDesc->consumeAdapter);
    if (result.IsSuccess() && consumeOnSuccess) {
        mAdapterIsConsumed = true;
    }
    return result;
}

std::pair<Ref<DeviceBase::DeviceLostEvent>, ResultOrUnknownError<Ref<DeviceBase>>>
AdapterBase::CreateDevice(const DeviceDescriptor* descriptor) {
    DAWN_CHECK(descriptor != nullptr);

    Ref<DeviceBase::DeviceLostEvent> lostEvent = DeviceBase::DeviceLostEvent::Create(descriptor);
    auto result = CreateDeviceInternal(descriptor, lostEvent);

    // Catch any errors to directly complete the device lost event with the error message.
    if (result.IsError()) {
        std::unique_ptr<UnknownError> error = result.AcquireError();
        lostEvent->SetLost(mInstance->GetEventManager(), wgpu::DeviceLostReason::FailedCreation,
                           "Failed to create device:\n" + error->GetFormattedMessage());

        // When the device fails to initialize, we need to ensure that an external ref exists to
        // properly clean up resources, so we create one in this scope. We don't overwrite the
        // existing ref in the event though because we need it for cleanup in the event as well.
        APIRef<DeviceBase> device = lostEvent->mDevice;
        return {lostEvent, std::move(error)};
    }

    return {lostEvent, std::move(result)};
}

Future AdapterBase::APIRequestDevice(const DeviceDescriptor* descriptor,
                                     const WGPURequestDeviceCallbackInfo& callbackInfo) {
    struct RequestDeviceEvent final : public EventManager::TrackedEvent {
        WGPURequestDeviceCallback mCallback;
        raw_ptr<void> mUserdata1;
        raw_ptr<void> mUserdata2;

        WGPURequestDeviceStatus mStatus;
        Ref<DeviceBase> mDevice = nullptr;
        std::string mMessage;

        RequestDeviceEvent(const WGPURequestDeviceCallbackInfo& callbackInfo,
                           Ref<DeviceBase> device)
            : TrackedEvent(static_cast<wgpu::CallbackMode>(callbackInfo.mode),
                           TrackedEvent::Completed{}),
              mCallback(callbackInfo.callback),
              mUserdata1(callbackInfo.userdata1),
              mUserdata2(callbackInfo.userdata2),
              mStatus(WGPURequestDeviceStatus_Success),
              mDevice(std::move(device)) {}

        RequestDeviceEvent(const WGPURequestDeviceCallbackInfo& callbackInfo,
                           const std::string& message)
            : TrackedEvent(static_cast<wgpu::CallbackMode>(callbackInfo.mode),
                           TrackedEvent::Completed{}),
              mCallback(callbackInfo.callback),
              mUserdata1(callbackInfo.userdata1),
              mUserdata2(callbackInfo.userdata2),
              mStatus(WGPURequestDeviceStatus_Error),
              mMessage(message) {}

        ~RequestDeviceEvent() override { EnsureComplete(EventCompletionType::Shutdown); }

        void Complete(EventCompletionType completionType) override {
            if (completionType == EventCompletionType::Shutdown) {
                mStatus = WGPURequestDeviceStatus_CallbackCancelled;
                mDevice = nullptr;
                mMessage = "A valid external Instance reference no longer exists.";
            }
            mCallback(mStatus, ToAPI(ReturnToAPI(std::move(mDevice))), ToOutputStringView(mMessage),
                      mUserdata1.ExtractAsDangling(), mUserdata2.ExtractAsDangling());
        }
    };

    if (descriptor == nullptr) {
        descriptor = &kDefaultDeviceDesc;
    }

    FutureID futureID = kNullFutureID;
    auto [lostEvent, result] = CreateDevice(descriptor);
    if (result.IsSuccess()) {
        futureID = mInstance->GetEventManager()->TrackEvent(
            AcquireRef(new RequestDeviceEvent(callbackInfo, result.AcquireSuccess())));
    } else {
        futureID = mInstance->GetEventManager()->TrackEvent(AcquireRef(
            new RequestDeviceEvent(callbackInfo, result.AcquireError()->GetFormattedMessage())));
    }
    mInstance->GetEventManager()->TrackEvent(std::move(lostEvent));
    return {futureID};
}

wgpu::Status AdapterBase::APIGetFormatCapabilities(wgpu::TextureFormat format,
                                                   DawnFormatCapabilities* capabilities) {
    UnpackedPtr<DawnFormatCapabilities> unpacked;
    if (mInstance->ConsumedError(ValidateGetFormatCapabilities(capabilities), &unpacked)) {
        return wgpu::Status::Error;
    }

    mPhysicalDevice->PopulateBackendFormatCapabilities(format, unpacked);
    return wgpu::Status::Success;
}

ResultOrValError<UnpackedPtr<DawnFormatCapabilities>> AdapterBase::ValidateGetFormatCapabilities(
    DawnFormatCapabilities* capabilities) {
    DAWN_INVALID_IF(!mSupportedFeatures.IsEnabled(wgpu::FeatureName::DawnFormatCapabilities),
                    "Feature DawnFormatCapabilities is not available.");

    DAWN_CHECK(capabilities != nullptr);

    UnpackedPtr<DawnFormatCapabilities> unpacked;
    DAWN_TRY_ASSIGN(unpacked, ValidateAndUnpack(capabilities));

    DAWN_INVALID_IF(unpacked.Has<DawnDrmFormatCapabilities>() &&
                        !mSupportedFeatures.IsEnabled(wgpu::FeatureName::DawnDrmFormatCapabilities),
                    "Feature DawnDrmFormatCapabilities is not available.");

    return unpacked;
}

const TogglesState& AdapterBase::GetTogglesState() const {
    return mTogglesState;
}

std::vector<const char*> AdapterBase::GetTogglesUsed() const {
    return mTogglesState.GetEnabledToggleNames();
}

std::vector<const char*> AdapterBase::GetDeviceTogglesUsed(
    const DeviceDescriptor* rawDescriptor) const {
    const DawnTogglesDescriptor* deviceTogglesDesc = nullptr;
    if (rawDescriptor != nullptr) {
        deviceTogglesDesc = Unpack(rawDescriptor).Get<DawnTogglesDescriptor>();
    }
    return CreateDeviceToggles(deviceTogglesDesc).GetEnabledToggleNames();
}

wgpu::FeatureLevel AdapterBase::GetFeatureLevel() const {
    return mFeatureLevel;
}

const std::string& AdapterBase::GetName() const {
    return mPhysicalDevice->GetName();
}

std::vector<Ref<AdapterBase>> SortAdapters(std::vector<Ref<AdapterBase>> adapters,
                                           const UnpackedPtr<RequestAdapterOptions>& options) {
    int discreteRank = 1;
    int integratedRank = 1;
    switch (options->powerPreference) {
        case wgpu::PowerPreference::HighPerformance:
            // Prioritize discrete GPUs in this case.
            discreteRank = 0;
            break;
        case wgpu::PowerPreference::LowPower:
            // Prioritize integrated GPUs in this case.
            integratedRank = 0;
            break;
        case wgpu::PowerPreference::Undefined:
            // Deliberately leave both discrete and integrated ranks at 1 so that the original
            // OS-provided order of adapters is preserved.
            break;
    }

    const auto ComputeAdapterTypeRank = [&](const Ref<AdapterBase>& a) {
        switch (a->GetPhysicalDevice()->GetAdapterType()) {
            case wgpu::AdapterType::DiscreteGPU:
                return discreteRank;
            case wgpu::AdapterType::IntegratedGPU:
                return integratedRank;
            case wgpu::AdapterType::CPU:
                return 2;
            case wgpu::AdapterType::Unknown:
                return 3;
        }
        DAWN_UNREACHABLE();
    };

    const auto ComputeBackendTypeRank = [](const Ref<AdapterBase>& a) {
        switch (a->GetPhysicalDevice()->GetBackendType()) {
            // Sort backends generally in order of Core -> Compat -> Testing,
            // while preferring OS-specific backends like Metal/D3D.
            case wgpu::BackendType::Metal:
            case wgpu::BackendType::D3D12:
                return 0;
            case wgpu::BackendType::Vulkan:
                return 1;
            case wgpu::BackendType::D3D11:
                return 2;
            case wgpu::BackendType::OpenGLES:
                return 3;
            case wgpu::BackendType::OpenGL:
                return 4;
            case wgpu::BackendType::WebGPU:
                return 5;
            case wgpu::BackendType::Null:
                return 6;
            case wgpu::BackendType::Undefined:
                break;
        }
        DAWN_UNREACHABLE();
    };

    std::stable_sort(adapters.begin(), adapters.end(),
                     [&](const Ref<AdapterBase>& a, const Ref<AdapterBase>& b) -> bool {
                         return std::tuple(ComputeAdapterTypeRank(a), ComputeBackendTypeRank(a)) <
                                std::tuple(ComputeAdapterTypeRank(b), ComputeBackendTypeRank(b));
                     });

    return adapters;
}

}  // namespace dawn::native
