// Copyright 2019 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "dawn/native/metal/BackendMTL.h"

#include "dawn/common/CoreFoundationRef.h"
#include "dawn/common/GPUInfo.h"
#include "dawn/common/Log.h"
#include "dawn/common/NSRef.h"
#include "dawn/common/Platform.h"
#include "dawn/common/SystemUtils.h"
#include "dawn/native/Instance.h"
#include "dawn/native/MetalBackend.h"
#include "dawn/native/metal/BufferMTL.h"
#include "dawn/native/metal/DeviceMTL.h"

#if defined(DAWN_PLATFORM_MACOS)
#    import <IOKit/IOKitLib.h>
#    include "dawn/common/IOKitRef.h"
#endif

#include <vector>

namespace dawn::native::metal {

    namespace {

        struct PCIIDs {
            uint32_t vendorId;
            uint32_t deviceId;
        };

        struct Vendor {
            const char* trademark;
            uint32_t vendorId;
        };

#if defined(DAWN_PLATFORM_MACOS)
        const Vendor kVendors[] = {{"AMD", gpu_info::kVendorID_AMD},
                                   {"Radeon", gpu_info::kVendorID_AMD},
                                   {"Intel", gpu_info::kVendorID_Intel},
                                   {"Geforce", gpu_info::kVendorID_Nvidia},
                                   {"Quadro", gpu_info::kVendorID_Nvidia}};

        // Find vendor ID from MTLDevice name.
        MaybeError GetVendorIdFromVendors(id<MTLDevice> device, PCIIDs* ids) {
            uint32_t vendorId = 0;
            const char* deviceName = [device.name UTF8String];
            for (const auto& it : kVendors) {
                if (strstr(deviceName, it.trademark) != nullptr) {
                    vendorId = it.vendorId;
                    break;
                }
            }

            if (vendorId == 0) {
                return DAWN_INTERNAL_ERROR("Failed to find vendor id with the device");
            }

            // Set vendor id with 0
            *ids = PCIIDs{vendorId, 0};
            return {};
        }

        // Extracts an integer property from a registry entry.
        uint32_t GetEntryProperty(io_registry_entry_t entry, CFStringRef name) {
            uint32_t value = 0;

            // Recursively search registry entry and its parents for property name
            // The data should release with CFRelease
            CFRef<CFDataRef> data =
                AcquireCFRef(static_cast<CFDataRef>(IORegistryEntrySearchCFProperty(
                    entry, kIOServicePlane, name, kCFAllocatorDefault,
                    kIORegistryIterateRecursively | kIORegistryIterateParents)));

            if (data == nullptr) {
                return value;
            }

            // CFDataGetBytePtr() is guaranteed to return a read-only pointer
            value = *reinterpret_cast<const uint32_t*>(CFDataGetBytePtr(data.Get()));
            return value;
        }

