use crate::Error;
use crate::metal::{
BinaryArchive, ComputePipelineState, DynamicLibrary, Library, RenderPipelineState,
SamplePosition, Size,
};
use crate::metal4::{
BinaryFunction, BinaryFunctionDescriptor, CommandAllocator, Compiler, CompilerTask,
CompilerTaskOptions, ComputePipelineDescriptor, FunctionDescriptor, LibraryDescriptor,
MachineLearningPipelineDescriptor, MachineLearningPipelineState, MeshRenderPipelineDescriptor,
PipelineDataSetSerializer, PipelineStageDynamicLinkingDescriptor, RenderPassDescriptor,
RenderPipelineBinaryFunctionsDescriptor, RenderPipelineColorAttachmentDescriptor,
RenderPipelineColorAttachmentDescriptorArray, RenderPipelineDescriptor,
RenderPipelineDynamicLinkingDescriptor, StaticLinkingDescriptor, StitchedFunctionDescriptor,
TileRenderPipelineDescriptor,
};
use std::collections::HashMap;
use std::path::Path;
#[derive(Clone, Copy)]
pub enum RenderPipelineBuildDescriptor<'a> {
Render(&'a RenderPipelineDescriptor),
Mesh(&'a MeshRenderPipelineDescriptor),
Tile(&'a TileRenderPipelineDescriptor),
}
impl<'a> RenderPipelineBuildDescriptor<'a> {
fn to_ffi(self) -> metal_rust_ffi::RenderPipelineBuildDescriptor<'a> {
match self {
Self::Render(value) => {
metal_rust_ffi::RenderPipelineBuildDescriptor::Render(&value.inner)
}
Self::Mesh(value) => metal_rust_ffi::RenderPipelineBuildDescriptor::Mesh(&value.inner),
Self::Tile(value) => metal_rust_ffi::RenderPipelineBuildDescriptor::Tile(&value.inner),
}
}
}
impl Compiler {
pub fn new_library(&self, descriptor: &LibraryDescriptor) -> Result<Library, Error> {
self.inner
.new_library(&descriptor.inner)
.map(Library::from_ffi)
.map_err(Error::from_ffi)
}
pub fn new_compute_pipeline(
&self,
descriptor: &ComputePipelineDescriptor,
linking: Option<&PipelineStageDynamicLinkingDescriptor>,
options: Option<&CompilerTaskOptions>,
) -> Result<ComputePipelineState, Error> {
self.inner
.new_compute_pipeline(
&descriptor.inner,
linking.map(|value| &value.inner),
options.map(|value| &value.inner),
)
.map(|inner| ComputePipelineState { inner })
.map_err(Error::from_ffi)
}
pub fn new_render_pipeline(
&self,
descriptor: RenderPipelineBuildDescriptor<'_>,
linking: Option<&RenderPipelineDynamicLinkingDescriptor>,
options: Option<&CompilerTaskOptions>,
) -> Result<RenderPipelineState, Error> {
self.inner
.new_render_pipeline(
descriptor.to_ffi(),
linking.map(|value| &value.inner),
options.map(|value| &value.inner),
)
.map(|inner| RenderPipelineState { inner })
.map_err(Error::from_ffi)
}
pub fn specialize_render_pipeline(
&self,
descriptor: RenderPipelineBuildDescriptor<'_>,
pipeline: &RenderPipelineState,
) -> Result<RenderPipelineState, Error> {
self.inner
.specialize_render_pipeline(descriptor.to_ffi(), &pipeline.inner)
.map(|inner| RenderPipelineState { inner })
.map_err(Error::from_ffi)
}
pub fn new_binary_function(
&self,
descriptor: &BinaryFunctionDescriptor,
options: Option<&CompilerTaskOptions>,
) -> Result<BinaryFunction, Error> {
self.inner
.new_binary_function(&descriptor.inner, options.map(|value| &value.inner))
.map(BinaryFunction::from_ffi)
.map_err(Error::from_ffi)
}
pub fn new_machine_learning_pipeline(
&self,
descriptor: &MachineLearningPipelineDescriptor,
) -> Result<MachineLearningPipelineState, Error> {
self.inner
.new_machine_learning_pipeline(&descriptor.inner)
.map(MachineLearningPipelineState::from_ffi)
.map_err(Error::from_ffi)
}
pub fn new_dynamic_library(&self, library: &Library) -> Result<DynamicLibrary, Error> {
self.inner
.new_dynamic_library(&library.inner)
.map(DynamicLibrary::from_ffi)
.map_err(Error::from_ffi)
}
pub fn new_dynamic_library_from_path(
&self,
path: impl AsRef<Path>,
) -> Result<DynamicLibrary, Error> {
self.inner
.new_dynamic_library_from_path(path)
.map(DynamicLibrary::from_ffi)
.map_err(Error::from_ffi)
}
pub fn new_library_async(
&self,
descriptor: &LibraryDescriptor,
handler: impl FnOnce(Result<Library, Error>) + Send + 'static,
) -> Result<CompilerTask, Error> {
self.inner
.new_library_async(&descriptor.inner, move |result| {
handler(result.map(Library::from_ffi).map_err(Error::from_ffi));
})
.map(CompilerTask::from_ffi)
.map_err(Error::from_ffi)
}
pub fn new_compute_pipeline_async(
&self,
descriptor: &ComputePipelineDescriptor,
options: Option<&CompilerTaskOptions>,
handler: impl FnOnce(Result<ComputePipelineState, Error>) + Send + 'static,
) -> Result<CompilerTask, Error> {
self.inner
.new_compute_pipeline_async(
&descriptor.inner,
options.map(|value| &value.inner),
move |result| {
handler(
result
.map(|inner| ComputePipelineState { inner })
.map_err(Error::from_ffi),
);
},
)
.map(CompilerTask::from_ffi)
.map_err(Error::from_ffi)
}
pub fn new_compute_pipeline_linked_async(
&self,
descriptor: &ComputePipelineDescriptor,
linking: Option<&PipelineStageDynamicLinkingDescriptor>,
options: Option<&CompilerTaskOptions>,
handler: impl FnOnce(Result<ComputePipelineState, Error>) + Send + 'static,
) -> Result<CompilerTask, Error> {
self.inner
.new_compute_pipeline_linked_async(
&descriptor.inner,
linking.map(|value| &value.inner),
options.map(|value| &value.inner),
move |result| {
handler(
result
.map(|inner| ComputePipelineState { inner })
.map_err(Error::from_ffi),
);
},
)
.map(CompilerTask::from_ffi)
.map_err(Error::from_ffi)
}
pub fn new_render_pipeline_async(
&self,
descriptor: RenderPipelineBuildDescriptor<'_>,
options: Option<&CompilerTaskOptions>,
handler: impl FnOnce(Result<RenderPipelineState, Error>) + Send + 'static,
) -> Result<CompilerTask, Error> {
self.inner
.new_render_pipeline_async(
descriptor.to_ffi(),
options.map(|value| &value.inner),
move |result| {
handler(
result
.map(|inner| RenderPipelineState { inner })
.map_err(Error::from_ffi),
);
},
)
.map(CompilerTask::from_ffi)
.map_err(Error::from_ffi)
}
pub fn new_render_pipeline_linked_async(
&self,
descriptor: RenderPipelineBuildDescriptor<'_>,
linking: Option<&RenderPipelineDynamicLinkingDescriptor>,
options: Option<&CompilerTaskOptions>,
handler: impl FnOnce(Result<RenderPipelineState, Error>) + Send + 'static,
) -> Result<CompilerTask, Error> {
self.inner
.new_render_pipeline_linked_async(
descriptor.to_ffi(),
linking.map(|value| &value.inner),
options.map(|value| &value.inner),
move |result| {
handler(
result
.map(|inner| RenderPipelineState { inner })
.map_err(Error::from_ffi),
);
},
)
.map(CompilerTask::from_ffi)
.map_err(Error::from_ffi)
}
pub fn specialize_render_pipeline_async(
&self,
descriptor: RenderPipelineBuildDescriptor<'_>,
pipeline: &RenderPipelineState,
handler: impl FnOnce(Result<RenderPipelineState, Error>) + Send + 'static,
) -> Result<CompilerTask, Error> {
self.inner
.specialize_render_pipeline_async(descriptor.to_ffi(), &pipeline.inner, move |result| {
handler(
result
.map(|inner| RenderPipelineState { inner })
.map_err(Error::from_ffi),
);
})
.map(CompilerTask::from_ffi)
.map_err(Error::from_ffi)
}
pub fn new_binary_function_async(
&self,
descriptor: &BinaryFunctionDescriptor,
options: Option<&CompilerTaskOptions>,
handler: impl FnOnce(Result<BinaryFunction, Error>) + Send + 'static,
) -> Result<CompilerTask, Error> {
self.inner
.new_binary_function_async(
&descriptor.inner,
options.map(|value| &value.inner),
move |result| {
handler(
result
.map(BinaryFunction::from_ffi)
.map_err(Error::from_ffi),
);
},
)
.map(CompilerTask::from_ffi)
.map_err(Error::from_ffi)
}
pub fn new_machine_learning_pipeline_async(
&self,
descriptor: &MachineLearningPipelineDescriptor,
handler: impl FnOnce(Result<MachineLearningPipelineState, Error>) + Send + 'static,
) -> Result<CompilerTask, Error> {
self.inner
.new_machine_learning_pipeline_async(&descriptor.inner, move |result| {
handler(
result
.map(MachineLearningPipelineState::from_ffi)
.map_err(Error::from_ffi),
);
})
.map(CompilerTask::from_ffi)
.map_err(Error::from_ffi)
}
pub fn new_dynamic_library_async(
&self,
library: &Library,
handler: impl FnOnce(Result<DynamicLibrary, Error>) + Send + 'static,
) -> Result<CompilerTask, Error> {
self.inner
.new_dynamic_library_async(&library.inner, move |result| {
handler(
result
.map(DynamicLibrary::from_ffi)
.map_err(Error::from_ffi),
);
})
.map(CompilerTask::from_ffi)
.map_err(Error::from_ffi)
}
pub fn new_dynamic_library_from_path_async(
&self,
path: impl AsRef<Path>,
handler: impl FnOnce(Result<DynamicLibrary, Error>) + Send + 'static,
) -> Result<CompilerTask, Error> {
self.inner
.new_dynamic_library_from_path_async(path, move |result| {
handler(
result
.map(DynamicLibrary::from_ffi)
.map_err(Error::from_ffi),
);
})
.map(CompilerTask::from_ffi)
.map_err(Error::from_ffi)
}
}
impl CompilerTaskOptions {
pub fn lookup_archives_vec(&self) -> Result<Vec<BinaryArchive>, Error> {
self.inner
.lookup_archives_vec()
.map(|values| values.into_iter().map(BinaryArchive::from_ffi).collect())
.map_err(Error::from_ffi)
}
pub fn set_lookup_archives_slice(&self, values: &[BinaryArchive]) -> Result<(), Error> {
let values: Vec<_> = values.iter().map(|value| value.inner.clone()).collect();
self.inner
.set_lookup_archives_slice(&values)
.map_err(Error::from_ffi)
}
}
impl StaticLinkingDescriptor {
pub fn function_descriptors_vec(&self) -> Result<Vec<FunctionDescriptor>, Error> {
self.inner
.function_descriptors_vec()
.map(|values| {
values
.into_iter()
.map(FunctionDescriptor::from_ffi)
.collect()
})
.map_err(Error::from_ffi)
}
pub fn set_function_descriptors_slice(
&self,
values: &[FunctionDescriptor],
) -> Result<(), Error> {
let values: Vec<_> = values.iter().map(|value| value.inner.clone()).collect();
self.inner
.set_function_descriptors_slice(&values)
.map_err(Error::from_ffi)
}
pub fn internal_functions(&self) -> Result<Vec<FunctionDescriptor>, Error> {
self.inner
.internal_functions()
.map(|values| {
values
.into_iter()
.map(FunctionDescriptor::from_ffi)
.collect()
})
.map_err(Error::from_ffi)
}
pub fn set_internal_functions(&self, values: &[FunctionDescriptor]) -> Result<(), Error> {
let values: Vec<_> = values.iter().map(|value| value.inner.clone()).collect();
self.inner
.set_internal_functions(&values)
.map_err(Error::from_ffi)
}
pub fn groups_map(&self) -> Result<HashMap<String, Vec<FunctionDescriptor>>, Error> {
self.inner
.groups_map()
.map(|groups| {
groups
.into_iter()
.map(|(name, values)| {
(
name,
values
.into_iter()
.map(FunctionDescriptor::from_ffi)
.collect(),
)
})
.collect()
})
.map_err(Error::from_ffi)
}
pub fn set_groups_map(
&self,
groups: &HashMap<String, Vec<FunctionDescriptor>>,
) -> Result<(), Error> {
let groups = groups
.iter()
.map(|(name, values)| {
(
name.clone(),
values.iter().map(|value| value.inner.clone()).collect(),
)
})
.collect();
self.inner.set_groups_map(&groups).map_err(Error::from_ffi)
}
}
impl PipelineStageDynamicLinkingDescriptor {
pub fn binary_linked_functions_vec(&self) -> Result<Vec<BinaryFunction>, Error> {
self.inner
.binary_linked_functions_vec()
.map(|values| values.into_iter().map(BinaryFunction::from_ffi).collect())
.map_err(Error::from_ffi)
}
pub fn set_binary_linked_functions_slice(
&self,
values: &[BinaryFunction],
) -> Result<(), Error> {
let values: Vec<_> = values.iter().map(|value| value.inner.clone()).collect();
self.inner
.set_binary_linked_functions_slice(&values)
.map_err(Error::from_ffi)
}
pub fn preloaded_libraries_vec(&self) -> Result<Vec<DynamicLibrary>, Error> {
self.inner
.preloaded_libraries_vec()
.map(|values| values.into_iter().map(DynamicLibrary::from_ffi).collect())
.map_err(Error::from_ffi)
}
pub fn set_preloaded_libraries_slice(&self, values: &[DynamicLibrary]) -> Result<(), Error> {
let values: Vec<_> = values.iter().map(|value| value.inner.clone()).collect();
self.inner
.set_preloaded_libraries_slice(&values)
.map_err(Error::from_ffi)
}
}
macro_rules! facade_binary_function_list {
($getter:ident, $setter:ident) => {
pub fn $getter(&self) -> Result<Vec<BinaryFunction>, Error> {
self.inner
.$getter()
.map(|values| values.into_iter().map(BinaryFunction::from_ffi).collect())
.map_err(Error::from_ffi)
}
pub fn $setter(&self, values: &[BinaryFunction]) -> Result<(), Error> {
let values: Vec<_> = values.iter().map(|value| value.inner.clone()).collect();
self.inner.$setter(&values).map_err(Error::from_ffi)
}
};
}
impl RenderPipelineBinaryFunctionsDescriptor {
facade_binary_function_list!(
fragment_additional_binary_functions_vec,
set_fragment_additional_binary_functions_slice
);
facade_binary_function_list!(
mesh_additional_binary_functions_vec,
set_mesh_additional_binary_functions_slice
);
facade_binary_function_list!(
object_additional_binary_functions_vec,
set_object_additional_binary_functions_slice
);
facade_binary_function_list!(
tile_additional_binary_functions_vec,
set_tile_additional_binary_functions_slice
);
facade_binary_function_list!(
vertex_additional_binary_functions_vec,
set_vertex_additional_binary_functions_slice
);
pub fn reset_safe(&self) -> Result<(), Error> {
self.inner.reset_safe().map_err(Error::from_ffi)
}
}
impl RenderPipelineColorAttachmentDescriptor {
pub fn reset_safe(&self) -> Result<(), Error> {
self.inner.reset_safe().map_err(Error::from_ffi)
}
}
impl RenderPipelineColorAttachmentDescriptorArray {
pub fn attachment(
&self,
index: usize,
) -> Result<Option<RenderPipelineColorAttachmentDescriptor>, Error> {
self.inner
.attachment(index)
.map(|value| value.map(RenderPipelineColorAttachmentDescriptor::from_ffi))
.map_err(Error::from_ffi)
}
pub fn set_attachment(
&self,
index: usize,
value: &RenderPipelineColorAttachmentDescriptor,
) -> Result<(), Error> {
self.inner
.set_attachment(index, &value.inner)
.map_err(Error::from_ffi)
}
pub fn reset_safe(&self) -> Result<(), Error> {
self.inner.reset_safe().map_err(Error::from_ffi)
}
}
impl RenderPipelineDescriptor {
pub fn reset_safe(&self) -> Result<(), Error> {
self.inner.reset_safe().map_err(Error::from_ffi)
}
}
macro_rules! facade_required_threads_descriptor {
($type:ty) => {
impl $type {
pub fn required_threads_per_threadgroup_safe(&self) -> Result<Size, Error> {
self.inner
.required_threads_per_threadgroup_safe()
.map_err(Error::from_ffi)
}
pub fn set_required_threads_per_threadgroup_safe(
&self,
size: Size,
) -> Result<(), Error> {
self.inner
.set_required_threads_per_threadgroup_safe(size)
.map_err(Error::from_ffi)
}
pub fn reset_pipeline_descriptor(&self) -> Result<(), Error> {
self.inner
.reset_pipeline_descriptor()
.map_err(Error::from_ffi)
}
}
};
}
facade_required_threads_descriptor!(ComputePipelineDescriptor);
facade_required_threads_descriptor!(TileRenderPipelineDescriptor);
impl StitchedFunctionDescriptor {
pub fn function_descriptors_vec(&self) -> Result<Vec<FunctionDescriptor>, Error> {
self.inner
.function_descriptors_vec()
.map(|values| {
values
.into_iter()
.map(FunctionDescriptor::from_ffi)
.collect()
})
.map_err(Error::from_ffi)
}
pub fn set_function_descriptors_slice(
&self,
values: &[FunctionDescriptor],
) -> Result<(), Error> {
let values: Vec<_> = values.iter().map(|value| value.inner.clone()).collect();
self.inner
.set_function_descriptors_slice(&values)
.map_err(Error::from_ffi)
}
}
impl RenderPassDescriptor {
pub fn sample_positions_vec(&self, count: usize) -> Result<Vec<SamplePosition>, Error> {
self.inner
.sample_positions_vec(count)
.map_err(Error::from_ffi)
}
pub fn set_sample_positions_slice(&self, values: &[SamplePosition]) -> Result<(), Error> {
self.inner
.set_sample_positions_slice(values)
.map_err(Error::from_ffi)
}
}
impl PipelineDataSetSerializer {
pub fn serialize_archive_to_path(&self, path: impl AsRef<Path>) -> Result<(), Error> {
self.inner
.serialize_archive_to_path(path)
.map_err(Error::from_ffi)
}
pub fn serialize_pipelines_script(&self) -> Result<Vec<u8>, Error> {
self.inner
.serialize_pipelines_script()
.map_err(Error::from_ffi)
}
}
impl CommandAllocator {
pub fn allocated_size_safe(&self) -> Result<u64, Error> {
self.inner.allocated_size_safe().map_err(Error::from_ffi)
}
pub fn reset_safe(&self) -> Result<(), Error> {
self.inner.reset_safe().map_err(Error::from_ffi)
}
}
impl CompilerTask {
pub fn wait_until_completed_safe(&self) -> Result<(), Error> {
self.inner
.wait_until_completed_safe()
.map_err(Error::from_ffi)
}
}