//! This file has been automatically generated by `objc2`'s `header-translator`.
//! DO NOT EDIT
use core::ops::Range;

use objc2::runtime::ProtocolObject;
use objc2::{Message, extern_protocol, msg_send};
use objc2_foundation::NSRange;

use crate::*;

extern_protocol!(
    /// Encodes a compute pass and other memory operations into a command buffer.
    ///
    /// Use instances of this abstraction to encode a compute pass into ``MTL4CommandBuffer`` instances, as well as commands
    /// that copy and modify the underlying memory of various Metal resources, and commands that build or refit acceleration
    /// structures.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtl4computecommandencoder?language=objc)
    pub unsafe trait MTL4ComputeCommandEncoder: MTL4CommandEncoder {
        /// Queries a bitmask representing the shader stages on which commands currently present in this command encoder
        /// operate.
        ///
        /// Metal dynamically updates this property based on the commands you encode into the command encoder, for example,
        /// it sets the bit ``MTLStages/MTLStageDispatch`` if this encoder contains any commands that dispatch a compute kernel.
        ///
        /// Similarly, it sets the bit ``MTLStages/MTLStageBlit`` if this encoder contains any commands to copy or modify buffers,
        /// textures, or indirect command buffers.
        ///
        /// Finally, Metal sets the bit ``MTLStages/MTLStageAccelerationStructure`` if this encoder contains any commands that
        /// build, copy, or refit acceleration structures.
        ///
        /// - Returns: a bitmask representing shader stages that commands currently present in this command encoder operate on.
        #[unsafe(method(stages))]
        #[unsafe(method_family = none)]
        fn stages(&self) -> MTLRenderStages;

        /// Configures this encoder with a compute pipeline state that applies to your subsequent dispatch commands.
        ///
        /// - Parameter state: a non-`nil` ``MTLComputePipelineState``.
        #[unsafe(method(setComputePipelineState:))]
        #[unsafe(method_family = none)]
        fn set_compute_pipeline_state(
            &self,
            state: &ProtocolObject<dyn MTLComputePipelineState>,
        );

        /// Configures the size of a threadgroup memory buffer for a threadgroup argument in the compute shader function.
        ///
        /// - Parameters:
        /// - length: The size of the threadgroup memory, in bytes. Use a multiple of `16` bytes.
        /// - index: An integer that corresponds to the index of the argument you annotate with attribute `[[threadgroup(index)]]`
        /// in the shader function.
        #[unsafe(method(setThreadgroupMemoryLength:atIndex:))]
        #[unsafe(method_family = none)]
        fn set_threadgroup_memory_length_at_index(&self, length: usize, index: usize);

        /// Specifies the size, in pixels, of imageblock data in tile memory.
        ///
        /// - Parameters:
        /// - width:  The width of the imageblock, in pixels.
        /// - height: The height of the imageblock, in pixels.
        #[unsafe(method(setImageblockWidth:height:))]
        #[unsafe(method_family = none)]
        fn set_imageblock_width_height(&self, width: usize, height: usize);

        /// Encodes a compute dispatch command using an arbitrarily-sized grid.
        ///
        /// - Parameters:
        /// - threadsPerGrid:        An ``MTLSize`` instance that represents the number of threads in the grid,
        /// in each dimension.
        /// - threadsPerThreadgroup: An ``MTLSize`` instance that represents the number of threads in one
        /// threadgroup, in each dimension.
        #[unsafe(method(dispatchThreads:threadsPerThreadgroup:))]
        #[unsafe(method_family = none)]
        fn dispatch_threads_threads_per_threadgroup(
            &self,
            threads_per_grid: MTLSize,
            threads_per_threadgroup: MTLSize,
        );

        /// Encodes a compute dispatch command with a grid that aligns to threadgroup boundaries.
        ///
        /// - Parameters:
        /// - threadgroupsPerGrid:   An ``MTLSize`` instance that represents the number of threadgroups in the grid,
        /// in each dimension.
        /// - threadsPerThreadgroup: An ``MTLSize`` instance that represents the number of threads in one
        /// threadgroup, in each dimension.
        #[unsafe(method(dispatchThreadgroups:threadsPerThreadgroup:))]
        #[unsafe(method_family = none)]
        fn dispatch_threadgroups_threads_per_threadgroup(
            &self,
            threadgroups_per_grid: MTLSize,
            threads_per_threadgroup: MTLSize,
        );

        /// Encodes a compute dispatch command with a grid that aligns to threadgroup boundaries, using an indirect buffer
        /// for arguments.
        ///
        /// This method allows you to supply the threadgroups-per-grid counts indirectly via an ``MTLBuffer`` index. This
        /// enables you to calculate this value in the GPU timeline from a shader function, enabling GPU-driven workflows.
        ///
        /// Metal assumes that the buffer contents correspond to the layout of struct ``MTLDispatchThreadgroupsIndirectArguments``.
        /// You are responsible for ensuring this address aligns to 4-bytes.
        ///
        /// Use an instance of ``MTLResidencySet`` to mark residency of the indirect buffer that the `indirectBuffer`
        /// parameter references.
        ///
        /// - Parameters:
        /// - indirectBuffer:        GPUAddress of a ``MTLBuffer`` instance providing compute parameters.
        /// Lay out the data in this buffer as described in the
        /// ``MTLDispatchThreadgroupsIndirectArguments`` structure. This address
        /// requires 4-byte alignment.
        /// - threadsPerThreadgroup: A ``MTLSize`` instance that represents the number of threads in one
        /// threadgroup, in each dimension.
        #[unsafe(method(dispatchThreadgroupsWithIndirectBuffer:threadsPerThreadgroup:))]
        #[unsafe(method_family = none)]
        fn dispatch_threadgroups_with_indirect_buffer_threads_per_threadgroup(
            &self,
            indirect_buffer: MTLGPUAddress,
            threads_per_threadgroup: MTLSize,
        );

        /// Encodes a compute dispatch command with an arbitrarily sized grid, using an indirect buffer for arguments.
        ///
        /// - Parameters:
        /// - indirectBuffer: GPUAddress of a ``MTLBuffer`` instance providing arguments. Lay out the data
        /// in this buffer as described in the ``MTLDispatchThreadsIndirectArguments``
        /// structure. This address requires 4-byte alignment.
        #[unsafe(method(dispatchThreadsWithIndirectBuffer:))]
        #[unsafe(method_family = none)]
        fn dispatch_threads_with_indirect_buffer(&self, indirect_buffer: MTLGPUAddress);

        /// Encodes an instruction to execute commands from an indirect command buffer, using an indirect buffer for
        /// arguments.
        ///
        /// Use an instance of ``MTLResidencySet`` to mark residency of the indirect buffer that the `indirectRangeBuffer`
        /// parameter references.
        ///
        /// - Parameters:
        /// - indirectCommandbuffer: ``MTLIndirectCommandBuffer`` instance containing the commands to execute.
        /// - indirectRangeBuffer:   GPUAddress of a ``MTLBuffer`` containing the execution range. Lay out the data
        /// in this buffer as described in the ``MTLIndirectCommandBufferExecutionRange``
        /// structure. This address requires 4-byte alignment.
        #[unsafe(method(executeCommandsInBuffer:indirectBuffer:))]
        #[unsafe(method_family = none)]
        fn execute_commands_in_buffer_indirect_buffer(
            &self,
            indirect_commandbuffer: &ProtocolObject<dyn MTLIndirectCommandBuffer>,
            indirect_range_buffer: MTLGPUAddress,
        );

        /// Encodes a command that copies data from a texture to another.
        ///
        /// - Parameters:
        /// - sourceTexture:      An ``MTLTexture`` instance the command copies data from.
        /// - destinationTexture: Another ``MTLTexture`` instance the command copies the data into that has the same
        /// ``MTLTexture/pixelFormat`` and ``MTLTexture/sampleCount`` as `sourceTexture`.
        #[unsafe(method(copyFromTexture:toTexture:))]
        #[unsafe(method_family = none)]
        fn copy_from_texture_to_texture(
            &self,
            source_texture: &ProtocolObject<dyn MTLTexture>,
            destination_texture: &ProtocolObject<dyn MTLTexture>,
        );

        /// Encodes a command that copies slices of a texture to slices of another texture.
        ///
        /// - Parameters:
        /// - sourceTexture:      A ``MTLTexture`` texture that the command copies data from. To read the source
        /// texture contents, you need to set its ``MTLTexture/framebufferOnly`` property
        /// to
        /// <doc
        /// ://com.apple.documentation/documentation/swift/false> prior to drawing into it.
        /// - sourceSlice:        A slice within `sourceTexture` the command uses as a starting point to copy
        /// data from. Set this to `0` if `sourceTexture` isn’t a texture array or a
        /// cube texture.
        /// - sourceLevel:        A mipmap level within `sourceTexture`.
        /// - destinationTexture: Another ``MTLTexture`` the command copies the data to that has the same
        /// ``MTLTexture/pixelFormat`` and ``MTLTexture/sampleCount`` as `sourceTexture`.
        /// To write the contents into this texture, you need to set its ``MTLTexture/framebufferOnly``
        /// property to
        /// <doc
        /// ://com.apple.documentation/documentation/swift/false>.
        /// - destinationSlice:   A slice within `destinationTexture` the command uses as its starting point
        /// for copying data to. Set this to `0` if `destinationTexture` isn’t a texture
        /// array or a cube texture.
        /// - destinationLevel:   A mipmap level within `destinationTexture`. The mipmap level you reference needs to
        /// have the same size as the `sourceTexture` slice's mipmap at `sourceLevel`.
        /// - sliceCount:         The number of slices the command copies so that it satisfies the conditions
        /// that the sum of `sourceSlice` and `sliceCount` doesn’t exceed the number of
        /// slices in `sourceTexture` and the sum of `destinationSlice` and `sliceCount`
        /// doesn’t exceed the number of slices in `destinationTexture`.
        /// - levelCount:         The number of mipmap levels the command copies so that it satisfies the
        /// conditions that the sum of `sourceLevel` and `levelCount` doesn’t exceed the
        /// number of mipmap levels in `sourceTexture` and the sum of `destinationLevel`
        /// and `levelCount` doesn’t exceed the number of mipmap levels in `destinationTexture`.
        #[unsafe(method(copyFromTexture:sourceSlice:sourceLevel:toTexture:destinationSlice:destinationLevel:sliceCount:levelCount:))]
        #[unsafe(method_family = none)]
        fn copy_from_texture_source_slice_source_level_to_texture_destination_slice_destination_level_slice_count_level_count(
            &self,
            source_texture: &ProtocolObject<dyn MTLTexture>,
            source_slice: usize,
            source_level: usize,
            destination_texture: &ProtocolObject<dyn MTLTexture>,
            destination_slice: usize,
            destination_level: usize,
            slice_count: usize,
            level_count: usize,
        );

        /// Encodes a command that copies image data from a slice of a texture into a slice of another texture.
        ///
        /// - Parameters:
        /// - sourceTexture:      An ``MTLTexture`` texture that the command copies data from. To read the source
        /// texture contents, you need to set its ``MTLTexture/framebufferOnly`` property
        /// to
        /// <doc
        /// ://com.apple.documentation/documentation/swift/false> prior to drawing into it.
        /// - sourceSlice:        A slice within `sourceTexture` the command uses as a starting point to copy
        /// data from. Set this to `0` if `sourceTexture` isn’t a texture array or a
        /// cube texture.
        /// - sourceLevel:        A mipmap level within `sourceTexture`.
        /// - sourceOrigin:       An ``MTLOrigin`` instance that represents a location within `sourceTexture`
        /// that the command begins copying data from. Assign `0` to each dimension
        /// that’s not relevant to `sourceTexture`.
        /// - sourceSize:         An ``MTLSize`` instance that represents the size of the region, in pixels,
        /// that the command copies from `sourceTexture`, starting at `sourceOrigin`.
        /// Assign `1` to each dimension that’s not relevant to `sourceTexture`. If
        /// sourceTexture uses a compressed pixel format, set `sourceSize` to a multiple
        /// of the pixel format’s block size. If the block extends outside the bounds of
        /// the texture, clamp `sourceSize` to the edge of the texture.
        /// - destinationTexture: Another ``MTLTexture`` the command copies the data to that has the same
        /// ``MTLTexture/pixelFormat`` and ``MTLTexture/sampleCount`` as `sourceTexture`.
        /// To write the contents into this texture, you need to set its ``MTLTexture/framebufferOnly``
        /// property to
        /// <doc
        /// ://com.apple.documentation/documentation/swift/false>.
        /// - destinationSlice:   A slice within `destinationTexture` the command uses as its starting point
        /// for copying data to. Set this to `0` if `destinationTexture` isn’t a texture
        /// array or a cube texture.
        /// - destinationLevel:   A mipmap level within `destinationTexture`. The mipmap level you reference needs to
        /// have the same size as the `sourceTexture` slice's mipmap at `sourceLevel`.
        /// - destinationOrigin:  An ``MTLOrigin`` instance that represents a location within `destinationTexture`
        /// that the command begins copying data to. Assign `0` to each dimension that’s
        /// not relevant to `destinationTexture`.
        #[unsafe(method(copyFromTexture:sourceSlice:sourceLevel:sourceOrigin:sourceSize:toTexture:destinationSlice:destinationLevel:destinationOrigin:))]
        #[unsafe(method_family = none)]
        fn copy_from_texture_source_slice_source_level_source_origin_source_size_to_texture_destination_slice_destination_level_destination_origin(
            &self,
            source_texture: &ProtocolObject<dyn MTLTexture>,
            source_slice: usize,
            source_level: usize,
            source_origin: MTLOrigin,
            source_size: MTLSize,
            destination_texture: &ProtocolObject<dyn MTLTexture>,
            destination_slice: usize,
            destination_level: usize,
            destination_origin: MTLOrigin,
        );

        /// Encodes a command that copies image data from a slice of an ``MTLTexture`` instance to an ``MTLBuffer`` instance.
        ///
        /// - Parameters:
        /// - sourceTexture:            An ``MTLTexture`` texture that the command copies data from. To read the source
        /// texture contents, you need to set its ``MTLTexture/framebufferOnly`` property
        /// to
        /// <doc
        /// ://com.apple.documentation/documentation/swift/false> prior to drawing into it.
        /// - sourceSlice:              A slice within `sourceTexture` the command uses as a starting point to copy
        /// data from. Set this to `0` if `sourceTexture` isn’t a texture array or a
        /// cube texture.
        /// - sourceLevel:              A mipmap level within `sourceTexture`.
        /// - sourceOrigin:             An ``MTLOrigin`` instance that represents a location within `sourceTexture`
        /// that the command begins copying data from. Assign `0` to each dimension
        /// that’s not relevant to `sourceTexture`.
        /// - sourceSize:               An ``MTLSize`` instance that represents the size of the region, in pixels,
        /// that the command copies from `sourceTexture`, starting at `sourceOrigin`.
        /// Assign `1` to each dimension that’s not relevant to `sourceTexture`.
        /// If `sourceTexture` uses a compressed pixel format, set `sourceSize` to a
        /// multiple of the `sourceTexture's` ``MTLTexture/pixelFormat`` block size.
        /// If the block extends outside the bounds of the texture, clamp `sourceSize`
        /// to the edge of the texture.
        /// - destinationBuffer:        An ``MTLBuffer`` instance the command copies data to.
        /// - destinationOffset:        A byte offset within `destinationBuffer` the command copies to. The value
        /// you provide as this argument needs to be a multiple of `sourceTexture's` pixel size,
        /// in bytes.
        /// - destinationBytesPerRow:   The number of bytes between adjacent rows of pixels in `destinationBuffer`.
        /// This value must be a multiple of `sourceTexture's` pixel size, in bytes,
        /// and less than or equal to the product of `sourceTexture's` pixel size,
        /// in bytes, and the largest pixel width `sourceTexture’s` type allows. If
        /// `sourceTexture` uses a compressed pixel format, set `destinationBytesPerRow`
        /// to the number of bytes between the starts of two row blocks.
        /// - destinationBytesPerImage: The number of bytes between each 2D image of a 3D texture. This value must
        /// be a multiple of `sourceTexture's` pixel size, in bytes. Set this value to
        /// `0` if `sourceSize's` ``MTLSize/depth`` value is `1`.
        #[unsafe(method(copyFromTexture:sourceSlice:sourceLevel:sourceOrigin:sourceSize:toBuffer:destinationOffset:destinationBytesPerRow:destinationBytesPerImage:))]
        #[unsafe(method_family = none)]
        fn copy_from_texture_source_slice_source_level_source_origin_source_size_to_buffer_destination_offset_destination_bytes_per_row_destination_bytes_per_image(
            &self,
            source_texture: &ProtocolObject<dyn MTLTexture>,
            source_slice: usize,
            source_level: usize,
            source_origin: MTLOrigin,
            source_size: MTLSize,
            destination_buffer: &ProtocolObject<dyn MTLBuffer>,
            destination_offset: usize,
            destination_bytes_per_row: usize,
            destination_bytes_per_image: usize,
        );

        /// Encodes a command that copies image data from a slice of a texture instance to a buffer, with
        /// options for special texture formats.
        ///
        /// - Parameters:
        /// - sourceTexture:            An ``MTLTexture`` texture that the command copies data from. To read the source
        /// texture contents, you need to set its ``MTLTexture/framebufferOnly`` property
        /// to
        /// <doc
        /// ://com.apple.documentation/documentation/swift/false> prior to drawing into it.
        /// - sourceSlice:              A slice within `sourceTexture` the command uses as a starting point to copy
        /// data from. Set this to `0` if `sourceTexture` isn’t a texture array or a
        /// cube texture.
        /// - sourceLevel:              A mipmap level within `sourceTexture`.
        /// - sourceOrigin:             An ``MTLOrigin`` instance that represents a location within `sourceTexture`
        /// that the command begins copying data from. Assign `0` to each dimension
        /// that’s not relevant to `sourceTexture`.
        /// - sourceSize:               An ``MTLSize`` instance that represents the size of the region, in pixels,
        /// that the command copies from `sourceTexture`, starting at `sourceOrigin`.
        /// Assign `1` to each dimension that’s not relevant to `sourceTexture`.
        /// If `sourceTexture` uses a compressed pixel format, set `sourceSize` to a
        /// multiple of the `sourceTexture's` ``MTLTexture/pixelFormat`` block size.
        /// If the block extends outside the bounds of the texture, clamp `sourceSize`
        /// to the edge of the texture.
        /// - destinationBuffer:        An ``MTLBuffer`` instance the command copies data to.
        /// - destinationOffset:        A byte offset within `destinationBuffer` the command copies to. The value
        /// you provide as this argument needs to be a multiple of `sourceTexture's` pixel size,
        /// in bytes.
        /// - destinationBytesPerRow:   The number of bytes between adjacent rows of pixels in `destinationBuffer`.
        /// This value must be a multiple of `sourceTexture's` pixel size, in bytes,
        /// and less than or equal to the product of `sourceTexture's` pixel size,
        /// in bytes, and the largest pixel width `sourceTexture’s` type allows. If
        /// `sourceTexture` uses a compressed pixel format, set `destinationBytesPerRow`
        /// to the number of bytes between the starts of two row blocks.
        /// - destinationBytesPerImage: The number of bytes between each 2D image of a 3D texture. This value must
        /// be a multiple of `sourceTexture's` pixel size, in bytes. Set this value to
        /// `0` if `sourceSize's` ``MTLSize/depth`` value is `1`.
        /// - options:                  A ``MTLBlitOption`` value that applies to textures with applicable pixel
        /// formats, such as combined depth/stencil or PVRTC formats. If `sourceTexture's`
        /// ``MTLTexture/pixelFormat`` is a combined depth/stencil format, set `options`
        /// to either ``MTLBlitOption/MTLBlitOptionDepthFromDepthStencil`` or
        /// ``MTLBlitOption/MTLBlitOptionStencilFromDepthStencil``, but not both.
        /// If `sourceTexture's` ``MTLTexture/pixelFormat`` is a PVRTC format, set
        /// `options` to ``MTLBlitOption/MTLBlitOptionRowLinearPVRTC``.
        #[unsafe(method(copyFromTexture:sourceSlice:sourceLevel:sourceOrigin:sourceSize:toBuffer:destinationOffset:destinationBytesPerRow:destinationBytesPerImage:options:))]
        #[unsafe(method_family = none)]
        fn copy_from_texture_source_slice_source_level_source_origin_source_size_to_buffer_destination_offset_destination_bytes_per_row_destination_bytes_per_image_options(
            &self,
            source_texture: &ProtocolObject<dyn MTLTexture>,
            source_slice: usize,
            source_level: usize,
            source_origin: MTLOrigin,
            source_size: MTLSize,
            destination_buffer: &ProtocolObject<dyn MTLBuffer>,
            destination_offset: usize,
            destination_bytes_per_row: usize,
            destination_bytes_per_image: usize,
            options: MTLBlitOption,
        );

        /// Encodes a command that copies data from a buffer instance into another.
        ///
        /// - Parameters:
        /// - sourceBuffer:      An ``MTLBuffer`` instance the command copies data from.
        /// - sourceOffset:      A byte offset within `sourceBuffer` the command copies from.
        /// - destinationBuffer: An ``MTLBuffer`` instance the command copies data to.
        /// - destinationOffset: A byte offset within `destinationBuffer` the command copies to.
        /// - size:              The number of bytes the command copies from `sourceBuffer` to `destinationBuffer`.
        #[unsafe(method(copyFromBuffer:sourceOffset:toBuffer:destinationOffset:size:))]
        #[unsafe(method_family = none)]
        fn copy_from_buffer_source_offset_to_buffer_destination_offset_size(
            &self,
            source_buffer: &ProtocolObject<dyn MTLBuffer>,
            source_offset: usize,
            destination_buffer: &ProtocolObject<dyn MTLBuffer>,
            destination_offset: usize,
            size: usize,
        );

        /// Encodes a command to copy image data from a buffer instance into a texture.
        ///
        /// - Parameters:
        /// - sourceBuffer:        A ``MTLBuffer`` instance the command copies data from.
        /// - sourceOffset:        A byte offset within `sourceBuffer` the command copies from. Set this value to
        /// a multiple of `destinationTexture's` pixel size, in bytes.
        /// - sourceBytesPerRow:   The number of bytes between adjacent rows of pixels in `sourceBuffer`. Set this value to
        /// a multiple of `destinationTexture's` pixel size, in bytes, and less than or equal to
        /// the product of `destinationTexture's` pixel size, in bytes, and the largest pixel width
        /// `destinationTexture's` type allows. If `destinationTexture` uses a compressed pixel format,
        /// set `sourceBytesPerRow` to the number of bytes between the starts of two row blocks.
        /// - sourceBytesPerImage: The number of bytes between each 2D image of a 3D texture. Set this value to a
        /// multiple of `destinationTexture's` pixel size, in bytes, or `0`
        /// if `sourceSize's` ``MTLSize/depth`` value is `1`.
        /// - sourceSize:          A ``MTLSize`` instance that represents the size of the region in
        /// `destinationTexture`, in pixels, that the command copies data to, starting at
        /// `destinationOrigin`. Assign `1` to each dimension that’s not relevant to
        /// `destinationTexture`. If `destinationTexture` uses a compressed pixel format,
        /// set `sourceSize` to a multiple of `destinationTexture's` ``MTLTexture/pixelFormat``
        /// block size. If the block extends outside the bounds of the texture, clamp
        /// `sourceSize` to the edge of the texture.
        /// - destinationTexture:  An ``MTLTexture`` instance the command copies data to. In order to copy the contents into
        /// the destination texture, set its ``MTLTexture/framebufferOnly`` property to
        /// <doc
        /// ://com.apple.documentation/documentation/swift/false> and don't
        /// use a combined depth/stencil ``MTLTexture/pixelFormat``.
        /// - destinationSlice:    A slice within `destinationTexture` the command uses as its starting point for
        /// copying data to. Set this to `0` if `destinationTexture` isn’t a texture array
        /// or a cube texture.
        /// - destinationLevel:    A mipmap level within `destinationTexture` the command copies data to.
        /// - destinationOrigin:   An ``MTLOrigin`` instance that represents a location within `destinationTexture`
        /// that the command begins copying data to. Assign `0` to each dimension that’s not
        /// relevant to `destinationTexture`.
        #[unsafe(method(copyFromBuffer:sourceOffset:sourceBytesPerRow:sourceBytesPerImage:sourceSize:toTexture:destinationSlice:destinationLevel:destinationOrigin:))]
        #[unsafe(method_family = none)]
        fn copy_from_buffer_source_offset_source_bytes_per_row_source_bytes_per_image_source_size_to_texture_destination_slice_destination_level_destination_origin(
            &self,
            source_buffer: &ProtocolObject<dyn MTLBuffer>,
            source_offset: usize,
            source_bytes_per_row: usize,
            source_bytes_per_image: usize,
            source_size: MTLSize,
            destination_texture: &ProtocolObject<dyn MTLTexture>,
            destination_slice: usize,
            destination_level: usize,
            destination_origin: MTLOrigin,
        );

        /// Encodes a command to copy image data from a buffer into a texture with options for special texture formats.
        ///
        /// - Parameters:
        /// - sourceBuffer:        An ``MTLBuffer`` instance the command copies data from.
        /// - sourceOffset:        A byte offset within `sourceBuffer` the command copies from. Set this value to
        /// a multiple of `destinationTexture's` pixel size, in bytes.
        /// - sourceBytesPerRow:   The number of bytes between adjacent rows of pixels in `sourceBuffer`. Set this value to
        /// a multiple of `destinationTexture's` pixel size, in bytes, and less than or equal to
        /// the product of `destinationTexture's` pixel size, in bytes, and the largest pixel width
        /// `destinationTexture's` type allows. If `destinationTexture` uses a compressed pixel format,
        /// set `sourceBytesPerRow` to the number of bytes between the starts of two row blocks.
        /// - sourceBytesPerImage: The number of bytes between each 2D image of a 3D texture. Set this value to a
        /// multiple of `destinationTexture's` pixel size, in bytes, or `0`
        /// if `sourceSize's` ``MTLSize/depth`` value is `1`.
        /// - sourceSize:          An ``MTLSize`` instance that represents the size of the region in
        /// `destinationTexture`, in pixels, that the command copies data to, starting at
        /// `destinationOrigin`. Assign `1` to each dimension that’s not relevant to
        /// `destinationTexture`. If `destinationTexture` uses a compressed pixel format,
        /// set `sourceSize` to a multiple of `destinationTexture's` ``MTLTexture/pixelFormat``
        /// block size. If the block extends outside the bounds of the texture, clamp
        /// `sourceSize` to the edge of the texture.
        /// - destinationTexture:  An ``MTLTexture`` instance the command copies data to. In order to copy the contents into
        /// the destination texture, set its ``MTLTexture/framebufferOnly`` property to
        /// <doc
        /// ://com.apple.documentation/documentation/swift/false> and don't
        /// use a combined depth/stencil ``MTLTexture/pixelFormat``.
        /// - destinationSlice:    A slice within `destinationTexture` the command uses as its starting point for
        /// copying data to. Set this to `0` if `destinationTexture` isn’t a texture array
        /// or a cube texture.
        /// - destinationLevel:    A mipmap level within `destinationTexture` the command copies data to.
        /// - destinationOrigin:   An ``MTLOrigin`` instance that represents a location within `destinationTexture`
        /// that the command begins copying data to. Assign `0` to each dimension that’s not
        /// relevant to `destinationTexture`.
        /// - options:             An ``MTLBlitOption`` value that applies to textures with applicable pixel formats,
        /// such as combined depth/stencil or PVRTC formats. If `destinationTexture's`
        /// ``MTLTexture/pixelFormat`` is a combined depth/stencil format, set `options` to
        /// either ``MTLBlitOption/MTLBlitOptionDepthFromDepthStencil`` or
        /// ``MTLBlitOption/MTLBlitOptionStencilFromDepthStencil``, but not both.
        /// If `destinationTexture's` ``MTLTexture/pixelFormat`` is a PVRTC format, set
        /// `options` to ``MTLBlitOption/MTLBlitOptionRowLinearPVRTC``.
        #[unsafe(method(copyFromBuffer:sourceOffset:sourceBytesPerRow:sourceBytesPerImage:sourceSize:toTexture:destinationSlice:destinationLevel:destinationOrigin:options:))]
        #[unsafe(method_family = none)]
        fn copy_from_buffer_source_offset_source_bytes_per_row_source_bytes_per_image_source_size_to_texture_destination_slice_destination_level_destination_origin_options(
            &self,
            source_buffer: &ProtocolObject<dyn MTLBuffer>,
            source_offset: usize,
            source_bytes_per_row: usize,
            source_bytes_per_image: usize,
            source_size: MTLSize,
            destination_texture: &ProtocolObject<dyn MTLTexture>,
            destination_slice: usize,
            destination_level: usize,
            destination_origin: MTLOrigin,
            options: MTLBlitOption,
        );

        /// Encodes a command to copy data from a tensor instance into another.
        ///
        /// If the `sourceTensor` and `destinationTensor` instances are not aliasable, this command applies the correct reshapes
        /// to enable this operation.
        ///
        /// - Parameters:
        /// - sourceTensor:      An ``MTLTensor`` instance the command copies data from.
        /// - sourceSlice:       The slice of `sourceTensor` from which Metal copies data.
        /// - destinationTensor: An ``MTLTensor`` instance the command copies data to.
        /// - destinationSlice:  The slice of `destinationTensor` to which Metal copies data.
        #[unsafe(method(copyFromTensor:sourceOrigin:sourceDimensions:toTensor:destinationOrigin:destinationDimensions:))]
        #[unsafe(method_family = none)]
        fn copy_from_tensor_source_origin_source_dimensions_to_tensor_destination_origin_destination_dimensions(
            &self,
            source_tensor: &ProtocolObject<dyn MTLTensor>,
            source_origin: &MTLTensorExtents,
            source_dimensions: &MTLTensorExtents,
            destination_tensor: &ProtocolObject<dyn MTLTensor>,
            destination_origin: &MTLTensorExtents,
            destination_dimensions: &MTLTensorExtents,
        );

        /// Encodes a command that generates mipmaps for a texture instance from the base mipmap level up to the highest
        /// mipmap level.
        ///
        /// This method generates mipmaps for a mipmapped texture. The texture you provide needs to have a
        /// ``MTLTexture/mipmapLevelCount`` greater than `1`, and a color-renderable or color-filterable
        /// ``MTLTexture/pixelFormat``.
        ///
        /// - Parameter texture: A mipmapped, color-renderable or color-filterable ``MTLTexture`` instance the command generates mipmaps for.
        #[unsafe(method(generateMipmapsForTexture:))]
        #[unsafe(method_family = none)]
        fn generate_mipmaps_for_texture(&self, texture: &ProtocolObject<dyn MTLTexture>);

        /// Encodes a command that modifies the contents of a texture to improve the performance of GPU accesses
        /// to its contents.
        ///
        /// Optimizing a texture for GPU access may affect the performance of CPU accesses, however, the data the CPU
        /// retrieves from the texture remains consistent.
        ///
        /// You typically run this command for:
        /// * Textures the GPU accesses for an extended period of time.
        /// * Textures with a ``MTLTextureDescriptor/storageMode`` property that's ``MTLStorageMode/MTLStorageModeShared`` or
        /// ``MTLStorageMode/MTLStorageModeManaged``.
        ///
        /// - Parameter texture: A ``MTLTexture`` instance the command optimizes for GPU access.
        #[unsafe(method(optimizeContentsForGPUAccess:))]
        #[unsafe(method_family = none)]
        fn optimize_contents_for_gpu_access(&self, texture: &ProtocolObject<dyn MTLTexture>);

        /// Encodes a command that modifies the contents of a texture instance to improve the performance of GPU accesses
        /// to its contents in a specific region.
        ///
        /// Optimizing a texture for GPU access may affect the performance of CPU accesses, however, the data the CPU
        /// retrieves from the texture remains consistent.
        ///
        /// You typically run this command for:
        /// * Textures the GPU accesses for an extended period of time.
        /// * Textures with a ``MTLTextureDescriptor/storageMode`` property that's ``MTLStorageMode/MTLStorageModeShared`` or
        /// ``MTLStorageMode/MTLStorageModeManaged``.
        ///
        /// - Parameters:
        /// - texture: A ``MTLTexture`` the command optimizes for GPU access.
        /// - slice:   A slice within `texture`.
        /// - level:   A mipmap level within `texture`.
        #[unsafe(method(optimizeContentsForGPUAccess:slice:level:))]
        #[unsafe(method_family = none)]
        fn optimize_contents_for_gpu_access_slice_level(
            &self,
            texture: &ProtocolObject<dyn MTLTexture>,
            slice: usize,
            level: usize,
        );

        /// Encodes a command that modifies the contents of a texture to improve the performance of CPU accesses to
        /// its contents.
        ///
        /// Optimizing a texture for CPU access may affect the performance of GPU accesses, however, the data the GPU
        /// retrieves from the texture remains consistent.
        ///
        /// You typically use this command for:
        /// * Textures the CPU accesses for an extended period of time.
        /// * Textures with a ``MTLTextureDescriptor/storageMode`` property that's ``MTLStorageMode/MTLStorageModeShared`` or
        /// ``MTLStorageMode/MTLStorageModeManaged``.
        ///
        /// - Parameter texture: A ``MTLTexture`` instance the command optimizes for CPU access.
        #[unsafe(method(optimizeContentsForCPUAccess:))]
        #[unsafe(method_family = none)]
        fn optimize_contents_for_cpu_access(&self, texture: &ProtocolObject<dyn MTLTexture>);

        /// Encodes a command that modifies the contents of a texture to improve the performance of CPU accesses
        /// to its contents in a specific region.
        ///
        /// Optimizing a texture for CPU access may affect the performance of GPU accesses, however, the data the GPU
        /// retrieves from the texture remains consistent.
        ///
        /// You typically use this command for:
        /// * Textures the CPU accesses for an extended period of time.
        /// * Textures with a ``MTLTextureDescriptor/storageMode`` property that's ``MTLStorageMode/MTLStorageModeShared`` or
        /// ``MTLStorageMode/MTLStorageModeManaged``.
        ///
        /// - Parameters:
        /// - texture: A ``MTLTexture`` the command optimizes for CPU access.
        /// - slice:   A slice within `texture`.
        /// - level:   A mipmap level within `texture`.
        #[unsafe(method(optimizeContentsForCPUAccess:slice:level:))]
        #[unsafe(method_family = none)]
        fn optimize_contents_for_cpu_access_slice_level(
            &self,
            texture: &ProtocolObject<dyn MTLTexture>,
            slice: usize,
            level: usize,
        );

        /// Sets an argument table for the compute shader stage of this pipeline.
        ///
        /// Metal takes a snapshot of the resources in the argument table when you make dispatch or execute calls on
        /// this encoder instance. Metal makes the snapshot contents available to the compute shader function of the
        /// current pipeline state.
        ///
        /// - Parameters:
        /// - argumentTable: A ``MTL4ArgumentTable`` to set on the command encoder.
        #[unsafe(method(setArgumentTable:))]
        #[unsafe(method_family = none)]
        fn set_argument_table(
            &self,
            argument_table: Option<&ProtocolObject<dyn MTL4ArgumentTable>>,
        );

        /// Encodes an acceleration structure build into the command buffer.
        ///
        /// Before you build an instance acceleration structure, you are responsible for ensuring the build operations for all
        /// primitive acceleration structures is complete. The built acceleration structure doesn't retain any references to
        /// the input buffers of the descriptor, such as the vertex buffer or instance buffer, among others.
        ///
        /// The acceleration structure build process may continue as long as the command buffer is not completed. However,
        /// you can safely encode ray tracing work against the acceleration structure if you schedule and synchronize the
        /// command buffers that contain this ray tracing work such that the command buffer with the build command is complete
        /// by the time ray tracing starts.
        ///
        /// You are responsible for ensuring that the acceleration structure and scratch buffer are at least the size
        /// that the query ``MTLDevice/accelerationStructureSizesWithDescriptor:`` returns.
        ///
        /// Use an instance of ``MTLResidencySet`` to mark residency of the scratch buffer the `scratchBuffer` parameter references,
        /// as well as for all the primitive acceleration structures you directly and indirectly reference.
        ///
        /// - Parameters:
        /// - accelerationStructure: Acceleration structure storage to build into.
        /// - descriptor:            A descriptor for the acceleration structure Metal builds.
        /// - scratchBuffer:         Scratch buffer Metal can use while building the acceleration structure.
        /// Metal may overwrite the contents of this buffer, and you should consider
        /// them "undefined" after the refit operation starts and completes.
        #[unsafe(method(buildAccelerationStructure:descriptor:scratchBuffer:))]
        #[unsafe(method_family = none)]
        fn build_acceleration_structure_descriptor_scratch_buffer(
            &self,
            acceleration_structure: &ProtocolObject<dyn MTLAccelerationStructure>,
            descriptor: &MTL4AccelerationStructureDescriptor,
            scratch_buffer: MTL4BufferRange,
        );

        /// Encodes an acceleration structure refit into the command buffer.
        ///
        /// You refit an acceleration structure to update it when the geometry it references changes. This operation is typically
        /// much faster than rebuilding the acceleration structure from scratch. The trade off is that after you refit the
        /// acceleration structure, its quality, as well as the performance of any subsequent ray tracing operation degrades,
        /// depending on how much the geometry changes.
        ///
        /// After certain operations, refitting an acceleration structure may not be possible, for example, after adding or
        /// removing geometry.
        ///
        /// When you refit an acceleration structure, you can do so in place, by specifying the same source and destination
        /// acceleration structures, or by providing a `nil` destination acceleration structure. If the source and destination
        /// acceleration structures aren't the same, then you are responsible for ensuring they don't overlap in memory.
        ///
        /// Typically, the destination acceleration structure is at least as large as the source acceleration structure,
        /// except in cases where you compact the source acceleration structure. In this case, you need to allocate the
        /// destination acceleration to be at least as large as the compacted size of the source acceleration structure.
        ///
        /// The scratch buffer you provide for the refit operation needs to be at least as large as the size that the query
        /// ``MTLDevice/accelerationStructureSizesWithDescriptor:`` returns. If the size this query returns is zero, you
        /// can omit providing a scratch buffer by passing `0` as the address to the `scratchBuffer` parameter.
        ///
        /// Use an instance of ``MTLResidencySet`` to mark residency of the scratch buffer the `scratchBuffer` parameter references,
        /// as well as for all the instance and primitive acceleration structures you directly and indirectly reference.
        ///
        /// - Parameters:
        /// - sourceAccelerationStructure:      Acceleration structure to refit.
        /// - descriptor:                       A descriptor for the acceleration structure to refit.
        /// - destinationAccelerationStructure: Acceleration structure to store the refit result into.
        /// If `destinationAccelerationStructure` is `nil`, Metal performs an in-place
        /// refit operation of the `sourceAccelerationStructure`.
        /// - scratchBuffer:                    Scratch buffer Metal can use while refitting the acceleration structure.
        /// Metal may overwrite the contents of this buffer, and you should consider
        /// them "undefined" after the refit operation starts and completes.
        #[unsafe(method(refitAccelerationStructure:descriptor:destination:scratchBuffer:))]
        #[unsafe(method_family = none)]
        fn refit_acceleration_structure_descriptor_destination_scratch_buffer(
            &self,
            source_acceleration_structure: &ProtocolObject<dyn MTLAccelerationStructure>,
            descriptor: &MTL4AccelerationStructureDescriptor,
            destination_acceleration_structure: Option<
                &ProtocolObject<dyn MTLAccelerationStructure>,
            >,
            scratch_buffer: MTL4BufferRange,
        );

        /// Encodes an acceleration structure refit operation into the command buffer, providing additional options.
        ///
        /// You refit an acceleration structure to update it when the geometry it references changes. This operation is typically
        /// much faster than rebuilding the acceleration structure from scratch. The trade off is that after you refit the
        /// acceleration structure, its quality, as well as the performance of any subsequent ray tracing operation degrades,
        /// depending on how much the geometry changes.
        ///
        /// After certain operations, refitting an acceleration structure may not be possible, for example, after adding or
        /// removing geometry.
        ///
        /// When you refit an acceleration structure, you can do so in place, by specifying the same source and destination
        /// acceleration structures, or by providing a `nil` destination acceleration structure. If the source and destination
        /// acceleration structures aren't the same, then you are responsible for ensuring they don't overlap in memory.
        ///
        /// Typically, the destination acceleration structure is at least as large as the source acceleration structure,
        /// except in cases where you compact the source acceleration structure. In this case, you need to allocate the
        /// destination acceleration to be at least as large as the compacted size of the source acceleration structure.
        ///
        /// The scratch buffer you provide for the refit operation needs to be at least as large as the size that the query
        /// ``MTLDevice/accelerationStructureSizesWithDescriptor:`` returns. If the size this query returns is zero, you
        /// can omit providing a scratch buffer by passing `0` as the address to the `scratchBuffer` parameter.
        ///
        /// Use an instance of ``MTLResidencySet`` to mark residency of the scratch buffer the `scratchBuffer` parameter references,
        /// as well as for all the instance and primitive acceleration structures you directly and indirectly reference.
        ///
        /// - Parameters:
        /// - sourceAccelerationStructure:      Acceleration structure to refit.
        /// - descriptor:                       A descriptor for the acceleration structure to refit.
        /// - destinationAccelerationStructure: Acceleration structure to store the refit result into.
        /// If `destinationAccelerationStructure` is `nil`, Metal performs an in-place
        /// refit operation of the `sourceAccelerationStructure`.
        /// - scratchBuffer:                    Scratch buffer Metal can use while refitting the acceleration structure.
        /// Metal may overwrite the contents of this buffer, and you should consider
        /// them "undefined" after the refit operation starts and completes.
        /// - options:                          Options specifying the elements of the acceleration structure to refit.
        #[unsafe(method(refitAccelerationStructure:descriptor:destination:scratchBuffer:options:))]
        #[unsafe(method_family = none)]
        fn refit_acceleration_structure_descriptor_destination_scratch_buffer_options(
            &self,
            source_acceleration_structure: &ProtocolObject<dyn MTLAccelerationStructure>,
            descriptor: &MTL4AccelerationStructureDescriptor,
            destination_acceleration_structure: Option<
                &ProtocolObject<dyn MTLAccelerationStructure>,
            >,
            scratch_buffer: MTL4BufferRange,
            options: MTLAccelerationStructureRefitOptions,
        );

        /// Encodes an acceleration structure copy operation into the command buffer.
        ///
        /// You are responsible for ensuring the source and destination acceleration structures don't overlap in memory.
        /// If this is an instance acceleration structure, Metal preserves references to the primitive acceleration structures
        /// it references.
        ///
        /// Typically, the destination acceleration structure is at least as large as the source acceleration structure,
        /// except in cases where you compact the source acceleration structure. In this case, you need to allocate the
        /// destination acceleration to be at least as large as the compacted size of the source acceleration structure.
        ///
        /// - Parameters:
        /// - sourceAccelerationStructure:      Acceleration structure to copy from.
        /// - destinationAccelerationStructure: Acceleration structure to copy to.
        #[unsafe(method(copyAccelerationStructure:toAccelerationStructure:))]
        #[unsafe(method_family = none)]
        fn copy_acceleration_structure_to_acceleration_structure(
            &self,
            source_acceleration_structure: &ProtocolObject<dyn MTLAccelerationStructure>,
            destination_acceleration_structure: &ProtocolObject<dyn MTLAccelerationStructure>,
        );

        /// Encodes a command to compute the size an acceleration structure can compact into, writing the result
        /// into a buffer.
        ///
        /// This size is potentially smaller than the acceleration structure. To perform compaction, you typically read
        /// this size from the buffer once the command buffer completes. You then use it to allocate a new, potentially
        /// smaller acceleration structure. Finally, you call the ``copyAndCompactAccelerationStructure:toAccelerationStructure:``
        /// method to perform the copy.
        ///
        /// - Parameters:
        /// - accelerationStructure: Source acceleration structure.
        /// - buffer:                Destination size buffer. Metal writes the compacted size as a 64-bit unsigned integer
        /// value, representing the compacted size in bytes.
        #[unsafe(method(writeCompactedAccelerationStructureSize:toBuffer:))]
        #[unsafe(method_family = none)]
        fn write_compacted_acceleration_structure_size_to_buffer(
            &self,
            acceleration_structure: &ProtocolObject<dyn MTLAccelerationStructure>,
            buffer: MTL4BufferRange,
        );

        /// Encodes a command to copy and compact an acceleration structure.
        ///
        /// You are responsible for ensuring that the source and destination acceleration structures don't overlap in memory.
        /// If this is an instance acceleration structure, Metal preserves references to primitive acceleration structures it
        /// references.
        ///
        /// This operation requires that the destination acceleration structure is at least as large as the compacted size of
        /// the source acceleration structure. You can compute this size by calling the
        /// ``writeCompactedAccelerationStructureSize:toBuffer:`` method.
        ///
        /// - Parameters:
        /// - sourceAccelerationStructure:      Acceleration structure to copy and compact.
        /// - destinationAccelerationStructure: Acceleration structure to copy to.
        #[unsafe(method(copyAndCompactAccelerationStructure:toAccelerationStructure:))]
        #[unsafe(method_family = none)]
        fn copy_and_compact_acceleration_structure_to_acceleration_structure(
            &self,
            source_acceleration_structure: &ProtocolObject<dyn MTLAccelerationStructure>,
            destination_acceleration_structure: &ProtocolObject<dyn MTLAccelerationStructure>,
        );

        /// Writes a GPU timestamp into a heap.
        ///
        /// The method ensures that any prior work finishes, but doesn't delay any subsequent work.
        ///
        /// You can alter this command's behavior through the `granularity` parameter.
        /// - Pass ``MTL4TimestampGranularity/MTL4TimestampGranularityRelaxed`` to allow Metal to provide timestamps with
        /// minimal impact to runtime performance, but with less detail. For example, the command may group all timestamps for
        /// a pass together.
        /// - Pass ``MTL4TimestampGranularity/MTL4TimestampGranularityPrecise`` to request that Metal provides timestamps
        /// with the most detail. This can affect runtime performance.
        ///
        /// - Parameters:
        /// - granularity: ``MTL4TimestampGranularity`` hint to Metal about acceptable the level of precision.
        /// - counterHeap: ``MTL4CounterHeap`` to write timestamps into.
        /// - index:       The index value into which Metal writes the timestamp.
        #[unsafe(method(writeTimestampWithGranularity:intoHeap:atIndex:))]
        #[unsafe(method_family = none)]
        fn write_timestamp_with_granularity_into_heap_at_index(
            &self,
            granularity: MTL4TimestampGranularity,
            counter_heap: &ProtocolObject<dyn MTL4CounterHeap>,
            index: usize,
        );
    }
);