        // Queries the IO Registry to find the PCI device and vendor IDs of the MTLDevice.
        // The registry entry correponding to [device registryID] doesn't contain the exact PCI ids
        // because it corresponds to a driver. However its parent entry corresponds to the device
        // itself and has uint32_t "device-id" and "registry-id" keys. For example on a dual-GPU
        // MacBook Pro 2017 the IORegistry explorer shows the following tree (simplified here):
        //
        //  - PCI0@0
        //  | - AppleACPIPCI
        //  | | - IGPU@2 (type IOPCIDevice)
        //  | | | - IntelAccelerator (type IOGraphicsAccelerator2)
        //  | | - PEG0@1
        //  | | | - IOPP
        //  | | | | - GFX0@0 (type IOPCIDevice)
        //  | | | | | - AMDRadeonX4000_AMDBaffinGraphicsAccelerator (type IOGraphicsAccelerator2)
        //
        // [device registryID] is the ID for one of the IOGraphicsAccelerator2 and we can see that
        // their parent always is an IOPCIDevice that has properties for the device and vendor IDs.
        MaybeError API_AVAILABLE(macos(10.13))
            GetDeviceIORegistryPCIInfo(id<MTLDevice> device, PCIIDs* ids) {
            // Get a matching dictionary for the IOGraphicsAccelerator2
            CFRef<CFMutableDictionaryRef> matchingDict =
                AcquireCFRef(IORegistryEntryIDMatching([device registryID]));
            if (matchingDict == nullptr) {
                return DAWN_INTERNAL_ERROR("Failed to create the matching dict for the device");
            }

            // IOServiceGetMatchingService will consume the reference on the matching dictionary,
            // so we don't need to release the dictionary.
            IORef<io_registry_entry_t> acceleratorEntry = AcquireIORef(
                IOServiceGetMatchingService(kIOMasterPortDefault, matchingDict.Detach()));
            if (acceleratorEntry == IO_OBJECT_NULL) {
                return DAWN_INTERNAL_ERROR(
                    "Failed to get the IO registry entry for the accelerator");
            }

            // Get the parent entry that will be the IOPCIDevice
            IORef<io_registry_entry_t> deviceEntry;
            if (IORegistryEntryGetParentEntry(acceleratorEntry.Get(), kIOServicePlane,
                                              deviceEntry.InitializeInto()) != kIOReturnSuccess) {
                return DAWN_INTERNAL_ERROR("Failed to get the IO registry entry for the device");
            }

            ASSERT(deviceEntry != IO_OBJECT_NULL);

            uint32_t vendorId = GetEntryProperty(deviceEntry.Get(), CFSTR("vendor-id"));
            uint32_t deviceId = GetEntryProperty(deviceEntry.Get(), CFSTR("device-id"));

            *ids = PCIIDs{vendorId, deviceId};

            return {};
        }

        MaybeError GetDevicePCIInfo(id<MTLDevice> device, PCIIDs* ids) {
            // [device registryID] is introduced on macOS 10.13+, otherwise workaround to get vendor
            // id by vendor name on old macOS
            if (@available(macos 10.13, *)) {
                return GetDeviceIORegistryPCIInfo(device, ids);
            } else {
                return GetVendorIdFromVendors(device, ids);
            }
        }

        bool IsMetalSupported() {
            // Metal was first introduced in macOS 10.11
            // WebGPU is targeted at macOS 10.12+
            // TODO(dawn:1181): Dawn native should allow non-conformant WebGPU on macOS 10.11
            return IsMacOSVersionAtLeast(10, 12);
        }
#elif defined(DAWN_PLATFORM_IOS)
        MaybeError GetDevicePCIInfo(id<MTLDevice> device, PCIIDs* ids) {
            DAWN_UNUSED(device);
            *ids = PCIIDs{0, 0};
            return {};
        }

        bool IsMetalSupported() {
            return true;
        }
#else
#    error "Unsupported Apple platform."
#endif

        DAWN_NOINLINE bool IsCounterSamplingBoundarySupport(id<MTLDevice> device)
            API_AVAILABLE(macos(11.0), ios(14.0)) {
            bool isBlitBoundarySupported =
                [device supportsCounterSampling:MTLCounterSamplingPointAtBlitBoundary];
            bool isDispatchBoundarySupported =
                [device supportsCounterSampling:MTLCounterSamplingPointAtDispatchBoundary];
            bool isDrawBoundarySupported =
                [device supportsCounterSampling:MTLCounterSamplingPointAtDrawBoundary];

            return isBlitBoundarySupported && isDispatchBoundarySupported &&
                   isDrawBoundarySupported;
        }

