//! This file has been automatically generated by `objc2`'s `header-translator`.
//! DO NOT EDIT
use core::ffi::*;
use core::ptr::NonNull;
#[cfg(feature = "dispatch2")]
use dispatch2::*;
use objc2::__framework_prelude::*;
use objc2_foundation::*;
#[cfg(feature = "objc2-io-surface")]
use objc2_io_surface::*;

use crate::*;

/// [Apple's documentation](https://developer.apple.com/documentation/metal/mtliocompressionmethod?language=objc)
// NS_ENUM
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct MTLIOCompressionMethod(pub NSInteger);
impl MTLIOCompressionMethod {
    #[doc(alias = "MTLIOCompressionMethodZlib")]
    pub const Zlib: Self = Self(0);
    #[doc(alias = "MTLIOCompressionMethodLZFSE")]
    pub const LZFSE: Self = Self(1);
    #[doc(alias = "MTLIOCompressionMethodLZ4")]
    pub const LZ4: Self = Self(2);
    #[doc(alias = "MTLIOCompressionMethodLZMA")]
    pub const LZMA: Self = Self(3);
    #[doc(alias = "MTLIOCompressionMethodLZBitmap")]
    pub const LZBitmap: Self = Self(4);
}

unsafe impl Encode for MTLIOCompressionMethod {
    const ENCODING: Encoding = NSInteger::ENCODING;
}

unsafe impl RefEncode for MTLIOCompressionMethod {
    const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING);
}

/// Returns a reference to the preferred system default Metal device.
///
/// On Mac OS X systems that support automatic graphics switching, calling
/// this API to get a Metal device will cause the system to switch to the high power
/// GPU.  On other systems that support more than one GPU it will return the GPU that
/// is associated with the main display.
#[inline]
pub extern "C-unwind" fn MTLCreateSystemDefaultDevice(
) -> Option<Retained<ProtocolObject<dyn MTLDevice>>> {
    extern "C-unwind" {
        fn MTLCreateSystemDefaultDevice() -> *mut ProtocolObject<dyn MTLDevice>;
    }
    let ret = unsafe { MTLCreateSystemDefaultDevice() };
    unsafe { Retained::from_raw(ret) }
}

/// Type for device notifications
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtldevicenotificationname?language=objc)
// NS_TYPED_ENUM
pub type MTLDeviceNotificationName = NSString;

extern "C" {
    /// This notification is posted when a new Metal device is added to the system
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtldevicewasaddednotification?language=objc)
    pub static MTLDeviceWasAddedNotification: &'static MTLDeviceNotificationName;
}

extern "C" {
    /// This notification is posted when the user has requested that applications cease using a particular device.  Applications
    /// should assume that the device will be removed (terminated) imminently.  Additionally, the device will be removed from the internal
    /// device array prior to this notification being posted.  Applications should immediately begin the process of releasing all resources
    /// created on the given device, as well as any references to the device itself.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtldeviceremovalrequestednotification?language=objc)
    pub static MTLDeviceRemovalRequestedNotification: &'static MTLDeviceNotificationName;
}

extern "C" {
    /// This notification is posted if the device is removed while there are still outstanding references to it, due to either a surprise
    /// or forced disconnect by the user.  Applications must expect that any attempt to use the device after this point will fail.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtldevicewasremovednotification?language=objc)
    pub static MTLDeviceWasRemovedNotification: &'static MTLDeviceNotificationName;
}

/// Block signature for device notifications
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtldevicenotificationhandler?language=objc)
#[cfg(feature = "block2")]
pub type MTLDeviceNotificationHandler = *mut block2::DynBlock<
    dyn Fn(NonNull<ProtocolObject<dyn MTLDevice>>, NonNull<MTLDeviceNotificationName>),
>;

/// Returns an NSArray of the current set of available Metal devices and installs a notification handler
/// to be notified of any further changes (additions, removals, etc.).  The observer return value is retained by Metal and may be
/// passed to MTLRemoveDeviceObserver() if the application no longer wishes to receive notifications.
///
/// Note: The observer out parameter is returned with a +1 retain count in addition to the retain mentioned above.
///
/// # Safety
///
/// - `observer` must be a valid pointer.
/// - `handler` must be a valid pointer.
#[cfg(feature = "block2")]
#[inline]
pub unsafe extern "C-unwind" fn MTLCopyAllDevicesWithObserver(
    observer: NonNull<*mut ProtocolObject<dyn NSObjectProtocol>>,
    handler: MTLDeviceNotificationHandler,
) -> Retained<NSArray<ProtocolObject<dyn MTLDevice>>> {
    extern "C-unwind" {
        fn MTLCopyAllDevicesWithObserver(
            observer: NonNull<*mut ProtocolObject<dyn NSObjectProtocol>>,
            handler: MTLDeviceNotificationHandler,
        ) -> *mut NSArray<ProtocolObject<dyn MTLDevice>>;
    }
    let ret = unsafe { MTLCopyAllDevicesWithObserver(observer, handler) };
    unsafe { Retained::from_raw(ret) }
        .expect("function was marked as returning non-null, but actually returned NULL")
}

extern "C-unwind" {
    /// Removes a previously installed observer for device change notifications.
    ///
    /// # Safety
    ///
    /// `observer` should be of the correct type.
    pub fn MTLRemoveDeviceObserver(observer: &ProtocolObject<dyn NSObjectProtocol>);
}

/// [Apple's documentation](https://developer.apple.com/documentation/metal/mtlfeatureset?language=objc)
// NS_ENUM
#[deprecated = "Use MTLGPUFamily instead"]
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct MTLFeatureSet(pub NSUInteger);
impl MTLFeatureSet {
    #[doc(alias = "MTLFeatureSet_iOS_GPUFamily1_v1")]
    pub const iOS_GPUFamily1_v1: Self = Self(0);
    #[doc(alias = "MTLFeatureSet_iOS_GPUFamily2_v1")]
    pub const iOS_GPUFamily2_v1: Self = Self(1);
    #[doc(alias = "MTLFeatureSet_iOS_GPUFamily1_v2")]
    pub const iOS_GPUFamily1_v2: Self = Self(2);
    #[doc(alias = "MTLFeatureSet_iOS_GPUFamily2_v2")]
    pub const iOS_GPUFamily2_v2: Self = Self(3);
    #[doc(alias = "MTLFeatureSet_iOS_GPUFamily3_v1")]
    pub const iOS_GPUFamily3_v1: Self = Self(4);
    #[doc(alias = "MTLFeatureSet_iOS_GPUFamily1_v3")]
    pub const iOS_GPUFamily1_v3: Self = Self(5);
    #[doc(alias = "MTLFeatureSet_iOS_GPUFamily2_v3")]
    pub const iOS_GPUFamily2_v3: Self = Self(6);
    #[doc(alias = "MTLFeatureSet_iOS_GPUFamily3_v2")]
    pub const iOS_GPUFamily3_v2: Self = Self(7);
    #[doc(alias = "MTLFeatureSet_iOS_GPUFamily1_v4")]
    pub const iOS_GPUFamily1_v4: Self = Self(8);
    #[doc(alias = "MTLFeatureSet_iOS_GPUFamily2_v4")]
    pub const iOS_GPUFamily2_v4: Self = Self(9);
    #[doc(alias = "MTLFeatureSet_iOS_GPUFamily3_v3")]
    pub const iOS_GPUFamily3_v3: Self = Self(10);
    #[doc(alias = "MTLFeatureSet_iOS_GPUFamily4_v1")]
    pub const iOS_GPUFamily4_v1: Self = Self(11);
    #[doc(alias = "MTLFeatureSet_iOS_GPUFamily1_v5")]
    pub const iOS_GPUFamily1_v5: Self = Self(12);
    #[doc(alias = "MTLFeatureSet_iOS_GPUFamily2_v5")]
    pub const iOS_GPUFamily2_v5: Self = Self(13);
    #[doc(alias = "MTLFeatureSet_iOS_GPUFamily3_v4")]
    pub const iOS_GPUFamily3_v4: Self = Self(14);
    #[doc(alias = "MTLFeatureSet_iOS_GPUFamily4_v2")]
    pub const iOS_GPUFamily4_v2: Self = Self(15);
    #[doc(alias = "MTLFeatureSet_iOS_GPUFamily5_v1")]
    pub const iOS_GPUFamily5_v1: Self = Self(16);
    #[doc(alias = "MTLFeatureSet_macOS_GPUFamily1_v1")]
    pub const macOS_GPUFamily1_v1: Self = Self(10000);
    #[doc(alias = "MTLFeatureSet_OSX_GPUFamily1_v1")]
    pub const OSX_GPUFamily1_v1: Self = Self(MTLFeatureSet::macOS_GPUFamily1_v1.0);
    #[doc(alias = "MTLFeatureSet_macOS_GPUFamily1_v2")]
    pub const macOS_GPUFamily1_v2: Self = Self(10001);
    #[doc(alias = "MTLFeatureSet_OSX_GPUFamily1_v2")]
    pub const OSX_GPUFamily1_v2: Self = Self(MTLFeatureSet::macOS_GPUFamily1_v2.0);
    #[doc(alias = "MTLFeatureSet_macOS_ReadWriteTextureTier2")]
    pub const macOS_ReadWriteTextureTier2: Self = Self(10002);
    #[doc(alias = "MTLFeatureSet_OSX_ReadWriteTextureTier2")]
    pub const OSX_ReadWriteTextureTier2: Self = Self(MTLFeatureSet::macOS_ReadWriteTextureTier2.0);
    #[doc(alias = "MTLFeatureSet_macOS_GPUFamily1_v3")]
    pub const macOS_GPUFamily1_v3: Self = Self(10003);
    #[doc(alias = "MTLFeatureSet_macOS_GPUFamily1_v4")]
    pub const macOS_GPUFamily1_v4: Self = Self(10004);
    #[doc(alias = "MTLFeatureSet_macOS_GPUFamily2_v1")]
    pub const macOS_GPUFamily2_v1: Self = Self(10005);
    #[doc(alias = "MTLFeatureSet_tvOS_GPUFamily1_v1")]
    pub const tvOS_GPUFamily1_v1: Self = Self(30000);
    #[doc(alias = "MTLFeatureSet_TVOS_GPUFamily1_v1")]
    pub const TVOS_GPUFamily1_v1: Self = Self(MTLFeatureSet::tvOS_GPUFamily1_v1.0);
    #[doc(alias = "MTLFeatureSet_tvOS_GPUFamily1_v2")]
    pub const tvOS_GPUFamily1_v2: Self = Self(30001);
    #[doc(alias = "MTLFeatureSet_tvOS_GPUFamily1_v3")]
    pub const tvOS_GPUFamily1_v3: Self = Self(30002);
    #[doc(alias = "MTLFeatureSet_tvOS_GPUFamily2_v1")]
    pub const tvOS_GPUFamily2_v1: Self = Self(30003);
    #[doc(alias = "MTLFeatureSet_tvOS_GPUFamily1_v4")]
    pub const tvOS_GPUFamily1_v4: Self = Self(30004);
    #[doc(alias = "MTLFeatureSet_tvOS_GPUFamily2_v2")]
    pub const tvOS_GPUFamily2_v2: Self = Self(30005);
}

unsafe impl Encode for MTLFeatureSet {
    const ENCODING: Encoding = NSUInteger::ENCODING;
}

unsafe impl RefEncode for MTLFeatureSet {
    const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING);
}

