use core::{ffi::c_void, ops::Range, ptr::NonNull};
use objc2::{Message, extern_protocol, msg_send, rc::Retained, runtime::ProtocolObject};
use objc2_foundation::{NSObjectProtocol, NSRange, NSString};
use crate::util::opt_ref_slice_as_ptr;
use crate::{
MTLAccelerationStructure, MTLBuffer, MTLComputePipelineState, MTLDepthStencilState, MTLDevice,
MTLIndirectCommandBuffer, MTLIntersectionFunctionTable, MTLRenderPipelineState, MTLSamplerState, MTLTexture,
MTLVisibleFunctionTable,
};
pub const MTL_ATTRIBUTE_STRIDE_STATIC: usize = usize::MAX;
extern_protocol!(
pub unsafe trait MTLArgumentEncoder: NSObjectProtocol {
#[unsafe(method(device))]
#[unsafe(method_family = none)]
fn device(&self) -> Retained<ProtocolObject<dyn MTLDevice>>;
#[unsafe(method(label))]
#[unsafe(method_family = none)]
fn label(&self) -> Option<Retained<NSString>>;
#[unsafe(method(setLabel:))]
#[unsafe(method_family = none)]
fn set_label(
&self,
label: Option<&NSString>,
);
#[unsafe(method(encodedLength))]
#[unsafe(method_family = none)]
fn encoded_length(&self) -> usize;
#[unsafe(method(alignment))]
#[unsafe(method_family = none)]
fn alignment(&self) -> usize;
#[unsafe(method(setArgumentBuffer:offset:))]
#[unsafe(method_family = none)]
fn set_argument_buffer(
&self,
argument_buffer: Option<&ProtocolObject<dyn MTLBuffer>>,
offset: usize,
);
#[unsafe(method(setArgumentBuffer:startOffset:arrayElement:))]
#[unsafe(method_family = none)]
fn set_argument_buffer_with_array_element(
&self,
argument_buffer: Option<&ProtocolObject<dyn MTLBuffer>>,
start_offset: usize,
array_element: usize,
);
#[unsafe(method(setBuffer:offset:atIndex:))]
#[unsafe(method_family = none)]
fn set_buffer(
&self,
buffer: Option<&ProtocolObject<dyn MTLBuffer>>,
offset: usize,
index: usize,
);
#[unsafe(method(setTexture:atIndex:))]
#[unsafe(method_family = none)]
fn set_texture(
&self,
texture: Option<&ProtocolObject<dyn MTLTexture>>,
index: usize,
);
#[unsafe(method(setSamplerState:atIndex:))]
#[unsafe(method_family = none)]
fn set_sampler_state(
&self,
sampler: Option<&ProtocolObject<dyn MTLSamplerState>>,
index: usize,
);
#[unsafe(method(constantDataAtIndex:))]
#[unsafe(method_family = none)]
fn constant_data_at_index(
&self,
index: usize,
) -> NonNull<c_void>;
#[unsafe(method(setRenderPipelineState:atIndex:))]
#[unsafe(method_family = none)]
fn set_render_pipeline_state(
&self,
pipeline: Option<&ProtocolObject<dyn MTLRenderPipelineState>>,
index: usize,
);
#[unsafe(method(setComputePipelineState:atIndex:))]
#[unsafe(method_family = none)]
fn set_compute_pipeline_state(
&self,
pipeline: Option<&ProtocolObject<dyn MTLComputePipelineState>>,
index: usize,
);
#[unsafe(method(setIndirectCommandBuffer:atIndex:))]
#[unsafe(method_family = none)]
fn set_indirect_command_buffer(
&self,
indirect_command_buffer: Option<&ProtocolObject<dyn MTLIndirectCommandBuffer>>,
index: usize,
);
#[unsafe(method(setAccelerationStructure:atIndex:))]
#[unsafe(method_family = none)]
fn set_acceleration_structure(
&self,
acceleration_structure: Option<&ProtocolObject<dyn MTLAccelerationStructure>>,
index: usize,
);
#[unsafe(method(newArgumentEncoderForBufferAtIndex:))]
#[unsafe(method_family = new)]
fn new_argument_encoder_for_buffer_at_index(
&self,
index: usize,
) -> Option<Retained<ProtocolObject<dyn super::MTLArgumentEncoder>>>;
#[unsafe(method(setVisibleFunctionTable:atIndex:))]
#[unsafe(method_family = none)]
fn set_visible_function_table(
&self,
visible_function_table: Option<&ProtocolObject<dyn MTLVisibleFunctionTable>>,
index: usize,
);
#[unsafe(method(setIntersectionFunctionTable:atIndex:))]
#[unsafe(method_family = none)]
fn set_intersection_function_table(
&self,
intersection_function_table: Option<&ProtocolObject<dyn MTLIntersectionFunctionTable>>,
index: usize,
);
#[unsafe(method(setDepthStencilState:atIndex:))]
#[unsafe(method_family = none)]
fn set_depth_stencil_state(
&self,
depth_stencil_state: Option<&ProtocolObject<dyn MTLDepthStencilState>>,
index: usize,
);
}
);
pub trait MTLArgumentEncoderExt: MTLArgumentEncoder + Message {
fn set_buffers(
&self,
buffers: &[Option<&ProtocolObject<dyn MTLBuffer>>],
offsets: &[usize],
range: Range<usize>,
) where
Self: Sized,
{
assert_eq!(buffers.len(), offsets.len());
let ptr = opt_ref_slice_as_ptr(buffers);
unsafe { msg_send![self, setBuffers: ptr, offsets: offsets.as_ptr(), withRange: NSRange::from(range)] }
}
fn set_textures(
&self,
textures: &[Option<&ProtocolObject<dyn MTLTexture>>],
range: Range<usize>,
) where
Self: Sized,
{
let ptr = opt_ref_slice_as_ptr(textures);
unsafe { msg_send![self, setTextures: ptr, withRange: NSRange::from(range)] }
}
fn set_sampler_states(
&self,
samplers: &[Option<&ProtocolObject<dyn MTLSamplerState>>],
range: Range<usize>,
) where
Self: Sized,
{
let ptr = opt_ref_slice_as_ptr(samplers);
unsafe { msg_send![self, setSamplerStates: ptr, withRange: NSRange::from(range)] }
}
fn set_render_pipeline_states(
&self,
pipelines: &[Option<&ProtocolObject<dyn MTLRenderPipelineState>>],
range: Range<usize>,
) where
Self: Sized,
{
let ptr = opt_ref_slice_as_ptr(pipelines);
unsafe { msg_send![self, setRenderPipelineStates: ptr, withRange: NSRange::from(range)] }
}
fn set_compute_pipeline_states(
&self,
pipelines: &[Option<&ProtocolObject<dyn MTLComputePipelineState>>],
range: Range<usize>,
) where
Self: Sized,
{
let ptr = opt_ref_slice_as_ptr(pipelines);
unsafe { msg_send![self, setComputePipelineStates: ptr, withRange: NSRange::from(range)] }
}
fn set_indirect_command_buffers(
&self,
buffers: &[Option<&ProtocolObject<dyn MTLIndirectCommandBuffer>>],
range: Range<usize>,
) where
Self: Sized,
{
let ptr = opt_ref_slice_as_ptr(buffers);
unsafe { msg_send![self, setIndirectCommandBuffers: ptr, withRange: NSRange::from(range)] }
}
fn set_visible_function_tables(
&self,
tables: &[Option<&ProtocolObject<dyn MTLVisibleFunctionTable>>],
range: Range<usize>,
) where
Self: Sized,
{
let ptr = opt_ref_slice_as_ptr(tables);
unsafe { msg_send![self, setVisibleFunctionTables: ptr, withRange: NSRange::from(range)] }
}
fn set_intersection_function_tables(
&self,
tables: &[Option<&ProtocolObject<dyn MTLIntersectionFunctionTable>>],
range: Range<usize>,
) where
Self: Sized,
{
let ptr = opt_ref_slice_as_ptr(tables);
unsafe { msg_send![self, setIntersectionFunctionTables: ptr, withRange: NSRange::from(range)] }
}
fn set_depth_stencil_states(
&self,
states: &[Option<&ProtocolObject<dyn MTLDepthStencilState>>],
range: Range<usize>,
) where
Self: Sized,
{
let ptr = opt_ref_slice_as_ptr(states);
unsafe { msg_send![self, setDepthStencilStates: ptr, withRange: NSRange::from(range)] }
}
}
impl<T: MTLArgumentEncoder + Message> MTLArgumentEncoderExt for T {}