        // This method has seen hard-to-debug crashes. See crbug.com/dawn/1102.
        // For now, it is written defensively, with many potentially unnecessary guards until
        // we narrow down the cause of the problem.
        DAWN_NOINLINE bool IsGPUCounterSupported(id<MTLDevice> device,
                                                 MTLCommonCounterSet counterSetName,
                                                 std::vector<MTLCommonCounter> counterNames)
            API_AVAILABLE(macos(10.15), ios(14.0)) {
            NSPRef<id<MTLCounterSet>> counterSet = nil;
            if (![device respondsToSelector:@selector(counterSets)]) {
                dawn::ErrorLog() << "MTLDevice does not respond to selector: counterSets.";
                return false;
            }
            NSArray<id<MTLCounterSet>>* counterSets = device.counterSets;
            if (counterSets == nil) {
                // On some systems, [device counterSets] may be null and not an empty array.
                return false;
            }
            // MTLDevice’s counterSets property declares which counter sets it supports. Check
            // whether it's available on the device before requesting a counter set.
            // Note: Don't do for..in loop to avoid potentially crashy interaction with
            // NSFastEnumeration.
            for (NSUInteger i = 0; i < counterSets.count; ++i) {
                id<MTLCounterSet> set = [counterSets objectAtIndex:i];
                if ([set.name caseInsensitiveCompare:counterSetName] == NSOrderedSame) {
                    counterSet = set;
                    break;
                }
            }

            // The counter set is not supported.
            if (counterSet == nil) {
                return false;
            }

            if (![*counterSet respondsToSelector:@selector(counters)]) {
                dawn::ErrorLog() << "MTLCounterSet does not respond to selector: counters.";
                return false;
            }
            NSArray<id<MTLCounter>>* countersInSet = (*counterSet).counters;
            if (countersInSet == nil) {
                // On some systems, [MTLCounterSet counters] may be null and not an empty array.
                return false;
            }

            // A GPU might support a counter set, but only support a subset of the counters in that
            // set, check if the counter set supports all specific counters we need. Return false
            // if there is a counter unsupported.
            for (MTLCommonCounter counterName : counterNames) {
                bool found = false;
                // Note: Don't do for..in loop to avoid potentially crashy interaction with
                // NSFastEnumeration.
                for (NSUInteger i = 0; i < countersInSet.count; ++i) {
                    id<MTLCounter> counter = [countersInSet objectAtIndex:i];
                    if ([counter.name caseInsensitiveCompare:counterName] == NSOrderedSame) {
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    return false;
                }
            }

            if (@available(macOS 11.0, iOS 14.0, *)) {
                // Check whether it can read GPU counters at the specified command boundary. Apple
                // family GPUs do not support sampling between different Metal commands, because
                // they defer fragment processing until after the GPU processes all the primitives
                // in the render pass.
                if (!IsCounterSamplingBoundarySupport(device)) {
                    return false;
                }
            }

            return true;
        }

    }  // anonymous namespace

    // The Metal backend's Adapter.

    class Adapter : public AdapterBase {
      public:
        Adapter(InstanceBase* instance, id<MTLDevice> device)
            : AdapterBase(instance, wgpu::BackendType::Metal), mDevice(device) {
            mName = std::string([[*mDevice name] UTF8String]);

            PCIIDs ids;
            if (!instance->ConsumedError(GetDevicePCIInfo(device, &ids))) {
                mVendorId = ids.vendorId;
                mDeviceId = ids.deviceId;
            }

#if defined(DAWN_PLATFORM_IOS)
            mAdapterType = wgpu::AdapterType::IntegratedGPU;
            const char* systemName = "iOS ";
#elif defined(DAWN_PLATFORM_MACOS)
            if ([device isLowPower]) {
                mAdapterType = wgpu::AdapterType::IntegratedGPU;
            } else {
                mAdapterType = wgpu::AdapterType::DiscreteGPU;
            }
            const char* systemName = "macOS ";
#else
#    error "Unsupported Apple platform."
#endif

            NSString* osVersion = [[NSProcessInfo processInfo] operatingSystemVersionString];
            mDriverDescription =
                "Metal driver on " + std::string(systemName) + [osVersion UTF8String];
        }

        // AdapterBase Implementation
        bool SupportsExternalImages() const override {
            // Via dawn::native::metal::WrapIOSurface
            return true;
        }

      private:
        ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(
            const DeviceDescriptor* descriptor) override {
            return Device::Create(this, mDevice, descriptor);
        }

        MaybeError InitializeImpl() override {
            return {};
        }

