use std::{ops::Deref, path::Path};
use block2::{Block, DynBlock, RcBlock};
use objc2::{
Message, extern_class, extern_conformance, extern_methods, extern_protocol, msg_send,
rc::{Allocated, Retained},
runtime::ProtocolObject,
};
use objc2_foundation::{CopyingHelper, NSArray, NSCopying, NSError, NSObject, NSObjectProtocol, NSString, NSURL};
use crate::*;
pub struct MTLNewLibraryCompletionHandler(RcBlock<dyn Fn(*mut ProtocolObject<dyn MTLLibrary>, *mut NSError)>);
impl MTLNewLibraryCompletionHandler {
pub fn new<F>(handler: F) -> Self
where
F: Fn(Option<Retained<ProtocolObject<dyn MTLLibrary>>>, *mut NSError) + 'static,
{
Self(RcBlock::new(move |library_ptr: *mut ProtocolObject<dyn MTLLibrary>, error: *mut NSError| {
let library = unsafe { Retained::from_raw(library_ptr) };
handler(library, error);
}))
}
pub fn copy(ptr: *mut DynBlock<dyn Fn(*mut ProtocolObject<dyn MTLLibrary>, *mut NSError)>) -> Self {
Self(unsafe { RcBlock::copy(ptr) }.unwrap())
}
}
impl Deref for MTLNewLibraryCompletionHandler {
type Target = Block<dyn Fn(*mut ProtocolObject<dyn MTLLibrary>, *mut NSError)>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
pub struct MTLNewDynamicLibraryCompletionHandler(
RcBlock<dyn Fn(*mut ProtocolObject<dyn MTLDynamicLibrary>, *mut NSError)>,
);
impl MTLNewDynamicLibraryCompletionHandler {
pub fn new<F>(handler: F) -> Self
where
F: Fn(Option<Retained<ProtocolObject<dyn MTLDynamicLibrary>>>, *mut NSError) + 'static,
{
Self(RcBlock::new(move |library_ptr: *mut ProtocolObject<dyn MTLDynamicLibrary>, error: *mut NSError| {
let library = unsafe { Retained::from_raw(library_ptr) };
handler(library, error);
}))
}
pub fn copy(ptr: *mut DynBlock<dyn Fn(*mut ProtocolObject<dyn MTLDynamicLibrary>, *mut NSError)>) -> Self {
Self(unsafe { RcBlock::copy(ptr) }.unwrap())
}
}
impl Deref for MTLNewDynamicLibraryCompletionHandler {
type Target = Block<dyn Fn(*mut ProtocolObject<dyn MTLDynamicLibrary>, *mut NSError)>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
pub struct MTLNewComputePipelineStateCompletionHandler(
RcBlock<dyn Fn(*mut ProtocolObject<dyn MTLComputePipelineState>, *mut NSError)>,
);
impl MTLNewComputePipelineStateCompletionHandler {
pub fn new<F>(handler: F) -> Self
where
F: Fn(Option<Retained<ProtocolObject<dyn MTLComputePipelineState>>>, *mut NSError) + 'static,
{
Self(RcBlock::new(
move |pipeline_ptr: *mut ProtocolObject<dyn MTLComputePipelineState>, error: *mut NSError| {
let pipeline = unsafe { Retained::from_raw(pipeline_ptr) };
handler(pipeline, error);
},
))
}
pub fn copy(ptr: *mut DynBlock<dyn Fn(*mut ProtocolObject<dyn MTLComputePipelineState>, *mut NSError)>) -> Self {
Self(unsafe { RcBlock::copy(ptr) }.unwrap())
}
}
impl Deref for MTLNewComputePipelineStateCompletionHandler {
type Target = Block<dyn Fn(*mut ProtocolObject<dyn MTLComputePipelineState>, *mut NSError)>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
pub struct MTLNewRenderPipelineStateCompletionHandler(
RcBlock<dyn Fn(*mut ProtocolObject<dyn MTLRenderPipelineState>, *mut NSError)>,
);
impl MTLNewRenderPipelineStateCompletionHandler {
pub fn new<F>(handler: F) -> Self
where
F: Fn(Option<Retained<ProtocolObject<dyn MTLRenderPipelineState>>>, *mut NSError) + 'static,
{
Self(RcBlock::new(move |pipeline_ptr: *mut ProtocolObject<dyn MTLRenderPipelineState>, error: *mut NSError| {
let pipeline = unsafe { Retained::from_raw(pipeline_ptr) };
handler(pipeline, error);
}))
}
pub fn copy(ptr: *mut DynBlock<dyn Fn(*mut ProtocolObject<dyn MTLRenderPipelineState>, *mut NSError)>) -> Self {
Self(unsafe { RcBlock::copy(ptr) }.unwrap())
}
}
impl Deref for MTLNewRenderPipelineStateCompletionHandler {
type Target = Block<dyn Fn(*mut ProtocolObject<dyn MTLRenderPipelineState>, *mut NSError)>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
extern_class!(
#[unsafe(super(NSObject))]
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct MTL4CompilerDescriptor;
);
extern_conformance!(
unsafe impl NSCopying for MTL4CompilerDescriptor {}
);
unsafe impl CopyingHelper for MTL4CompilerDescriptor {
type Result = Self;
}
extern_conformance!(
unsafe impl NSObjectProtocol for MTL4CompilerDescriptor {}
);
impl MTL4CompilerDescriptor {
extern_methods!(
#[unsafe(method(pipelineDataSetSerializer))]
#[unsafe(method_family = none)]
pub fn pipeline_data_set_serializer(
&self
) -> Option<Retained<ProtocolObject<dyn MTL4PipelineDataSetSerializer>>>;
#[unsafe(method(setPipelineDataSetSerializer:))]
#[unsafe(method_family = none)]
pub fn set_pipeline_data_set_serializer(
&self,
pipeline_data_set_serializer: Option<&ProtocolObject<dyn MTL4PipelineDataSetSerializer>>,
);
);
pub fn label(&self) -> Option<String> {
let label: Option<Retained<NSString>> = unsafe { msg_send![self, label] };
label.map(|label| label.to_string())
}
pub fn set_label(
&self,
label: Option<&str>,
) {
unsafe {
let _: () = msg_send![self, setLabel: label.map(NSString::from_str).as_deref()];
}
}
}
impl MTL4CompilerDescriptor {
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>;
);
}
extern_class!(
#[unsafe(super(NSObject))]
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct MTL4CompilerTaskOptions;
);
extern_conformance!(
unsafe impl NSCopying for MTL4CompilerTaskOptions {}
);
unsafe impl CopyingHelper for MTL4CompilerTaskOptions {
type Result = Self;
}
extern_conformance!(
unsafe impl NSObjectProtocol for MTL4CompilerTaskOptions {}
);
impl MTL4CompilerTaskOptions {
extern_methods!(
#[unsafe(method(lookupArchives))]
#[unsafe(method_family = none)]
pub fn lookup_archives(&self) -> Option<Retained<NSArray<ProtocolObject<dyn MTL4Archive>>>>;
#[unsafe(method(setLookupArchives:))]
#[unsafe(method_family = none)]
pub fn set_lookup_archives(
&self,
lookup_archives: Option<&NSArray<ProtocolObject<dyn MTL4Archive>>>,
);
);
}
impl MTL4CompilerTaskOptions {
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>;
);
}
pub struct MTL4NewBinaryFunctionCompletionHandler(
RcBlock<dyn Fn(*mut ProtocolObject<dyn MTL4BinaryFunction>, *mut NSError)>,
);
impl MTL4NewBinaryFunctionCompletionHandler {
pub fn new<F>(handler: F) -> Self
where
F: Fn(Option<Retained<ProtocolObject<dyn MTL4BinaryFunction>>>, *mut NSError) + 'static,
{
Self(RcBlock::new(move |binary_fn_ptr: *mut ProtocolObject<dyn MTL4BinaryFunction>, error: *mut NSError| {
let binary_fn = unsafe { Retained::from_raw(binary_fn_ptr) };
handler(binary_fn, error);
}))
}
pub fn copy(ptr: *mut DynBlock<dyn Fn(*mut ProtocolObject<dyn MTL4BinaryFunction>, *mut NSError)>) -> Self {
Self(unsafe { RcBlock::copy(ptr) }.unwrap())
}
}
impl Deref for MTL4NewBinaryFunctionCompletionHandler {
type Target = Block<dyn Fn(*mut ProtocolObject<dyn MTL4BinaryFunction>, *mut NSError)>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
pub struct MTL4NewMachineLearningPipelineStateCompletionHandler(
RcBlock<dyn Fn(*mut ProtocolObject<dyn MTL4MachineLearningPipelineState>, *mut NSError)>,
);
impl MTL4NewMachineLearningPipelineStateCompletionHandler {
pub fn new<F>(handler: F) -> Self
where
F: Fn(Option<Retained<ProtocolObject<dyn MTL4MachineLearningPipelineState>>>, *mut NSError) + 'static,
{
Self(RcBlock::new(
move |pipeline_ptr: *mut ProtocolObject<dyn MTL4MachineLearningPipelineState>, error: *mut NSError| {
let pipeline = unsafe { Retained::from_raw(pipeline_ptr) };
handler(pipeline, error);
},
))
}
pub fn copy(
ptr: *mut DynBlock<dyn Fn(*mut ProtocolObject<dyn MTL4MachineLearningPipelineState>, *mut NSError)>
) -> Self {
Self(unsafe { RcBlock::copy(ptr) }.unwrap())
}
}
impl Deref for MTL4NewMachineLearningPipelineStateCompletionHandler {
type Target = Block<dyn Fn(*mut ProtocolObject<dyn MTL4MachineLearningPipelineState>, *mut NSError)>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
extern_protocol!(
pub unsafe trait MTL4Compiler: NSObjectProtocol + Send + Sync {
#[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(pipelineDataSetSerializer))]
#[unsafe(method_family = none)]
fn pipeline_data_set_serializer(&self) -> Option<Retained<ProtocolObject<dyn MTL4PipelineDataSetSerializer>>>;
#[unsafe(method(newLibraryWithDescriptor:error:_))]
#[unsafe(method_family = new)]
fn new_library_with_descriptor_error(
&self,
descriptor: &MTL4LibraryDescriptor,
) -> Result<Retained<ProtocolObject<dyn MTLLibrary>>, Retained<NSError>>;
#[unsafe(method(newDynamicLibrary:error:_))]
#[unsafe(method_family = new)]
fn new_dynamic_library_error(
&self,
library: &ProtocolObject<dyn MTLLibrary>,
) -> Result<Retained<ProtocolObject<dyn MTLDynamicLibrary>>, Retained<NSError>>;
#[unsafe(method(newComputePipelineStateWithDescriptor:compilerTaskOptions:error:_))]
#[unsafe(method_family = new)]
fn new_compute_pipeline_state_with_descriptor_compiler_task_options_error(
&self,
descriptor: &MTL4ComputePipelineDescriptor,
compiler_task_options: Option<&MTL4CompilerTaskOptions>,
) -> Result<Retained<ProtocolObject<dyn MTLComputePipelineState>>, Retained<NSError>>;
#[unsafe(method(newComputePipelineStateWithDescriptor:dynamicLinkingDescriptor:compilerTaskOptions:error:_))]
#[unsafe(method_family = new)]
fn new_compute_pipeline_state_with_descriptor_dynamic_linking_descriptor_compiler_task_options_error(
&self,
descriptor: &MTL4ComputePipelineDescriptor,
dynamic_linking_descriptor: Option<&MTL4PipelineStageDynamicLinkingDescriptor>,
compiler_task_options: Option<&MTL4CompilerTaskOptions>,
) -> Result<Retained<ProtocolObject<dyn MTLComputePipelineState>>, Retained<NSError>>;
#[unsafe(method(newRenderPipelineStateWithDescriptor:compilerTaskOptions:error:_))]
#[unsafe(method_family = new)]
fn new_render_pipeline_state_with_descriptor_compiler_task_options_error(
&self,
descriptor: &MTL4PipelineDescriptor,
compiler_task_options: Option<&MTL4CompilerTaskOptions>,
) -> Result<Retained<ProtocolObject<dyn MTLRenderPipelineState>>, Retained<NSError>>;
#[unsafe(method(newRenderPipelineStateWithDescriptor:dynamicLinkingDescriptor:compilerTaskOptions:error:_))]
#[unsafe(method_family = new)]
fn new_render_pipeline_state_with_descriptor_dynamic_linking_descriptor_compiler_task_options_error(
&self,
descriptor: &MTL4PipelineDescriptor,
dynamic_linking_descriptor: Option<&MTL4RenderPipelineDynamicLinkingDescriptor>,
compiler_task_options: Option<&MTL4CompilerTaskOptions>,
) -> Result<Retained<ProtocolObject<dyn MTLRenderPipelineState>>, Retained<NSError>>;
#[unsafe(method(newRenderPipelineStateBySpecializationWithDescriptor:pipeline:error:_))]
#[unsafe(method_family = new)]
fn new_render_pipeline_state_by_specialization_with_descriptor_pipeline_error(
&self,
descriptor: &MTL4PipelineDescriptor,
pipeline: &ProtocolObject<dyn MTLRenderPipelineState>,
) -> Result<Retained<ProtocolObject<dyn MTLRenderPipelineState>>, Retained<NSError>>;
#[unsafe(method(newBinaryFunctionWithDescriptor:compilerTaskOptions:error:_))]
#[unsafe(method_family = new)]
fn new_binary_function_with_descriptor_compiler_task_options_error(
&self,
descriptor: &MTL4BinaryFunctionDescriptor,
compiler_task_options: Option<&MTL4CompilerTaskOptions>,
) -> Result<Retained<ProtocolObject<dyn MTL4BinaryFunction>>, Retained<NSError>>;
#[unsafe(method(newMachineLearningPipelineStateWithDescriptor:error:_))]
#[unsafe(method_family = new)]
fn new_machine_learning_pipeline_state_with_descriptor_error(
&self,
descriptor: &MTL4MachineLearningPipelineDescriptor,
) -> Result<Retained<ProtocolObject<dyn MTL4MachineLearningPipelineState>>, Retained<NSError>>;
}
);
pub trait MTL4CompilerExt: MTL4Compiler + Message {
fn new_dynamic_library_with_path(
&self,
path: &Path,
) -> Result<Retained<ProtocolObject<dyn MTLDynamicLibrary>>, Retained<NSError>>
where
Self: Sized,
{
let url = NSURL::from_file_path(path).expect("path must be a valid file URL path");
let mut error: *mut NSError = std::ptr::null_mut();
let library: Option<Retained<ProtocolObject<dyn MTLDynamicLibrary>>> =
unsafe { msg_send![self, newDynamicLibraryWithURL: &*url, error: &mut error] };
match (library, unsafe { Retained::retain(error) }) {
(Some(library), None) => Ok(library),
(None, Some(error)) => Err(error),
(library, error) => unreachable!("Metal API contract violated: {library:?} {error:?}"),
}
}
fn new_library_with_descriptor_completion_handler(
&self,
descriptor: &MTL4LibraryDescriptor,
completion_handler: MTLNewLibraryCompletionHandler,
) -> Retained<ProtocolObject<dyn MTL4CompilerTask>>
where
Self: Sized,
{
unsafe {
msg_send![
self,
newLibraryWithDescriptor: descriptor,
completionHandler: &*completion_handler
]
}
}
fn new_dynamic_library_completion_handler(
&self,
library: &ProtocolObject<dyn MTLLibrary>,
completion_handler: MTLNewDynamicLibraryCompletionHandler,
) -> Retained<ProtocolObject<dyn MTL4CompilerTask>>
where
Self: Sized,
{
unsafe {
msg_send![
self,
newDynamicLibrary: library,
completionHandler: &*completion_handler
]
}
}
fn new_dynamic_library_with_path_completion_handler(
&self,
path: &Path,
completion_handler: MTLNewDynamicLibraryCompletionHandler,
) -> Retained<ProtocolObject<dyn MTL4CompilerTask>>
where
Self: Sized,
{
let url = NSURL::from_file_path(path).expect("path must be a valid file URL path");
unsafe {
msg_send![
self,
newDynamicLibraryWithURL: &*url,
completionHandler: &*completion_handler
]
}
}
fn new_compute_pipeline_state_with_descriptor_compiler_task_options_completion_handler(
&self,
descriptor: &MTL4ComputePipelineDescriptor,
compiler_task_options: Option<&MTL4CompilerTaskOptions>,
completion_handler: MTLNewComputePipelineStateCompletionHandler,
) -> Retained<ProtocolObject<dyn MTL4CompilerTask>>
where
Self: Sized,
{
unsafe {
msg_send![
self,
newComputePipelineStateWithDescriptor: descriptor,
compilerTaskOptions: compiler_task_options,
completionHandler: &*completion_handler
]
}
}
fn new_compute_pipeline_state_with_descriptor_dynamic_linking_descriptor_compiler_task_options_completion_handler(
&self,
descriptor: &MTL4ComputePipelineDescriptor,
dynamic_linking_descriptor: Option<&MTL4PipelineStageDynamicLinkingDescriptor>,
compiler_task_options: Option<&MTL4CompilerTaskOptions>,
completion_handler: MTLNewComputePipelineStateCompletionHandler,
) -> Retained<ProtocolObject<dyn MTL4CompilerTask>>
where
Self: Sized,
{
unsafe {
msg_send![
self,
newComputePipelineStateWithDescriptor: descriptor,
dynamicLinkingDescriptor: dynamic_linking_descriptor,
compilerTaskOptions: compiler_task_options,
completionHandler: &*completion_handler
]
}
}
fn new_render_pipeline_state_with_descriptor_compiler_task_options_completion_handler(
&self,
descriptor: &MTL4PipelineDescriptor,
compiler_task_options: Option<&MTL4CompilerTaskOptions>,
completion_handler: MTLNewRenderPipelineStateCompletionHandler,
) -> Retained<ProtocolObject<dyn MTL4CompilerTask>>
where
Self: Sized,
{
unsafe {
msg_send![
self,
newRenderPipelineStateWithDescriptor: descriptor,
compilerTaskOptions: compiler_task_options,
completionHandler: &*completion_handler
]
}
}
fn new_render_pipeline_state_with_descriptor_dynamic_linking_descriptor_compiler_task_options_completion_handler(
&self,
descriptor: &MTL4PipelineDescriptor,
dynamic_linking_descriptor: Option<&MTL4RenderPipelineDynamicLinkingDescriptor>,
compiler_task_options: Option<&MTL4CompilerTaskOptions>,
completion_handler: MTLNewRenderPipelineStateCompletionHandler,
) -> Retained<ProtocolObject<dyn MTL4CompilerTask>>
where
Self: Sized,
{
unsafe {
msg_send![
self,
newRenderPipelineStateWithDescriptor: descriptor,
dynamicLinkingDescriptor: dynamic_linking_descriptor,
compilerTaskOptions: compiler_task_options,
completionHandler: &*completion_handler
]
}
}
fn new_render_pipeline_state_by_specialization_with_descriptor_pipeline_completion_handler(
&self,
descriptor: &MTL4PipelineDescriptor,
pipeline: &ProtocolObject<dyn MTLRenderPipelineState>,
completion_handler: MTLNewRenderPipelineStateCompletionHandler,
) -> Retained<ProtocolObject<dyn MTL4CompilerTask>>
where
Self: Sized,
{
unsafe {
msg_send![
self,
newRenderPipelineStateBySpecializationWithDescriptor: descriptor,
pipeline: pipeline,
completionHandler: &*completion_handler
]
}
}
fn new_binary_function_with_descriptor_compiler_task_options_completion_handler(
&self,
descriptor: &MTL4BinaryFunctionDescriptor,
compiler_task_options: Option<&MTL4CompilerTaskOptions>,
completion_handler: MTL4NewBinaryFunctionCompletionHandler,
) -> Retained<ProtocolObject<dyn MTL4CompilerTask>>
where
Self: Sized,
{
unsafe {
msg_send![
self,
newBinaryFunctionWithDescriptor: descriptor,
compilerTaskOptions: compiler_task_options,
completionHandler: &*completion_handler
]
}
}
fn new_machine_learning_pipeline_state_with_descriptor_completion_handler(
&self,
descriptor: &MTL4MachineLearningPipelineDescriptor,
completion_handler: MTL4NewMachineLearningPipelineStateCompletionHandler,
) -> Retained<ProtocolObject<dyn MTL4CompilerTask>>
where
Self: Sized,
{
unsafe {
msg_send![
self,
newMachineLearningPipelineStateWithDescriptor: descriptor,
completionHandler: &*completion_handler
]
}
}
}
impl<T: MTL4Compiler + Message> MTL4CompilerExt for T {}