//! 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!(
    /// Options to configure a command buffer before encoding work into it.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtl4commandbufferoptions?language=objc)
    #[unsafe(super(NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct MTL4CommandBufferOptions;
);

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

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

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

impl MTL4CommandBufferOptions {
    extern_methods!(
        #[cfg(feature = "MTLLogState")]
        /// Contains information related to shader logging.
        ///
        /// To enable shader logging, call ``MTL4CommandBuffer/beginCommandBufferWithAllocator:options:`` with an instance
        /// of ``MTL4CommandBufferOptions`` that contains a non-`nil` ``MTLLogState`` instance in this property.
        ///
        /// Shader functions log messages until the command buffer ends.
        #[unsafe(method(logState))]
        #[unsafe(method_family = none)]
        pub fn logState(&self) -> Option<Retained<ProtocolObject<dyn MTLLogState>>>;

        #[cfg(feature = "MTLLogState")]
        /// Setter for [`logState`][Self::logState].
        #[unsafe(method(setLogState:))]
        #[unsafe(method_family = none)]
        pub fn setLogState(&self, log_state: Option<&ProtocolObject<dyn MTLLogState>>);
    );
}

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

extern_protocol!(
    /// Records a sequence of GPU commands.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtl4commandbuffer?language=objc)
    pub unsafe trait MTL4CommandBuffer: NSObjectProtocol {
        #[cfg(feature = "MTLDevice")]
        /// Returns the GPU device that this command buffer belongs to.
        #[unsafe(method(device))]
        #[unsafe(method_family = none)]
        fn device(&self) -> Retained<ProtocolObject<dyn MTLDevice>>;

        /// Assigns an optional label with this command buffer.
        #[unsafe(method(label))]
        #[unsafe(method_family = none)]
        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)]
        fn setLabel(&self, label: Option<&NSString>);

        #[cfg(feature = "MTL4CommandAllocator")]
        /// Prepares a command buffer for encoding.
        ///
        /// Attaches the command buffer to the specified ``MTL4CommandAllocator`` and declares that the
        /// application is ready to encode commands into the command buffer.
        ///
        /// Command allocators only service a single command buffer at a time. If you need to issue multiple
        /// calls to this method simultaneously, for example, in a multi-threaded command encoding scenario,
        /// create multiple instances of ``MTLCommandAllocator`` and use one for each call.
        ///
        /// You can safely reuse command allocators after ending the command buffer using it by calling
        /// ``endCommandBuffer``.
        ///
        /// After calling this method, any prior calls to ``useResidencySet:`` and ``useResidencySets:count:``
        /// on this command buffer instance no longer apply. Make sure to call these methods again to signal
        /// your residency requirements to Metal.
        ///
        /// - Parameter allocator: ``MTL4CommandAllocator`` to attach to.
        #[unsafe(method(beginCommandBufferWithAllocator:))]
        #[unsafe(method_family = none)]
        fn beginCommandBufferWithAllocator(
            &self,
            allocator: &ProtocolObject<dyn MTL4CommandAllocator>,
        );

        #[cfg(feature = "MTL4CommandAllocator")]
        /// Prepares a command buffer for encoding with additional options.
        ///
        /// Attaches the command buffer to the specified ``MTL4CommandAllocator`` and declares that the
        /// application is ready to encode commands into the command buffer.
        ///
        /// Command allocators only service a single command buffer at a time. If you need to issue multiple
        /// calls to this method simultaneously, for example, in a multi-threaded command encoding scenario,
        /// create multiple instances of ``MTLCommandAllocator`` and use one for each call.
        ///
        /// You can safely reuse command allocators after ending the command buffer using it by calling
        /// ``endCommandBuffer``.
        ///
        /// After calling this method, any prior calls to ``useResidencySet:`` and ``useResidencySets:count:``
        /// on this command buffer instance no longer apply. Make sure to call these methods again to signal
        /// your residency requirements to Metal.
        ///
        /// The options you provide configure the command buffer only until the command buffer ends, in the
        /// next call to ``endCommandBuffer``.
        ///
        /// - Parameters:
        /// - allocator: ``MTL4CommandAllocator`` to attach to.
        /// - options: ``MTL4CommandBufferOptions`` to configure the command buffer.
        #[unsafe(method(beginCommandBufferWithAllocator:options:))]
        #[unsafe(method_family = none)]
        fn beginCommandBufferWithAllocator_options(
            &self,
            allocator: &ProtocolObject<dyn MTL4CommandAllocator>,
            options: &MTL4CommandBufferOptions,
        );

        /// Closes a command buffer to prepare it for submission to a command queue.
        ///
        /// Explicitly ending the command buffer allows you to reuse the ``MTL4CommandAllocator`` to start servicing other
        /// command buffers. It is an error to call ``commit`` on a command buffer previously recording before calling this
        /// method.
        #[unsafe(method(endCommandBuffer))]
        #[unsafe(method_family = none)]
        fn endCommandBuffer(&self);

        #[cfg(all(
            feature = "MTL4CommandEncoder",
            feature = "MTL4RenderCommandEncoder",
            feature = "MTL4RenderPass"
        ))]
        /// Creates a render command encoder from a render pass descriptor.
        ///
        /// - Parameters:
        /// - descriptor: Descriptor for the render pass.
        /// - Returns: The created ``MTL4RenderCommandEncoder`` instance, or `nil` if the function failed.
        #[unsafe(method(renderCommandEncoderWithDescriptor:))]
        #[unsafe(method_family = none)]
        fn renderCommandEncoderWithDescriptor(
            &self,
            descriptor: &MTL4RenderPassDescriptor,
        ) -> Option<Retained<ProtocolObject<dyn MTL4RenderCommandEncoder>>>;

        #[cfg(all(
            feature = "MTL4CommandEncoder",
            feature = "MTL4RenderCommandEncoder",
            feature = "MTL4RenderPass"
        ))]
        /// Creates a render command encoder from a render pass descriptor with additional options.
        ///
        /// This method creates a render command encoder to encode a render pass, whilst providing you the option to define
        /// some render pass characteristics via an instance of ``MTL4RenderEncoderOptions``.
        ///
        /// Use these options to configure suspending/resuming render command encoders, which allow you to encode render passes
        /// from multiple threads simultaneously.
        ///
        /// - Parameters:
        /// - descriptor: Descriptor for the render pass.
        /// - options: ``MTL4RenderEncoderOptions`` instance that provide render pass options.
        /// - Returns: The created ``MTL4RenderCommandEncoder`` instance, or `nil` if the function fails.
        #[unsafe(method(renderCommandEncoderWithDescriptor:options:))]
        #[unsafe(method_family = none)]
        fn renderCommandEncoderWithDescriptor_options(
            &self,
            descriptor: &MTL4RenderPassDescriptor,
            options: MTL4RenderEncoderOptions,
        ) -> Option<Retained<ProtocolObject<dyn MTL4RenderCommandEncoder>>>;

        #[cfg(all(feature = "MTL4CommandEncoder", feature = "MTL4ComputeCommandEncoder"))]
        /// Creates a compute command encoder.
        ///
        /// - Returns: The created ``MTL4ComputeCommandEncoder`` instance, or `nil` if the function fails.
        #[unsafe(method(computeCommandEncoder))]
        #[unsafe(method_family = none)]
        fn computeCommandEncoder(
            &self,
        ) -> Option<Retained<ProtocolObject<dyn MTL4ComputeCommandEncoder>>>;

        #[cfg(all(
            feature = "MTL4CommandEncoder",
            feature = "MTL4MachineLearningCommandEncoder"
        ))]
        /// Creates a machine learning command encoder.
        ///
        /// - Returns: The created ``MTL4MachineLearningCommandEncoder`` instance , or `nil` if the function fails.
        #[unsafe(method(machineLearningCommandEncoder))]
        #[unsafe(method_family = none)]
        fn machineLearningCommandEncoder(
            &self,
        ) -> Option<Retained<ProtocolObject<dyn MTL4MachineLearningCommandEncoder>>>;

        #[cfg(feature = "MTLResidencySet")]
        /// Marks a residency set as part of the command buffer's execution.
        ///
        /// Ensures that Metal makes resident the resources that residency set contains during execution of this command buffer.
        ///
        /// - Parameter residencySet: ``MTLResidencySet`` instance to mark resident.
        #[unsafe(method(useResidencySet:))]
        #[unsafe(method_family = none)]
        fn useResidencySet(&self, residency_set: &ProtocolObject<dyn MTLResidencySet>);

        #[cfg(feature = "MTLResidencySet")]
        /// Marks an array of residency sets as part of the command buffer's execution.
        ///
        /// Ensures that Metal makes resident the resources that residency sets contain during execution of this command buffer.
        ///
        /// - Parameters:
        /// - residencySets: Array of ``MTLResidencySet`` instances to mark resident.
        /// - count: Number of ``MTLResidencySet`` instances in the array.
        ///
        /// # Safety
        ///
        /// - `residency_sets` must be a valid pointer.
        /// - `count` might not be bounds-checked.
        #[unsafe(method(useResidencySets:count:))]
        #[unsafe(method_family = none)]
        unsafe fn useResidencySets_count(
            &self,
            residency_sets: NonNull<NonNull<ProtocolObject<dyn MTLResidencySet>>>,
            count: NSUInteger,
        );

        /// Pushes a string onto a stack of debug groups for this command buffer.
        ///
        /// - Parameter string: The string to push.
        #[unsafe(method(pushDebugGroup:))]
        #[unsafe(method_family = none)]
        fn pushDebugGroup(&self, string: &NSString);

        /// Pops the latest string from the stack of debug groups for this command buffer.
        #[unsafe(method(popDebugGroup))]
        #[unsafe(method_family = none)]
        fn popDebugGroup(&self);

        #[cfg(feature = "MTL4Counters")]
        /// Writes a GPU timestamp into the given counter heap.
        ///
        /// This method captures a timestamp after work prior to this command in the command buffer is complete.
        /// Work after this call may or may not have started.
        ///
        /// You are responsible for ensuring the `counterHeap` is of type ``MTL4CounterHeapType/MTL4CounterHeapTypeTimestamp``.
        ///
        /// - Parameters:
        /// - counterHeap: ``MTL4CounterHeap`` to write the timestamp into.
        /// - index: The index within the ``MTL4CounterHeap`` that Metal writes the timestamp to.
        ///
        /// # Safety
        ///
        /// `index` might not be bounds-checked.
        #[unsafe(method(writeTimestampIntoHeap:atIndex:))]
        #[unsafe(method_family = none)]
        unsafe fn writeTimestampIntoHeap_atIndex(
            &self,
            counter_heap: &ProtocolObject<dyn MTL4CounterHeap>,
            index: NSUInteger,
        );

        #[cfg(all(
            feature = "MTL4BufferRange",
            feature = "MTL4Counters",
            feature = "MTLFence",
            feature = "MTLGPUAddress"
        ))]
        /// Encodes a command that resolves an opaque counter heap into a buffer.
        ///
        /// The command this method encodes converts the data within `counterHeap` into a common format
        /// and stores it into the `bufferRange` parameter.
        ///
        /// The command places each entry in the counter heap within `range` sequentially, starting at `alignedOffset`.
        /// Each entry needs to be a fixed size that you can query by calling the
        /// ``MTLDevice/sizeOfCounterHeapEntry:`` method.
        ///
        /// This command runs during the `MTLStageBlit` stage of the GPU timeline. Barrier against this stage
        /// to ensure the data is present in the resolve buffer parameter before you access it.
        ///
        /// - Note: Your app needs ensure the GPU places data in the heap before you resolve it by
        /// synchronizing this stage with other GPU operations.
        ///
        /// Similarly, your app needs to synchronize any GPU accesses to `bufferRange` after
        /// the command completes with barrier.
        ///
        /// If your app needs to access `bufferRange` from the CPU, signal an ``MTLSharedEvent``
        /// to notify the CPU when it's ready.
        /// Alternatively, you can resolve the heap's data from the CPU by calling
        /// the heap's ``MTL4CounterHeap/resolveCounterRange:`` method.
        ///
        /// - Parameters:
        /// - counterHeap: A heap the command resolves.
        /// - range: A range of index values within the heap the command resolves.
        /// - bufferRange: The buffer the command saves the data it resolves into.
        /// - fenceToWait: A fence the GPU waits for before starting, if applicable; otherwise `nil`.
        /// - fenceToUpdate: A fence the system updates after the command finishes resolving the data; otherwise `nil`.
        ///
        /// # Safety
        ///
        /// - `range` might not be bounds-checked.
        /// - `bufferRange` might not be bounds-checked.
        #[unsafe(method(resolveCounterHeap:withRange:intoBuffer:waitFence:updateFence:))]
        #[unsafe(method_family = none)]
        unsafe fn resolveCounterHeap_withRange_intoBuffer_waitFence_updateFence(
            &self,
            counter_heap: &ProtocolObject<dyn MTL4CounterHeap>,
            range: NSRange,
            buffer_range: MTL4BufferRange,
            fence_to_wait: Option<&ProtocolObject<dyn MTLFence>>,
            fence_to_update: Option<&ProtocolObject<dyn MTLFence>>,
        );
    }
);