        MaybeError InitializeSupportedFeaturesImpl() override {
            // Check compressed texture format with deprecated MTLFeatureSet way.
#if defined(DAWN_PLATFORM_MACOS)
            if ([*mDevice supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v1]) {
                mSupportedFeatures.EnableFeature(Feature::TextureCompressionBC);
            }
#endif
#if defined(DAWN_PLATFORM_IOS)
            if ([*mDevice supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily1_v1]) {
                mSupportedFeatures.EnableFeature(Feature::TextureCompressionETC2);
            }
            if ([*mDevice supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily2_v1]) {
                mSupportedFeatures.EnableFeature(Feature::TextureCompressionASTC);
            }
#endif

            // Check compressed texture format with MTLGPUFamily
            if (@available(macOS 10.15, iOS 13.0, *)) {
                if ([*mDevice supportsFamily:MTLGPUFamilyMac1]) {
                    mSupportedFeatures.EnableFeature(Feature::TextureCompressionBC);
                }
                if ([*mDevice supportsFamily:MTLGPUFamilyApple2]) {
                    mSupportedFeatures.EnableFeature(Feature::TextureCompressionETC2);
                }
                if ([*mDevice supportsFamily:MTLGPUFamilyApple3]) {
                    mSupportedFeatures.EnableFeature(Feature::TextureCompressionASTC);
                }
            }

            if (@available(macOS 10.15, iOS 14.0, *)) {
                if (IsGPUCounterSupported(
                        *mDevice, MTLCommonCounterSetStatistic,
                        {MTLCommonCounterVertexInvocations, MTLCommonCounterClipperInvocations,
                         MTLCommonCounterClipperPrimitivesOut, MTLCommonCounterFragmentInvocations,
                         MTLCommonCounterComputeKernelInvocations})) {
                    mSupportedFeatures.EnableFeature(Feature::PipelineStatisticsQuery);
                }

                if (IsGPUCounterSupported(*mDevice, MTLCommonCounterSetTimestamp,
                                          {MTLCommonCounterTimestamp})) {
                    bool enableTimestampQuery = true;

#if defined(DAWN_PLATFORM_MACOS)
                    // Disable timestamp query on < macOS 11.0 on AMD GPU because WriteTimestamp
                    // fails to call without any copy commands on MTLBlitCommandEncoder. This issue
                    // has been fixed on macOS 11.0. See crbug.com/dawn/545.
                    if (gpu_info::IsAMD(mVendorId) && !IsMacOSVersionAtLeast(11)) {
                        enableTimestampQuery = false;
                    }
#endif

                    if (enableTimestampQuery) {
                        mSupportedFeatures.EnableFeature(Feature::TimestampQuery);
                    }
                }
            }

            if (@available(macOS 10.11, iOS 11.0, *)) {
                mSupportedFeatures.EnableFeature(Feature::DepthClamping);
            }

            if (@available(macOS 10.11, iOS 9.0, *)) {
                mSupportedFeatures.EnableFeature(Feature::Depth32FloatStencil8);
            }

            // Uses newTextureWithDescriptor::iosurface::plane which is available
            // on ios 11.0+ and macOS 11.0+
            if (@available(macOS 10.11, iOS 11.0, *)) {
                mSupportedFeatures.EnableFeature(Feature::MultiPlanarFormats);
            }

#if defined(DAWN_PLATFORM_MACOS)
            // MTLPixelFormatDepth24Unorm_Stencil8 is only available on macOS 10.11+
            if ([*mDevice isDepth24Stencil8PixelFormatSupported]) {
                mSupportedFeatures.EnableFeature(Feature::Depth24UnormStencil8);
            }
#endif

            return {};
        }

        enum class MTLGPUFamily {
            Apple1,
            Apple2,
            Apple3,
            Apple4,
            Apple5,
            Apple6,
            Apple7,
            Mac1,
            Mac2,
        };

