//! This file has been automatically generated by `objc2`'s `header-translator`.
//! DO NOT EDIT
use core::ffi::*;
use core::ptr::NonNull;
use objc2::__framework_prelude::*;
use objc2_foundation::*;

use crate::*;

extern_class!(
    /// Base class for Metal 4 acceleration structure descriptors.
    ///
    /// Don't use this class directly. Use one of its subclasses instead.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtl4accelerationstructuredescriptor?language=objc)
    #[unsafe(super(MTLAccelerationStructureDescriptor, NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    #[cfg(feature = "MTLAccelerationStructure")]
    pub struct MTL4AccelerationStructureDescriptor;
);

#[cfg(feature = "MTLAccelerationStructure")]
extern_conformance!(
    unsafe impl NSCopying for MTL4AccelerationStructureDescriptor {}
);

#[cfg(feature = "MTLAccelerationStructure")]
unsafe impl CopyingHelper for MTL4AccelerationStructureDescriptor {
    type Result = Self;
}

#[cfg(feature = "MTLAccelerationStructure")]
extern_conformance!(
    unsafe impl NSObjectProtocol for MTL4AccelerationStructureDescriptor {}
);

#[cfg(feature = "MTLAccelerationStructure")]
impl MTL4AccelerationStructureDescriptor {
    extern_methods!();
}

/// Methods declared on superclass `NSObject`.
#[cfg(feature = "MTLAccelerationStructure")]
impl MTL4AccelerationStructureDescriptor {
    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>;
    );
}

#[cfg(feature = "MTLAccelerationStructure")]
impl DefaultRetained for MTL4AccelerationStructureDescriptor {
    #[inline]
    fn default_retained() -> Retained<Self> {
        Self::new()
    }
}

extern_class!(
    /// Base class for all Metal 4 acceleration structure geometry descriptors.
    ///
    /// Don't use this class directly. Use one of the derived classes instead.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtl4accelerationstructuregeometrydescriptor?language=objc)
    #[unsafe(super(NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct MTL4AccelerationStructureGeometryDescriptor;
);

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

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

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

impl MTL4AccelerationStructureGeometryDescriptor {
    extern_methods!(
        /// Sets the offset that this geometry contributes to determining the intersection function to invoke when a ray intersects it.
        ///
        /// When you perform a ray tracing operation in the Metal Shading Language, and provide the ray intersector object
        /// with an instance of ``MTLIntersectionFunctionTable``, Metal adds this offset to the instance offset from structs such
        /// as:
        ///
        /// - ``MTLAccelerationStructureInstanceDescriptor``
        /// - ``MTLAccelerationStructureUserIDInstanceDescriptor``
        /// - ``MTLAccelerationStructureMotionInstanceDescriptor``
        /// - ``MTLIndirectAccelerationStructureInstanceDescriptor``
        /// - ``MTLIndirectAccelerationStructureMotionInstanceDescriptor``
        ///
        /// The sum of these offsets provides an index into the intersection function table that the ray tracing system uses
        /// to retrieve and invoke the function at this index, allowing you to customize the intersection evaluation process.
        #[unsafe(method(intersectionFunctionTableOffset))]
        #[unsafe(method_family = none)]
        pub fn intersectionFunctionTableOffset(&self) -> NSUInteger;

        /// Setter for [`intersectionFunctionTableOffset`][Self::intersectionFunctionTableOffset].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setIntersectionFunctionTableOffset:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setIntersectionFunctionTableOffset(
            &self,
            intersection_function_table_offset: NSUInteger,
        );

        /// Provides a hint to Metal that this geometry is opaque, potentially accelerating the ray/primitive intersection process.
        #[unsafe(method(opaque))]
        #[unsafe(method_family = none)]
        pub fn opaque(&self) -> bool;

        /// Setter for [`opaque`][Self::opaque].
        #[unsafe(method(setOpaque:))]
        #[unsafe(method_family = none)]
        pub fn setOpaque(&self, opaque: bool);

        /// A boolean value that indicates whether the ray-tracing system in Metal allows the invocation of intersection functions
        /// more than once per ray-primitive intersection.
        ///
        /// The property's default value is
        /// <doc
        /// ://com.apple.documentation/documentation/swift/true>.
        #[unsafe(method(allowDuplicateIntersectionFunctionInvocation))]
        #[unsafe(method_family = none)]
        pub fn allowDuplicateIntersectionFunctionInvocation(&self) -> bool;

        /// Setter for [`allowDuplicateIntersectionFunctionInvocation`][Self::allowDuplicateIntersectionFunctionInvocation].
        #[unsafe(method(setAllowDuplicateIntersectionFunctionInvocation:))]
        #[unsafe(method_family = none)]
        pub fn setAllowDuplicateIntersectionFunctionInvocation(
            &self,
            allow_duplicate_intersection_function_invocation: bool,
        );

        /// Assigns an optional label you can assign to this geometry for debugging purposes.
        #[unsafe(method(label))]
        #[unsafe(method_family = none)]
        pub fn label(&self) -> Option<Retained<NSString>>;

        /// Setter for [`label`][Self::label].
        ///
        /// This is [copied][objc2_foundation::NSCopying::copy] when set.
        #[unsafe(method(setLabel:))]
        #[unsafe(method_family = none)]
        pub fn setLabel(&self, label: Option<&NSString>);

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Assigns optional buffer containing data to associate with each primitive in this geometry.
        ///
        /// You can use zero as the buffer address in this buffer range.
        #[unsafe(method(primitiveDataBuffer))]
        #[unsafe(method_family = none)]
        pub fn primitiveDataBuffer(&self) -> MTL4BufferRange;

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Setter for [`primitiveDataBuffer`][Self::primitiveDataBuffer].
        #[unsafe(method(setPrimitiveDataBuffer:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setPrimitiveDataBuffer(&self, primitive_data_buffer: MTL4BufferRange);

        /// Defines the stride, in bytes, between each primitive's data in the primitive data buffer ``primitiveDataBuffer`` references.
        ///
        /// You are responsible for ensuring the stride is at least ``primitiveDataElementSize`` in size and a multiple of 4 bytes.
        ///
        /// This property defaults to `0` bytes,  which indicates the stride is equal to ``primitiveDataElementSize``.
        #[unsafe(method(primitiveDataStride))]
        #[unsafe(method_family = none)]
        pub fn primitiveDataStride(&self) -> NSUInteger;

        /// Setter for [`primitiveDataStride`][Self::primitiveDataStride].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setPrimitiveDataStride:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setPrimitiveDataStride(&self, primitive_data_stride: NSUInteger);

        /// Sets the size, in bytes, of the data for each primitive in the primitive data buffer ``primitiveDataBuffer`` references.
        ///
        /// This size needs to be at most ``primitiveDataStride`` in size and a multiple of 4 bytes.
        ///
        /// This property defaults to 0 bytes.
        #[unsafe(method(primitiveDataElementSize))]
        #[unsafe(method_family = none)]
        pub fn primitiveDataElementSize(&self) -> NSUInteger;

        /// Setter for [`primitiveDataElementSize`][Self::primitiveDataElementSize].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setPrimitiveDataElementSize:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setPrimitiveDataElementSize(&self, primitive_data_element_size: NSUInteger);
    );
}

/// Methods declared on superclass `NSObject`.
impl MTL4AccelerationStructureGeometryDescriptor {
    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 MTL4AccelerationStructureGeometryDescriptor {
    #[inline]
    fn default_retained() -> Retained<Self> {
        Self::new()
    }
}

extern_class!(
    /// Descriptor for a primitive acceleration structure that directly references geometric shapes, such as triangles and
    /// bounding boxes.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtl4primitiveaccelerationstructuredescriptor?language=objc)
    #[unsafe(super(
        MTL4AccelerationStructureDescriptor,
        MTLAccelerationStructureDescriptor,
        NSObject
    ))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    #[cfg(feature = "MTLAccelerationStructure")]
    pub struct MTL4PrimitiveAccelerationStructureDescriptor;
);

#[cfg(feature = "MTLAccelerationStructure")]
extern_conformance!(
    unsafe impl NSCopying for MTL4PrimitiveAccelerationStructureDescriptor {}
);

#[cfg(feature = "MTLAccelerationStructure")]
unsafe impl CopyingHelper for MTL4PrimitiveAccelerationStructureDescriptor {
    type Result = Self;
}

#[cfg(feature = "MTLAccelerationStructure")]
extern_conformance!(
    unsafe impl NSObjectProtocol for MTL4PrimitiveAccelerationStructureDescriptor {}
);

