//! 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::*;

/// A bitfield of commands that may be performed indirectly.
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtlindirectcommandtype?language=objc)
// NS_OPTIONS
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct MTLIndirectCommandType(pub NSUInteger);
bitflags::bitflags! {
    impl MTLIndirectCommandType: NSUInteger {
        #[doc(alias = "MTLIndirectCommandTypeDraw")]
        const Draw = 1<<0;
        #[doc(alias = "MTLIndirectCommandTypeDrawIndexed")]
        const DrawIndexed = 1<<1;
        #[doc(alias = "MTLIndirectCommandTypeDrawPatches")]
        const DrawPatches = 1<<2;
        #[doc(alias = "MTLIndirectCommandTypeDrawIndexedPatches")]
        const DrawIndexedPatches = 1<<3;
        #[doc(alias = "MTLIndirectCommandTypeConcurrentDispatch")]
        const ConcurrentDispatch = 1<<5;
        #[doc(alias = "MTLIndirectCommandTypeConcurrentDispatchThreads")]
        const ConcurrentDispatchThreads = 1<<6;
        #[doc(alias = "MTLIndirectCommandTypeDrawMeshThreadgroups")]
        const DrawMeshThreadgroups = 1<<7;
        #[doc(alias = "MTLIndirectCommandTypeDrawMeshThreads")]
        const DrawMeshThreads = 1<<8;
    }
}

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

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

/// The data layout required for specifying an indirect command buffer execution range.
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtlindirectcommandbufferexecutionrange?language=objc)
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct MTLIndirectCommandBufferExecutionRange {
    pub location: u32,
    pub length: u32,
}

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

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

impl MTLIndirectCommandBufferExecutionRange {
    // TODO: pub fn MTLIndirectCommandBufferExecutionRangeMake(location: u32,length: u32,) -> MTLIndirectCommandBufferExecutionRange;
}

extern_class!(
    /// Describes the limits and features that can be used in an indirect command
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtlindirectcommandbufferdescriptor?language=objc)
    #[unsafe(super(NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct MTLIndirectCommandBufferDescriptor;
);

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

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

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