        ResultOrError<MTLGPUFamily> GetMTLGPUFamily() const {
            // https://developer.apple.com/documentation/metal/mtldevice/detecting_gpu_features_and_metal_software_versions?language=objc

            if (@available(macOS 10.15, iOS 10.13, *)) {
                if ([*mDevice supportsFamily:MTLGPUFamilyMac2]) {
                    return MTLGPUFamily::Mac2;
                }
                if ([*mDevice supportsFamily:MTLGPUFamilyMac1]) {
                    return MTLGPUFamily::Mac1;
                }
                if ([*mDevice supportsFamily:MTLGPUFamilyApple7]) {
                    return MTLGPUFamily::Apple7;
                }
                if ([*mDevice supportsFamily:MTLGPUFamilyApple6]) {
                    return MTLGPUFamily::Apple6;
                }
                if ([*mDevice supportsFamily:MTLGPUFamilyApple5]) {
                    return MTLGPUFamily::Apple5;
                }
                if ([*mDevice supportsFamily:MTLGPUFamilyApple4]) {
                    return MTLGPUFamily::Apple4;
                }
                if ([*mDevice supportsFamily:MTLGPUFamilyApple3]) {
                    return MTLGPUFamily::Apple3;
                }
                if ([*mDevice supportsFamily:MTLGPUFamilyApple2]) {
                    return MTLGPUFamily::Apple2;
                }
                if ([*mDevice supportsFamily:MTLGPUFamilyApple1]) {
                    return MTLGPUFamily::Apple1;
                }
            }

#if TARGET_OS_OSX
            if (@available(macOS 10.14, *)) {
                if ([*mDevice supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily2_v1]) {
                    return MTLGPUFamily::Mac2;
                }
            }
            if (@available(macOS 10.11, *)) {
                if ([*mDevice supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v1]) {
                    return MTLGPUFamily::Mac1;
                }
            }
#elif TARGET_OS_IOS
            if (@available(iOS 10.11, *)) {
                if ([*mDevice supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily4_v1]) {
                    return MTLGPUFamily::Apple4;
                }
            }
            if (@available(iOS 9.0, *)) {
                if ([*mDevice supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v1]) {
                    return MTLGPUFamily::Apple3;
                }
            }
            if (@available(iOS 8.0, *)) {
                if ([*mDevice supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily2_v1]) {
                    return MTLGPUFamily::Apple2;
                }
            }
            if (@available(iOS 8.0, *)) {
                if ([*mDevice supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily1_v1]) {
                    return MTLGPUFamily::Apple1;
                }
            }
#endif
            return DAWN_INTERNAL_ERROR("Unsupported Metal device");
        }