#[cfg(feature = "MTLAccelerationStructure")]
impl MTL4PrimitiveAccelerationStructureDescriptor {
    extern_methods!(
        /// Associates the array of geometry descriptors that comprise this primitive acceleration structure.
        ///
        /// If you enable keyframe motion by setting property ``motionKeyframeCount`` to a value greater than `1`, then
        /// all geometry descriptors this array references need to be motion geometry descriptors and have a number of
        /// primitive buffers equals to ``motionKeyframeCount``.
        ///
        /// Example of motion geometry descriptors include: ``MTL4AccelerationStructureMotionTriangleGeometryDescriptor``,
        /// ``MTL4AccelerationStructureMotionBoundingBoxGeometryDescriptor``, ``MTL4AccelerationStructureMotionCurveGeometryDescriptor``.
        #[unsafe(method(geometryDescriptors))]
        #[unsafe(method_family = none)]
        pub fn geometryDescriptors(
            &self,
        ) -> Option<Retained<NSArray<MTL4AccelerationStructureGeometryDescriptor>>>;

        /// Setter for [`geometryDescriptors`][Self::geometryDescriptors].
        #[unsafe(method(setGeometryDescriptors:))]
        #[unsafe(method_family = none)]
        pub fn setGeometryDescriptors(
            &self,
            geometry_descriptors: Option<&NSArray<MTL4AccelerationStructureGeometryDescriptor>>,
        );

        /// Configures the behavior when the ray-tracing system samples the acceleration structure before the motion start time.
        ///
        /// Use this property to control the behavior when the ray-tracing system samples the acceleration structure
        /// at a time prior to the one you set for ``motionStartTime``.
        ///
        /// The default value of this property is `MTLMotionBorderModeClamp`.
        #[unsafe(method(motionStartBorderMode))]
        #[unsafe(method_family = none)]
        pub fn motionStartBorderMode(&self) -> MTLMotionBorderMode;

        /// Setter for [`motionStartBorderMode`][Self::motionStartBorderMode].
        #[unsafe(method(setMotionStartBorderMode:))]
        #[unsafe(method_family = none)]
        pub fn setMotionStartBorderMode(&self, motion_start_border_mode: MTLMotionBorderMode);

        /// Configures the motion border mode.
        ///
        /// This property controls what happens if Metal samples the acceleration structure after ``motionEndTime``.
        ///
        /// Its default value is `MTLMotionBorderModeClamp`.
        #[unsafe(method(motionEndBorderMode))]
        #[unsafe(method_family = none)]
        pub fn motionEndBorderMode(&self) -> MTLMotionBorderMode;

        /// Setter for [`motionEndBorderMode`][Self::motionEndBorderMode].
        #[unsafe(method(setMotionEndBorderMode:))]
        #[unsafe(method_family = none)]
        pub fn setMotionEndBorderMode(&self, motion_end_border_mode: MTLMotionBorderMode);

        /// Configures the motion start time for this geometry.
        ///
        /// The default value of this property is `0.0f`.
        #[unsafe(method(motionStartTime))]
        #[unsafe(method_family = none)]
        pub fn motionStartTime(&self) -> c_float;

        /// Setter for [`motionStartTime`][Self::motionStartTime].
        #[unsafe(method(setMotionStartTime:))]
        #[unsafe(method_family = none)]
        pub fn setMotionStartTime(&self, motion_start_time: c_float);

        /// Configures the motion end time for this geometry.
        ///
        /// The default value of this property is `1.0f`.
        #[unsafe(method(motionEndTime))]
        #[unsafe(method_family = none)]
        pub fn motionEndTime(&self) -> c_float;

        /// Setter for [`motionEndTime`][Self::motionEndTime].
        #[unsafe(method(setMotionEndTime:))]
        #[unsafe(method_family = none)]
        pub fn setMotionEndTime(&self, motion_end_time: c_float);

        /// Sets the motion keyframe count.
        ///
        /// This property's default is `1`, indicating no motion.
        #[unsafe(method(motionKeyframeCount))]
        #[unsafe(method_family = none)]
        pub fn motionKeyframeCount(&self) -> NSUInteger;

        /// Setter for [`motionKeyframeCount`][Self::motionKeyframeCount].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setMotionKeyframeCount:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setMotionKeyframeCount(&self, motion_keyframe_count: NSUInteger);
    );
}

/// Methods declared on superclass `NSObject`.
#[cfg(feature = "MTLAccelerationStructure")]
impl MTL4PrimitiveAccelerationStructureDescriptor {
    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>;
    );
}

#[cfg(feature = "MTLAccelerationStructure")]
impl DefaultRetained for MTL4PrimitiveAccelerationStructureDescriptor {
    #[inline]
    fn default_retained() -> Retained<Self> {
        Self::new()
    }
}

extern_class!(
    /// Describes triangle geometry suitable for ray tracing.
    ///
    /// Use a ``MTLResidencySet`` to mark residency of all buffers this descriptor references when you build this
    /// acceleration structure.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtl4accelerationstructuretrianglegeometrydescriptor?language=objc)
    #[unsafe(super(MTL4AccelerationStructureGeometryDescriptor, NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct MTL4AccelerationStructureTriangleGeometryDescriptor;
);

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

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

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

impl MTL4AccelerationStructureTriangleGeometryDescriptor {
    extern_methods!(
        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Associates a vertex buffer containing triangle vertices.
        ///
        /// You are responsible for ensuring that the format of all vertex positions match the ``vertexFormat`` property, and
        /// that the buffer address for the buffer range is not zero.
        #[unsafe(method(vertexBuffer))]
        #[unsafe(method_family = none)]
        pub fn vertexBuffer(&self) -> MTL4BufferRange;

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Setter for [`vertexBuffer`][Self::vertexBuffer].
        #[unsafe(method(setVertexBuffer:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setVertexBuffer(&self, vertex_buffer: MTL4BufferRange);

        #[cfg(feature = "MTLStageInputOutputDescriptor")]
        /// Describes the format of the vertices in the vertex buffer.
        ///
        /// This property controls the format of the position attribute of the vertices the ``vertexBuffer`` references.
        ///
        /// The format defaults to `MTLAttributeFormatFloat3`, corresponding to three packed floating point numbers.
        #[unsafe(method(vertexFormat))]
        #[unsafe(method_family = none)]
        pub fn vertexFormat(&self) -> MTLAttributeFormat;

        #[cfg(feature = "MTLStageInputOutputDescriptor")]
        /// Setter for [`vertexFormat`][Self::vertexFormat].
        #[unsafe(method(setVertexFormat:))]
        #[unsafe(method_family = none)]
        pub fn setVertexFormat(&self, vertex_format: MTLAttributeFormat);

        /// Sets the stride, in bytes, between vertices in the vertex buffer.
        ///
        /// The stride you specify needs to be a multiple of the size of the vertex format you provide in the ``vertexFormat``
        /// property. Similarly, you are responsible for ensuring this stride matches the vertex format data type's alignment.
        ///
        /// Defaults to `0`, which signals the stride matches the size of the ``vertexFormat`` data.
        #[unsafe(method(vertexStride))]
        #[unsafe(method_family = none)]
        pub fn vertexStride(&self) -> NSUInteger;

        /// Setter for [`vertexStride`][Self::vertexStride].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setVertexStride:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setVertexStride(&self, vertex_stride: NSUInteger);

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Sets an optional index buffer containing references to vertices in the `vertexBuffer`.
        ///
        /// You can set this property to `0`, the default, to avoid specifying an index buffer.
        #[unsafe(method(indexBuffer))]
        #[unsafe(method_family = none)]
        pub fn indexBuffer(&self) -> MTL4BufferRange;

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Setter for [`indexBuffer`][Self::indexBuffer].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setIndexBuffer:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setIndexBuffer(&self, index_buffer: MTL4BufferRange);

        #[cfg(feature = "MTLArgument")]
        /// Configures the size of the indices the `indexBuffer` contains, which is typically either 16 or 32-bits for each index.
        #[unsafe(method(indexType))]
        #[unsafe(method_family = none)]
        pub fn indexType(&self) -> MTLIndexType;

        #[cfg(feature = "MTLArgument")]
        /// Setter for [`indexType`][Self::indexType].
        #[unsafe(method(setIndexType:))]
        #[unsafe(method_family = none)]
        pub fn setIndexType(&self, index_type: MTLIndexType);

        /// Declares the number of triangles in this geometry descriptor.
        #[unsafe(method(triangleCount))]
        #[unsafe(method_family = none)]
        pub fn triangleCount(&self) -> NSUInteger;

        /// Setter for [`triangleCount`][Self::triangleCount].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setTriangleCount:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setTriangleCount(&self, triangle_count: NSUInteger);

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Assigns an optional reference to a buffer containing a `float4x3` transformation matrix.
        ///
        /// When the buffer address is non-zero, Metal applies this transform to the vertex data positions when building
        /// the acceleration structure.
        ///
        /// Building an acceleration structure with a descriptor that specifies this property doesn't modify the contents of
        /// the input `vertexBuffer`.
        #[unsafe(method(transformationMatrixBuffer))]
        #[unsafe(method_family = none)]
        pub fn transformationMatrixBuffer(&self) -> MTL4BufferRange;

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Setter for [`transformationMatrixBuffer`][Self::transformationMatrixBuffer].
        #[unsafe(method(setTransformationMatrixBuffer:))]
        #[unsafe(method_family = none)]
        pub fn setTransformationMatrixBuffer(&self, transformation_matrix_buffer: MTL4BufferRange);

        #[cfg(feature = "MTLAccelerationStructure")]
        /// Configures the layout for the transformation matrix in the transformation matrix buffer.
        ///
        /// You can provide matrices in column-major or row-major form, and this property allows you to control
        /// how Metal interprets them.
        ///
        /// Defaults to `MTLMatrixLayoutColumnMajor`.
        #[unsafe(method(transformationMatrixLayout))]
        #[unsafe(method_family = none)]
        pub fn transformationMatrixLayout(&self) -> MTLMatrixLayout;

        #[cfg(feature = "MTLAccelerationStructure")]
        /// Setter for [`transformationMatrixLayout`][Self::transformationMatrixLayout].
        #[unsafe(method(setTransformationMatrixLayout:))]
        #[unsafe(method_family = none)]
        pub fn setTransformationMatrixLayout(&self, transformation_matrix_layout: MTLMatrixLayout);
    );
}