pub trait MTL4ComputeCommandEncoderExt: MTL4ComputeCommandEncoder + Message {
    /// Encodes a command to execute a series of commands from an indirect command buffer.
    ///
    /// - Parameters:
    /// - indirectCommandBuffer: ``MTLIndirectCommandBuffer`` instance containing the commands to execute.
    /// - executionRange:        The range of commands to execute.
    fn execute_commands_in_buffer_with_range(
        &self,
        indirect_command_buffer: &ProtocolObject<dyn MTLIndirectCommandBuffer>,
        execution_range: Range<usize>,
    ) {
        let execution_range = NSRange {
            location: execution_range.start,
            length: execution_range.end.saturating_sub(execution_range.start),
        };
        unsafe {
            let _: () = msg_send![
                self,
                executeCommandsInBuffer: indirect_command_buffer,
                withRange: execution_range
            ];
        }
    }

    /// Encodes a command that fills a buffer with a constant value for each byte.
    ///
    /// - Parameters:
    /// - buffer: A ``MTLBuffer`` instance for which this command assigns each byte in a range to a value.
    /// - range:  A range of bytes within `buffer` the command assigns value to. When calling this method, pass in a
    /// range with a length greater than `0`.
    /// - value:  The value to write to each byte.
    fn fill_buffer_range_value(
        &self,
        buffer: &ProtocolObject<dyn MTLBuffer>,
        range: Range<usize>,
        value: u8,
    ) {
        let range = NSRange {
            location: range.start,
            length: range.end.saturating_sub(range.start),
        };
        unsafe {
            let _: () = msg_send![self, fillBuffer: buffer, range: range, value: value];
        }
    }