        MaybeError InitializeSupportedLimitsImpl(CombinedLimits* limits) override {
            struct MTLDeviceLimits {
                uint32_t maxVertexAttribsPerDescriptor;
                uint32_t maxBufferArgumentEntriesPerFunc;
                uint32_t maxTextureArgumentEntriesPerFunc;
                uint32_t maxSamplerStateArgumentEntriesPerFunc;
                uint32_t maxThreadsPerThreadgroup;
                uint32_t maxTotalThreadgroupMemory;
                uint32_t maxFragmentInputComponents;
                uint32_t max1DTextureSize;
                uint32_t max2DTextureSize;
                uint32_t max3DTextureSize;
                uint32_t maxTextureArrayLayers;
                uint32_t minBufferOffsetAlignment;
            };

            struct LimitsForFamily {
                uint32_t MTLDeviceLimits::*limit;
                ityp::array<MTLGPUFamily, uint32_t, 9> values;
            };

            // clang-format off
            // https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf
            //                                                               Apple                                                      Mac
            //                                                                   1,      2,      3,      4,      5,      6,      7,       1,      2
            constexpr LimitsForFamily kMTLLimits[12] = {
                {&MTLDeviceLimits::maxVertexAttribsPerDescriptor,         {    31u,    31u,    31u,    31u,    31u,    31u,    31u,     31u,    31u }},
                {&MTLDeviceLimits::maxBufferArgumentEntriesPerFunc,       {    31u,    31u,    31u,    31u,    31u,    31u,    31u,     31u,    31u }},
                {&MTLDeviceLimits::maxTextureArgumentEntriesPerFunc,      {    31u,    31u,    31u,    96u,    96u,   128u,   128u,    128u,   128u }},
                {&MTLDeviceLimits::maxSamplerStateArgumentEntriesPerFunc, {    16u,    16u,    16u,    16u,    16u,    16u,    16u,     16u,    16u }},
                {&MTLDeviceLimits::maxThreadsPerThreadgroup,              {   512u,   512u,   512u,  1024u,  1024u,  1024u,  1024u,   1024u,  1024u }},
                {&MTLDeviceLimits::maxTotalThreadgroupMemory,             { 16352u, 16352u, 16384u, 32768u, 32768u, 32768u, 32768u,  32768u, 32768u }},
                {&MTLDeviceLimits::maxFragmentInputComponents,            {    60u,    60u,    60u,   124u,   124u,   124u,   124u,    124u,   124u }},
                {&MTLDeviceLimits::max1DTextureSize,                      {  8192u,  8192u, 16384u, 16384u, 16384u, 16384u, 16384u,  16384u, 16384u }},
                {&MTLDeviceLimits::max2DTextureSize,                      {  8192u,  8192u, 16384u, 16384u, 16384u, 16384u, 16384u,  16384u, 16384u }},
                {&MTLDeviceLimits::max3DTextureSize,                      {  2048u,  2048u,  2048u,  2048u,  2048u,  2048u,  2048u,   2048u,  2048u }},
                {&MTLDeviceLimits::maxTextureArrayLayers,                 {  2048u,  2048u,  2048u,  2048u,  2048u,  2048u,  2048u,   2048u,  2048u }},
                {&MTLDeviceLimits::minBufferOffsetAlignment,              {     4u,     4u,     4u,     4u,     4u,     4u,     4u,    256u,   256u }},
            };
            // clang-format on

            MTLGPUFamily mtlGPUFamily;
            DAWN_TRY_ASSIGN(mtlGPUFamily, GetMTLGPUFamily());

            MTLDeviceLimits mtlLimits;
            for (const auto& limitsForFamily : kMTLLimits) {
                mtlLimits.*limitsForFamily.limit = limitsForFamily.values[mtlGPUFamily];
            }

            GetDefaultLimits(&limits->v1);

            limits->v1.maxTextureDimension1D = mtlLimits.max1DTextureSize;
            limits->v1.maxTextureDimension2D = mtlLimits.max2DTextureSize;
            limits->v1.maxTextureDimension3D = mtlLimits.max3DTextureSize;
            limits->v1.maxTextureArrayLayers = mtlLimits.maxTextureArrayLayers;

            uint32_t maxBuffersPerStage = mtlLimits.maxBufferArgumentEntriesPerFunc;
            maxBuffersPerStage -= 1;  // One slot is reserved to store buffer lengths.

            uint32_t baseMaxBuffersPerStage = limits->v1.maxStorageBuffersPerShaderStage +
                                              limits->v1.maxUniformBuffersPerShaderStage +
                                              limits->v1.maxVertexBuffers;

            ASSERT(maxBuffersPerStage >= baseMaxBuffersPerStage);
            {
                uint32_t additional = maxBuffersPerStage - baseMaxBuffersPerStage;
                limits->v1.maxStorageBuffersPerShaderStage += additional / 3;
                limits->v1.maxUniformBuffersPerShaderStage += additional / 3;
                limits->v1.maxVertexBuffers += (additional - 2 * (additional / 3));
            }

            uint32_t baseMaxTexturesPerStage = limits->v1.maxSampledTexturesPerShaderStage +
                                               limits->v1.maxStorageTexturesPerShaderStage;

            ASSERT(mtlLimits.maxTextureArgumentEntriesPerFunc >= baseMaxTexturesPerStage);
            {
                uint32_t additional =
                    mtlLimits.maxTextureArgumentEntriesPerFunc - baseMaxTexturesPerStage;
                limits->v1.maxSampledTexturesPerShaderStage += additional / 2;
                limits->v1.maxStorageTexturesPerShaderStage += (additional - additional / 2);
            }

            limits->v1.maxSamplersPerShaderStage = mtlLimits.maxSamplerStateArgumentEntriesPerFunc;

            // Metal limits are per-function, so the layout limits are the same as the stage
            // limits. Note: this should likely change if the implementation uses Metal argument
            // buffers. Non-dynamic buffers will probably be bound argument buffers, but dynamic
            // buffers may be set directly.
            //   Mac GPU families with tier 1 argument buffers support 64
            //   buffers, 128 textures, and 16 samplers. Mac GPU families
            //   with tier 2 argument buffers support 500000 buffers and
            //   textures, and 1024 unique samplers
            limits->v1.maxDynamicUniformBuffersPerPipelineLayout =
                limits->v1.maxUniformBuffersPerShaderStage;
            limits->v1.maxDynamicStorageBuffersPerPipelineLayout =
                limits->v1.maxStorageBuffersPerShaderStage;

            // The WebGPU limit is the limit across all vertex buffers, combined.
            limits->v1.maxVertexAttributes =
                limits->v1.maxVertexBuffers * mtlLimits.maxVertexAttribsPerDescriptor;

            limits->v1.maxInterStageShaderComponents = mtlLimits.maxFragmentInputComponents;

            limits->v1.maxComputeWorkgroupStorageSize = mtlLimits.maxTotalThreadgroupMemory;
            limits->v1.maxComputeInvocationsPerWorkgroup = mtlLimits.maxThreadsPerThreadgroup;
            limits->v1.maxComputeWorkgroupSizeX = mtlLimits.maxThreadsPerThreadgroup;
            limits->v1.maxComputeWorkgroupSizeY = mtlLimits.maxThreadsPerThreadgroup;
            limits->v1.maxComputeWorkgroupSizeZ = mtlLimits.maxThreadsPerThreadgroup;

            limits->v1.minUniformBufferOffsetAlignment = mtlLimits.minBufferOffsetAlignment;
            limits->v1.minStorageBufferOffsetAlignment = mtlLimits.minBufferOffsetAlignment;

            uint64_t maxBufferSize = Buffer::QueryMaxBufferLength(*mDevice);

            // Metal has no documented limit on the size of a binding. Use the maximum
            // buffer size.
            limits->v1.maxUniformBufferBindingSize = maxBufferSize;
            limits->v1.maxStorageBufferBindingSize = maxBufferSize;

            // TODO(crbug.com/dawn/685):
            // LIMITS NOT SET:
            // - maxBindGroups
            // - maxVertexBufferArrayStride

            return {};
        }