/// Methods declared on superclass `NSObject`.
impl MTL4AccelerationStructureTriangleGeometryDescriptor {
    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 MTL4AccelerationStructureTriangleGeometryDescriptor {
    #[inline]
    fn default_retained() -> Retained<Self> {
        Self::new()
    }
}

extern_class!(
    /// Describes bounding-box geometry suitable for ray tracing.
    ///
    /// You use bounding boxes to implement procedural geometry for ray tracing, such as spheres or any other shape
    /// you define by using intersection functions.
    ///
    /// Use a ``MTLResidencySet`` to mark residency of all buffers this descriptor references when you build this
    /// acceleration structure.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtl4accelerationstructureboundingboxgeometrydescriptor?language=objc)
    #[unsafe(super(MTL4AccelerationStructureGeometryDescriptor, NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct MTL4AccelerationStructureBoundingBoxGeometryDescriptor;
);

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

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

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

impl MTL4AccelerationStructureBoundingBoxGeometryDescriptor {
    extern_methods!(
        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// References a buffer containing bounding box data in `MTLAxisAlignedBoundingBoxes` format.
        ///
        /// You are responsible for ensuring the buffer address of the range is not zero.
        #[unsafe(method(boundingBoxBuffer))]
        #[unsafe(method_family = none)]
        pub fn boundingBoxBuffer(&self) -> MTL4BufferRange;

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Setter for [`boundingBoxBuffer`][Self::boundingBoxBuffer].
        #[unsafe(method(setBoundingBoxBuffer:))]
        #[unsafe(method_family = none)]
        pub fn setBoundingBoxBuffer(&self, bounding_box_buffer: MTL4BufferRange);

        /// Assigns the stride, in bytes, between bounding boxes in the bounding box buffer `boundingBoxBuffer` references.
        ///
        /// You are responsible for ensuring this stride is at least 24 bytes and a multiple of 4 bytes.
        ///
        /// This property defaults to `24` bytes.
        #[unsafe(method(boundingBoxStride))]
        #[unsafe(method_family = none)]
        pub fn boundingBoxStride(&self) -> NSUInteger;

        /// Setter for [`boundingBoxStride`][Self::boundingBoxStride].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setBoundingBoxStride:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setBoundingBoxStride(&self, bounding_box_stride: NSUInteger);

        /// Describes the number of bounding boxes the `boundingBoxBuffer` contains.
        #[unsafe(method(boundingBoxCount))]
        #[unsafe(method_family = none)]
        pub fn boundingBoxCount(&self) -> NSUInteger;

        /// Setter for [`boundingBoxCount`][Self::boundingBoxCount].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setBoundingBoxCount:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setBoundingBoxCount(&self, bounding_box_count: NSUInteger);
    );
}

/// Methods declared on superclass `NSObject`.
impl MTL4AccelerationStructureBoundingBoxGeometryDescriptor {
    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 MTL4AccelerationStructureBoundingBoxGeometryDescriptor {
    #[inline]
    fn default_retained() -> Retained<Self> {
        Self::new()
    }
}

extern_class!(
    /// Describes motion triangle geometry, suitable for motion ray tracing.
    ///
    /// Use a ``MTLResidencySet`` to mark residency of all buffers this descriptor references when you build this
    /// acceleration structure.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtl4accelerationstructuremotiontrianglegeometrydescriptor?language=objc)
    #[unsafe(super(MTL4AccelerationStructureGeometryDescriptor, NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct MTL4AccelerationStructureMotionTriangleGeometryDescriptor;
);

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

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

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

impl MTL4AccelerationStructureMotionTriangleGeometryDescriptor {
    extern_methods!(
        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Assigns a buffer where each entry contains a reference to a vertex buffer.
        ///
        /// This property references a buffer that conceptually represents an array with one entry for each keyframe in the
        /// motion animation. Each one of these entries consists of a ``MTL4BufferRange`` that, in turn, references a
        /// vertex buffer containing the vertex data for the keyframe.
        ///
        /// You are responsible for ensuring the buffer address is not zero for the top-level buffer, as well as for all
        /// the vertex buffers it references.
        #[unsafe(method(vertexBuffers))]
        #[unsafe(method_family = none)]
        pub fn vertexBuffers(&self) -> MTL4BufferRange;

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Setter for [`vertexBuffers`][Self::vertexBuffers].
        #[unsafe(method(setVertexBuffers:))]
        #[unsafe(method_family = none)]
        pub fn setVertexBuffers(&self, vertex_buffers: MTL4BufferRange);

        #[cfg(feature = "MTLStageInputOutputDescriptor")]
        /// Defines the format of the vertices in the vertex buffers.
        ///
        /// All keyframes share the same vertex format. Defaults to `MTLAttributeFormatFloat3`, corresponding to three packed
        /// floating point numbers.
        #[unsafe(method(vertexFormat))]
        #[unsafe(method_family = none)]
        pub fn vertexFormat(&self) -> MTLAttributeFormat;

        #[cfg(feature = "MTLStageInputOutputDescriptor")]
        /// Setter for [`vertexFormat`][Self::vertexFormat].
        #[unsafe(method(setVertexFormat:))]
        #[unsafe(method_family = none)]
        pub fn setVertexFormat(&self, vertex_format: MTLAttributeFormat);

        /// Sets the stride, in bytes, between vertices in all the vertex buffer.
        ///
        /// All keyframes share the same vertex stride. This stride needs to be a multiple of the size of the vertex format you
        /// provide in the ``vertexFormat`` property.
        ///
        /// Similarly, you are responsible for ensuring this stride matches the vertex format data type's alignment.
        ///
        /// Defaults to `0`, which signals the stride matches the size of the ``vertexFormat`` data.
        #[unsafe(method(vertexStride))]
        #[unsafe(method_family = none)]
        pub fn vertexStride(&self) -> NSUInteger;

        /// Setter for [`vertexStride`][Self::vertexStride].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setVertexStride:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setVertexStride(&self, vertex_stride: NSUInteger);

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Assigns an optional index buffer containing references to vertices in the vertex buffers you reference through the
        /// vertex buffers property.
        ///
        /// You can set this property to `0`, the default, to avoid specifying an index buffer. All keyframes share the same
        /// index buffer.
        #[unsafe(method(indexBuffer))]
        #[unsafe(method_family = none)]
        pub fn indexBuffer(&self) -> MTL4BufferRange;

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Setter for [`indexBuffer`][Self::indexBuffer].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setIndexBuffer:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setIndexBuffer(&self, index_buffer: MTL4BufferRange);

        #[cfg(feature = "MTLArgument")]
        /// Specifies the size of the indices the `indexBuffer` contains, which is typically either 16 or 32-bits for each index.
        #[unsafe(method(indexType))]
        #[unsafe(method_family = none)]
        pub fn indexType(&self) -> MTLIndexType;

        #[cfg(feature = "MTLArgument")]
        /// Setter for [`indexType`][Self::indexType].
        #[unsafe(method(setIndexType:))]
        #[unsafe(method_family = none)]
        pub fn setIndexType(&self, index_type: MTLIndexType);

        /// Declares the number of triangles in the vertex buffers that the buffer in the vertex buffers property references.
        ///
        /// All keyframes share the same triangle count.
        #[unsafe(method(triangleCount))]
        #[unsafe(method_family = none)]
        pub fn triangleCount(&self) -> NSUInteger;

        /// Setter for [`triangleCount`][Self::triangleCount].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setTriangleCount:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setTriangleCount(&self, triangle_count: NSUInteger);

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Assings an optional reference to a buffer containing a `float4x3` transformation matrix.
        ///
        /// When the buffer address is non-zero, Metal applies this transform to the vertex data positions when building
        /// the acceleration structure. All keyframes share the same transformation matrix.
        ///
        /// Building an acceleration structure with a descriptor that specifies this property doesn't modify the contents of
        /// the input `vertexBuffer`.
        #[unsafe(method(transformationMatrixBuffer))]
        #[unsafe(method_family = none)]
        pub fn transformationMatrixBuffer(&self) -> MTL4BufferRange;

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Setter for [`transformationMatrixBuffer`][Self::transformationMatrixBuffer].
        #[unsafe(method(setTransformationMatrixBuffer:))]
        #[unsafe(method_family = none)]
        pub fn setTransformationMatrixBuffer(&self, transformation_matrix_buffer: MTL4BufferRange);

        #[cfg(feature = "MTLAccelerationStructure")]
        /// Configures the layout for the transformation matrix in the transformation matrix buffer.
        ///
        /// You can provide matrices in column-major or row-major form, and this property allows you to control
        /// how Metal interprets them.
        ///
        /// Defaults to `MTLMatrixLayoutColumnMajor`.
        #[unsafe(method(transformationMatrixLayout))]
        #[unsafe(method_family = none)]
        pub fn transformationMatrixLayout(&self) -> MTLMatrixLayout;

        #[cfg(feature = "MTLAccelerationStructure")]
        /// Setter for [`transformationMatrixLayout`][Self::transformationMatrixLayout].
        #[unsafe(method(setTransformationMatrixLayout:))]
        #[unsafe(method_family = none)]
        pub fn setTransformationMatrixLayout(&self, transformation_matrix_layout: MTLMatrixLayout);
    );
}

/// Methods declared on superclass `NSObject`.
impl MTL4AccelerationStructureMotionTriangleGeometryDescriptor {
    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 MTL4AccelerationStructureMotionTriangleGeometryDescriptor {
    #[inline]
    fn default_retained() -> Retained<Self> {
        Self::new()
    }
}

extern_class!(
    /// Describes motion bounding box geometry, suitable for motion ray tracing.
    ///
    /// You use bounding boxes to implement procedural geometry for ray tracing, such as spheres or any other shape
    /// you define by using intersection functions.
    ///
    /// Use a ``MTLResidencySet`` to mark residency of all buffers this descriptor references when you build this
    /// acceleration structure.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtl4accelerationstructuremotionboundingboxgeometrydescriptor?language=objc)
    #[unsafe(super(MTL4AccelerationStructureGeometryDescriptor, NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct MTL4AccelerationStructureMotionBoundingBoxGeometryDescriptor;
);

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

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

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

impl MTL4AccelerationStructureMotionBoundingBoxGeometryDescriptor {
    extern_methods!(
        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Configures a reference to a buffer where each entry contains a reference to a buffer of bounding boxes.
        ///
        /// This property references a buffer that conceptually represents an array with one entry for each keyframe in the
        /// motion animation. Each one of these entries consists of a ``MTL4BufferRange`` that, in turn, references a
        /// vertex buffer containing the bounding box data for the keyframe.
        ///
        /// You are responsible for ensuring the buffer address is not zero for the top-level buffer, as well as for all
        /// the vertex buffers it references.
        #[unsafe(method(boundingBoxBuffers))]
        #[unsafe(method_family = none)]
        pub fn boundingBoxBuffers(&self) -> MTL4BufferRange;

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Setter for [`boundingBoxBuffers`][Self::boundingBoxBuffers].
        #[unsafe(method(setBoundingBoxBuffers:))]
        #[unsafe(method_family = none)]
        pub fn setBoundingBoxBuffers(&self, bounding_box_buffers: MTL4BufferRange);

        /// Declares the stride, in bytes, between bounding boxes in the bounding box buffers each entry in `boundingBoxBuffer`
        /// references.
        ///
        /// All keyframes share the same bounding box stride. You are responsible for ensuring this stride is at least 24 bytes
        /// and a multiple of 4 bytes.
        ///
        /// This property defaults to `24` bytes.
        #[unsafe(method(boundingBoxStride))]
        #[unsafe(method_family = none)]
        pub fn boundingBoxStride(&self) -> NSUInteger;

        /// Setter for [`boundingBoxStride`][Self::boundingBoxStride].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setBoundingBoxStride:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setBoundingBoxStride(&self, bounding_box_stride: NSUInteger);

        /// Declares the number of bounding boxes in each buffer that `boundingBoxBuffer` references.
        ///
        /// All keyframes share the same bounding box count.
        #[unsafe(method(boundingBoxCount))]
        #[unsafe(method_family = none)]
        pub fn boundingBoxCount(&self) -> NSUInteger;

        /// Setter for [`boundingBoxCount`][Self::boundingBoxCount].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setBoundingBoxCount:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setBoundingBoxCount(&self, bounding_box_count: NSUInteger);
    );
}

/// Methods declared on superclass `NSObject`.
impl MTL4AccelerationStructureMotionBoundingBoxGeometryDescriptor {
    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 MTL4AccelerationStructureMotionBoundingBoxGeometryDescriptor {
    #[inline]
    fn default_retained() -> Retained<Self> {
        Self::new()
    }
}

extern_class!(
    /// Describes curve geometry suitable for ray tracing.
    ///
    /// Use a ``MTLResidencySet`` to mark residency of all buffers this descriptor references when you build this
    /// acceleration structure.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtl4accelerationstructurecurvegeometrydescriptor?language=objc)
    #[unsafe(super(MTL4AccelerationStructureGeometryDescriptor, NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct MTL4AccelerationStructureCurveGeometryDescriptor;
);

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

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

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

impl MTL4AccelerationStructureCurveGeometryDescriptor {
    extern_methods!(
        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// References a buffer containing curve control points.
        ///
        /// Control points are interpolated according to the basis function you specify in ``curveBasis``.
        ///
        /// You are responsible for ensuring each control is in a format matching the control point format ``controlPointFormat``
        /// specifies, as well as ensuring that the buffer address of the range is not zero.
        #[unsafe(method(controlPointBuffer))]
        #[unsafe(method_family = none)]
        pub fn controlPointBuffer(&self) -> MTL4BufferRange;

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Setter for [`controlPointBuffer`][Self::controlPointBuffer].
        #[unsafe(method(setControlPointBuffer:))]
        #[unsafe(method_family = none)]
        pub fn setControlPointBuffer(&self, control_point_buffer: MTL4BufferRange);

        /// Declares the number of control points in the control point buffer.
        #[unsafe(method(controlPointCount))]
        #[unsafe(method_family = none)]
        pub fn controlPointCount(&self) -> NSUInteger;

        /// Setter for [`controlPointCount`][Self::controlPointCount].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setControlPointCount:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setControlPointCount(&self, control_point_count: NSUInteger);

        /// Sets the stride, in bytes, between control points in the control point buffer the control point buffer references.
        ///
        /// You are responsible for ensuring this stride is a multiple of the control point format's element size, and
        /// at a minimum exactly the control point format's size.
        ///
        /// This property defaults to `0`, indicating that the control points are tightly-packed.
        #[unsafe(method(controlPointStride))]
        #[unsafe(method_family = none)]
        pub fn controlPointStride(&self) -> NSUInteger;

        /// Setter for [`controlPointStride`][Self::controlPointStride].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setControlPointStride:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setControlPointStride(&self, control_point_stride: NSUInteger);

        #[cfg(feature = "MTLStageInputOutputDescriptor")]
        /// Declares the format of the control points the control point buffer references.
        ///
        /// Defaults to `MTLAttributeFormatFloat3`, representing 3 floating point values tightly packed.
        #[unsafe(method(controlPointFormat))]
        #[unsafe(method_family = none)]
        pub fn controlPointFormat(&self) -> MTLAttributeFormat;

        #[cfg(feature = "MTLStageInputOutputDescriptor")]
        /// Setter for [`controlPointFormat`][Self::controlPointFormat].
        #[unsafe(method(setControlPointFormat:))]
        #[unsafe(method_family = none)]
        pub fn setControlPointFormat(&self, control_point_format: MTLAttributeFormat);

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Assigns a reference to a buffer containing the curve radius for each control point.
        ///
        /// Metal interpolates curve radii according to the basis function you specify via ``curveBasis``.
        ///
        /// You are responsible for ensuring the type of each radius matches the type property ``radiusFormat`` specifies,
        /// that each radius is at least zero, and that the buffer address of the range is not zero.
        #[unsafe(method(radiusBuffer))]
        #[unsafe(method_family = none)]
        pub fn radiusBuffer(&self) -> MTL4BufferRange;

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Setter for [`radiusBuffer`][Self::radiusBuffer].
        #[unsafe(method(setRadiusBuffer:))]
        #[unsafe(method_family = none)]
        pub fn setRadiusBuffer(&self, radius_buffer: MTL4BufferRange);

        #[cfg(feature = "MTLStageInputOutputDescriptor")]
        /// Declares the format of the radii in the radius buffer.
        ///
        /// Defaults to  `MTLAttributeFormatFloat`.
        #[unsafe(method(radiusFormat))]
        #[unsafe(method_family = none)]
        pub fn radiusFormat(&self) -> MTLAttributeFormat;

        #[cfg(feature = "MTLStageInputOutputDescriptor")]
        /// Setter for [`radiusFormat`][Self::radiusFormat].
        #[unsafe(method(setRadiusFormat:))]
        #[unsafe(method_family = none)]
        pub fn setRadiusFormat(&self, radius_format: MTLAttributeFormat);

        /// Configures the stride, in bytes, between radii in the radius buffer.
        ///
        /// You are responsible for ensuring this property is set to a multiple of the size corresponding to the ``radiusFormat``.
        ///
        /// This property defaults to `0` bytes, indicating that the radii are tightly packed.
        #[unsafe(method(radiusStride))]
        #[unsafe(method_family = none)]
        pub fn radiusStride(&self) -> NSUInteger;

        /// Setter for [`radiusStride`][Self::radiusStride].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setRadiusStride:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setRadiusStride(&self, radius_stride: NSUInteger);

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Assigns an optional index buffer containing references to control points in the control point buffer.
        ///
        /// Each index represents the first control point of a curve segment. You are responsible for ensuring the buffer
        /// address of the range is not zero.
        #[unsafe(method(indexBuffer))]
        #[unsafe(method_family = none)]
        pub fn indexBuffer(&self) -> MTL4BufferRange;

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Setter for [`indexBuffer`][Self::indexBuffer].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setIndexBuffer:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setIndexBuffer(&self, index_buffer: MTL4BufferRange);

        #[cfg(feature = "MTLArgument")]
        /// Specifies the size of the indices the `indexBuffer` contains, which is typically either 16 or 32-bits for each index.
        #[unsafe(method(indexType))]
        #[unsafe(method_family = none)]
        pub fn indexType(&self) -> MTLIndexType;

        #[cfg(feature = "MTLArgument")]
        /// Setter for [`indexType`][Self::indexType].
        #[unsafe(method(setIndexType:))]
        #[unsafe(method_family = none)]
        pub fn setIndexType(&self, index_type: MTLIndexType);

        /// Declares the number of curve segments.
        #[unsafe(method(segmentCount))]
        #[unsafe(method_family = none)]
        pub fn segmentCount(&self) -> NSUInteger;

        /// Setter for [`segmentCount`][Self::segmentCount].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setSegmentCount:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setSegmentCount(&self, segment_count: NSUInteger);

        /// Declares the number of control points per curve segment.
        ///
        /// Valid values for this property are `2`, `3`, or `4`.
        #[unsafe(method(segmentControlPointCount))]
        #[unsafe(method_family = none)]
        pub fn segmentControlPointCount(&self) -> NSUInteger;

        /// Setter for [`segmentControlPointCount`][Self::segmentControlPointCount].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setSegmentControlPointCount:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setSegmentControlPointCount(&self, segment_control_point_count: NSUInteger);

        #[cfg(feature = "MTLAccelerationStructure")]
        /// Controls the curve type.
        ///
        /// Defaults to `MTLCurveTypeRound`.
        #[unsafe(method(curveType))]
        #[unsafe(method_family = none)]
        pub fn curveType(&self) -> MTLCurveType;

        #[cfg(feature = "MTLAccelerationStructure")]
        /// Setter for [`curveType`][Self::curveType].
        #[unsafe(method(setCurveType:))]
        #[unsafe(method_family = none)]
        pub fn setCurveType(&self, curve_type: MTLCurveType);

        #[cfg(feature = "MTLAccelerationStructure")]
        /// Controls the curve basis function, determining how Metal interpolates the control points.
        ///
        /// Defaults to `MTLCurveBasisBSpline`.
        #[unsafe(method(curveBasis))]
        #[unsafe(method_family = none)]
        pub fn curveBasis(&self) -> MTLCurveBasis;

        #[cfg(feature = "MTLAccelerationStructure")]
        /// Setter for [`curveBasis`][Self::curveBasis].
        #[unsafe(method(setCurveBasis:))]
        #[unsafe(method_family = none)]
        pub fn setCurveBasis(&self, curve_basis: MTLCurveBasis);

        #[cfg(feature = "MTLAccelerationStructure")]
        /// Sets the type of curve end caps.
        ///
        /// Defaults to `MTLCurveEndCapsNone`.
        #[unsafe(method(curveEndCaps))]
        #[unsafe(method_family = none)]
        pub fn curveEndCaps(&self) -> MTLCurveEndCaps;

        #[cfg(feature = "MTLAccelerationStructure")]
        /// Setter for [`curveEndCaps`][Self::curveEndCaps].
        #[unsafe(method(setCurveEndCaps:))]
        #[unsafe(method_family = none)]
        pub fn setCurveEndCaps(&self, curve_end_caps: MTLCurveEndCaps);
    );
}

/// Methods declared on superclass `NSObject`.
impl MTL4AccelerationStructureCurveGeometryDescriptor {
    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 MTL4AccelerationStructureCurveGeometryDescriptor {
    #[inline]
    fn default_retained() -> Retained<Self> {
        Self::new()
    }
}

extern_class!(
    /// Describes motion curve geometry, suitable for motion ray tracing.
    ///
    /// Use a ``MTLResidencySet`` to mark residency of all buffers this descriptor references when you build this
    /// acceleration structure.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtl4accelerationstructuremotioncurvegeometrydescriptor?language=objc)
    #[unsafe(super(MTL4AccelerationStructureGeometryDescriptor, NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct MTL4AccelerationStructureMotionCurveGeometryDescriptor;
);

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

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

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

impl MTL4AccelerationStructureMotionCurveGeometryDescriptor {
    extern_methods!(
        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Assigns a reference to a buffer where each entry contains a reference to a buffer of control points.
        ///
        /// This property references a buffer that conceptually represents an array with one entry for each keyframe in the
        /// motion animation. Each one of these entries consists of a ``MTL4BufferRange`` that, in turn, references a
        /// buffer containing the control points corresponding to the keyframe.
        ///
        /// You are responsible for ensuring the buffer address is not zero for the top-level buffer, as well as for all
        /// the vertex buffers it references.
        #[unsafe(method(controlPointBuffers))]
        #[unsafe(method_family = none)]
        pub fn controlPointBuffers(&self) -> MTL4BufferRange;

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Setter for [`controlPointBuffers`][Self::controlPointBuffers].
        #[unsafe(method(setControlPointBuffers:))]
        #[unsafe(method_family = none)]
        pub fn setControlPointBuffers(&self, control_point_buffers: MTL4BufferRange);

        /// Specifies the number of control points in the buffers the control point buffers reference.
        ///
        /// All keyframes have the same number of control points.
        #[unsafe(method(controlPointCount))]
        #[unsafe(method_family = none)]
        pub fn controlPointCount(&self) -> NSUInteger;

        /// Setter for [`controlPointCount`][Self::controlPointCount].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setControlPointCount:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setControlPointCount(&self, control_point_count: NSUInteger);

        /// Sets the stride, in bytes, between control points in the control point buffer.
        ///
        /// All keyframes share the same control point stride.
        ///
        /// You are responsible for ensuring this stride is a multiple of the control point format's element size, and
        /// at a minimum exactly the control point format's size.
        ///
        /// This property defaults to `0`, indicating that the control points are tightly-packed.
        #[unsafe(method(controlPointStride))]
        #[unsafe(method_family = none)]
        pub fn controlPointStride(&self) -> NSUInteger;

        /// Setter for [`controlPointStride`][Self::controlPointStride].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setControlPointStride:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setControlPointStride(&self, control_point_stride: NSUInteger);

        #[cfg(feature = "MTLStageInputOutputDescriptor")]
        /// Declares the format of the control points in the buffers that the control point buffers reference.
        ///
        /// All keyframes share the same control point format. Defaults to `MTLAttributeFormatFloat3`, representing 3 floating
        /// point values tightly packed.
        #[unsafe(method(controlPointFormat))]
        #[unsafe(method_family = none)]
        pub fn controlPointFormat(&self) -> MTLAttributeFormat;

        #[cfg(feature = "MTLStageInputOutputDescriptor")]
        /// Setter for [`controlPointFormat`][Self::controlPointFormat].
        #[unsafe(method(setControlPointFormat:))]
        #[unsafe(method_family = none)]
        pub fn setControlPointFormat(&self, control_point_format: MTLAttributeFormat);

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Assigns a reference to a buffer containing, in turn, references to curve radii buffers.
        ///
        /// This property references a buffer that conceptually represents an array with one entry for each keyframe in the
        /// motion animation. Each one of these entries consists of a ``MTL4BufferRange`` that, in turn, references a
        /// buffer containing the radii corresponding to the keyframe.
        ///
        /// Metal interpolates curve radii according to the basis function you specify via ``curveBasis``.
        ///
        /// You are responsible for ensuring the type of each radius matches the type property ``radiusFormat`` specifies,
        /// that each radius is at least zero, and that the buffer address of the top-level buffer, as well as of buffer
        /// it references, is not zero.
        #[unsafe(method(radiusBuffers))]
        #[unsafe(method_family = none)]
        pub fn radiusBuffers(&self) -> MTL4BufferRange;

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Setter for [`radiusBuffers`][Self::radiusBuffers].
        #[unsafe(method(setRadiusBuffers:))]
        #[unsafe(method_family = none)]
        pub fn setRadiusBuffers(&self, radius_buffers: MTL4BufferRange);

        #[cfg(feature = "MTLStageInputOutputDescriptor")]
        /// Sets the format of the radii in the radius buffer.
        ///
        /// Defaults to  `MTLAttributeFormatFloat`. All keyframes share the same radius format.
        #[unsafe(method(radiusFormat))]
        #[unsafe(method_family = none)]
        pub fn radiusFormat(&self) -> MTLAttributeFormat;

        #[cfg(feature = "MTLStageInputOutputDescriptor")]
        /// Setter for [`radiusFormat`][Self::radiusFormat].
        #[unsafe(method(setRadiusFormat:))]
        #[unsafe(method_family = none)]
        pub fn setRadiusFormat(&self, radius_format: MTLAttributeFormat);

        /// Sets the stride, in bytes, between radii in the radius buffer.
        ///
        /// You are responsible for ensuring this property is set to a multiple of the size corresponding to the ``radiusFormat``.
        /// All keyframes share the same radius stride.
        ///
        /// This property defaults to `0` bytes, indicating that the radii are tightly packed.
        #[unsafe(method(radiusStride))]
        #[unsafe(method_family = none)]
        pub fn radiusStride(&self) -> NSUInteger;

        /// Setter for [`radiusStride`][Self::radiusStride].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setRadiusStride:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setRadiusStride(&self, radius_stride: NSUInteger);

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Assigns an optional index buffer containing references to control points in the control point buffers.
        ///
        /// All keyframes share the same index buffer, with each index representing the first control point of a curve segment.
        ///
        /// You are responsible for ensuring the buffer address of the range is not zero.
        #[unsafe(method(indexBuffer))]
        #[unsafe(method_family = none)]
        pub fn indexBuffer(&self) -> MTL4BufferRange;

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Setter for [`indexBuffer`][Self::indexBuffer].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setIndexBuffer:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setIndexBuffer(&self, index_buffer: MTL4BufferRange);

        #[cfg(feature = "MTLArgument")]
        /// Configures the size of the indices the `indexBuffer` contains, which is typically either 16 or 32-bits for each index.
        #[unsafe(method(indexType))]
        #[unsafe(method_family = none)]
        pub fn indexType(&self) -> MTLIndexType;

        #[cfg(feature = "MTLArgument")]
        /// Setter for [`indexType`][Self::indexType].
        #[unsafe(method(setIndexType:))]
        #[unsafe(method_family = none)]
        pub fn setIndexType(&self, index_type: MTLIndexType);

        /// Declares the number of curve segments.
        ///
        /// All keyframes have the same number of curve segments.
        #[unsafe(method(segmentCount))]
        #[unsafe(method_family = none)]
        pub fn segmentCount(&self) -> NSUInteger;

        /// Setter for [`segmentCount`][Self::segmentCount].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setSegmentCount:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setSegmentCount(&self, segment_count: NSUInteger);

        /// Controls the number of control points per curve segment.
        ///
        /// Valid values for this property are `2`, `3`, or `4`. All keyframes have the same number of control points per curve segment.
        #[unsafe(method(segmentControlPointCount))]
        #[unsafe(method_family = none)]
        pub fn segmentControlPointCount(&self) -> NSUInteger;

        /// Setter for [`segmentControlPointCount`][Self::segmentControlPointCount].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setSegmentControlPointCount:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setSegmentControlPointCount(&self, segment_control_point_count: NSUInteger);

        #[cfg(feature = "MTLAccelerationStructure")]
        /// Controls the curve type.
        ///
        /// Defaults to `MTLCurveTypeRound`. All keyframes share the same curve type.
        #[unsafe(method(curveType))]
        #[unsafe(method_family = none)]
        pub fn curveType(&self) -> MTLCurveType;

        #[cfg(feature = "MTLAccelerationStructure")]
        /// Setter for [`curveType`][Self::curveType].
        #[unsafe(method(setCurveType:))]
        #[unsafe(method_family = none)]
        pub fn setCurveType(&self, curve_type: MTLCurveType);

        #[cfg(feature = "MTLAccelerationStructure")]
        /// Sets the curve basis function, determining how Metal interpolates the control points.
        ///
        /// Defaults to `MTLCurveBasisBSpline`. All keyframes share the same curve basis function.
        #[unsafe(method(curveBasis))]
        #[unsafe(method_family = none)]
        pub fn curveBasis(&self) -> MTLCurveBasis;

        #[cfg(feature = "MTLAccelerationStructure")]
        /// Setter for [`curveBasis`][Self::curveBasis].
        #[unsafe(method(setCurveBasis:))]
        #[unsafe(method_family = none)]
        pub fn setCurveBasis(&self, curve_basis: MTLCurveBasis);

        #[cfg(feature = "MTLAccelerationStructure")]
        /// Configures the type of curve end caps.
        ///
        /// Defaults to `MTLCurveEndCapsNone`. All keyframes share the same end cap type.
        #[unsafe(method(curveEndCaps))]
        #[unsafe(method_family = none)]
        pub fn curveEndCaps(&self) -> MTLCurveEndCaps;

        #[cfg(feature = "MTLAccelerationStructure")]
        /// Setter for [`curveEndCaps`][Self::curveEndCaps].
        #[unsafe(method(setCurveEndCaps:))]
        #[unsafe(method_family = none)]
        pub fn setCurveEndCaps(&self, curve_end_caps: MTLCurveEndCaps);
    );
}

/// Methods declared on superclass `NSObject`.
impl MTL4AccelerationStructureMotionCurveGeometryDescriptor {
    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 MTL4AccelerationStructureMotionCurveGeometryDescriptor {
    #[inline]
    fn default_retained() -> Retained<Self> {
        Self::new()
    }
}

extern_class!(
    /// Descriptor for an instance acceleration structure.
    ///
    /// An instance acceleration structure references other acceleration structures, and provides the ability to
    /// "instantiate" them multiple times, each one with potentially a different transformation matrix.
    ///
    /// You specify the properties of the instances in the acceleration structure this descriptor builds by providing a
    /// buffer of `structs` via its ``instanceDescriptorBuffer`` property.
    ///
    /// Use a ``MTLResidencySet`` to mark residency of all buffers and acceleration structures this descriptor references
    /// when you build this acceleration structure.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtl4instanceaccelerationstructuredescriptor?language=objc)
    #[unsafe(super(
        MTL4AccelerationStructureDescriptor,
        MTLAccelerationStructureDescriptor,
        NSObject
    ))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    #[cfg(feature = "MTLAccelerationStructure")]
    pub struct MTL4InstanceAccelerationStructureDescriptor;
);

#[cfg(feature = "MTLAccelerationStructure")]
extern_conformance!(
    unsafe impl NSCopying for MTL4InstanceAccelerationStructureDescriptor {}
);

#[cfg(feature = "MTLAccelerationStructure")]
unsafe impl CopyingHelper for MTL4InstanceAccelerationStructureDescriptor {
    type Result = Self;
}

#[cfg(feature = "MTLAccelerationStructure")]
extern_conformance!(
    unsafe impl NSObjectProtocol for MTL4InstanceAccelerationStructureDescriptor {}
);

#[cfg(feature = "MTLAccelerationStructure")]
impl MTL4InstanceAccelerationStructureDescriptor {
    extern_methods!(
        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Assigns a reference to a buffer containing instance descriptors for acceleration structures to reference.
        ///
        /// This buffer conceptually represents an array of instance data. The specific format for the structs that comprise
        /// each entry depends on the value of the  ``instanceDescriptorType`` property.
        ///
        /// You are responsible for ensuring the buffer address the range contains is not zero.
        #[unsafe(method(instanceDescriptorBuffer))]
        #[unsafe(method_family = none)]
        pub fn instanceDescriptorBuffer(&self) -> MTL4BufferRange;

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Setter for [`instanceDescriptorBuffer`][Self::instanceDescriptorBuffer].
        #[unsafe(method(setInstanceDescriptorBuffer:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setInstanceDescriptorBuffer(
            &self,
            instance_descriptor_buffer: MTL4BufferRange,
        );