/// [Apple's documentation](https://developer.apple.com/documentation/metal/mtlgpufamily?language=objc)
// NS_ENUM
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct MTLGPUFamily(pub NSInteger);
impl MTLGPUFamily {
    #[doc(alias = "MTLGPUFamilyApple1")]
    pub const Apple1: Self = Self(1001);
    #[doc(alias = "MTLGPUFamilyApple2")]
    pub const Apple2: Self = Self(1002);
    #[doc(alias = "MTLGPUFamilyApple3")]
    pub const Apple3: Self = Self(1003);
    #[doc(alias = "MTLGPUFamilyApple4")]
    pub const Apple4: Self = Self(1004);
    #[doc(alias = "MTLGPUFamilyApple5")]
    pub const Apple5: Self = Self(1005);
    #[doc(alias = "MTLGPUFamilyApple6")]
    pub const Apple6: Self = Self(1006);
    #[doc(alias = "MTLGPUFamilyApple7")]
    pub const Apple7: Self = Self(1007);
    #[doc(alias = "MTLGPUFamilyApple8")]
    pub const Apple8: Self = Self(1008);
    #[doc(alias = "MTLGPUFamilyApple9")]
    pub const Apple9: Self = Self(1009);
    #[doc(alias = "MTLGPUFamilyApple10")]
    pub const Apple10: Self = Self(1010);
    #[doc(alias = "MTLGPUFamilyMac1")]
    #[deprecated]
    pub const Mac1: Self = Self(2001);
    #[doc(alias = "MTLGPUFamilyMac2")]
    pub const Mac2: Self = Self(2002);
    #[doc(alias = "MTLGPUFamilyCommon1")]
    pub const Common1: Self = Self(3001);
    #[doc(alias = "MTLGPUFamilyCommon2")]
    pub const Common2: Self = Self(3002);
    #[doc(alias = "MTLGPUFamilyCommon3")]
    pub const Common3: Self = Self(3003);
    #[doc(alias = "MTLGPUFamilyMacCatalyst1")]
    #[deprecated]
    pub const MacCatalyst1: Self = Self(4001);
    #[doc(alias = "MTLGPUFamilyMacCatalyst2")]
    #[deprecated]
    pub const MacCatalyst2: Self = Self(4002);
    #[doc(alias = "MTLGPUFamilyMetal3")]
    pub const Metal3: Self = Self(5001);
    #[doc(alias = "MTLGPUFamilyMetal4")]
    pub const Metal4: Self = Self(5002);
}

unsafe impl Encode for MTLGPUFamily {
    const ENCODING: Encoding = NSInteger::ENCODING;
}

unsafe impl RefEncode for MTLGPUFamily {
    const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING);
}

/// Specifies the location of the GPU on macOS
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtldevicelocation?language=objc)
// NS_ENUM
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct MTLDeviceLocation(pub NSUInteger);
impl MTLDeviceLocation {
    #[doc(alias = "MTLDeviceLocationBuiltIn")]
    pub const BuiltIn: Self = Self(0);
    #[doc(alias = "MTLDeviceLocationSlot")]
    pub const Slot: Self = Self(1);
    #[doc(alias = "MTLDeviceLocationExternal")]
    pub const External: Self = Self(2);
    #[doc(alias = "MTLDeviceLocationUnspecified")]
    pub const Unspecified: Self = Self(NSUIntegerMax as _);
}

unsafe impl Encode for MTLDeviceLocation {
    const ENCODING: Encoding = NSUInteger::ENCODING;
}

unsafe impl RefEncode for MTLDeviceLocation {
    const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING);
}

/// Controls the creation of the pipeline
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtlpipelineoption?language=objc)
// NS_OPTIONS
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct MTLPipelineOption(pub NSUInteger);
bitflags::bitflags! {
    impl MTLPipelineOption: NSUInteger {
        #[doc(alias = "MTLPipelineOptionNone")]
        const None = 0;
        #[doc(alias = "MTLPipelineOptionArgumentInfo")]
#[deprecated]
        const ArgumentInfo = 1<<0;
        #[doc(alias = "MTLPipelineOptionBindingInfo")]
        const BindingInfo = 1<<0;
        #[doc(alias = "MTLPipelineOptionBufferTypeInfo")]
        const BufferTypeInfo = 1<<1;
        #[doc(alias = "MTLPipelineOptionFailOnBinaryArchiveMiss")]
        const FailOnBinaryArchiveMiss = 1<<2;
    }
}

unsafe impl Encode for MTLPipelineOption {
    const ENCODING: Encoding = NSUInteger::ENCODING;
}

unsafe impl RefEncode for MTLPipelineOption {
    const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING);
}

/// MTLReadWriteTextureTier determines support level for read-write texture formats.
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtlreadwritetexturetier?language=objc)
// NS_ENUM
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct MTLReadWriteTextureTier(pub NSUInteger);
impl MTLReadWriteTextureTier {
    #[doc(alias = "MTLReadWriteTextureTierNone")]
    pub const TierNone: Self = Self(0);
    #[doc(alias = "MTLReadWriteTextureTier1")]
    pub const Tier1: Self = Self(1);
    #[doc(alias = "MTLReadWriteTextureTier2")]
    pub const Tier2: Self = Self(2);
}

unsafe impl Encode for MTLReadWriteTextureTier {
    const ENCODING: Encoding = NSUInteger::ENCODING;
}

unsafe impl RefEncode for MTLReadWriteTextureTier {
    const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING);
}

/// MTLArgumentBuffersTier determines support level for argument buffers.
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtlargumentbufferstier?language=objc)
// NS_ENUM
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct MTLArgumentBuffersTier(pub NSUInteger);
impl MTLArgumentBuffersTier {
    #[doc(alias = "MTLArgumentBuffersTier1")]
    pub const Tier1: Self = Self(0);
    #[doc(alias = "MTLArgumentBuffersTier2")]
    pub const Tier2: Self = Self(1);
}

unsafe impl Encode for MTLArgumentBuffersTier {
    const ENCODING: Encoding = NSUInteger::ENCODING;
}

unsafe impl RefEncode for MTLArgumentBuffersTier {
    const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING);
}

/// MTLSparseTextureRegionAlignmentMode determines type of alignment used when converting from pixel region to tile region.
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtlsparsetextureregionalignmentmode?language=objc)
// NS_ENUM
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct MTLSparseTextureRegionAlignmentMode(pub NSUInteger);
impl MTLSparseTextureRegionAlignmentMode {
    #[doc(alias = "MTLSparseTextureRegionAlignmentModeOutward")]
    pub const Outward: Self = Self(0);
    #[doc(alias = "MTLSparseTextureRegionAlignmentModeInward")]
    pub const Inward: Self = Self(1);
}

unsafe impl Encode for MTLSparseTextureRegionAlignmentMode {
    const ENCODING: Encoding = NSUInteger::ENCODING;
}

unsafe impl RefEncode for MTLSparseTextureRegionAlignmentMode {
    const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING);
}

/// Describes the memory requirements for an acceleration structure
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtlaccelerationstructuresizes?language=objc)
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct MTLAccelerationStructureSizes {
    /// The required size, in bytes, of the built acceleration structure
    pub accelerationStructureSize: NSUInteger,
    /// The required size, in bytes, of the scratch buffer used to build the acceleration structure
    pub buildScratchBufferSize: NSUInteger,
    /// The required size, in bytes, of the scratch buffer used to refit the acceleration structure
    pub refitScratchBufferSize: NSUInteger,
}

unsafe impl Encode for MTLAccelerationStructureSizes {
    const ENCODING: Encoding = Encoding::Struct(
        "?",
        &[
            <NSUInteger>::ENCODING,
            <NSUInteger>::ENCODING,
            <NSUInteger>::ENCODING,
        ],
    );
}

unsafe impl RefEncode for MTLAccelerationStructureSizes {
    const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING);
}

/// MTLCounterSamplingPoint determines type of sampling points that are supported on given device.
///
///
/// Counter sampling points at render, compute, and blit command encoder stage boundary are supported.
///
///
/// Counter sampling at draw boundary is supported, render encoder method sampleCountersInBuffer can be used for sampling.
///
///
/// Counter sampling at compute dispatch boundary is supported, compute encoder method sampleCountersInBuffer can be used for sampling.
///
///
/// Counter sampling at tile shader dispatch boundary is supported.
///
///
/// Counter sampling at blit boundary is supported, blit encoder method sampleCountersInBuffer can be used for sampling.
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtlcountersamplingpoint?language=objc)
// NS_ENUM
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct MTLCounterSamplingPoint(pub NSUInteger);
impl MTLCounterSamplingPoint {
    #[doc(alias = "MTLCounterSamplingPointAtStageBoundary")]
    pub const AtStageBoundary: Self = Self(0);
    #[doc(alias = "MTLCounterSamplingPointAtDrawBoundary")]
    pub const AtDrawBoundary: Self = Self(1);
    #[doc(alias = "MTLCounterSamplingPointAtDispatchBoundary")]
    pub const AtDispatchBoundary: Self = Self(2);
    #[doc(alias = "MTLCounterSamplingPointAtTileDispatchBoundary")]
    pub const AtTileDispatchBoundary: Self = Self(3);
    #[doc(alias = "MTLCounterSamplingPointAtBlitBoundary")]
    pub const AtBlitBoundary: Self = Self(4);
}

unsafe impl Encode for MTLCounterSamplingPoint {
    const ENCODING: Encoding = NSUInteger::ENCODING;
}

unsafe impl RefEncode for MTLCounterSamplingPoint {
    const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING);
}

/// Represent a memory size and alignment in bytes.
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtlsizeandalign?language=objc)
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct MTLSizeAndAlign {
    pub size: NSUInteger,
    pub align: NSUInteger,
}

unsafe impl Encode for MTLSizeAndAlign {
    const ENCODING: Encoding =
        Encoding::Struct("?", &[<NSUInteger>::ENCODING, <NSUInteger>::ENCODING]);
}

unsafe impl RefEncode for MTLSizeAndAlign {
    const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING);
}

extern_class!(
    /// Represents a member of an argument buffer
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtlargumentdescriptor?language=objc)
    #[unsafe(super(NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct MTLArgumentDescriptor;
);

extern_conformance!(
    unsafe impl NSCopying for MTLArgumentDescriptor {}
);

unsafe impl CopyingHelper for MTLArgumentDescriptor {
    type Result = Self;
}

extern_conformance!(
    unsafe impl NSObjectProtocol for MTLArgumentDescriptor {}
);

impl MTLArgumentDescriptor {
    extern_methods!(
        /// Create an autoreleased default argument descriptor
        #[unsafe(method(argumentDescriptor))]
        #[unsafe(method_family = none)]
        pub fn argumentDescriptor() -> Retained<MTLArgumentDescriptor>;

        #[cfg(feature = "MTLDataType")]
        /// For constants, the data type. Otherwise, MTLDataTypeTexture, MTLDataTypeSampler, or
        /// MTLDataTypePointer.
        #[unsafe(method(dataType))]
        #[unsafe(method_family = none)]
        pub fn dataType(&self) -> MTLDataType;

        #[cfg(feature = "MTLDataType")]
        /// Setter for [`dataType`][Self::dataType].
        #[unsafe(method(setDataType:))]
        #[unsafe(method_family = none)]
        pub fn setDataType(&self, data_type: MTLDataType);

        /// The binding point index of the argument
        #[unsafe(method(index))]
        #[unsafe(method_family = none)]
        pub fn index(&self) -> NSUInteger;

        /// Setter for [`index`][Self::index].
        #[unsafe(method(setIndex:))]
        #[unsafe(method_family = none)]
        pub fn setIndex(&self, index: NSUInteger);

        /// The length of an array of constants, textures, or samplers, or 0 for non-array arguments
        #[unsafe(method(arrayLength))]
        #[unsafe(method_family = none)]
        pub fn arrayLength(&self) -> NSUInteger;

        /// Setter for [`arrayLength`][Self::arrayLength].
        #[unsafe(method(setArrayLength:))]
        #[unsafe(method_family = none)]
        pub fn setArrayLength(&self, array_length: NSUInteger);

        #[cfg(feature = "MTLArgument")]
        /// Access flags for the argument
        #[unsafe(method(access))]
        #[unsafe(method_family = none)]
        pub fn access(&self) -> MTLBindingAccess;

        #[cfg(feature = "MTLArgument")]
        /// Setter for [`access`][Self::access].
        #[unsafe(method(setAccess:))]
        #[unsafe(method_family = none)]
        pub fn setAccess(&self, access: MTLBindingAccess);

        #[cfg(feature = "MTLTexture")]
        /// For texture arguments, the texture type
        #[unsafe(method(textureType))]
        #[unsafe(method_family = none)]
        pub fn textureType(&self) -> MTLTextureType;

        #[cfg(feature = "MTLTexture")]
        /// Setter for [`textureType`][Self::textureType].
        #[unsafe(method(setTextureType:))]
        #[unsafe(method_family = none)]
        pub fn setTextureType(&self, texture_type: MTLTextureType);

        /// if set forces the constant block to be aligned to the given alignment
        ///
        /// Should only be set on the first constant of the block and is only valid if a corresponding
        /// explicit "alignas" is applied to the constant in the metal shader language.
        #[unsafe(method(constantBlockAlignment))]
        #[unsafe(method_family = none)]
        pub fn constantBlockAlignment(&self) -> NSUInteger;

        /// Setter for [`constantBlockAlignment`][Self::constantBlockAlignment].
        #[unsafe(method(setConstantBlockAlignment:))]
        #[unsafe(method_family = none)]
        pub fn setConstantBlockAlignment(&self, constant_block_alignment: NSUInteger);
    );
}