        NSPRef<id<MTLDevice>> mDevice;
    };

    // Implementation of the Metal backend's BackendConnection

    Backend::Backend(InstanceBase* instance)
        : BackendConnection(instance, wgpu::BackendType::Metal) {
        if (GetInstance()->IsBackendValidationEnabled()) {
            setenv("METAL_DEVICE_WRAPPER_TYPE", "1", 1);
        }
    }

    std::vector<Ref<AdapterBase>> Backend::DiscoverDefaultAdapters() {
        AdapterDiscoveryOptions options;
        auto result = DiscoverAdapters(&options);
        if (result.IsError()) {
            GetInstance()->ConsumedError(result.AcquireError());
            return {};
        }
        return result.AcquireSuccess();
    }

    ResultOrError<std::vector<Ref<AdapterBase>>> Backend::DiscoverAdapters(
        const AdapterDiscoveryOptionsBase* optionsBase) {
        ASSERT(optionsBase->backendType == WGPUBackendType_Metal);

        std::vector<Ref<AdapterBase>> adapters;
        BOOL supportedVersion = NO;
#if defined(DAWN_PLATFORM_MACOS)
        if (@available(macOS 10.11, *)) {
            supportedVersion = YES;

            NSRef<NSArray<id<MTLDevice>>> devices = AcquireNSRef(MTLCopyAllDevices());

            for (id<MTLDevice> device in devices.Get()) {
                Ref<Adapter> adapter = AcquireRef(new Adapter(GetInstance(), device));
                if (!GetInstance()->ConsumedError(adapter->Initialize())) {
                    adapters.push_back(std::move(adapter));
                }
            }
        }
#endif

#if defined(DAWN_PLATFORM_IOS)
        if (@available(iOS 8.0, *)) {
            supportedVersion = YES;
            // iOS only has a single device so MTLCopyAllDevices doesn't exist there.
            Ref<Adapter> adapter =
                AcquireRef(new Adapter(GetInstance(), MTLCreateSystemDefaultDevice()));
            if (!GetInstance()->ConsumedError(adapter->Initialize())) {
                adapters.push_back(std::move(adapter));
            }
        }
#endif
        if (!supportedVersion) {
            UNREACHABLE();
        }
        return adapters;
    }

    BackendConnection* Connect(InstanceBase* instance) {
        if (!IsMetalSupported()) {
            return nullptr;
        }
        return new Backend(instance);
    }

}  // namespace dawn::native::metal