        /// Sets the stride, in bytes, between instance descriptors the instance descriptor buffer references.
        ///
        /// You are responsible for ensuring this stride is at least the size of the structure type corresponding to the instance
        /// descriptor type and a multiple of 4 bytes.
        ///
        /// Defaults to `0`, indicating the instance descriptors are tightly packed.
        #[unsafe(method(instanceDescriptorStride))]
        #[unsafe(method_family = none)]
        pub fn instanceDescriptorStride(&self) -> NSUInteger;

        /// Setter for [`instanceDescriptorStride`][Self::instanceDescriptorStride].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setInstanceDescriptorStride:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setInstanceDescriptorStride(&self, instance_descriptor_stride: NSUInteger);

        /// Controls the number of instance descriptors in the instance descriptor buffer references.
        #[unsafe(method(instanceCount))]
        #[unsafe(method_family = none)]
        pub fn instanceCount(&self) -> NSUInteger;

        /// Setter for [`instanceCount`][Self::instanceCount].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setInstanceCount:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setInstanceCount(&self, instance_count: NSUInteger);

        /// Sets the type of instance descriptor that the instance descriptor buffer references.
        ///
        /// This value determines the layout Metal expects for the structs the instance descriptor buffer contains.
        ///
        /// Defaults to `MTLAccelerationStructureInstanceDescriptorTypeIndirect`. Valid values for this property are
        /// `MTLAccelerationStructureInstanceDescriptorTypeIndirect` or `MTLAccelerationStructureInstanceDescriptorTypeIndirectMotion`.
        #[unsafe(method(instanceDescriptorType))]
        #[unsafe(method_family = none)]
        pub fn instanceDescriptorType(&self) -> MTLAccelerationStructureInstanceDescriptorType;