/// Methods declared on superclass `NSObject`.
impl MTLArgumentDescriptor {
    extern_methods!(
        #[unsafe(method(init))]
        #[unsafe(method_family = init)]
        pub fn init(this: Allocated<Self>) -> Retained<Self>;

        #[unsafe(method(new))]
        #[unsafe(method_family = new)]
        pub fn new() -> Retained<Self>;
    );
}

impl DefaultRetained for MTLArgumentDescriptor {
    #[inline]
    fn default_retained() -> Retained<Self> {
        Self::new()
    }
}

extern_class!(
    /// Contains information about the device's architecture
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtlarchitecture?language=objc)
    #[unsafe(super(NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct MTLArchitecture;
);

extern_conformance!(
    unsafe impl NSCopying for MTLArchitecture {}
);

unsafe impl CopyingHelper for MTLArchitecture {
    type Result = Self;
}

extern_conformance!(
    unsafe impl NSObjectProtocol for MTLArchitecture {}
);

impl MTLArchitecture {
    extern_methods!(
        /// The device's architecture name.
        #[unsafe(method(name))]
        #[unsafe(method_family = none)]
        pub fn name(&self) -> Retained<NSString>;
    );
}

/// Methods declared on superclass `NSObject`.
impl MTLArchitecture {
    extern_methods!(
        #[unsafe(method(init))]
        #[unsafe(method_family = init)]
        pub fn init(this: Allocated<Self>) -> Retained<Self>;

        #[unsafe(method(new))]
        #[unsafe(method_family = new)]
        pub fn new() -> Retained<Self>;
    );
}

impl DefaultRetained for MTLArchitecture {
    #[inline]
    fn default_retained() -> Retained<Self> {
        Self::new()
    }
}

/// [Apple's documentation](https://developer.apple.com/documentation/metal/mtltimestamp?language=objc)
pub type MTLTimestamp = u64;

