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

/// Memory consistency options for synchronization commands.
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtl4visibilityoptions?language=objc)
// NS_OPTIONS
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct MTL4VisibilityOptions(pub NSUInteger);
bitflags::bitflags! {
    impl MTL4VisibilityOptions: NSUInteger {
/// Don't flush caches. When you use this option on a barrier, it turns it into an execution barrier.
        #[doc(alias = "MTL4VisibilityOptionNone")]
        const None = 0;
/// Flushes caches to the GPU (device) memory coherence point.
        #[doc(alias = "MTL4VisibilityOptionDevice")]
        const Device = 1<<0;
/// Flushes caches to ensure that aliased virtual addresses are memory consistent.
///
/// On some systems this may be the GPU+CPU (system) memory coherence point
/// and on other systems it may be the GPU (device) memory coherence point.
        #[doc(alias = "MTL4VisibilityOptionResourceAlias")]
        const ResourceAlias = 1<<1;
    }
}

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

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

extern_protocol!(
    /// An encoder that writes GPU commands into a command buffer.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtl4commandencoder?language=objc)
    pub unsafe trait MTL4CommandEncoder: NSObjectProtocol {
        /// Provides an optional label to assign to the command encoder for debug purposes.
        #[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 = "MTL4CommandBuffer")]
        /// Returns the command buffer that is currently encoding commands.
        ///
        /// This property may return undefined results if you call it after calling ``endEncoding``.
        #[unsafe(method(commandBuffer))]
        #[unsafe(method_family = none)]
        fn commandBuffer(&self) -> Option<Retained<ProtocolObject<dyn MTL4CommandBuffer>>>;

        #[cfg(feature = "MTLCommandEncoder")]
        /// Encodes a consumer barrier on work you commit to the same command queue.
        ///
        /// Encode a barrier that guarantees that any subsequent work you encode in the current command encoder that corresponds
        /// to the `beforeStages` stages doesn't proceed until Metal completes all work prior to the current command encoder
        /// corresponding to the `afterQueueStages` stages, completes.
        ///
        /// Metal can reorder the exact point where it applies the barrier, so encode the barrier as close to the command that
        /// consumes the resource as possible. Don't use this method for synchronizing resource access within the same pass.
        ///
        /// If you need to synchronize work within a pass that you encode with an instance of a subclass of ``MTLCommandEncoder``,
        /// use memory barriers instead. For subclasses of ``MTL4CommandEncoder``, use encoder barriers.
        ///
        /// You can specify `afterQueueStages` and `beforeStages` that contain ``MTLStages`` unrelated to the current command
        /// encoder.
        ///
        /// - Parameters:
        /// - afterQueueStages: ``MTLStages`` mask that represents the stages of work to wait for.
        /// This argument applies to work corresponding to these stages you
        /// encode in prior command encoders, and not for the current encoder.
        /// - beforeStages:     ``MTLStages`` mask that represents the stages of work that wait.
        /// This argument applies to work you encode in the current command encoder.
        /// - visibilityOptions: ``MTL4VisibilityOptions`` of the barrier.
        #[unsafe(method(barrierAfterQueueStages:beforeStages:visibilityOptions:))]
        #[unsafe(method_family = none)]
        fn barrierAfterQueueStages_beforeStages_visibilityOptions(
            &self,
            after_queue_stages: MTLStages,
            before_stages: MTLStages,
            visibility_options: MTL4VisibilityOptions,
        );

        #[cfg(feature = "MTLCommandEncoder")]
        /// Encodes a producer barrier on work committed to the same command queue.
        ///
        /// This method encodes a barrier that guarantees that any work you encode using *subsequent command encoders*,
        /// corresponding to `beforeQueueStages`, don't begin until all commands you previously encode in the current
        /// encoder (and prior encoders), corresponding to `afterStages`, complete.
        ///
        /// When calling this method, you can pass any ``MTLStages`` to parameters `afterStages` and `beforeQueueStages`,
        /// even stages that don't relate to the current or prior command encoders.
        ///
        /// - Parameters:
        /// - afterStages:       ``MTLStages`` mask that represents the stages of work to wait for.
        /// This argument applies to work corresponding to these stages you encode in
        /// the current command encoder prior to this barrier command.
        /// - beforeQueueStages: ``MTLStages`` mask that represents the stages of work that need to wait.
        /// This argument applies to subsequent encoders and not to work in the current
        /// command encoder.
        /// - visibilityOptions: ``MTL4VisibilityOptions`` of the barrier, controlling cache flush behavior.
        #[unsafe(method(barrierAfterStages:beforeQueueStages:visibilityOptions:))]
        #[unsafe(method_family = none)]
        fn barrierAfterStages_beforeQueueStages_visibilityOptions(
            &self,
            after_stages: MTLStages,
            before_queue_stages: MTLStages,
            visibility_options: MTL4VisibilityOptions,
        );

        #[cfg(feature = "MTLCommandEncoder")]
        /// Encodes an intra-pass barrier.
        ///
        /// Encode a barrier that guarantees that any subsequent work you encode in the *current command encoder*,
        /// corresponding to `beforeEncoderStages`, doesn't begin until all prior commands in this command encoder,
        /// corresponding to `afterEncoderStages`, completes.
        ///
        /// When calling this method, it's your responsibility to ensure parameters `afterEncoderStages` and `beforeEncoderStages`
        /// contain a combination of ``MTLStages`` for which this encoder can encode commands. For example, for a
        /// ``MTL4ComputeCommandEncoder`` instance, you can provide any combination of ``MTLStages/MTLStageDispatch``,
        /// ``MTLStages/MTLStageBlit`` and ``MTLStages/MTLStageAccelerationStructure``.
        ///
        /// - Parameters:
        /// - afterEncoderStages:  ``MTLStages`` mask that represents the stages of work to wait for.
        /// This argument only applies to subsequent work you encode in the current command encoder.
        /// - beforeEncoderStages: ``MTLStages`` mask that represents the stages of work that wait.
        /// This argument only applies to work you encode in the current command encoder prior to
        /// this barrier.
        /// - visibilityOptions: ``MTL4VisibilityOptions`` of the barrier, controlling cache flush behavior.
        #[unsafe(method(barrierAfterEncoderStages:beforeEncoderStages:visibilityOptions:))]
        #[unsafe(method_family = none)]
        fn barrierAfterEncoderStages_beforeEncoderStages_visibilityOptions(
            &self,
            after_encoder_stages: MTLStages,
            before_encoder_stages: MTLStages,
            visibility_options: MTL4VisibilityOptions,
        );

        #[cfg(all(feature = "MTLCommandEncoder", feature = "MTLFence"))]
        /// Encodes a command to update a GPU fence.
        ///
        /// This method encodes a command that updates a ``MTLFence`` instance after all previously-encoded commands in the
        /// current command encoder, corresponding to `afterEncoderStages`, complete.
        ///
        /// Use parameter `afterEncoderStages` to pass in a combination of ``MTLStages`` for which this encoder can encode work.
        /// For example, for a ``MTL4ComputeCommandEncoder`` you can provide any combination of ``MTLStages/MTLStageDispatch``,
        /// ``MTLStages/MTLStageBlit`` and ``MTLStages/MTLStageAccelerationStructure``.
        ///
        /// - Parameters:
        /// - fence:              ``MTLFence`` instance to update.
        /// - afterEncoderStages: ``MTLStages`` value that represents the stages of work to wait for.
        /// This argument only applies to work encoded in the current command encoder.
        #[unsafe(method(updateFence:afterEncoderStages:))]
        #[unsafe(method_family = none)]
        fn updateFence_afterEncoderStages(
            &self,
            fence: &ProtocolObject<dyn MTLFence>,
            after_encoder_stages: MTLStages,
        );

        #[cfg(all(feature = "MTLCommandEncoder", feature = "MTLFence"))]
        /// Encodes a command to wait on a GPU fence.
        ///
        /// Encode a command that guarantees that any subsequent work you encode via this current command encoder,
        /// corresponding to `beforeEncoderStages`, doesn't begin until all prior updates to the fence is complete.
        ///
        /// To successfully wait for a fence update, schedule update and wait operations on the same command queue.
        ///
        /// Use parameter `beforeEncoderStages` to pass in a combination of ``MTLStages`` for which this encoder can encode
        /// work. For example, for a ``MTL4ComputeCommandEncoder`` you can provide any combination of
        /// ``MTLStages/MTLStageDispatch``, ``MTLStages/MTLStageBlit`` and ``MTLStages/MTLStageAccelerationStructure``.
        ///
        /// - Parameters:
        /// - fence:              ``MTLFence`` instance to wait for.
        /// - beforeEncoderStages:``MTLStages`` value that represents the stages of work that wait.
        /// This argument only applies to work you encode in the current command encoder.
        #[unsafe(method(waitForFence:beforeEncoderStages:))]
        #[unsafe(method_family = none)]
        fn waitForFence_beforeEncoderStages(
            &self,
            fence: &ProtocolObject<dyn MTLFence>,
            before_encoder_stages: MTLStages,
        );

        /// Inserts a debug string into the frame data to aid debugging.
        ///
        /// Calling this method doesn't change any behaviors, but can be useful for debugging purposes.
        ///
        /// - Parameter string: The debug string to insert as a signpost.
        #[unsafe(method(insertDebugSignpost:))]
        #[unsafe(method_family = none)]
        fn insertDebugSignpost(&self, string: &NSString);

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

        /// Pops the latest debug group string from this encoder's stack of debug groups.
        #[unsafe(method(popDebugGroup))]
        #[unsafe(method_family = none)]
        fn popDebugGroup(&self);

        /// Declares that all command generation from this encoder is complete.
        #[unsafe(method(endEncoding))]
        #[unsafe(method_family = none)]
        fn endEncoding(&self);
    }
);