        /// Setter for [`instanceDescriptorType`][Self::instanceDescriptorType].
        #[unsafe(method(setInstanceDescriptorType:))]
        #[unsafe(method_family = none)]
        pub fn setInstanceDescriptorType(
            &self,
            instance_descriptor_type: MTLAccelerationStructureInstanceDescriptorType,
        );

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// A buffer containing transformation information for instance motion keyframes, formatted according
        /// to the motion transform type.
        ///
        /// Each instance can have a different number of keyframes that you configure via individual instance
        /// descriptors.
        ///
        /// You are responsible for ensuring the buffer address the range references is not zero when using motion instance descriptors.
        #[unsafe(method(motionTransformBuffer))]
        #[unsafe(method_family = none)]
        pub fn motionTransformBuffer(&self) -> MTL4BufferRange;

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Setter for [`motionTransformBuffer`][Self::motionTransformBuffer].
        #[unsafe(method(setMotionTransformBuffer:))]
        #[unsafe(method_family = none)]
        pub fn setMotionTransformBuffer(&self, motion_transform_buffer: MTL4BufferRange);

        /// Controls the total number of motion transforms in the motion transform buffer.
        #[unsafe(method(motionTransformCount))]
        #[unsafe(method_family = none)]
        pub fn motionTransformCount(&self) -> NSUInteger;