impl MTLIndirectCommandBufferDescriptor {
    extern_methods!(
        /// A bitfield of the command types that be encoded.
        ///
        /// MTLCommandTypeDispatch cannot be mixed with any other command type.
        #[unsafe(method(commandTypes))]
        #[unsafe(method_family = none)]
        pub fn commandTypes(&self) -> MTLIndirectCommandType;

        /// Setter for [`commandTypes`][Self::commandTypes].
        #[unsafe(method(setCommandTypes:))]
        #[unsafe(method_family = none)]
        pub fn setCommandTypes(&self, command_types: MTLIndirectCommandType);

        /// Whether the render or compute pipeline are inherited from the encoder
        #[unsafe(method(inheritPipelineState))]
        #[unsafe(method_family = none)]
        pub fn inheritPipelineState(&self) -> bool;

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

        /// Whether the render or compute pipeline can set arguments.
        #[unsafe(method(inheritBuffers))]
        #[unsafe(method_family = none)]
        pub fn inheritBuffers(&self) -> bool;

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

        /// Configures whether the indirect command buffer inherits the depth stencil state from the encoder.
        ///
        /// The property's default value is
        /// <doc
        /// ://com.apple.documentation/documentation/swift/true>.
        #[unsafe(method(inheritDepthStencilState))]
        #[unsafe(method_family = none)]
        pub fn inheritDepthStencilState(&self) -> bool;

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

        /// Configures whether the indirect command buffer inherits the depth bias from the encoder.
        ///
        /// The property's default value is
        /// <doc
        /// ://com.apple.documentation/documentation/swift/true>.
        #[unsafe(method(inheritDepthBias))]
        #[unsafe(method_family = none)]
        pub fn inheritDepthBias(&self) -> bool;

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

        /// Configures whether the indirect command buffer inherits the depth clip mode from the encoder.
        ///
        /// The property's default value is
        /// <doc
        /// ://com.apple.documentation/documentation/swift/true>.
        #[unsafe(method(inheritDepthClipMode))]
        #[unsafe(method_family = none)]
        pub fn inheritDepthClipMode(&self) -> bool;

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

        /// Configures whether the indirect command buffer inherits the cull mode from the encoder.
        ///
        /// The property's default value is
        /// <doc
        /// ://com.apple.documentation/documentation/swift/true>.
        #[unsafe(method(inheritCullMode))]
        #[unsafe(method_family = none)]
        pub fn inheritCullMode(&self) -> bool;

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

        /// Configures whether the indirect command buffer inherits the front facing winding from the encoder.
        ///
        /// The property's default value is
        /// <doc
        /// ://com.apple.documentation/documentation/swift/true>.
        #[unsafe(method(inheritFrontFacingWinding))]
        #[unsafe(method_family = none)]
        pub fn inheritFrontFacingWinding(&self) -> bool;

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

        /// Configures whether the indirect command buffer inherits the triangle fill mode from the encoder.
        ///
        /// The property's default value is
        /// <doc
        /// ://com.apple.documentation/documentation/swift/true>.
        #[unsafe(method(inheritTriangleFillMode))]
        #[unsafe(method_family = none)]
        pub fn inheritTriangleFillMode(&self) -> bool;

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

        /// The maximum bind index of vertex argument buffers that can be set per command.
        #[unsafe(method(maxVertexBufferBindCount))]
        #[unsafe(method_family = none)]
        pub fn maxVertexBufferBindCount(&self) -> NSUInteger;

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

        /// The maximum bind index of fragment argument buffers that can be set per command.
        #[unsafe(method(maxFragmentBufferBindCount))]
        #[unsafe(method_family = none)]
        pub fn maxFragmentBufferBindCount(&self) -> NSUInteger;

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

        /// The maximum bind index of kernel (or tile) argument buffers that can be set per command.
        #[unsafe(method(maxKernelBufferBindCount))]
        #[unsafe(method_family = none)]
        pub fn maxKernelBufferBindCount(&self) -> NSUInteger;

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

        /// The maximum bind index of kernel (or tile) threadgroup memory that can be set per command.
        /// The default value is 31.
        #[unsafe(method(maxKernelThreadgroupMemoryBindCount))]
        #[unsafe(method_family = none)]
        pub fn maxKernelThreadgroupMemoryBindCount(&self) -> NSUInteger;

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

        /// The maximum bind index of object stage buffers that can be set per render command.
        #[unsafe(method(maxObjectBufferBindCount))]
        #[unsafe(method_family = none)]
        pub fn maxObjectBufferBindCount(&self) -> NSUInteger;

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

        /// The maximum bind index of mesh stage buffers that can be set per render command.
        #[unsafe(method(maxMeshBufferBindCount))]
        #[unsafe(method_family = none)]
        pub fn maxMeshBufferBindCount(&self) -> NSUInteger;

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

        /// The maximum bind index of object threadgroup memory that can be set per render command.
        /// The default value is 0.
        #[unsafe(method(maxObjectThreadgroupMemoryBindCount))]
        #[unsafe(method_family = none)]
        pub fn maxObjectThreadgroupMemoryBindCount(&self) -> NSUInteger;

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

        /// Whether the render or compute commands can use ray tracing. Default value is NO.
        #[unsafe(method(supportRayTracing))]
        #[unsafe(method_family = none)]
        pub fn supportRayTracing(&self) -> bool;

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

        /// allows binding pipelines that have at least one MTLBufferLayout with a
        /// stride of `MTLBufferLayoutStrideDynamic`
        ///
        /// will allow setting attributeStride in `setVertexBuffer` / `setKernelBuffer`
        /// calls
        #[unsafe(method(supportDynamicAttributeStride))]
        #[unsafe(method_family = none)]
        pub fn supportDynamicAttributeStride(&self) -> bool;

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

        /// Specifies if the indirect command buffer should support color attachment mapping.
        #[unsafe(method(supportColorAttachmentMapping))]
        #[unsafe(method_family = none)]
        pub fn supportColorAttachmentMapping(&self) -> bool;

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

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

extern_protocol!(
    /// [Apple's documentation](https://developer.apple.com/documentation/metal/mtlindirectcommandbuffer?language=objc)
    #[cfg(all(feature = "MTLAllocation", feature = "MTLResource"))]
    pub unsafe trait MTLIndirectCommandBuffer: MTLResource {
        #[unsafe(method(size))]
        #[unsafe(method_family = none)]
        fn size(&self) -> NSUInteger;

        #[cfg(feature = "MTLTypes")]
        /// Handle of the GPU resource suitable for storing in an Argument Buffer
        #[unsafe(method(gpuResourceID))]
        #[unsafe(method_family = none)]
        fn gpuResourceID(&self) -> MTLResourceID;

        /// # Safety
        ///
        /// `range` might not be bounds-checked.
        #[unsafe(method(resetWithRange:))]
        #[unsafe(method_family = none)]
        unsafe fn resetWithRange(&self, range: NSRange);

        #[cfg(feature = "MTLIndirectCommandEncoder")]
        /// # Safety
        ///
        /// `commandIndex` might not be bounds-checked.
        #[unsafe(method(indirectRenderCommandAtIndex:))]
        #[unsafe(method_family = none)]
        unsafe fn indirectRenderCommandAtIndex(
            &self,
            command_index: NSUInteger,
        ) -> Retained<ProtocolObject<dyn MTLIndirectRenderCommand>>;

        #[cfg(feature = "MTLIndirectCommandEncoder")]
        /// # Safety
        ///
        /// `commandIndex` might not be bounds-checked.
        #[unsafe(method(indirectComputeCommandAtIndex:))]
        #[unsafe(method_family = none)]
        unsafe fn indirectComputeCommandAtIndex(
            &self,
            command_index: NSUInteger,
        ) -> Retained<ProtocolObject<dyn MTLIndirectComputeCommand>>;
    }
);