extern_protocol!(
    /// MTLDevice represents a processor capable of data parallel computations
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtldevice?language=objc)
    pub unsafe trait MTLDevice: NSObjectProtocol + Send + Sync {
        /// The full name of the vendor device.
        #[unsafe(method(name))]
        #[unsafe(method_family = none)]
        fn name(&self) -> Retained<NSString>;

        /// Returns the IORegistry ID for the Metal device
        ///
        /// The registryID value for a Metal device is global to all tasks, and may be used
        /// to identify the GPU across task boundaries.
        #[unsafe(method(registryID))]
        #[unsafe(method_family = none)]
        fn registryID(&self) -> u64;

        /// Returns the device's architecture information.
        #[unsafe(method(architecture))]
        #[unsafe(method_family = none)]
        fn architecture(&self) -> Retained<MTLArchitecture>;

        #[cfg(feature = "MTLTypes")]
        /// The maximum number of threads along each dimension.
        #[unsafe(method(maxThreadsPerThreadgroup))]
        #[unsafe(method_family = none)]
        fn maxThreadsPerThreadgroup(&self) -> MTLSize;

        /// On systems that support automatic graphics switching, this will return YES for the the low power device.
        #[unsafe(method(isLowPower))]
        #[unsafe(method_family = none)]
        fn isLowPower(&self) -> bool;

        /// On systems that include more that one GPU, this will return YES for any device that does not support any displays.  Only available on Mac OS X.
        #[unsafe(method(isHeadless))]
        #[unsafe(method_family = none)]
        fn isHeadless(&self) -> bool;

        /// If this GPU is removable, this property will return YES.
        ///
        /// If a GPU is is removed without warning, APIs may fail even with good input, even before a notification can get posted informing
        /// the application that the device has been removed.
        #[unsafe(method(isRemovable))]
        #[unsafe(method_family = none)]
        fn isRemovable(&self) -> bool;

        /// Returns YES if this GPU shares its memory with the rest of the machine (CPU, etc.)
        ///
        /// Some GPU architectures do not have dedicated local memory and instead only use the same memory shared with the rest
        /// of the machine.  This property will return YES for GPUs that fall into that category.
        #[unsafe(method(hasUnifiedMemory))]
        #[unsafe(method_family = none)]
        fn hasUnifiedMemory(&self) -> bool;

        /// Returns an approximation of how much memory this device can use with good performance.
        ///
        /// Performance may be improved by keeping the total size of all resources (texture and buffers)
        /// and heaps less than this threshold, beyond which the device is likely to be overcommitted and incur a
        /// performance penalty.
        #[unsafe(method(recommendedMaxWorkingSetSize))]
        #[unsafe(method_family = none)]
        fn recommendedMaxWorkingSetSize(&self) -> u64;

        /// Returns an enum that indicates where the GPU is located relative to the host computer.
        ///
        /// The returned value indicates if the GPU is built into the computer, inserted into
        /// a slot internal to the computer, or external to the computer. Otherwise it is Unspecified
        #[unsafe(method(location))]
        #[unsafe(method_family = none)]
        fn location(&self) -> MTLDeviceLocation;

        /// Returns a value that further specifies the GPU's location
        ///
        /// The returned value indicates which slot or Thunderbolt port the GPU is attached
        /// to. For Built-in GPUs, if LowPower this value is 0, otherwise it is 1.  It is possible for multiple GPUs to have
        /// the same location and locationNumber; e.g.: A PCI card with multiple GPUs, or an eGPU
        /// daisy-chained off of another eGPU attached to a host Thunderbolt port.
        #[unsafe(method(locationNumber))]
        #[unsafe(method_family = none)]
        fn locationNumber(&self) -> NSUInteger;

        /// Upper bound of System RAM
        /// <
        /// => VRAM transfer rate in bytes/sec
        ///
        /// The returned value indicates the theoretical maximum data rate in bytes/second
        /// from host memory to the GPU's VRAM. This is derived from the raw data clock rate and as
        /// such may not be reachable under real-world conditions. For Built-in GPUs this value is 0.
        #[unsafe(method(maxTransferRate))]
        #[unsafe(method_family = none)]
        fn maxTransferRate(&self) -> u64;

        /// If YES, device supports MTLPixelFormatDepth24Unorm_Stencil8.
        #[unsafe(method(isDepth24Stencil8PixelFormatSupported))]
        #[unsafe(method_family = none)]
        fn isDepth24Stencil8PixelFormatSupported(&self) -> bool;

        /// Query support tier for read-write texture formats.
        ///
        /// Returns: MTLReadWriteTextureTier enum value.
        #[unsafe(method(readWriteTextureSupport))]
        #[unsafe(method_family = none)]
        fn readWriteTextureSupport(&self) -> MTLReadWriteTextureTier;

        /// Query support tier for Argument Buffers.
        ///
        /// Returns: MTLArgumentBuffersTier enum value.
        #[unsafe(method(argumentBuffersSupport))]
        #[unsafe(method_family = none)]
        fn argumentBuffersSupport(&self) -> MTLArgumentBuffersTier;

        /// Query device for raster order groups support.
        ///
        /// Returns: BOOL value. If YES, the device supports raster order groups. If NO, the device does not.
        #[unsafe(method(areRasterOrderGroupsSupported))]
        #[unsafe(method_family = none)]
        fn areRasterOrderGroupsSupported(&self) -> bool;

        /// Query device for 32-bit Float texture filtering support. Specifically, R32Float, RG32Float, and RGBA32Float.
        ///
        /// Returns: BOOL value. If YES, the device supports filtering 32-bit Float textures. If NO, the device does not.
        #[unsafe(method(supports32BitFloatFiltering))]
        #[unsafe(method_family = none)]
        fn supports32BitFloatFiltering(&self) -> bool;

        /// Query device for 32-bit MSAA texture support. Specifically, added support for allocating 32-bit Integer format textures (R32Uint, R32Sint, RG32Uint, RG32Sint, RGBA32Uint, and RGBA32Sint) and resolving 32-bit Float format textures (R32Float, RG32Float, and RGBA32Float).
        ///
        /// Returns: BOOL value. If YES, the device supports these additional 32-bit MSAA texture capabilities. If NO, the devices does not.
        #[unsafe(method(supports32BitMSAA))]
        #[unsafe(method_family = none)]
        fn supports32BitMSAA(&self) -> bool;

        /// Query device for whether it supports the `calculate_clampled_lod` and `calculate_unclamped_lod` Metal shading language functionality.
        ///
        /// Returns: BOOL value. If YES, the device supports the calculate LOD functionality. If NO, the device does not.
        #[unsafe(method(supportsQueryTextureLOD))]
        #[unsafe(method_family = none)]
        fn supportsQueryTextureLOD(&self) -> bool;

        /// Query device for BC Texture format support
        ///
        /// Returns: BOOL value. If YES, the device supports compressed BC Texture formats. If NO, the device does not.
        #[unsafe(method(supportsBCTextureCompression))]
        #[unsafe(method_family = none)]
        fn supportsBCTextureCompression(&self) -> bool;

        /// Query device for pull model interpolation support which allows a fragment shader to compute multiple interpolations (at center, at centroid, at offset, at sample) of a fragment input.
        ///
        /// Returns: BOOL value. If YES, the device supports pull model interpolation. If NO, the device does not.
        #[unsafe(method(supportsPullModelInterpolation))]
        #[unsafe(method_family = none)]
        fn supportsPullModelInterpolation(&self) -> bool;

        /// Query device for Barycentric coordinates support; deprecated, use supportsShaderBarycentricCoordinates
        ///
        /// Returns: BOOL value. If YES, the device barycentric coordinates
        #[deprecated]
        #[unsafe(method(areBarycentricCoordsSupported))]
        #[unsafe(method_family = none)]
        fn areBarycentricCoordsSupported(&self) -> bool;

        /// Query device for Barycentric Coordinates support.
        ///
        /// Returns: BOOL value. If YES, the device supports barycentric coordinates. If NO, the device does not.
        #[unsafe(method(supportsShaderBarycentricCoordinates))]
        #[unsafe(method_family = none)]
        fn supportsShaderBarycentricCoordinates(&self) -> bool;

        /// The current size in bytes of all resources allocated by this device
        #[unsafe(method(currentAllocatedSize))]
        #[unsafe(method_family = none)]
        fn currentAllocatedSize(&self) -> NSUInteger;

        #[cfg(feature = "MTLLogState")]
        /// This method will create a new MTLLogState.
        #[unsafe(method(newLogStateWithDescriptor:error:_))]
        #[unsafe(method_family = new)]
        fn newLogStateWithDescriptor_error(
            &self,
            descriptor: &MTLLogStateDescriptor,
        ) -> Result<Retained<ProtocolObject<dyn MTLLogState>>, Retained<NSError>>;

        #[cfg(feature = "MTLCommandQueue")]
        /// Create and return a new command queue.   Command Queues created via this method will only allow up to 64 non-completed command buffers.
        ///
        /// Returns: The new command queue object
        #[unsafe(method(newCommandQueue))]
        #[unsafe(method_family = new)]
        fn newCommandQueue(&self) -> Option<Retained<ProtocolObject<dyn MTLCommandQueue>>>;

        #[cfg(feature = "MTLCommandQueue")]
        /// Create and return a new command queue with a given upper bound on non-completed command buffers.
        ///
        /// Returns: The new command queue object
        #[unsafe(method(newCommandQueueWithMaxCommandBufferCount:))]
        #[unsafe(method_family = new)]
        fn newCommandQueueWithMaxCommandBufferCount(
            &self,
            max_command_buffer_count: NSUInteger,
        ) -> Option<Retained<ProtocolObject<dyn MTLCommandQueue>>>;

        #[cfg(feature = "MTLCommandQueue")]
        /// Create a MTLCommandQueue according to MTLCommandQueueDescriptor.
        #[unsafe(method(newCommandQueueWithDescriptor:))]
        #[unsafe(method_family = new)]
        fn newCommandQueueWithDescriptor(
            &self,
            descriptor: &MTLCommandQueueDescriptor,
        ) -> Option<Retained<ProtocolObject<dyn MTLCommandQueue>>>;

        #[cfg(feature = "MTLTexture")]
        /// Determine the byte size of textures when sub-allocated from a heap.
        ///
        /// This method can be used to help determine the required heap size.
        #[unsafe(method(heapTextureSizeAndAlignWithDescriptor:))]
        #[unsafe(method_family = none)]
        fn heapTextureSizeAndAlignWithDescriptor(
            &self,
            desc: &MTLTextureDescriptor,
        ) -> MTLSizeAndAlign;

        #[cfg(feature = "MTLResource")]
        /// Determine the byte size of buffers when sub-allocated from a heap.
        ///
        /// This method can be used to help determine the required heap size.
        #[unsafe(method(heapBufferSizeAndAlignWithLength:options:))]
        #[unsafe(method_family = none)]
        fn heapBufferSizeAndAlignWithLength_options(
            &self,
            length: NSUInteger,
            options: MTLResourceOptions,
        ) -> MTLSizeAndAlign;

        #[cfg(all(feature = "MTLAllocation", feature = "MTLHeap"))]
        /// Create a new heap with the given descriptor.
        #[unsafe(method(newHeapWithDescriptor:))]
        #[unsafe(method_family = new)]
        fn newHeapWithDescriptor(
            &self,
            descriptor: &MTLHeapDescriptor,
        ) -> Option<Retained<ProtocolObject<dyn MTLHeap>>>;

        #[cfg(all(
            feature = "MTLAllocation",
            feature = "MTLBuffer",
            feature = "MTLResource"
        ))]
        /// Create a buffer by allocating new memory.
        #[unsafe(method(newBufferWithLength:options:))]
        #[unsafe(method_family = new)]
        fn newBufferWithLength_options(
            &self,
            length: NSUInteger,
            options: MTLResourceOptions,
        ) -> Option<Retained<ProtocolObject<dyn MTLBuffer>>>;

        #[cfg(all(
            feature = "MTLAllocation",
            feature = "MTLBuffer",
            feature = "MTLResource"
        ))]
        /// Create a buffer by allocating new memory and specifing the initial contents to be copied into it.
        ///
        /// # Safety
        ///
        /// `pointer` must be a valid pointer.
        #[unsafe(method(newBufferWithBytes:length:options:))]
        #[unsafe(method_family = new)]
        unsafe fn newBufferWithBytes_length_options(
            &self,
            pointer: NonNull<c_void>,
            length: NSUInteger,
            options: MTLResourceOptions,
        ) -> Option<Retained<ProtocolObject<dyn MTLBuffer>>>;

        #[cfg(all(
            feature = "MTLAllocation",
            feature = "MTLBuffer",
            feature = "MTLResource",
            feature = "block2"
        ))]
        /// Create a buffer by wrapping an existing part of the address space.
        ///
        /// # Safety
        ///
        /// - `pointer` must be a valid pointer.
        /// - `deallocator` block must be sendable.
        #[unsafe(method(newBufferWithBytesNoCopy:length:options:deallocator:))]
        #[unsafe(method_family = new)]
        unsafe fn newBufferWithBytesNoCopy_length_options_deallocator(
            &self,
            pointer: NonNull<c_void>,
            length: NSUInteger,
            options: MTLResourceOptions,
            deallocator: Option<&block2::DynBlock<dyn Fn(NonNull<c_void>, NSUInteger)>>,
        ) -> Option<Retained<ProtocolObject<dyn MTLBuffer>>>;

        #[cfg(feature = "MTLDepthStencil")]
        /// Create a depth/stencil test state object.
        #[unsafe(method(newDepthStencilStateWithDescriptor:))]
        #[unsafe(method_family = new)]
        fn newDepthStencilStateWithDescriptor(
            &self,
            descriptor: &MTLDepthStencilDescriptor,
        ) -> Option<Retained<ProtocolObject<dyn MTLDepthStencilState>>>;

        #[cfg(all(
            feature = "MTLAllocation",
            feature = "MTLResource",
            feature = "MTLTexture"
        ))]
        /// Allocate a new texture with privately owned storage.
        #[unsafe(method(newTextureWithDescriptor:))]
        #[unsafe(method_family = new)]
        fn newTextureWithDescriptor(
            &self,
            descriptor: &MTLTextureDescriptor,
        ) -> Option<Retained<ProtocolObject<dyn MTLTexture>>>;

        #[cfg(all(
            feature = "MTLAllocation",
            feature = "MTLResource",
            feature = "MTLTexture",
            feature = "objc2-io-surface"
        ))]
        /// Create a new texture from an IOSurface.
        ///
        /// Parameter `descriptor`: A description of the properties for the new texture.
        ///
        /// Parameter `iosurface`: The IOSurface to use as storage for the new texture.
        ///
        /// Parameter `plane`: The plane within the IOSurface to use.
        ///
        /// Returns: A new texture object.
        #[unsafe(method(newTextureWithDescriptor:iosurface:plane:))]
        #[unsafe(method_family = new)]
        fn newTextureWithDescriptor_iosurface_plane(
            &self,
            descriptor: &MTLTextureDescriptor,
            iosurface: &IOSurfaceRef,
            plane: NSUInteger,
        ) -> Option<Retained<ProtocolObject<dyn MTLTexture>>>;

        #[cfg(all(
            feature = "MTLAllocation",
            feature = "MTLResource",
            feature = "MTLTexture"
        ))]
        /// Create a new texture that can be shared across process boundaries.
        ///
        /// This texture can be shared between process boundaries
        /// but not between different GPUs, by passing its MTLSharedTextureHandle.
        ///
        /// Parameter `descriptor`: A description of the properties for the new texture.
        ///
        /// Returns: A new texture object.
        #[unsafe(method(newSharedTextureWithDescriptor:))]
        #[unsafe(method_family = new)]
        fn newSharedTextureWithDescriptor(
            &self,
            descriptor: &MTLTextureDescriptor,
        ) -> Option<Retained<ProtocolObject<dyn MTLTexture>>>;

        #[cfg(all(
            feature = "MTLAllocation",
            feature = "MTLResource",
            feature = "MTLTexture"
        ))]
        /// Recreate shared texture from received texture handle.
        ///
        /// This texture was shared between process boundaries by other
        /// process using MTLSharedTextureHandle. Current process will now share
        /// it with other processes and will be able to interact with it (but still
        /// in scope of the same GPUs).
        ///
        /// Parameter `sharedHandle`: Handle to shared texture in this process space.
        ///
        /// Returns: A new texture object.
        #[unsafe(method(newSharedTextureWithHandle:))]
        #[unsafe(method_family = new)]
        fn newSharedTextureWithHandle(
            &self,
            shared_handle: &MTLSharedTextureHandle,
        ) -> Option<Retained<ProtocolObject<dyn MTLTexture>>>;

        #[cfg(feature = "MTLSampler")]
        /// Create a new sampler.
        #[unsafe(method(newSamplerStateWithDescriptor:))]
        #[unsafe(method_family = new)]
        fn newSamplerStateWithDescriptor(
            &self,
            descriptor: &MTLSamplerDescriptor,
        ) -> Option<Retained<ProtocolObject<dyn MTLSamplerState>>>;

        #[cfg(feature = "MTLLibrary")]
        /// Returns the default library for the main bundle.
        ///
        /// use newDefaultLibraryWithBundle:error: to get an NSError in case of failure.
        #[unsafe(method(newDefaultLibrary))]
        #[unsafe(method_family = new)]
        fn newDefaultLibrary(&self) -> Option<Retained<ProtocolObject<dyn MTLLibrary>>>;

        #[cfg(feature = "MTLLibrary")]
        #[unsafe(method(newDefaultLibraryWithBundle:error:_))]
        #[unsafe(method_family = new)]
        fn newDefaultLibraryWithBundle_error(
            &self,
            bundle: &NSBundle,
        ) -> Result<Retained<ProtocolObject<dyn MTLLibrary>>, Retained<NSError>>;

        #[cfg(feature = "MTLLibrary")]
        /// Load a MTLLibrary from a metallib file.
        #[deprecated = "Use -newLibraryWithURL:error: instead"]
        #[unsafe(method(newLibraryWithFile:error:_))]
        #[unsafe(method_family = new)]
        fn newLibraryWithFile_error(
            &self,
            filepath: &NSString,
        ) -> Result<Retained<ProtocolObject<dyn MTLLibrary>>, Retained<NSError>>;

        #[cfg(feature = "MTLLibrary")]
        /// Load a MTLLibrary from a metallib file.
        #[unsafe(method(newLibraryWithURL:error:_))]
        #[unsafe(method_family = new)]
        fn newLibraryWithURL_error(
            &self,
            url: &NSURL,
        ) -> Result<Retained<ProtocolObject<dyn MTLLibrary>>, Retained<NSError>>;

        #[cfg(all(feature = "MTLLibrary", feature = "dispatch2"))]
        /// Load a MTLLibrary from a dispatch_data_t
        ///
        /// Parameter `data`: A metallib file already loaded as data in the form of dispatch_data_t.
        ///
        /// Parameter `error`: An error if we fail to open the metallib data.
        #[unsafe(method(newLibraryWithData:error:_))]
        #[unsafe(method_family = new)]
        fn newLibraryWithData_error(
            &self,
            data: &DispatchData,
        ) -> Result<Retained<ProtocolObject<dyn MTLLibrary>>, Retained<NSError>>;

        #[cfg(feature = "MTLLibrary")]
        /// Load a MTLLibrary from source.
        #[unsafe(method(newLibraryWithSource:options:error:_))]
        #[unsafe(method_family = new)]
        fn newLibraryWithSource_options_error(
            &self,
            source: &NSString,
            options: Option<&MTLCompileOptions>,
        ) -> Result<Retained<ProtocolObject<dyn MTLLibrary>>, Retained<NSError>>;

        #[cfg(all(feature = "MTLLibrary", feature = "block2"))]
        /// Load a MTLLibrary from source.
        ///
        /// # Safety
        ///
        /// `completion_handler` must be a valid pointer.
        #[unsafe(method(newLibraryWithSource:options:completionHandler:))]
        #[unsafe(method_family = none)]
        unsafe fn newLibraryWithSource_options_completionHandler(
            &self,
            source: &NSString,
            options: Option<&MTLCompileOptions>,
            completion_handler: MTLNewLibraryCompletionHandler,
        );

        #[cfg(all(feature = "MTLFunctionStitching", feature = "MTLLibrary"))]
        /// Returns a library generated using the graphs in the descriptor.
        #[unsafe(method(newLibraryWithStitchedDescriptor:error:_))]
        #[unsafe(method_family = new)]
        fn newLibraryWithStitchedDescriptor_error(
            &self,
            descriptor: &MTLStitchedLibraryDescriptor,
        ) -> Result<Retained<ProtocolObject<dyn MTLLibrary>>, Retained<NSError>>;

        #[cfg(all(
            feature = "MTLFunctionStitching",
            feature = "MTLLibrary",
            feature = "block2"
        ))]
        /// Generates a new library using the graphs in the descriptor.
        ///
        /// # Safety
        ///
        /// `completion_handler` must be a valid pointer.
        #[unsafe(method(newLibraryWithStitchedDescriptor:completionHandler:))]
        #[unsafe(method_family = none)]
        unsafe fn newLibraryWithStitchedDescriptor_completionHandler(
            &self,
            descriptor: &MTLStitchedLibraryDescriptor,
            completion_handler: MTLNewLibraryCompletionHandler,
        );

        #[cfg(all(feature = "MTLAllocation", feature = "MTLRenderPipeline"))]
        /// Create and compile a new MTLRenderPipelineState object synchronously.
        #[unsafe(method(newRenderPipelineStateWithDescriptor:error:_))]
        #[unsafe(method_family = new)]
        fn newRenderPipelineStateWithDescriptor_error(
            &self,
            descriptor: &MTLRenderPipelineDescriptor,
        ) -> Result<Retained<ProtocolObject<dyn MTLRenderPipelineState>>, Retained<NSError>>;

        #[cfg(all(
            feature = "MTLAllocation",
            feature = "MTLLibrary",
            feature = "MTLRenderPipeline"
        ))]
        /// Create and compile a new MTLRenderPipelineState object synchronously and returns additional reflection information.
        #[unsafe(method(newRenderPipelineStateWithDescriptor:options:reflection:error:_))]
        #[unsafe(method_family = new)]
        fn newRenderPipelineStateWithDescriptor_options_reflection_error(
            &self,
            descriptor: &MTLRenderPipelineDescriptor,
            options: MTLPipelineOption,
            reflection: Option<&mut Option<Retained<MTLAutoreleasedRenderPipelineReflection>>>,
        ) -> Result<Retained<ProtocolObject<dyn MTLRenderPipelineState>>, Retained<NSError>>;

        #[cfg(all(
            feature = "MTLAllocation",
            feature = "MTLLibrary",
            feature = "MTLRenderPipeline",
            feature = "block2"
        ))]
        /// Create and compile a new MTLRenderPipelineState object asynchronously.
        ///
        /// # Safety
        ///
        /// `completion_handler` must be a valid pointer.
        #[unsafe(method(newRenderPipelineStateWithDescriptor:completionHandler:))]
        #[unsafe(method_family = none)]
        unsafe fn newRenderPipelineStateWithDescriptor_completionHandler(
            &self,
            descriptor: &MTLRenderPipelineDescriptor,
            completion_handler: MTLNewRenderPipelineStateCompletionHandler,
        );

        #[cfg(all(
            feature = "MTLAllocation",
            feature = "MTLLibrary",
            feature = "MTLRenderPipeline",
            feature = "block2"
        ))]
        /// Create and compile a new MTLRenderPipelineState object asynchronously and returns additional reflection information
        ///
        /// # Safety
        ///
        /// `completion_handler` must be a valid pointer.
        #[unsafe(method(newRenderPipelineStateWithDescriptor:options:completionHandler:))]
        #[unsafe(method_family = none)]
        unsafe fn newRenderPipelineStateWithDescriptor_options_completionHandler(
            &self,
            descriptor: &MTLRenderPipelineDescriptor,
            options: MTLPipelineOption,
            completion_handler: MTLNewRenderPipelineStateWithReflectionCompletionHandler,
        );

        #[cfg(all(
            feature = "MTLAllocation",
            feature = "MTLComputePipeline",
            feature = "MTLLibrary"
        ))]
        /// Create and compile a new MTLComputePipelineState object synchronously.
        #[unsafe(method(newComputePipelineStateWithFunction:error:_))]
        #[unsafe(method_family = new)]
        fn newComputePipelineStateWithFunction_error(
            &self,
            compute_function: &ProtocolObject<dyn MTLFunction>,
        ) -> Result<Retained<ProtocolObject<dyn MTLComputePipelineState>>, Retained<NSError>>;

        #[cfg(all(
            feature = "MTLAllocation",
            feature = "MTLComputePipeline",
            feature = "MTLLibrary"
        ))]
        /// Create and compile a new MTLComputePipelineState object synchronously.
        ///
        /// # Safety
        ///
        /// - `compute_function` must be safe to call.
        /// - `compute_function` must have the correct argument and return types.
        #[unsafe(method(newComputePipelineStateWithFunction:options:reflection:error:_))]
        #[unsafe(method_family = new)]
        unsafe fn newComputePipelineStateWithFunction_options_reflection_error(
            &self,
            compute_function: &ProtocolObject<dyn MTLFunction>,
            options: MTLPipelineOption,
            reflection: Option<&mut Option<Retained<MTLAutoreleasedComputePipelineReflection>>>,
        ) -> Result<Retained<ProtocolObject<dyn MTLComputePipelineState>>, Retained<NSError>>;

        #[cfg(all(
            feature = "MTLAllocation",
            feature = "MTLComputePipeline",
            feature = "MTLLibrary",
            feature = "block2"
        ))]
        /// Create and compile a new MTLComputePipelineState object asynchronously.
        ///
        /// # Safety
        ///
        /// - `compute_function` must be safe to call.
        /// - `compute_function` must have the correct argument and return types.
        /// - `completion_handler` must be a valid pointer.
        #[unsafe(method(newComputePipelineStateWithFunction:completionHandler:))]
        #[unsafe(method_family = none)]
        unsafe fn newComputePipelineStateWithFunction_completionHandler(
            &self,
            compute_function: &ProtocolObject<dyn MTLFunction>,
            completion_handler: MTLNewComputePipelineStateCompletionHandler,
        );

        #[cfg(all(
            feature = "MTLAllocation",
            feature = "MTLComputePipeline",
            feature = "MTLLibrary",
            feature = "block2"
        ))]
        /// Create and compile a new MTLComputePipelineState object asynchronously.
        ///
        /// # Safety
        ///
        /// - `compute_function` must be safe to call.
        /// - `compute_function` must have the correct argument and return types.
        /// - `completion_handler` must be a valid pointer.
        #[unsafe(method(newComputePipelineStateWithFunction:options:completionHandler:))]
        #[unsafe(method_family = none)]
        unsafe fn newComputePipelineStateWithFunction_options_completionHandler(
            &self,
            compute_function: &ProtocolObject<dyn MTLFunction>,
            options: MTLPipelineOption,
            completion_handler: MTLNewComputePipelineStateWithReflectionCompletionHandler,
        );

        #[cfg(all(
            feature = "MTLAllocation",
            feature = "MTLComputePipeline",
            feature = "MTLLibrary"
        ))]
        /// Create and compile a new MTLComputePipelineState object synchronously.
        #[unsafe(method(newComputePipelineStateWithDescriptor:options:reflection:error:_))]
        #[unsafe(method_family = new)]
        fn newComputePipelineStateWithDescriptor_options_reflection_error(
            &self,
            descriptor: &MTLComputePipelineDescriptor,
            options: MTLPipelineOption,
            reflection: Option<&mut Option<Retained<MTLAutoreleasedComputePipelineReflection>>>,
        ) -> Result<Retained<ProtocolObject<dyn MTLComputePipelineState>>, Retained<NSError>>;

        #[cfg(all(
            feature = "MTLAllocation",
            feature = "MTLComputePipeline",
            feature = "MTLLibrary",
            feature = "block2"
        ))]
        /// Create and compile a new MTLComputePipelineState object asynchronously.
        ///
        /// # Safety
        ///
        /// `completion_handler` must be a valid pointer.
        #[unsafe(method(newComputePipelineStateWithDescriptor:options:completionHandler:))]
        #[unsafe(method_family = none)]
        unsafe fn newComputePipelineStateWithDescriptor_options_completionHandler(
            &self,
            descriptor: &MTLComputePipelineDescriptor,
            options: MTLPipelineOption,
            completion_handler: MTLNewComputePipelineStateWithReflectionCompletionHandler,
        );

        #[cfg(feature = "MTLFence")]
        /// Create a new MTLFence object
        #[unsafe(method(newFence))]
        #[unsafe(method_family = new)]
        fn newFence(&self) -> Option<Retained<ProtocolObject<dyn MTLFence>>>;

        /// Returns TRUE if the feature set is supported by this MTLDevice.
        #[deprecated = "Use supportsFamily instead"]
        #[unsafe(method(supportsFeatureSet:))]
        #[unsafe(method_family = none)]
        fn supportsFeatureSet(&self, feature_set: MTLFeatureSet) -> bool;

        /// Returns TRUE if the GPU Family is supported by this MTLDevice.
        #[unsafe(method(supportsFamily:))]
        #[unsafe(method_family = none)]
        fn supportsFamily(&self, gpu_family: MTLGPUFamily) -> bool;

        /// Query device if it support textures with a given sampleCount.
        ///
        /// Returns: BOOL value. If YES, device supports the given sampleCount for textures. If NO, device does not support the given sampleCount.
        #[unsafe(method(supportsTextureSampleCount:))]
        #[unsafe(method_family = none)]
        fn supportsTextureSampleCount(&self, sample_count: NSUInteger) -> bool;

        #[cfg(feature = "MTLPixelFormat")]
        /// Returns the minimum alignment required for offset and rowBytes when creating a linear texture. An error is thrown for queries with invalid pixel formats (depth, stencil, or compressed formats).
        #[unsafe(method(minimumLinearTextureAlignmentForPixelFormat:))]
        #[unsafe(method_family = none)]
        fn minimumLinearTextureAlignmentForPixelFormat(&self, format: MTLPixelFormat)
            -> NSUInteger;

        #[cfg(feature = "MTLPixelFormat")]
        /// Returns the minimum alignment required for offset and rowBytes when creating a texture buffer from a buffer.
        #[unsafe(method(minimumTextureBufferAlignmentForPixelFormat:))]
        #[unsafe(method_family = none)]
        fn minimumTextureBufferAlignmentForPixelFormat(&self, format: MTLPixelFormat)
            -> NSUInteger;

        #[cfg(all(
            feature = "MTLAllocation",
            feature = "MTLLibrary",
            feature = "MTLRenderPipeline"
        ))]
        /// Create and compile a new MTLRenderPipelineState object synchronously given a MTLTileRenderPipelineDescriptor.
        #[unsafe(method(newRenderPipelineStateWithTileDescriptor:options:reflection:error:_))]
        #[unsafe(method_family = new)]
        fn newRenderPipelineStateWithTileDescriptor_options_reflection_error(
            &self,
            descriptor: &MTLTileRenderPipelineDescriptor,
            options: MTLPipelineOption,
            reflection: Option<&mut Option<Retained<MTLAutoreleasedRenderPipelineReflection>>>,
        ) -> Result<Retained<ProtocolObject<dyn MTLRenderPipelineState>>, Retained<NSError>>;

        #[cfg(all(
            feature = "MTLAllocation",
            feature = "MTLLibrary",
            feature = "MTLRenderPipeline",
            feature = "block2"
        ))]
        /// Create and compile a new MTLRenderPipelineState object asynchronously given a MTLTileRenderPipelineDescriptor.
        ///
        /// # Safety
        ///
        /// `completion_handler` must be a valid pointer.
        #[unsafe(method(newRenderPipelineStateWithTileDescriptor:options:completionHandler:))]
        #[unsafe(method_family = none)]
        unsafe fn newRenderPipelineStateWithTileDescriptor_options_completionHandler(
            &self,
            descriptor: &MTLTileRenderPipelineDescriptor,
            options: MTLPipelineOption,
            completion_handler: MTLNewRenderPipelineStateWithReflectionCompletionHandler,
        );

        #[cfg(all(
            feature = "MTLAllocation",
            feature = "MTLLibrary",
            feature = "MTLRenderPipeline"
        ))]
        /// Create and compile a new MTLRenderPipelineState object synchronously given a MTLMeshRenderPipelineDescriptor.
        #[unsafe(method(newRenderPipelineStateWithMeshDescriptor:options:reflection:error:_))]
        #[unsafe(method_family = new)]
        fn newRenderPipelineStateWithMeshDescriptor_options_reflection_error(
            &self,
            descriptor: &MTLMeshRenderPipelineDescriptor,
            options: MTLPipelineOption,
            reflection: Option<&mut Option<Retained<MTLAutoreleasedRenderPipelineReflection>>>,
        ) -> Result<Retained<ProtocolObject<dyn MTLRenderPipelineState>>, Retained<NSError>>;

        #[cfg(all(
            feature = "MTLAllocation",
            feature = "MTLLibrary",
            feature = "MTLRenderPipeline",
            feature = "block2"
        ))]
        /// Create and compile a new MTLRenderPipelineState object asynchronously given a MTLMeshRenderPipelineDescriptor.
        ///
        /// # Safety
        ///
        /// `completion_handler` must be a valid pointer.
        #[unsafe(method(newRenderPipelineStateWithMeshDescriptor:options:completionHandler:))]
        #[unsafe(method_family = none)]
        unsafe fn newRenderPipelineStateWithMeshDescriptor_options_completionHandler(
            &self,
            descriptor: &MTLMeshRenderPipelineDescriptor,
            options: MTLPipelineOption,
            completion_handler: MTLNewRenderPipelineStateWithReflectionCompletionHandler,
        );

        /// The maximum threadgroup memory available, in bytes.
        #[unsafe(method(maxThreadgroupMemoryLength))]
        #[unsafe(method_family = none)]
        fn maxThreadgroupMemoryLength(&self) -> NSUInteger;

        /// The maximum number of unique argument buffer samplers per app.
        ///
        /// This limit is only applicable to samplers that have their supportArgumentBuffers property set to true. A MTLSamplerState object is considered unique if the configuration of its originating MTLSamplerDescriptor properties is unique. For example, two samplers with equal minFilter values but different magFilter values are considered unique.
        #[unsafe(method(maxArgumentBufferSamplerCount))]
        #[unsafe(method_family = none)]
        fn maxArgumentBufferSamplerCount(&self) -> NSUInteger;

        /// Query device for programmable sample position support.
        ///
        /// Returns: BOOL value. If YES, the device supports programmable sample positions. If NO, the device does not.
        #[unsafe(method(areProgrammableSamplePositionsSupported))]
        #[unsafe(method_family = none)]
        fn areProgrammableSamplePositionsSupported(&self) -> bool;

        #[cfg(feature = "MTLTypes")]
        /// Retrieve the default sample positions.
        ///
        /// Parameter `positions`: The destination array for default sample position data.
        ///
        /// Parameter `count`: Specifies the sample count for which to retrieve the default positions, the length of the positions array, and must be set to a valid sample count.
        ///
        /// # Safety
        ///
        /// - `positions` must be a valid pointer.
        /// - `count` might not be bounds-checked.
        #[unsafe(method(getDefaultSamplePositions:count:))]
        #[unsafe(method_family = none)]
        unsafe fn getDefaultSamplePositions_count(
            &self,
            positions: NonNull<MTLSamplePosition>,
            count: NSUInteger,
        );

        #[cfg(feature = "MTLArgumentEncoder")]
        /// Creates an argument encoder for an array of argument descriptors which will be encoded sequentially.
        #[unsafe(method(newArgumentEncoderWithArguments:))]
        #[unsafe(method_family = new)]
        fn newArgumentEncoderWithArguments(
            &self,
            arguments: &NSArray<MTLArgumentDescriptor>,
        ) -> Option<Retained<ProtocolObject<dyn MTLArgumentEncoder>>>;

        /// Query device for variable rasterization rate support with the given number of layers.
        ///
        /// Parameter `layerCount`: The number of layers for which to query device support.
        ///
        /// Returns: YES if the device supports creation of rendering using a MTLRasterizationRateMap with the given number of layers.
        ///
        /// # Safety
        ///
        /// `layerCount` might not be bounds-checked.
        #[unsafe(method(supportsRasterizationRateMapWithLayerCount:))]
        #[unsafe(method_family = none)]
        unsafe fn supportsRasterizationRateMapWithLayerCount(
            &self,
            layer_count: NSUInteger,
        ) -> bool;

        #[cfg(feature = "MTLRasterizationRate")]
        /// Creates a new variable rasterization rate map with the given descriptor.
        ///
        /// If '[self supportsRasterizationRateMapWithLayerCount:descriptor.layerCount]' returns NO, or descriptor.screenSize describes an empty region, the result will always be nil.
        ///
        /// Returns: A MTLRasterizationRateMap instance that can be used for rendering on this MTLDevice, or nil if the device does not support the combination of parameters stored in the descriptor.
        #[unsafe(method(newRasterizationRateMapWithDescriptor:))]
        #[unsafe(method_family = new)]
        fn newRasterizationRateMapWithDescriptor(
            &self,
            descriptor: &MTLRasterizationRateMapDescriptor,
        ) -> Option<Retained<ProtocolObject<dyn MTLRasterizationRateMap>>>;

        #[cfg(all(
            feature = "MTLAllocation",
            feature = "MTLIndirectCommandBuffer",
            feature = "MTLResource"
        ))]
        /// Creates a new indirect command buffer with the given descriptor and count.
        ///
        /// Parameter `descriptor`: The descriptor encodes the maximum logical stride of each command.
        ///
        /// Parameter `maxCount`: The maximum number of commands that this buffer can contain.
        ///
        /// Parameter `options`: The options for the indirect command buffer.
        ///
        /// The returned buffer can be safely executed without first encoding into (but is wasteful).
        ///
        /// # Safety
        ///
        /// `maxCount` might not be bounds-checked.
        #[unsafe(method(newIndirectCommandBufferWithDescriptor:maxCommandCount:options:))]
        #[unsafe(method_family = new)]
        unsafe fn newIndirectCommandBufferWithDescriptor_maxCommandCount_options(
            &self,
            descriptor: &MTLIndirectCommandBufferDescriptor,
            max_count: NSUInteger,
            options: MTLResourceOptions,
        ) -> Option<Retained<ProtocolObject<dyn MTLIndirectCommandBuffer>>>;

        #[cfg(feature = "MTLEvent")]
        /// Returns a new single-device non-shareable Metal event object
        #[unsafe(method(newEvent))]
        #[unsafe(method_family = new)]
        fn newEvent(&self) -> Option<Retained<ProtocolObject<dyn MTLEvent>>>;

        #[cfg(feature = "MTLEvent")]
        /// Returns a shareable multi-device event.
        #[unsafe(method(newSharedEvent))]
        #[unsafe(method_family = new)]
        fn newSharedEvent(&self) -> Option<Retained<ProtocolObject<dyn MTLSharedEvent>>>;

        #[cfg(feature = "MTLEvent")]
        /// Creates a shareable multi-device event from an existing shared event handle.
        #[unsafe(method(newSharedEventWithHandle:))]
        #[unsafe(method_family = new)]
        fn newSharedEventWithHandle(
            &self,
            shared_event_handle: &MTLSharedEventHandle,
        ) -> Option<Retained<ProtocolObject<dyn MTLSharedEvent>>>;

        /// If a device supports peer to peer transfers with another device (or devices), this property will return
        /// a unique 64-bit identifier associated with all devices in the same peer group.
        #[unsafe(method(peerGroupID))]
        #[unsafe(method_family = none)]
        fn peerGroupID(&self) -> u64;

        /// All Metal devices that are part of the same peer group will have a unique index value within the group in
        /// the range from 0 to peerCount - 1.
        #[unsafe(method(peerIndex))]
        #[unsafe(method_family = none)]
        fn peerIndex(&self) -> u32;

        /// For Metal devices that are part of a peer group, this property returns the total number of devices in that group.
        #[unsafe(method(peerCount))]
        #[unsafe(method_family = none)]
        fn peerCount(&self) -> u32;

        #[cfg(feature = "MTLIOCommandQueue")]
        /// Create and return a handle that points to a raw file on disk. This object can be used by
        /// MTLIOCommandBuffer load commands to source data for MTLResources. If the creation
        /// of the handle fails the return value will be nil and the optional error if passed in will be non-nil
        /// with details of the error.
        #[deprecated]
        #[unsafe(method(newIOHandleWithURL:error:_))]
        #[unsafe(method_family = new)]
        fn newIOHandleWithURL_error(
            &self,
            url: &NSURL,
        ) -> Result<Retained<ProtocolObject<dyn MTLIOFileHandle>>, Retained<NSError>>;

        #[cfg(feature = "MTLIOCommandQueue")]
        /// Create and return an IO queue. If the creation
        /// of the queue fails the return value will be nil and the optional error if passed in will be non-nil
        /// with details of the error.
        #[unsafe(method(newIOCommandQueueWithDescriptor:error:_))]
        #[unsafe(method_family = new)]
        fn newIOCommandQueueWithDescriptor_error(
            &self,
            descriptor: &MTLIOCommandQueueDescriptor,
        ) -> Result<Retained<ProtocolObject<dyn MTLIOCommandQueue>>, Retained<NSError>>;

        #[cfg(feature = "MTLIOCommandQueue")]
        /// Create and return a handle that points to a compressed file on disk (a file that was
        /// created with MTLIOCompressionContext). This object can be used by
        /// MTLIOCommandBuffer load commands to source data for MTLResources. If the creation
        /// of the handle fails the return value will be nil and the optional error if passed in will be non-nil
        /// with details of the error.
        #[deprecated]
        #[unsafe(method(newIOHandleWithURL:compressionMethod:error:_))]
        #[unsafe(method_family = new)]
        fn newIOHandleWithURL_compressionMethod_error(
            &self,
            url: &NSURL,
            compression_method: MTLIOCompressionMethod,
        ) -> Result<Retained<ProtocolObject<dyn MTLIOFileHandle>>, Retained<NSError>>;

        #[cfg(feature = "MTLIOCommandQueue")]
        /// Create and return a handle that points to a raw file on disk. This object can be used by
        /// MTLIOCommandBuffer load commands to source data for MTLResources. If the creation
        /// of the handle fails the return value will be nil and the optional error if passed in will be non-nil
        /// with details of the error.
        #[unsafe(method(newIOFileHandleWithURL:error:_))]
        #[unsafe(method_family = new)]
        fn newIOFileHandleWithURL_error(
            &self,
            url: &NSURL,
        ) -> Result<Retained<ProtocolObject<dyn MTLIOFileHandle>>, Retained<NSError>>;

        #[cfg(feature = "MTLIOCommandQueue")]
        /// Create and return a handle that points to a compressed file on disk (a file that was
        /// created with MTLIOCompressionContext). This object can be used by
        /// MTLIOCommandBuffer load commands to source data for MTLResources. If the creation
        /// of the handle fails the return value will be nil and the optional error if passed in will be non-nil
        /// with details of the error.
        #[unsafe(method(newIOFileHandleWithURL:compressionMethod:error:_))]
        #[unsafe(method_family = new)]
        fn newIOFileHandleWithURL_compressionMethod_error(
            &self,
            url: &NSURL,
            compression_method: MTLIOCompressionMethod,
        ) -> Result<Retained<ProtocolObject<dyn MTLIOFileHandle>>, Retained<NSError>>;

        #[cfg(all(
            feature = "MTLPixelFormat",
            feature = "MTLTexture",
            feature = "MTLTypes"
        ))]
        /// Returns tile size for sparse texture with given type, pixel format and sample count.
        ///
        /// # Safety
        ///
        /// `sampleCount` might not be bounds-checked.
        #[unsafe(method(sparseTileSizeWithTextureType:pixelFormat:sampleCount:))]
        #[unsafe(method_family = none)]
        unsafe fn sparseTileSizeWithTextureType_pixelFormat_sampleCount(
            &self,
            texture_type: MTLTextureType,
            pixel_format: MTLPixelFormat,
            sample_count: NSUInteger,
        ) -> MTLSize;

        /// Returns the number of bytes required to map one sparse texture tile.
        #[unsafe(method(sparseTileSizeInBytes))]
        #[unsafe(method_family = none)]
        fn sparseTileSizeInBytes(&self) -> NSUInteger;

        #[cfg(feature = "MTLTypes")]
        /// Converts regions in pixels to regions in sparse tiles using specified alignment mode.
        /// Tile size can be obtained from tileSizeWithTextureType:pixelFormat:sampleCount: method.
        ///
        /// # Safety
        ///
        /// - `pixel_regions` must be a valid pointer.
        /// - `tile_regions` must be a valid pointer.
        /// - `tileSize` might not be bounds-checked.
        #[optional]
        #[unsafe(method(convertSparsePixelRegions:toTileRegions:withTileSize:alignmentMode:numRegions:))]
        #[unsafe(method_family = none)]
        unsafe fn convertSparsePixelRegions_toTileRegions_withTileSize_alignmentMode_numRegions(
            &self,
            pixel_regions: NonNull<MTLRegion>,
            tile_regions: NonNull<MTLRegion>,
            tile_size: MTLSize,
            mode: MTLSparseTextureRegionAlignmentMode,
            num_regions: NSUInteger,
        );

        #[cfg(feature = "MTLTypes")]
        /// Convertes region in sparse tiles to region in pixels
        /// Tile size can be obtained from tileSizeWithTextureType:pixelFormat:sampleCount: method.
        ///
        /// # Safety
        ///
        /// - `tile_regions` must be a valid pointer.
        /// - `pixel_regions` must be a valid pointer.
        /// - `tileSize` might not be bounds-checked.
        #[optional]
        #[unsafe(method(convertSparseTileRegions:toPixelRegions:withTileSize:numRegions:))]
        #[unsafe(method_family = none)]
        unsafe fn convertSparseTileRegions_toPixelRegions_withTileSize_numRegions(
            &self,
            tile_regions: NonNull<MTLRegion>,
            pixel_regions: NonNull<MTLRegion>,
            tile_size: MTLSize,
            num_regions: NSUInteger,
        );

        #[cfg(feature = "MTLResource")]
        /// Returns the number of bytes required to map one sparse texture tile for a given MTLSparsePageSize
        #[unsafe(method(sparseTileSizeInBytesForSparsePageSize:))]
        #[unsafe(method_family = none)]
        fn sparseTileSizeInBytesForSparsePageSize(
            &self,
            sparse_page_size: MTLSparsePageSize,
        ) -> NSUInteger;

        #[cfg(all(
            feature = "MTLPixelFormat",
            feature = "MTLResource",
            feature = "MTLTexture",
            feature = "MTLTypes"
        ))]
        /// Returns tile size for sparse texture with given type, pixel format and sample count.
        ///
        /// # Safety
        ///
        /// `sampleCount` might not be bounds-checked.
        #[unsafe(method(sparseTileSizeWithTextureType:pixelFormat:sampleCount:sparsePageSize:))]
        #[unsafe(method_family = none)]
        unsafe fn sparseTileSizeWithTextureType_pixelFormat_sampleCount_sparsePageSize(
            &self,
            texture_type: MTLTextureType,
            pixel_format: MTLPixelFormat,
            sample_count: NSUInteger,
            sparse_page_size: MTLSparsePageSize,
        ) -> MTLSize;

        #[unsafe(method(maxBufferLength))]
        #[unsafe(method_family = none)]
        fn maxBufferLength(&self) -> NSUInteger;

        #[cfg(feature = "MTLCounters")]
        /// Returns the set of Counter Sets exposed by the device.
        #[unsafe(method(counterSets))]
        #[unsafe(method_family = none)]
        fn counterSets(&self) -> Option<Retained<NSArray<ProtocolObject<dyn MTLCounterSet>>>>;

        #[cfg(feature = "MTLCounters")]
        /// Given a counter sample buffer descriptor, allocate a new counter
        /// sample buffer.
        /// This may return nil if the counters may not all be collected simultaneously.
        ///
        /// Parameter `descriptor`: The descriptor to create a sample buffer for
        ///
        /// Parameter `error`: An error return on failure.
        #[unsafe(method(newCounterSampleBufferWithDescriptor:error:_))]
        #[unsafe(method_family = new)]
        fn newCounterSampleBufferWithDescriptor_error(
            &self,
            descriptor: &MTLCounterSampleBufferDescriptor,
        ) -> Result<Retained<ProtocolObject<dyn MTLCounterSampleBuffer>>, Retained<NSError>>;

        /// Sample the CPU and GPU timestamps as closely as possible.
        ///
        /// Parameter `cpuTimestamp`: The timestamp on the CPU
        ///
        /// Parameter `gpuTimestamp`: The timestamp on the GPU
        ///
        /// # Safety
        ///
        /// - `cpu_timestamp` must be a valid pointer.
        /// - `gpu_timestamp` must be a valid pointer.
        #[unsafe(method(sampleTimestamps:gpuTimestamp:))]
        #[unsafe(method_family = none)]
        unsafe fn sampleTimestamps_gpuTimestamp(
            &self,
            cpu_timestamp: NonNull<MTLTimestamp>,
            gpu_timestamp: NonNull<MTLTimestamp>,
        );

        #[cfg(all(feature = "MTLArgument", feature = "MTLArgumentEncoder"))]
        #[unsafe(method(newArgumentEncoderWithBufferBinding:))]
        #[unsafe(method_family = new)]
        fn newArgumentEncoderWithBufferBinding(
            &self,
            buffer_binding: &ProtocolObject<dyn MTLBufferBinding>,
        ) -> Retained<ProtocolObject<dyn MTLArgumentEncoder>>;

        /// Query device for counter sampling points support.
        ///
        /// Parameter `samplingPoint`: Query index
        ///
        /// Returns: BOOL value. If YES, the device supports counter sampling at given point.
        #[unsafe(method(supportsCounterSampling:))]
        #[unsafe(method_family = none)]
        fn supportsCounterSampling(&self, sampling_point: MTLCounterSamplingPoint) -> bool;

        /// Query device for vertex amplification support.
        ///
        /// Parameter `count`: The amplification count to check
        ///
        /// Returns: BOOL value. If YES, the device supports vertex amplification with the given count. If NO, the device does not.
        #[unsafe(method(supportsVertexAmplificationCount:))]
        #[unsafe(method_family = none)]
        fn supportsVertexAmplificationCount(&self, count: NSUInteger) -> bool;

        /// Query device support for creating and using dynamic libraries in a compute pipeline.
        ///
        /// Returns: BOOL value. If YES, the device supports creating and using dynamic libraries in a compute pipeline. If NO, the device does not.
        #[unsafe(method(supportsDynamicLibraries))]
        #[unsafe(method_family = none)]
        fn supportsDynamicLibraries(&self) -> bool;

        /// Query device support for creating and using dynamic libraries in render pipeline stages.
        ///
        /// Returns: BOOL value. If YES, the device supports creating and using dynamic libraries in render pipeline stages. If NO, the device does not.
        #[unsafe(method(supportsRenderDynamicLibraries))]
        #[unsafe(method_family = none)]
        fn supportsRenderDynamicLibraries(&self) -> bool;

        #[cfg(all(feature = "MTLDynamicLibrary", feature = "MTLLibrary"))]
        /// Creates a MTLDynamicLibrary by compiling the code in a MTLLibrary.
        ///
        /// See: MTLDynamicLibrary
        ///
        /// Parameter `library`: The MTLLibrary from which to compile code. This library must have .type set to MTLLibraryTypeDynamic.
        ///
        /// Parameter `error`: If an error occurs during creation, this parameter is updated to describe the failure.
        ///
        /// Returns: On success, the MTLDynamicLibrary containing compiled code. On failure, nil.
        #[unsafe(method(newDynamicLibrary:error:_))]
        #[unsafe(method_family = new)]
        fn newDynamicLibrary_error(
            &self,
            library: &ProtocolObject<dyn MTLLibrary>,
        ) -> Result<Retained<ProtocolObject<dyn MTLDynamicLibrary>>, Retained<NSError>>;

        #[cfg(feature = "MTLDynamicLibrary")]
        /// Creates a MTLDynamicLibrary by loading compiled code from a file.
        ///
        /// See: MTLDynamicLibrary
        ///
        /// Parameter `url`: The file URL from which to load. If the file contains no compiled code for this device, compilation is attempted as with newDynamicLibrary:error:
        ///
        /// Parameter `error`: If an error occurs during creation, this parameter is updated to describe the failure.
        ///
        /// Returns: On success, the MTLDynamicLibrary containing compiled code (either loaded or compiled). On failure, nil.
        #[unsafe(method(newDynamicLibraryWithURL:error:_))]
        #[unsafe(method_family = new)]
        fn newDynamicLibraryWithURL_error(
            &self,
            url: &NSURL,
        ) -> Result<Retained<ProtocolObject<dyn MTLDynamicLibrary>>, Retained<NSError>>;

        #[cfg(feature = "MTLBinaryArchive")]
        /// Creates a MTLBinaryArchive using the configuration in the descriptor.
        ///
        /// See: MTLBinaryArchive
        ///
        /// Parameter `descriptor`: The descriptor for the configuration of the binary archive to create.
        ///
        /// Parameter `error`: If an error occurs during creation, this parameter is updated to describe the failure.
        ///
        /// Returns: On success, the created MTLBinaryArchive. On failure, nil.
        #[unsafe(method(newBinaryArchiveWithDescriptor:error:_))]
        #[unsafe(method_family = new)]
        fn newBinaryArchiveWithDescriptor_error(
            &self,
            descriptor: &MTLBinaryArchiveDescriptor,
        ) -> Result<Retained<ProtocolObject<dyn MTLBinaryArchive>>, Retained<NSError>>;

        /// Query device support for using ray tracing from compute pipelines.
        ///
        /// Returns: BOOL value. If YES, the device supports ray tracing from compute pipelines. If NO, the device does not.
        #[unsafe(method(supportsRaytracing))]
        #[unsafe(method_family = none)]
        fn supportsRaytracing(&self) -> bool;

        #[cfg(feature = "MTLAccelerationStructure")]
        #[unsafe(method(accelerationStructureSizesWithDescriptor:))]
        #[unsafe(method_family = none)]
        fn accelerationStructureSizesWithDescriptor(
            &self,
            descriptor: &MTLAccelerationStructureDescriptor,
        ) -> MTLAccelerationStructureSizes;

        #[cfg(all(
            feature = "MTLAccelerationStructure",
            feature = "MTLAllocation",
            feature = "MTLResource"
        ))]
        #[unsafe(method(newAccelerationStructureWithSize:))]
        #[unsafe(method_family = new)]
        fn newAccelerationStructureWithSize(
            &self,
            size: NSUInteger,
        ) -> Option<Retained<ProtocolObject<dyn MTLAccelerationStructure>>>;

        #[cfg(all(
            feature = "MTLAccelerationStructure",
            feature = "MTLAllocation",
            feature = "MTLResource"
        ))]
        #[unsafe(method(newAccelerationStructureWithDescriptor:))]
        #[unsafe(method_family = new)]
        fn newAccelerationStructureWithDescriptor(
            &self,
            descriptor: &MTLAccelerationStructureDescriptor,
        ) -> Option<Retained<ProtocolObject<dyn MTLAccelerationStructure>>>;

        /// Determine the byte size of acceleration structures when sub-allocated from a heap.
        ///
        /// This method can be used to help determine the required heap size.
        ///
        /// # Safety
        ///
        /// `size` might not be bounds-checked.
        #[unsafe(method(heapAccelerationStructureSizeAndAlignWithSize:))]
        #[unsafe(method_family = none)]
        unsafe fn heapAccelerationStructureSizeAndAlignWithSize(
            &self,
            size: NSUInteger,
        ) -> MTLSizeAndAlign;

        #[cfg(feature = "MTLAccelerationStructure")]
        /// Determine the byte size of acceleration structures when sub-allocated from a heap. This is a convenience method which computes the acceleration structure size based on the descriptor.
        ///
        /// This method can be used to help determine the required heap size.
        #[unsafe(method(heapAccelerationStructureSizeAndAlignWithDescriptor:))]
        #[unsafe(method_family = none)]
        fn heapAccelerationStructureSizeAndAlignWithDescriptor(
            &self,
            descriptor: &MTLAccelerationStructureDescriptor,
        ) -> MTLSizeAndAlign;

        /// Query device support for using function pointers from compute pipelines.
        ///
        /// Returns: BOOL value. If YES, the device supports function pointers from compute pipelines. If NO, the device does not.
        #[unsafe(method(supportsFunctionPointers))]
        #[unsafe(method_family = none)]
        fn supportsFunctionPointers(&self) -> bool;

        /// Query device support for using function pointers from render pipeline stages.
        ///
        /// Returns: BOOL value. If YES, the device supports function pointers from render pipeline stages. If NO, the device does not.
        #[unsafe(method(supportsFunctionPointersFromRender))]
        #[unsafe(method_family = none)]
        fn supportsFunctionPointersFromRender(&self) -> bool;

        /// Query device support for using ray tracing from render pipeline stages.
        ///
        /// Returns: BOOL value. If YES, the device supports ray tracing from render pipeline stages. If NO, the device does not.
        #[unsafe(method(supportsRaytracingFromRender))]
        #[unsafe(method_family = none)]
        fn supportsRaytracingFromRender(&self) -> bool;

        /// Query device support for using ray tracing primitive motion blur.
        ///
        /// Returns: BOOL value. If YES, the device supports the primitive motion blur api. If NO, the device does not.
        #[unsafe(method(supportsPrimitiveMotionBlur))]
        #[unsafe(method_family = none)]
        fn supportsPrimitiveMotionBlur(&self) -> bool;

        /// Allow this device to use additional CPU threads (scaled automatically to the host machine) to be used for compilation tasks. Default is `NO`.
        ///
        /// Use the `maximumConcurrentCompilationTaskCount` property to determine the current number of concurrent CPU threads that this device is using.
        #[unsafe(method(shouldMaximizeConcurrentCompilation))]
        #[unsafe(method_family = none)]
        fn shouldMaximizeConcurrentCompilation(&self) -> bool;

        /// Setter for [`shouldMaximizeConcurrentCompilation`][Self::shouldMaximizeConcurrentCompilation].
        #[unsafe(method(setShouldMaximizeConcurrentCompilation:))]
        #[unsafe(method_family = none)]
        fn setShouldMaximizeConcurrentCompilation(
            &self,
            should_maximize_concurrent_compilation: bool,
        );

        /// Returns the maximum count of concurrent executing compilation tasks.
        ///
        /// The property returns a different value depending on the value of the property `shouldMaximizeConcurrentCompilation`.
        #[unsafe(method(maximumConcurrentCompilationTaskCount))]
        #[unsafe(method_family = none)]
        fn maximumConcurrentCompilationTaskCount(&self) -> NSUInteger;

        #[cfg(feature = "MTLResidencySet")]
        /// Creates a new residency set with a descriptor.
        #[unsafe(method(newResidencySetWithDescriptor:error:_))]
        #[unsafe(method_family = new)]
        fn newResidencySetWithDescriptor_error(
            &self,
            desc: &MTLResidencySetDescriptor,
        ) -> Result<Retained<ProtocolObject<dyn MTLResidencySet>>, Retained<NSError>>;

        #[cfg(feature = "MTLTensor")]
        /// Determines the size and alignment required to hold the data of a tensor you create with a descriptor in a buffer.
        ///
        /// - Parameters:
        /// - descriptor: A description of the properties for the new tensor.
        /// - Returns: The size and alignment required to hold the data of a tensor you create with `descriptor` in a buffer.
        #[unsafe(method(tensorSizeAndAlignWithDescriptor:))]
        #[unsafe(method_family = none)]
        fn tensorSizeAndAlignWithDescriptor(
            &self,
            descriptor: &MTLTensorDescriptor,
        ) -> MTLSizeAndAlign;

        #[cfg(all(
            feature = "MTLAllocation",
            feature = "MTLResource",
            feature = "MTLTensor"
        ))]
        /// Creates a tensor by allocating new memory.
        ///
        /// - Parameters:
        /// - descriptor: A description of the properties for the new tensor.
        /// - error: Metal populates this parameter with information in case an error occurs.
        /// - Returns: A new tensor instance that Metal configures using `descriptor` or `nil` if an error occurred.
        #[unsafe(method(newTensorWithDescriptor:error:_))]
        #[unsafe(method_family = new)]
        fn newTensorWithDescriptor_error(
            &self,
            descriptor: &MTLTensorDescriptor,
        ) -> Result<Retained<ProtocolObject<dyn MTLTensor>>, Retained<NSError>>;

        #[cfg(all(feature = "MTLFunctionHandle", feature = "MTLLibrary"))]
        /// Returns the function handle for a function that was compiled with MTLFunctionOptionPipelineIndependent and MTLFunctionOptionCompileToBinary.
        ///
        /// # Safety
        ///
        /// - `function` must be safe to call.
        /// - `function` must have the correct argument and return types.
        #[unsafe(method(functionHandleWithFunction:))]
        #[unsafe(method_family = none)]
        unsafe fn functionHandleWithFunction(
            &self,
            function: &ProtocolObject<dyn MTLFunction>,
        ) -> Option<Retained<ProtocolObject<dyn MTLFunctionHandle>>>;

        #[cfg(feature = "MTL4CommandAllocator")]
        /// Creates a new command allocator.
        ///
        /// - Returns: A ``MTL4CommandAllocator`` instance, or `nil` if the function failed.
        #[unsafe(method(newCommandAllocator))]
        #[unsafe(method_family = new)]
        fn newCommandAllocator(&self)
            -> Option<Retained<ProtocolObject<dyn MTL4CommandAllocator>>>;

        #[cfg(feature = "MTL4CommandAllocator")]
        /// Creates a new command allocator from a command allocator descriptor.
        ///
        /// - Parameters:
        /// - descriptor: A ``MTL4CommandAllocatorDescriptor`` instance that configures the
        /// ``MTL4CommandAllocator`` instance.
        /// - error:      Optional pointer to a `NSError` instance that Metal uses to describe the failure
        /// if this function fails.
        ///
        /// - Returns: A ``MTL4CommandAllocator`` instance, or `nil` if the function failed.
        #[unsafe(method(newCommandAllocatorWithDescriptor:error:_))]
        #[unsafe(method_family = new)]
        fn newCommandAllocatorWithDescriptor_error(
            &self,
            descriptor: &MTL4CommandAllocatorDescriptor,
        ) -> Result<Retained<ProtocolObject<dyn MTL4CommandAllocator>>, Retained<NSError>>;

        #[cfg(feature = "MTL4CommandQueue")]
        /// Creates a new command queue.
        ///
        /// - Returns: A ``MTL4CommandQueue`` instance, or `nil` if the function failed.
        #[unsafe(method(newMTL4CommandQueue))]
        #[unsafe(method_family = new)]
        fn newMTL4CommandQueue(&self) -> Option<Retained<ProtocolObject<dyn MTL4CommandQueue>>>;

        #[cfg(feature = "MTL4CommandQueue")]
        /// Creates a new command queue from a queue descriptor.
        ///
        /// - Parameters:
        /// - descriptor: A ``MTL4CommandQueueDescriptor`` instance that configures the
        /// ``MTL4CommandQueue`` instance.
        /// - error:      Optional pointer to a `NSError` instance that Metal uses to describe the failure
        /// if this function fails.
        ///
        /// - Returns: A ``MTL4CommandQueue`` instance, or `nil` if the function failed.
        #[unsafe(method(newMTL4CommandQueueWithDescriptor:error:_))]
        #[unsafe(method_family = new)]
        fn newMTL4CommandQueueWithDescriptor_error(
            &self,
            descriptor: &MTL4CommandQueueDescriptor,
        ) -> Result<Retained<ProtocolObject<dyn MTL4CommandQueue>>, Retained<NSError>>;

        #[cfg(feature = "MTL4CommandBuffer")]
        /// Creates a new command buffer.
        ///
        /// - Returns: A ``MTL4CommandBuffer`` instance, or `nil` if the function failed.
        #[unsafe(method(newCommandBuffer))]
        #[unsafe(method_family = new)]
        fn newCommandBuffer(&self) -> Option<Retained<ProtocolObject<dyn MTL4CommandBuffer>>>;

        #[cfg(feature = "MTL4ArgumentTable")]
        /// Creates a new argument table from an argument table descriptor.
        ///
        /// - Parameters:
        /// - descriptor: A ``MTL4ArgumentTableDescriptor`` instance that configures the
        /// ``MTL4ArgumentTable`` instance.
        /// - error:      Optional pointer to a `NSError` instance that Metal uses to describe the failure
        /// if this function fails.
        ///
        /// - Returns: A ``MTL4ArgumentTable`` instance, or `nil` if the function failed.
        #[unsafe(method(newArgumentTableWithDescriptor:error:_))]
        #[unsafe(method_family = new)]
        fn newArgumentTableWithDescriptor_error(
            &self,
            descriptor: &MTL4ArgumentTableDescriptor,
        ) -> Result<Retained<ProtocolObject<dyn MTL4ArgumentTable>>, Retained<NSError>>;

        #[cfg(all(feature = "MTLResourceViewPool", feature = "MTLTextureViewPool"))]
        /// Creates a new texture view pool from a resource view pool descriptor.
        ///
        /// - Parameters:
        /// - descriptor: A ``MTLResourceViewPoolDescriptor`` instance that configures the
        /// ``MTLTextureViewPool`` instance.
        /// - error:      Optional pointer to a `NSError` instance that Metal uses to describe the failure
        /// if this function fails.
        ///
        /// - Returns: A ``MTLTextureViewPool`` instance, or `nil` if the function failed.
        #[unsafe(method(newTextureViewPoolWithDescriptor:error:_))]
        #[unsafe(method_family = new)]
        fn newTextureViewPoolWithDescriptor_error(
            &self,
            descriptor: &MTLResourceViewPoolDescriptor,
        ) -> Result<Retained<ProtocolObject<dyn MTLTextureViewPool>>, Retained<NSError>>;

        #[cfg(feature = "MTL4Compiler")]
        /// Creates a new compiler from a compiler descriptor.
        ///
        /// - Parameters:
        /// - descriptor: A ``MTL4CompilerDescriptor`` instance that configures the
        /// ``MTL4Compiler`` instance.
        /// - error:      Optional pointer to a `NSError` instance that Metal uses to describe the failure
        /// if this function fails.
        ///
        /// - Returns: A ``MTL4Compiler`` instance, or `nil` if the function failed.
        #[unsafe(method(newCompilerWithDescriptor:error:_))]
        #[unsafe(method_family = new)]
        fn newCompilerWithDescriptor_error(
            &self,
            descriptor: &MTL4CompilerDescriptor,
        ) -> Result<Retained<ProtocolObject<dyn MTL4Compiler>>, Retained<NSError>>;

        #[cfg(feature = "MTL4Archive")]
        /// Creates a new archive from data available at an `NSURL` address.
        ///
        /// - Parameters:
        /// - url:   An `NSURL` instance that represents the path from which the device loads the ``MTL4Archive``.
        /// - error:      Optional pointer to a `NSError` instance that Metal uses to describe the failure
        /// if this function fails.
        ///
        /// - Returns: A ``MTL4Archive`` instance, or `nil` if the function failed.
        #[unsafe(method(newArchiveWithURL:error:_))]
        #[unsafe(method_family = new)]
        fn newArchiveWithURL_error(
            &self,
            url: &NSURL,
        ) -> Result<Retained<ProtocolObject<dyn MTL4Archive>>, Retained<NSError>>;

        #[cfg(feature = "MTL4PipelineDataSetSerializer")]
        /// Creates a new pipeline data set serializer instance from a descriptor.
        ///
        /// - Parameter descriptor: A ``MTL4PipelineDataSetSerializerDescriptor`` instance that configures
        /// the new ``MTL4PipelineDataSetSerializer`` instance.
        ///
        /// - Returns: A ``MTL4PipelineDataSetSerializer`` instance, or `nil` if the function failed.
        #[unsafe(method(newPipelineDataSetSerializerWithDescriptor:))]
        #[unsafe(method_family = new)]
        fn newPipelineDataSetSerializerWithDescriptor(
            &self,
            descriptor: &MTL4PipelineDataSetSerializerDescriptor,
        ) -> Retained<ProtocolObject<dyn MTL4PipelineDataSetSerializer>>;

        #[cfg(all(
            feature = "MTLAllocation",
            feature = "MTLBuffer",
            feature = "MTLResource"
        ))]
        /// Creates a new placement sparse buffer of a specific length.
        ///
        /// This method creates a new placement sparse ``MTLBuffer`` of a specific length. You assign memory to
        /// placement sparse buffers using a ``MTLHeap`` of type ``MTLHeapType/MTLHeapTypePlacement``.
        ///
        /// - Parameters:
        /// - length:                  The size of the ``MTLBuffer``, in bytes.
        /// - options:                 A ``MTLResourceOptions`` instance that establishes the buffer’s storage modes.
        /// - placementSparsePageSize: ``MTLSparsePageSize`` to use for the placement sparse buffer.
        ///
        /// - Returns: A ``MTLBuffer`` instance, or `nil` if the function failed.
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(newBufferWithLength:options:placementSparsePageSize:))]
        #[unsafe(method_family = new)]
        unsafe fn newBufferWithLength_options_placementSparsePageSize(
            &self,
            length: NSUInteger,
            options: MTLResourceOptions,
            placement_sparse_page_size: MTLSparsePageSize,
        ) -> Option<Retained<ProtocolObject<dyn MTLBuffer>>>;

        #[cfg(feature = "MTL4Counters")]
        /// Creates a new counter heap configured from a counter heap descriptor.
        ///
        /// - Parameters:
        /// - descriptor: ``MTL4CounterHeapDescriptor`` instance that configures the ``MTL4CounterHeap`` instance.
        /// - error:      Optional pointer to a `NSError` instance that Metal uses to describe the failure
        /// if this function fails.
        ///
        /// - Returns: A ``MTL4CounterHeap`` instance, or `nil` if the function failed.
        #[unsafe(method(newCounterHeapWithDescriptor:error:_))]
        #[unsafe(method_family = new)]
        fn newCounterHeapWithDescriptor_error(
            &self,
            descriptor: &MTL4CounterHeapDescriptor,
        ) -> Result<Retained<ProtocolObject<dyn MTL4CounterHeap>>, Retained<NSError>>;

        #[cfg(feature = "MTL4Counters")]
        /// Returns the size, in bytes, of each entry in a counter heap of a specific counter heap type when
        /// your app resolves it into a usable format.
        ///
        /// In order to use the data available in a ``MTL4CounterHeap``, your app first resolves it either in the CPU timeline
        /// or in the GPU timeline. When your app calls ``MTL4CommandBuffer/resolveCounterHeap:withRange:intoBuffer:waitFence:updateFence:``
        /// to resolve counter data in the GPU timeline, Metal writes the data into a ``MTLBuffer``.
        ///
        /// During this process, Metal transform the data in the heap into a format consisting of entries of the size
        /// that this method advertises, based on the ``MTL4CounterHeapType``.
        ///
        /// - Parameters:
        /// - type: ``MTL4CounterHeapType`` value that represents the type of the ``MTL4CounterHeap`` to resolve.
        ///
        /// - Returns: The size of the post-transformation entry from a ``MTL4CounterHeap`` of type ``MTL4CounterHeapType``.
        #[unsafe(method(sizeOfCounterHeapEntry:))]
        #[unsafe(method_family = none)]
        fn sizeOfCounterHeapEntry(&self, r#type: MTL4CounterHeapType) -> NSUInteger;

        /// Queries the frequency of the GPU timestamp in ticks per second.
        ///
        /// - Returns: The frequency of the GPU timestamp in ticks per second.
        #[unsafe(method(queryTimestampFrequency))]
        #[unsafe(method_family = none)]
        fn queryTimestampFrequency(&self) -> u64;

        #[cfg(all(feature = "MTL4BinaryFunction", feature = "MTLFunctionHandle"))]
        /// Get the function handle for the specified binary-linked function from the pipeline state.
        ///
        /// - Parameters:
        /// - function: A ``MTL4BinaryFunction`` instance representing the function binary.
        ///
        /// - Returns: A ``MTLFunctionHandle`` instance  for a binary function that was compiled with ``MTLFunctionOptionPipelineIndependent``, otherwise `nil`.
        #[unsafe(method(functionHandleWithBinaryFunction:))]
        #[unsafe(method_family = none)]
        fn functionHandleWithBinaryFunction(
            &self,
            function: &ProtocolObject<dyn MTL4BinaryFunction>,
        ) -> Option<Retained<ProtocolObject<dyn MTLFunctionHandle>>>;
    }
);