        /// Setter for [`motionTransformCount`][Self::motionTransformCount].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setMotionTransformCount:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setMotionTransformCount(&self, motion_transform_count: NSUInteger);

        /// Specifies the layout for the transformation matrices in the instance descriptor buffer and the motion transformation matrix buffer.
        ///
        /// Metal interprets the value of this property as the layout for the buffers that both ``instanceDescriptorBuffer`` and
        /// ``motionTransformBuffer`` reference.
        ///
        /// Defaults to `MTLMatrixLayoutColumnMajor`.
        #[unsafe(method(instanceTransformationMatrixLayout))]
        #[unsafe(method_family = none)]
        pub fn instanceTransformationMatrixLayout(&self) -> MTLMatrixLayout;

        /// Setter for [`instanceTransformationMatrixLayout`][Self::instanceTransformationMatrixLayout].
        #[unsafe(method(setInstanceTransformationMatrixLayout:))]
        #[unsafe(method_family = none)]
        pub fn setInstanceTransformationMatrixLayout(
            &self,
            instance_transformation_matrix_layout: MTLMatrixLayout,
        );

        /// Controls the type of motion transforms, either as a matrix or individual components.
        ///
        /// Defaults to `MTLTransformTypePackedFloat4x3`. Using a `MTLTransformTypeComponent` allows you to represent the
        /// rotation by a quaternion (instead as of part of the matrix), allowing for correct motion interpolation.
        #[unsafe(method(motionTransformType))]
        #[unsafe(method_family = none)]
        pub fn motionTransformType(&self) -> MTLTransformType;