    /// Encodes a command that resets a range of commands in an indirect command buffer.
    ///
    /// - Parameters:
    /// - buffer: An ``MTLIndirectCommandBuffer`` the command resets.
    /// - range: A range of commands within `buffer`.
    fn reset_commands_in_buffer_with_range(
        &self,
        buffer: &ProtocolObject<dyn MTLIndirectCommandBuffer>,
        range: Range<usize>,
    ) {
        let range = NSRange {
            location: range.start,
            length: range.end.saturating_sub(range.start),
        };
        unsafe {
            let _: () = msg_send![self, resetCommandsInBuffer: buffer, withRange: range];
        }
    }

    /// Encodes a command that copies commands from an indirect command buffer into another.
    ///
    /// - Parameters:
    /// - source:           An ``MTLIndirectCommandBuffer`` instance from where the command copies.
    /// - sourceRange:      The range of commands in `source` to copy.
    /// The copy operation requires that the source range starts at a valid execution point.
    /// - destination:      Another ``MTLIndirectCommandBuffer`` instance into which the command copies.
    /// - destinationIndex: An index in `destination` into where the command copies content to. The copy operation requires
    /// that the destination index is a valid execution point with enough space left in `destination`
    /// to accommodate `sourceRange.count` commands.
    fn copy_indirect_command_buffer_source_range_destination_destination_index(
        &self,
        source: &ProtocolObject<dyn MTLIndirectCommandBuffer>,
        source_range: Range<usize>,
        destination: &ProtocolObject<dyn MTLIndirectCommandBuffer>,
        destination_index: usize,
    ) {
        let source_range = NSRange {
            location: source_range.start,
            length: source_range.end.saturating_sub(source_range.start),
        };
        unsafe {
            let _: () = msg_send![
                self,
                copyIndirectCommandBuffer: source,
                sourceRange: source_range,
                destination: destination,
                destinationIndex: destination_index
            ];
        }
    }

    /// Encode a command to attempt to improve the performance of a range of commands within an indirect command buffer.
    ///
    /// - Parameters:
    /// - indirectCommandBuffer: An ``MTLIndirectCommandBuffer`` instance that this command optimizes.
    /// - range:                 A range of commands within `indirectCommandBuffer`.
    fn optimize_indirect_command_buffer_with_range(
        &self,
        indirect_command_buffer: &ProtocolObject<dyn MTLIndirectCommandBuffer>,
        range: Range<usize>,
    ) {
        let range = NSRange {
            location: range.start,
            length: range.end.saturating_sub(range.start),
        };
        unsafe {
            let _: () = msg_send![
                self,
                optimizeIndirectCommandBuffer: indirect_command_buffer,
                withRange: range
            ];
        }
    }
}

impl<T: MTL4ComputeCommandEncoder + Message> MTL4ComputeCommandEncoderExt for T {}