        /// Setter for [`motionTransformType`][Self::motionTransformType].
        #[unsafe(method(setMotionTransformType:))]
        #[unsafe(method_family = none)]
        pub fn setMotionTransformType(&self, motion_transform_type: MTLTransformType);

        /// Specify the stride for motion transform.
        ///
        /// Defaults to `0`, indicating that transforms are tightly packed according to the motion transform type.
        #[unsafe(method(motionTransformStride))]
        #[unsafe(method_family = none)]
        pub fn motionTransformStride(&self) -> NSUInteger;

        /// Setter for [`motionTransformStride`][Self::motionTransformStride].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setMotionTransformStride:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setMotionTransformStride(&self, motion_transform_stride: NSUInteger);
    );
}

/// Methods declared on superclass `NSObject`.
#[cfg(feature = "MTLAccelerationStructure")]
impl MTL4InstanceAccelerationStructureDescriptor {
    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>;
    );
}

#[cfg(feature = "MTLAccelerationStructure")]
impl DefaultRetained for MTL4InstanceAccelerationStructureDescriptor {
    #[inline]
    fn default_retained() -> Retained<Self> {
        Self::new()
    }
}

extern_class!(
    /// Descriptor for an "indirect" instance acceleration structure that allows providing the instance count and
    /// motion transform count indirectly, through buffer references.
    ///
    /// An instance acceleration structure references other acceleration structures, and provides the ability to
    /// "instantiate" them multiple times, each one with potentially a different transformation matrix.
    ///
    /// You specify the properties of the instances in the acceleration structure this descriptor builds by providing a
    /// buffer of `structs` via its ``instanceDescriptorBuffer`` property.
    ///
    /// Compared to ``MTL4InstanceAccelerationStructureDescriptor``, this descriptor allows you to provide the number
    /// of instances it references indirectly through a buffer reference, as well as the number of motion transforms.
    ///
    /// This enables you to determine these counts indirectly in the GPU timeline via a compute pipeline.
    /// Metal needs only to know the maximum possible number of instances and motion transforms to support,
    /// which you specify via the ``maxInstanceCount`` and ``maxMotionTransformCount`` properties.
    ///
    /// Use a ``MTLResidencySet`` to mark residency of all buffers and acceleration structures this descriptor references
    /// when you build this acceleration structure.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtl4indirectinstanceaccelerationstructuredescriptor?language=objc)
    #[unsafe(super(
        MTL4AccelerationStructureDescriptor,
        MTLAccelerationStructureDescriptor,
        NSObject
    ))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    #[cfg(feature = "MTLAccelerationStructure")]
    pub struct MTL4IndirectInstanceAccelerationStructureDescriptor;
);

#[cfg(feature = "MTLAccelerationStructure")]
extern_conformance!(
    unsafe impl NSCopying for MTL4IndirectInstanceAccelerationStructureDescriptor {}
);

#[cfg(feature = "MTLAccelerationStructure")]
unsafe impl CopyingHelper for MTL4IndirectInstanceAccelerationStructureDescriptor {
    type Result = Self;
}

#[cfg(feature = "MTLAccelerationStructure")]
extern_conformance!(
    unsafe impl NSObjectProtocol for MTL4IndirectInstanceAccelerationStructureDescriptor {}
);

#[cfg(feature = "MTLAccelerationStructure")]
impl MTL4IndirectInstanceAccelerationStructureDescriptor {
    extern_methods!(
        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Assigns a reference to a buffer containing instance descriptors for acceleration structures to reference.
        ///
        /// This buffer conceptually represents an array of instance data. The specific format for the structs that comprise
        /// each entry depends on the value of the  ``instanceDescriptorType`` property.
        ///
        /// You are responsible for ensuring the buffer address the range contains is not zero.
        #[unsafe(method(instanceDescriptorBuffer))]
        #[unsafe(method_family = none)]
        pub fn instanceDescriptorBuffer(&self) -> MTL4BufferRange;

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Setter for [`instanceDescriptorBuffer`][Self::instanceDescriptorBuffer].
        #[unsafe(method(setInstanceDescriptorBuffer:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setInstanceDescriptorBuffer(
            &self,
            instance_descriptor_buffer: MTL4BufferRange,
        );

        /// Sets the stride, in bytes, between instance descriptors in the instance descriptor buffer.
        ///
        /// You are responsible for ensuring this stride is at least the size of the structure type corresponding to the instance
        /// descriptor type and a multiple of 4 bytes.
        ///
        /// Defaults to `0`, indicating the instance descriptors are tightly packed.
        #[unsafe(method(instanceDescriptorStride))]
        #[unsafe(method_family = none)]
        pub fn instanceDescriptorStride(&self) -> NSUInteger;

        /// Setter for [`instanceDescriptorStride`][Self::instanceDescriptorStride].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setInstanceDescriptorStride:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setInstanceDescriptorStride(&self, instance_descriptor_stride: NSUInteger);

        /// Controls the maximum number of instance descriptors the instance descriptor buffer can reference.
        ///
        /// You are responsible for ensuring that the final number of instances at build time, which you provide indirectly
        /// via a buffer reference in ``instanceCountBuffer``, is less than or equal to this number.
        #[unsafe(method(maxInstanceCount))]
        #[unsafe(method_family = none)]
        pub fn maxInstanceCount(&self) -> NSUInteger;

        /// Setter for [`maxInstanceCount`][Self::maxInstanceCount].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setMaxInstanceCount:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setMaxInstanceCount(&self, max_instance_count: NSUInteger);

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Provides a reference to a buffer containing the number of instances in the instance descriptor buffer, formatted as a
        /// 32-bit unsigned integer.
        ///
        /// You are responsible for ensuring that the final number of instances at build time, which you provide indirectly
        /// via this buffer reference , is less than or equal to the value of property ``maxInstanceCount``.
        #[unsafe(method(instanceCountBuffer))]
        #[unsafe(method_family = none)]
        pub fn instanceCountBuffer(&self) -> MTL4BufferRange;

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Setter for [`instanceCountBuffer`][Self::instanceCountBuffer].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setInstanceCountBuffer:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setInstanceCountBuffer(&self, instance_count_buffer: MTL4BufferRange);

        /// Controls the type of instance descriptor that the instance descriptor buffer references.
        ///
        /// This value determines the layout Metal expects for the structs the instance descriptor buffer contains.
        ///
        /// Defaults to `MTLAccelerationStructureInstanceDescriptorTypeIndirect`. Valid values for this property are
        /// `MTLAccelerationStructureInstanceDescriptorTypeIndirect` or `MTLAccelerationStructureInstanceDescriptorTypeIndirectMotion`.
        #[unsafe(method(instanceDescriptorType))]
        #[unsafe(method_family = none)]
        pub fn instanceDescriptorType(&self) -> MTLAccelerationStructureInstanceDescriptorType;

        /// Setter for [`instanceDescriptorType`][Self::instanceDescriptorType].
        #[unsafe(method(setInstanceDescriptorType:))]
        #[unsafe(method_family = none)]
        pub fn setInstanceDescriptorType(
            &self,
            instance_descriptor_type: MTLAccelerationStructureInstanceDescriptorType,
        );

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// A buffer containing transformation information for instance motion keyframes, formatted according
        /// to the motion transform type.
        ///
        /// Each instance can have a different number of keyframes that you configure via individual instance
        /// descriptors.
        ///
        /// You are responsible for ensuring the buffer address the range references is not zero when using motion instance descriptors.
        #[unsafe(method(motionTransformBuffer))]
        #[unsafe(method_family = none)]
        pub fn motionTransformBuffer(&self) -> MTL4BufferRange;

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Setter for [`motionTransformBuffer`][Self::motionTransformBuffer].
        #[unsafe(method(setMotionTransformBuffer:))]
        #[unsafe(method_family = none)]
        pub fn setMotionTransformBuffer(&self, motion_transform_buffer: MTL4BufferRange);

        /// Controls the maximum number of motion transforms in the motion transform buffer.
        ///
        /// You are responsible for ensuring that final number of motion transforms at build time that the buffer
        /// ``motionTransformCountBuffer`` references is less than or equal to this number.
        #[unsafe(method(maxMotionTransformCount))]
        #[unsafe(method_family = none)]
        pub fn maxMotionTransformCount(&self) -> NSUInteger;

        /// Setter for [`maxMotionTransformCount`][Self::maxMotionTransformCount].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setMaxMotionTransformCount:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setMaxMotionTransformCount(&self, max_motion_transform_count: NSUInteger);

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Associates a buffer reference containing the number of motion transforms in the motion transform buffer, formatted as a
        /// 32-bit unsigned integer.
        ///
        /// You are responsible for ensuring that the final number of motion transforms at build time in the buffer this property
        /// references is less than or equal to the value of property ``maxMotionTransformCount``.
        #[unsafe(method(motionTransformCountBuffer))]
        #[unsafe(method_family = none)]
        pub fn motionTransformCountBuffer(&self) -> MTL4BufferRange;

        #[cfg(all(feature = "MTL4BufferRange", feature = "MTLGPUAddress"))]
        /// Setter for [`motionTransformCountBuffer`][Self::motionTransformCountBuffer].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setMotionTransformCountBuffer:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setMotionTransformCountBuffer(
            &self,
            motion_transform_count_buffer: MTL4BufferRange,
        );

        /// Specifies the layout for the transformation matrices in the instance descriptor buffer and the motion transformation matrix buffer.
        ///
        /// Metal interprets the value of this property as the layout for the buffers that both ``instanceDescriptorBuffer`` and
        /// ``motionTransformBuffer`` reference.
        ///
        /// Defaults to `MTLMatrixLayoutColumnMajor`.
        #[unsafe(method(instanceTransformationMatrixLayout))]
        #[unsafe(method_family = none)]
        pub fn instanceTransformationMatrixLayout(&self) -> MTLMatrixLayout;

        /// Setter for [`instanceTransformationMatrixLayout`][Self::instanceTransformationMatrixLayout].
        #[unsafe(method(setInstanceTransformationMatrixLayout:))]
        #[unsafe(method_family = none)]
        pub fn setInstanceTransformationMatrixLayout(
            &self,
            instance_transformation_matrix_layout: MTLMatrixLayout,
        );

        /// Sets the type of motion transforms, either as a matrix or individual components.
        ///
        /// Defaults to `MTLTransformTypePackedFloat4x3`. Using a `MTLTransformTypeComponent` allows you to represent the
        /// rotation by a quaternion (instead as of part of the matrix), allowing for correct motion interpolation.
        #[unsafe(method(motionTransformType))]
        #[unsafe(method_family = none)]
        pub fn motionTransformType(&self) -> MTLTransformType;

        /// Setter for [`motionTransformType`][Self::motionTransformType].
        #[unsafe(method(setMotionTransformType:))]
        #[unsafe(method_family = none)]
        pub fn setMotionTransformType(&self, motion_transform_type: MTLTransformType);

        /// Sets the stride for motion transform.
        ///
        /// Defaults to `0`, indicating that transforms are tightly packed according to the motion transform type.
        #[unsafe(method(motionTransformStride))]
        #[unsafe(method_family = none)]
        pub fn motionTransformStride(&self) -> NSUInteger;

        /// Setter for [`motionTransformStride`][Self::motionTransformStride].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setMotionTransformStride:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setMotionTransformStride(&self, motion_transform_stride: NSUInteger);
    );
}

/// Methods declared on superclass `NSObject`.
#[cfg(feature = "MTLAccelerationStructure")]
impl MTL4IndirectInstanceAccelerationStructureDescriptor {
    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>;
    );
}

#[cfg(feature = "MTLAccelerationStructure")]
impl DefaultRetained for MTL4IndirectInstanceAccelerationStructureDescriptor {
    #[inline]
    fn default_retained() -> Retained<Self> {
        Self::new()
    }
}
