use std::{ffi::c_void, path::Path, ptr::NonNull};
use block2::{Block, RcBlock};
use dispatch2::DispatchData;
use objc2::{Message, extern_protocol, msg_send, rc::Retained, runtime::ProtocolObject};
use objc2_foundation::{NSArray, NSBundle, NSError, NSObjectProtocol, NSString};
use objc2_io_surface::IOSurfaceRef;
use super::{MTLArchitecture, MTLSizeAndAlign};
#[cfg(target_os = "macos")]
#[allow(deprecated)]
use crate::MTLDeviceLocation;
#[allow(deprecated)]
use crate::MTLFeatureSet;
use crate::{
CallbackBlock, MTL4Archive, MTL4ArgumentTable, MTL4ArgumentTableDescriptor, MTL4BinaryFunction,
MTL4CommandAllocatorDescriptor, MTL4CommandQueueDescriptor, MTL4CompilerDescriptor, MTL4CounterHeap,
MTL4CounterHeapDescriptor, MTL4CounterHeapType, MTL4PipelineDataSetSerializer,
MTL4PipelineDataSetSerializerDescriptor, MTLAccelerationStructure, MTLArgumentBuffersTier, MTLArgumentEncoder,
MTLBinaryArchive, MTLBinaryArchiveDescriptor, MTLBuffer, MTLBufferBinding, MTLCommandQueue,
MTLCommandQueueDescriptor, MTLCompileOptions, MTLComputePipelineDescriptor, MTLComputePipelineState,
MTLCounterSampleBuffer, MTLCounterSampleBufferDescriptor, MTLCounterSamplingPoint, MTLCounterSet,
MTLDepthStencilDescriptor, MTLDepthStencilState, MTLDynamicLibrary, MTLEvent, MTLFence, MTLFunction,
MTLFunctionHandle, MTLGPUFamily, MTLHeap, MTLHeapDescriptor, MTLIOCommandQueue, MTLIOCommandQueueDescriptor,
MTLIOCompressionMethod, MTLIOFileHandle, MTLIndirectCommandBuffer, MTLIndirectCommandBufferDescriptor, MTLLibrary,
MTLLogState, MTLLogStateDescriptor, MTLMeshRenderPipelineDescriptor, MTLNewRenderPipelineStateCompletionHandler,
MTLNewRenderPipelineStateWithReflectionCompletionHandler, MTLPipelineOption, MTLPixelFormat,
MTLRasterizationRateMap, MTLRasterizationRateMapDescriptor, MTLReadWriteTextureTier, MTLRegion,
MTLRenderPipelineDescriptor, MTLRenderPipelineReflection, MTLRenderPipelineState, MTLResidencySet,
MTLResidencySetDescriptor, MTLResourceOptions, MTLResourceViewPoolDescriptor, MTLSamplePosition,
MTLSamplerDescriptor, MTLSamplerState, MTLSharedEvent, MTLSharedEventHandle, MTLSharedTextureHandle, MTLSize,
MTLSparsePageSize, MTLSparseTextureRegionAlignmentMode, MTLTensor, MTLTensorBufferAttachments, MTLTensorDescriptor,
MTLTexture, MTLTextureDescriptor, MTLTextureType, MTLTextureViewPool, MetalError,
acceleration_structure::{MTLAccelerationStructureDescriptor, MTLAccelerationStructureSizes},
argument::MTLArgumentDescriptor,
compute_pipeline::{
MTLComputePipelineReflection, NewComputePipelineStateCompletionHandler,
NewComputePipelineStateWithReflectionCompletionHandler,
},
function_stitching::MTLStitchedLibraryDescriptor,
library::NewLibraryCompletionHandler,
render_pipeline::MTLTileRenderPipelineDescriptor,
util::file_url,
};
pub type MTLTimestamp = u64;
extern_protocol!(
pub unsafe trait MTLDevice: NSObjectProtocol + Send + Sync {
#[unsafe(method(registryID))]
#[unsafe(method_family = none)]
fn registry_id(&self) -> u64;
#[unsafe(method(architecture))]
#[unsafe(method_family = none)]
fn architecture(&self) -> Retained<MTLArchitecture>;
#[unsafe(method(maxThreadsPerThreadgroup))]
#[unsafe(method_family = none)]
fn max_threads_per_threadgroup(&self) -> MTLSize;
#[cfg(any(target_os = "macos", target_abi = "macabi"))]
#[deprecated(note = "not applicable on Apple Silicon")]
#[unsafe(method(isLowPower))]
#[unsafe(method_family = none)]
fn is_low_power(&self) -> bool;
#[cfg(any(target_os = "macos", target_abi = "macabi"))]
#[deprecated(note = "not applicable on Apple Silicon")]
#[unsafe(method(isHeadless))]
#[unsafe(method_family = none)]
fn is_headless(&self) -> bool;
#[unsafe(method(hasUnifiedMemory))]
#[unsafe(method_family = none)]
fn has_unified_memory(&self) -> bool;
#[unsafe(method(recommendedMaxWorkingSetSize))]
#[unsafe(method_family = none)]
fn recommended_max_working_set_size(&self) -> u64;
#[cfg(target_os = "macos")]
#[allow(deprecated)]
#[deprecated(note = "not applicable on Apple Silicon")]
#[unsafe(method(location))]
#[unsafe(method_family = none)]
fn location(&self) -> MTLDeviceLocation;
#[cfg(target_os = "macos")]
#[deprecated(note = "not applicable on Apple Silicon")]
#[unsafe(method(locationNumber))]
#[unsafe(method_family = none)]
fn location_number(&self) -> usize;
#[cfg(target_os = "macos")]
#[deprecated(note = "not applicable on Apple Silicon")]
#[unsafe(method(maxTransferRate))]
#[unsafe(method_family = none)]
fn max_transfer_rate(&self) -> u64;
#[unsafe(method(readWriteTextureSupport))]
#[unsafe(method_family = none)]
fn read_write_texture_support(&self) -> MTLReadWriteTextureTier;
#[unsafe(method(argumentBuffersSupport))]
#[unsafe(method_family = none)]
fn argument_buffers_support(&self) -> MTLArgumentBuffersTier;
#[cfg(any(target_os = "macos", target_abi = "macabi"))]
#[deprecated(note = "never supported on Apple Silicon")]
#[unsafe(method(isDepth24Stencil8PixelFormatSupported))]
#[unsafe(method_family = none)]
fn is_depth24_stencil8_pixel_format_supported(&self) -> bool;
#[unsafe(method(supportsFamily:))]
#[unsafe(method_family = none)]
fn supports_family(
&self,
family: MTLGPUFamily,
) -> bool;
#[unsafe(method(supportsTextureSampleCount:))]
#[unsafe(method_family = none)]
fn supports_texture_sample_count(
&self,
sample_count: usize,
) -> bool;
#[unsafe(method(minimumLinearTextureAlignmentForPixelFormat:))]
#[unsafe(method_family = none)]
fn minimum_linear_texture_alignment_for_pixel_format(
&self,
format: MTLPixelFormat,
) -> usize;
#[unsafe(method(minimumTextureBufferAlignmentForPixelFormat:))]
#[unsafe(method_family = none)]
fn minimum_texture_buffer_alignment_for_pixel_format(
&self,
format: MTLPixelFormat,
) -> usize;
#[unsafe(method(newDepthStencilStateWithDescriptor:))]
#[unsafe(method_family = new)]
fn new_depth_stencil_state_with_descriptor(
&self,
descriptor: &MTLDepthStencilDescriptor,
) -> Option<Retained<ProtocolObject<dyn MTLDepthStencilState>>>;
#[unsafe(method(sampleTimestamps:gpuTimestamp:))]
#[unsafe(method_family = none)]
fn sample_timestamps_gpu_timestamp(
&self,
cpu_timestamp: &mut MTLTimestamp,
gpu_timestamp: &mut MTLTimestamp,
);
#[unsafe(method(supportsCounterSampling:))]
#[unsafe(method_family = none)]
fn supports_counter_sampling(
&self,
sampling_point: MTLCounterSamplingPoint,
) -> bool;
#[unsafe(method(supportsQueryTextureLOD))]
#[unsafe(method_family = none)]
fn supports_query_texture_lod(&self) -> bool;
#[unsafe(method(supportsBCTextureCompression))]
#[unsafe(method_family = none)]
fn supports_bc_texture_compression(&self) -> bool;
#[unsafe(method(supportsPullModelInterpolation))]
#[unsafe(method_family = none)]
fn supports_pull_model_interpolation(&self) -> bool;
#[deprecated(note = "use supports_shader_barycentric_coordinates")]
#[unsafe(method(areBarycentricCoordsSupported))]
#[unsafe(method_family = none)]
fn barycentric_coords_supported(&self) -> bool;
#[unsafe(method(supportsShaderBarycentricCoordinates))]
#[unsafe(method_family = none)]
fn supports_shader_barycentric_coordinates(&self) -> bool;
#[unsafe(method(currentAllocatedSize))]
#[unsafe(method_family = none)]
fn current_allocated_size(&self) -> usize;
#[cfg(any(target_os = "macos", target_abi = "macabi"))]
#[deprecated(note = "not applicable on Apple Silicon")]
#[unsafe(method(isRemovable))]
#[unsafe(method_family = none)]
fn is_removable(&self) -> bool;
#[unsafe(method(supports32BitFloatFiltering))]
#[unsafe(method_family = none)]
fn supports_32bit_float_filtering(&self) -> bool;
#[unsafe(method(supports32BitMSAA))]
#[unsafe(method_family = none)]
fn supports_32bit_msaa(&self) -> bool;
#[unsafe(method(maxArgumentBufferSamplerCount))]
#[unsafe(method_family = none)]
fn max_argument_buffer_sampler_count(&self) -> usize;
#[unsafe(method(areProgrammableSamplePositionsSupported))]
#[unsafe(method_family = none)]
fn are_programmable_sample_positions_supported(&self) -> bool;
#[cfg(target_os = "macos")]
#[deprecated(note = "not applicable on Apple Silicon")]
#[unsafe(method(peerGroupID))]
#[unsafe(method_family = none)]
fn peer_group_id(&self) -> u64;
#[cfg(target_os = "macos")]
#[deprecated(note = "not applicable on Apple Silicon")]
#[unsafe(method(peerIndex))]
#[unsafe(method_family = none)]
fn peer_index(&self) -> u32;
#[cfg(target_os = "macos")]
#[deprecated(note = "not applicable on Apple Silicon")]
#[unsafe(method(peerCount))]
#[unsafe(method_family = none)]
fn peer_count(&self) -> u32;
#[unsafe(method(sparseTileSizeInBytes))]
#[unsafe(method_family = none)]
fn sparse_tile_size_in_bytes(&self) -> usize;
#[unsafe(method(supportsDynamicLibraries))]
#[unsafe(method_family = none)]
fn supports_dynamic_libraries(&self) -> bool;
#[unsafe(method(supportsRenderDynamicLibraries))]
#[unsafe(method_family = none)]
fn supports_render_dynamic_libraries(&self) -> bool;
#[unsafe(method(supportsPlacementSparse))]
#[unsafe(method_family = none)]
fn supports_placement_sparse(&self) -> bool;
#[unsafe(method(supportsRaytracing))]
#[unsafe(method_family = none)]
fn supports_raytracing(&self) -> bool;
#[unsafe(method(supportsFunctionPointers))]
#[unsafe(method_family = none)]
fn supports_function_pointers(&self) -> bool;
#[unsafe(method(supportsFunctionPointersFromRender))]
#[unsafe(method_family = none)]
fn supports_function_pointers_from_render(&self) -> bool;
#[unsafe(method(supportsRaytracingFromRender))]
#[unsafe(method_family = none)]
fn supports_raytracing_from_render(&self) -> bool;
#[unsafe(method(supportsPrimitiveMotionBlur))]
#[unsafe(method_family = none)]
fn supports_primitive_motion_blur(&self) -> bool;
#[cfg(target_os = "macos")]
#[unsafe(method(shouldMaximizeConcurrentCompilation))]
#[unsafe(method_family = none)]
fn should_maximize_concurrent_compilation(&self) -> bool;
#[cfg(target_os = "macos")]
#[unsafe(method(setShouldMaximizeConcurrentCompilation:))]
#[unsafe(method_family = none)]
fn set_should_maximize_concurrent_compilation(
&self,
value: bool,
);
#[unsafe(method(maximumConcurrentCompilationTaskCount))]
#[unsafe(method_family = none)]
fn maximum_concurrent_compilation_task_count(&self) -> usize;
#[unsafe(method(supportsRasterizationRateMapWithLayerCount:))]
#[unsafe(method_family = none)]
fn supports_rasterization_rate_map_with_layer_count(
&self,
layer_count: usize,
) -> bool;
#[unsafe(method(supportsVertexAmplificationCount:))]
#[unsafe(method_family = none)]
fn supports_vertex_amplification_count(
&self,
count: usize,
) -> bool;
#[unsafe(method(sparseTileSizeWithTextureType:pixelFormat:sampleCount:))]
#[unsafe(method_family = none)]
fn sparse_tile_size(
&self,
texture_type: MTLTextureType,
pixel_format: MTLPixelFormat,
sample_count: usize,
) -> MTLSize;
#[unsafe(method(sparseTileSizeInBytesForSparsePageSize:))]
#[unsafe(method_family = none)]
fn sparse_tile_size_in_bytes_for_sparse_page_size(
&self,
sparse_page_size: MTLSparsePageSize,
) -> usize;
#[unsafe(method(sparseTileSizeWithTextureType:pixelFormat:sampleCount:sparsePageSize:))]
#[unsafe(method_family = none)]
fn sparse_tile_size_with_page_size(
&self,
texture_type: MTLTextureType,
pixel_format: MTLPixelFormat,
sample_count: usize,
sparse_page_size: MTLSparsePageSize,
) -> MTLSize;
#[unsafe(method(heapTextureSizeAndAlignWithDescriptor:))]
#[unsafe(method_family = none)]
fn heap_texture_size_and_align(
&self,
descriptor: &MTLTextureDescriptor,
) -> MTLSizeAndAlign;
#[unsafe(method(heapBufferSizeAndAlignWithLength:options:))]
#[unsafe(method_family = none)]
fn heap_buffer_size_and_align(
&self,
length: usize,
options: MTLResourceOptions,
) -> MTLSizeAndAlign;
#[unsafe(method(heapAccelerationStructureSizeAndAlignWithSize:))]
#[unsafe(method_family = none)]
fn heap_acceleration_structure_size_and_align_with_size(
&self,
size: usize,
) -> MTLSizeAndAlign;
#[unsafe(method(heapAccelerationStructureSizeAndAlignWithDescriptor:))]
#[unsafe(method_family = none)]
fn heap_acceleration_structure_size_and_align_with_descriptor(
&self,
descriptor: &MTLAccelerationStructureDescriptor,
) -> MTLSizeAndAlign;
#[unsafe(method(accelerationStructureSizesWithDescriptor:))]
#[unsafe(method_family = none)]
fn acceleration_structure_sizes_with_descriptor(
&self,
descriptor: &MTLAccelerationStructureDescriptor,
) -> MTLAccelerationStructureSizes;
#[unsafe(method(newCommandQueueWithDescriptor:))]
#[unsafe(method_family = new)]
fn new_command_queue_with_descriptor(
&self,
descriptor: &MTLCommandQueueDescriptor,
) -> Option<Retained<ProtocolObject<dyn MTLCommandQueue>>>;
#[unsafe(method(newSharedTextureWithDescriptor:))]
#[unsafe(method_family = new)]
fn new_shared_texture_with_descriptor(
&self,
descriptor: &MTLTextureDescriptor,
) -> Option<Retained<ProtocolObject<dyn MTLTexture>>>;
#[unsafe(method(newSharedTextureWithHandle:))]
#[unsafe(method_family = new)]
fn new_shared_texture_with_handle(
&self,
shared_handle: &MTLSharedTextureHandle,
) -> Option<Retained<ProtocolObject<dyn MTLTexture>>>;
#[unsafe(method(newRasterizationRateMapWithDescriptor:))]
#[unsafe(method_family = new)]
fn new_rasterization_rate_map_with_descriptor(
&self,
descriptor: &MTLRasterizationRateMapDescriptor,
) -> Option<Retained<ProtocolObject<dyn MTLRasterizationRateMap>>>;
#[unsafe(method(newIndirectCommandBufferWithDescriptor:maxCommandCount:options:))]
#[unsafe(method_family = new)]
fn new_indirect_command_buffer_with_descriptor(
&self,
descriptor: &MTLIndirectCommandBufferDescriptor,
max_count: usize,
options: MTLResourceOptions,
) -> Option<Retained<ProtocolObject<dyn MTLIndirectCommandBuffer>>>;
#[unsafe(method(newArgumentEncoderWithBufferBinding:))]
#[unsafe(method_family = new)]
fn new_argument_encoder_with_buffer_binding(
&self,
buffer_binding: &ProtocolObject<dyn MTLBufferBinding>,
) -> Retained<ProtocolObject<dyn MTLArgumentEncoder>>;
}
);
pub trait MTLDeviceExt: MTLDevice + Message {
fn name(&self) -> String;
fn raster_order_groups_supported(&self) -> bool;
fn max_threadgroup_memory_length(&self) -> usize;
fn max_buffer_length(&self) -> usize;
fn counter_sets(&self) -> Option<Box<[Retained<ProtocolObject<dyn MTLCounterSet>>]>>;
fn new_counter_sample_buffer_with_descriptor(
&self,
descriptor: &MTLCounterSampleBufferDescriptor,
) -> Result<Retained<ProtocolObject<dyn MTLCounterSampleBuffer>>, MetalError>;
fn new_log_state_with_descriptor(
&self,
descriptor: &MTLLogStateDescriptor,
) -> Result<Retained<ProtocolObject<dyn MTLLogState>>, MetalError>;
fn new_command_queue(&self) -> Option<Retained<ProtocolObject<dyn MTLCommandQueue>>>;
fn new_command_queue_with_max_command_buffer_count(
&self,
max_count: usize,
) -> Option<Retained<ProtocolObject<dyn MTLCommandQueue>>>;
fn new_heap_with_descriptor(
&self,
descriptor: &MTLHeapDescriptor,
) -> Option<Retained<ProtocolObject<dyn MTLHeap>>>;
fn new_buffer(
&self,
length: usize,
options: MTLResourceOptions,
) -> Option<Retained<ProtocolObject<dyn MTLBuffer>>>;
fn new_buffer_with_data(
&self,
data: &[u8],
options: MTLResourceOptions,
) -> Option<Retained<ProtocolObject<dyn MTLBuffer>>>;
fn new_buffer_with_bytes_no_copy(
&self,
ptr: NonNull<c_void>,
length: usize,
options: MTLResourceOptions,
) -> Option<Retained<ProtocolObject<dyn MTLBuffer>>>;
fn new_buffer_with_bytes_no_copy_with_deallocator<F>(
&self,
ptr: NonNull<c_void>,
length: usize,
options: MTLResourceOptions,
deallocator: F,
) -> Option<Retained<ProtocolObject<dyn MTLBuffer>>>
where
Self: Sized,
F: Fn(*mut c_void, usize) + Send + Sync + 'static;
fn new_texture_with_descriptor(
&self,
descriptor: &MTLTextureDescriptor,
) -> Option<Retained<ProtocolObject<dyn MTLTexture>>>;
fn new_texture_with_descriptor_iosurface(
&self,
descriptor: &MTLTextureDescriptor,
iosurface: &IOSurfaceRef,
plane: usize,
) -> Option<Retained<ProtocolObject<dyn MTLTexture>>>;
fn new_sampler_state_with_descriptor(
&self,
descriptor: &MTLSamplerDescriptor,
) -> Option<Retained<ProtocolObject<dyn MTLSamplerState>>>;
fn new_default_library(&self) -> Option<Retained<ProtocolObject<dyn MTLLibrary>>>;
fn new_default_library_with_bundle_path(
&self,
path: &Path,
) -> Result<Retained<ProtocolObject<dyn MTLLibrary>>, MetalError>;
#[deprecated(note = "use new_library_with_path")]
fn new_library_with_file(
&self,
path: &str,
) -> Result<Retained<ProtocolObject<dyn MTLLibrary>>, MetalError>;
fn new_library_with_path(
&self,
path: &Path,
) -> Result<Retained<ProtocolObject<dyn MTLLibrary>>, MetalError>;
fn new_library_with_data(
&self,
data: &[u8],
) -> Result<Retained<ProtocolObject<dyn MTLLibrary>>, MetalError>;
fn new_library_with_source(
&self,
source: &str,
options: Option<&MTLCompileOptions>,
) -> Result<Retained<ProtocolObject<dyn MTLLibrary>>, MetalError>;
fn new_library_with_stitched_descriptor(
&self,
descriptor: &MTLStitchedLibraryDescriptor,
) -> Result<Retained<ProtocolObject<dyn MTLLibrary>>, MetalError>;
fn new_render_pipeline_state_with_descriptor(
&self,
descriptor: &MTLRenderPipelineDescriptor,
) -> Result<Retained<ProtocolObject<dyn MTLRenderPipelineState>>, MetalError>;
fn new_compute_pipeline_state_with_function(
&self,
function: &ProtocolObject<dyn MTLFunction>,
) -> Result<Retained<ProtocolObject<dyn MTLComputePipelineState>>, MetalError>;
fn new_compute_pipeline_state_with_descriptor(
&self,
descriptor: &MTLComputePipelineDescriptor,
options: MTLPipelineOption,
) -> Result<
(Retained<ProtocolObject<dyn MTLComputePipelineState>>, Option<Retained<MTLComputePipelineReflection>>),
MetalError,
>;
fn new_fence(&self) -> Option<Retained<ProtocolObject<dyn MTLFence>>>;
#[allow(deprecated)]
#[deprecated(note = "use supports_family")]
fn supports_feature_set(
&self,
feature_set: MTLFeatureSet,
) -> bool;
fn new_argument_encoder_with_arguments(
&self,
arguments: &[&MTLArgumentDescriptor],
) -> Option<Retained<ProtocolObject<dyn MTLArgumentEncoder>>>;
fn new_event(&self) -> Option<Retained<ProtocolObject<dyn MTLEvent>>>;
fn new_shared_event(&self) -> Option<Retained<ProtocolObject<dyn MTLSharedEvent>>>;
fn new_shared_event_with_handle(
&self,
handle: &MTLSharedEventHandle,
) -> Option<Retained<ProtocolObject<dyn MTLSharedEvent>>>;
fn new_binary_archive_with_descriptor(
&self,
descriptor: &MTLBinaryArchiveDescriptor,
) -> Result<Retained<ProtocolObject<dyn MTLBinaryArchive>>, MetalError>;
fn new_io_command_queue_with_descriptor(
&self,
descriptor: &MTLIOCommandQueueDescriptor,
) -> Result<Retained<ProtocolObject<dyn MTLIOCommandQueue>>, MetalError>;
fn new_dynamic_library(
&self,
library: &ProtocolObject<dyn MTLLibrary>,
) -> Result<Retained<ProtocolObject<dyn MTLDynamicLibrary>>, MetalError>;
fn new_dynamic_library_with_path(
&self,
path: &Path,
) -> Result<Retained<ProtocolObject<dyn MTLDynamicLibrary>>, MetalError>;
fn new_acceleration_structure_with_size(
&self,
size: usize,
) -> Option<Retained<ProtocolObject<dyn MTLAccelerationStructure>>>;
fn new_acceleration_structure_with_descriptor(
&self,
descriptor: &MTLAccelerationStructureDescriptor,
) -> Option<Retained<ProtocolObject<dyn MTLAccelerationStructure>>>;
fn new_residency_set_with_descriptor(
&self,
descriptor: &MTLResidencySetDescriptor,
) -> Result<Retained<ProtocolObject<dyn MTLResidencySet>>, MetalError>;
fn tensor_size_and_align_with_descriptor(
&self,
descriptor: &MTLTensorDescriptor,
) -> MTLSizeAndAlign;
fn new_tensor_with_descriptor(
&self,
descriptor: &MTLTensorDescriptor,
) -> Result<Retained<ProtocolObject<dyn MTLTensor>>, MetalError>;
fn new_tensor_with_descriptor_attachments(
&self,
descriptor: &MTLTensorDescriptor,
attachments: &MTLTensorBufferAttachments,
) -> Result<Retained<ProtocolObject<dyn MTLTensor>>, MetalError>;
fn function_handle_with_function(
&self,
function: &ProtocolObject<dyn MTLFunction>,
) -> Option<Retained<ProtocolObject<dyn MTLFunctionHandle>>>;
fn new_command_allocator(&self) -> Option<Retained<ProtocolObject<dyn crate::MTL4CommandAllocator>>>;
fn new_command_allocator_with_descriptor(
&self,
descriptor: &MTL4CommandAllocatorDescriptor,
) -> Result<Retained<ProtocolObject<dyn crate::MTL4CommandAllocator>>, MetalError>;
fn new_mtl4_command_queue(&self) -> Option<Retained<ProtocolObject<dyn crate::MTL4CommandQueue>>>;
fn new_mtl4_command_queue_with_descriptor(
&self,
descriptor: &MTL4CommandQueueDescriptor,
) -> Result<Retained<ProtocolObject<dyn crate::MTL4CommandQueue>>, MetalError>;
fn new_mtl4_command_buffer(&self) -> Option<Retained<ProtocolObject<dyn crate::MTL4CommandBuffer>>>;
fn new_argument_table_with_descriptor(
&self,
descriptor: &MTL4ArgumentTableDescriptor,
) -> Result<Retained<ProtocolObject<dyn MTL4ArgumentTable>>, MetalError>;
fn new_texture_view_pool_with_descriptor(
&self,
descriptor: &MTLResourceViewPoolDescriptor,
) -> Result<Retained<ProtocolObject<dyn MTLTextureViewPool>>, MetalError>;
fn new_compiler_with_descriptor(
&self,
descriptor: &MTL4CompilerDescriptor,
) -> Result<Retained<ProtocolObject<dyn crate::MTL4Compiler>>, MetalError>;
fn new_archive_with_path(
&self,
path: &Path,
) -> Result<Retained<ProtocolObject<dyn MTL4Archive>>, MetalError>;
fn new_pipeline_data_set_serializer_with_descriptor(
&self,
descriptor: &MTL4PipelineDataSetSerializerDescriptor,
) -> Retained<ProtocolObject<dyn MTL4PipelineDataSetSerializer>>;
fn new_buffer_with_length_options_placement_sparse_page_size(
&self,
length: usize,
options: MTLResourceOptions,
placement_sparse_page_size: MTLSparsePageSize,
) -> Option<Retained<ProtocolObject<dyn MTLBuffer>>>;
fn new_counter_heap_with_descriptor(
&self,
descriptor: &MTL4CounterHeapDescriptor,
) -> Result<Retained<ProtocolObject<dyn MTL4CounterHeap>>, MetalError>;
fn size_of_counter_heap_entry(
&self,
counter_heap_type: MTL4CounterHeapType,
) -> usize;
fn query_timestamp_frequency(&self) -> u64;
fn function_handle_with_binary_function(
&self,
function: &ProtocolObject<dyn MTL4BinaryFunction>,
) -> Option<Retained<ProtocolObject<dyn MTLFunctionHandle>>>;
fn default_sample_positions(
&self,
sample_count: usize,
) -> Box<[MTLSamplePosition]>;
fn get_default_sample_positions(
&self,
positions: &mut [MTLSamplePosition],
);
fn convert_sparse_pixel_regions_to_tile_regions(
&self,
pixel_regions: &[MTLRegion],
tile_regions: &mut [MTLRegion],
tile_size: MTLSize,
alignment_mode: MTLSparseTextureRegionAlignmentMode,
);
fn convert_sparse_tile_regions_to_pixel_regions(
&self,
tile_regions: &[MTLRegion],
pixel_regions: &mut [MTLRegion],
tile_size: MTLSize,
);
fn new_io_file_handle_with_url(
&self,
path: &Path,
) -> Result<Retained<ProtocolObject<dyn MTLIOFileHandle>>, MetalError>;
fn new_io_file_handle_with_url_compression_method(
&self,
path: &Path,
compression_method: MTLIOCompressionMethod,
) -> Result<Retained<ProtocolObject<dyn MTLIOFileHandle>>, MetalError>;
fn new_render_pipeline_state_with_descriptor_options(
&self,
descriptor: &MTLRenderPipelineDescriptor,
options: MTLPipelineOption,
) -> Result<
(Retained<ProtocolObject<dyn MTLRenderPipelineState>>, Option<Retained<MTLRenderPipelineReflection>>),
MetalError,
>;
fn new_render_pipeline_state_with_mesh_descriptor_options(
&self,
descriptor: &MTLMeshRenderPipelineDescriptor,
options: MTLPipelineOption,
) -> Result<
(Retained<ProtocolObject<dyn MTLRenderPipelineState>>, Option<Retained<MTLRenderPipelineReflection>>),
MetalError,
>;
fn new_compute_pipeline_state_with_function_options(
&self,
function: &ProtocolObject<dyn MTLFunction>,
options: MTLPipelineOption,
) -> Result<
(Retained<ProtocolObject<dyn MTLComputePipelineState>>, Option<Retained<MTLComputePipelineReflection>>),
MetalError,
>;
fn new_render_pipeline_state_with_tile_descriptor(
&self,
descriptor: &MTLTileRenderPipelineDescriptor,
options: MTLPipelineOption,
) -> Result<
(Retained<ProtocolObject<dyn MTLRenderPipelineState>>, Option<Retained<MTLRenderPipelineReflection>>),
MetalError,
>;
fn new_render_pipeline_state_with_descriptor_completion_handler(
&self,
descriptor: &MTLRenderPipelineDescriptor,
completion_handler: MTLNewRenderPipelineStateCompletionHandler,
);
fn new_render_pipeline_state_with_descriptor_options_completion_handler(
&self,
descriptor: &MTLRenderPipelineDescriptor,
options: MTLPipelineOption,
completion_handler: MTLNewRenderPipelineStateWithReflectionCompletionHandler,
);
fn new_render_pipeline_state_with_tile_descriptor_options_completion_handler(
&self,
descriptor: &MTLTileRenderPipelineDescriptor,
options: MTLPipelineOption,
completion_handler: MTLNewRenderPipelineStateWithReflectionCompletionHandler,
);
fn new_render_pipeline_state_with_mesh_descriptor_options_completion_handler(
&self,
descriptor: &MTLMeshRenderPipelineDescriptor,
options: MTLPipelineOption,
completion_handler: MTLNewRenderPipelineStateWithReflectionCompletionHandler,
);
fn new_library_with_source_completion_handler(
&self,
source: &str,
options: Option<&MTLCompileOptions>,
completion_handler: NewLibraryCompletionHandler,
);
fn new_library_with_stitched_descriptor_completion_handler(
&self,
descriptor: &MTLStitchedLibraryDescriptor,
completion_handler: NewLibraryCompletionHandler,
);
fn new_compute_pipeline_state_with_function_completion_handler(
&self,
function: &ProtocolObject<dyn MTLFunction>,
completion_handler: NewComputePipelineStateCompletionHandler,
);
fn new_compute_pipeline_state_with_function_options_completion_handler(
&self,
function: &ProtocolObject<dyn MTLFunction>,
options: MTLPipelineOption,
completion_handler: NewComputePipelineStateWithReflectionCompletionHandler,
);
fn new_compute_pipeline_state_with_descriptor_options_completion_handler(
&self,
descriptor: &MTLComputePipelineDescriptor,
options: MTLPipelineOption,
completion_handler: NewComputePipelineStateWithReflectionCompletionHandler,
);
}
impl MTLDeviceExt for ProtocolObject<dyn MTLDevice> {
fn name(&self) -> String {
let ns: Retained<NSString> = unsafe { msg_send![self, name] };
ns.to_string()
}
fn raster_order_groups_supported(&self) -> bool {
unsafe { msg_send![self, areRasterOrderGroupsSupported] }
}
fn max_threadgroup_memory_length(&self) -> usize {
unsafe { msg_send![self, maxThreadgroupMemoryLength] }
}
fn max_buffer_length(&self) -> usize {
unsafe { msg_send![self, maxBufferLength] }
}
fn counter_sets(&self) -> Option<Box<[Retained<ProtocolObject<dyn MTLCounterSet>>]>> {
let array: Option<Retained<NSArray<ProtocolObject<dyn MTLCounterSet>>>> =
unsafe { msg_send![self, counterSets] };
array.map(|a| a.to_vec().into_boxed_slice())
}
fn new_counter_sample_buffer_with_descriptor(
&self,
descriptor: &MTLCounterSampleBufferDescriptor,
) -> Result<Retained<ProtocolObject<dyn MTLCounterSampleBuffer>>, MetalError> {
unsafe { msg_send![self, newCounterSampleBufferWithDescriptor: descriptor, error: _] }
.map_err(MetalError::from_nserror)
}
fn new_log_state_with_descriptor(
&self,
descriptor: &MTLLogStateDescriptor,
) -> Result<Retained<ProtocolObject<dyn MTLLogState>>, MetalError> {
unsafe { msg_send![self, newLogStateWithDescriptor: descriptor, error: _] }.map_err(MetalError::from_nserror)
}
fn new_command_queue(&self) -> Option<Retained<ProtocolObject<dyn MTLCommandQueue>>> {
unsafe { msg_send![self, newCommandQueue] }
}
fn new_command_queue_with_max_command_buffer_count(
&self,
max_count: usize,
) -> Option<Retained<ProtocolObject<dyn MTLCommandQueue>>> {
unsafe { msg_send![self, newCommandQueueWithMaxCommandBufferCount: max_count] }
}
fn new_heap_with_descriptor(
&self,
descriptor: &MTLHeapDescriptor,
) -> Option<Retained<ProtocolObject<dyn MTLHeap>>> {
unsafe { msg_send![self, newHeapWithDescriptor: descriptor] }
}
fn new_buffer(
&self,
length: usize,
options: MTLResourceOptions,
) -> Option<Retained<ProtocolObject<dyn MTLBuffer>>> {
unsafe { msg_send![self, newBufferWithLength: length, options: options] }
}
fn new_buffer_with_data(
&self,
data: &[u8],
options: MTLResourceOptions,
) -> Option<Retained<ProtocolObject<dyn MTLBuffer>>> {
unsafe {
msg_send![
self,
newBufferWithBytes: data.as_ptr() as *const c_void,
length: data.len(),
options: options
]
}
}
fn new_buffer_with_bytes_no_copy(
&self,
ptr: NonNull<c_void>,
length: usize,
options: MTLResourceOptions,
) -> Option<Retained<ProtocolObject<dyn MTLBuffer>>> {
let deallocator: Option<&Block<dyn Fn(*mut c_void, usize)>> = None;
unsafe {
msg_send![
self,
newBufferWithBytesNoCopy: ptr.as_ptr(),
length: length,
options: options,
deallocator: deallocator
]
}
}
fn new_buffer_with_bytes_no_copy_with_deallocator<F>(
&self,
ptr: NonNull<c_void>,
length: usize,
options: MTLResourceOptions,
deallocator: F,
) -> Option<Retained<ProtocolObject<dyn MTLBuffer>>>
where
F: Fn(*mut c_void, usize) + Send + Sync + 'static,
{
let deallocator = RcBlock::new(move |pointer: *mut c_void, length: usize| {
deallocator(pointer, length);
});
let deallocator: &Block<dyn Fn(*mut c_void, usize)> = &deallocator;
unsafe {
msg_send![
self,
newBufferWithBytesNoCopy: ptr.as_ptr(),
length: length,
options: options,
deallocator: deallocator
]
}
}
fn new_texture_with_descriptor(
&self,
descriptor: &MTLTextureDescriptor,
) -> Option<Retained<ProtocolObject<dyn MTLTexture>>> {
unsafe { msg_send![self, newTextureWithDescriptor: descriptor] }
}
fn new_texture_with_descriptor_iosurface(
&self,
descriptor: &MTLTextureDescriptor,
iosurface: &IOSurfaceRef,
plane: usize,
) -> Option<Retained<ProtocolObject<dyn MTLTexture>>> {
unsafe { msg_send![self, newTextureWithDescriptor: descriptor, iosurface: iosurface, plane: plane] }
}
fn new_sampler_state_with_descriptor(
&self,
descriptor: &MTLSamplerDescriptor,
) -> Option<Retained<ProtocolObject<dyn MTLSamplerState>>> {
unsafe { msg_send![self, newSamplerStateWithDescriptor: descriptor] }
}
fn new_default_library(&self) -> Option<Retained<ProtocolObject<dyn MTLLibrary>>> {
unsafe { msg_send![self, newDefaultLibrary] }
}
fn new_default_library_with_bundle_path(
&self,
path: &Path,
) -> Result<Retained<ProtocolObject<dyn MTLLibrary>>, MetalError> {
let url = file_url(path, "newDefaultLibraryWithBundle:error:")?;
let bundle = NSBundle::bundleWithURL(&url).ok_or_else(|| {
MetalError::invalid_input("newDefaultLibraryWithBundle:error:", "path does not identify a bundle")
})?;
unsafe { msg_send![self, newDefaultLibraryWithBundle: &*bundle, error: _] }.map_err(MetalError::from_nserror)
}
fn new_library_with_file(
&self,
path: &str,
) -> Result<Retained<ProtocolObject<dyn MTLLibrary>>, MetalError> {
let path = NSString::from_str(path);
unsafe { msg_send![self, newLibraryWithFile: &*path, error: _] }.map_err(MetalError::from_nserror)
}
fn new_library_with_path(
&self,
path: &Path,
) -> Result<Retained<ProtocolObject<dyn MTLLibrary>>, MetalError> {
let url = file_url(path, "newLibraryWithURL:error:")?;
unsafe { msg_send![self, newLibraryWithURL: &*url, error: _] }.map_err(MetalError::from_nserror)
}
fn new_library_with_data(
&self,
data: &[u8],
) -> Result<Retained<ProtocolObject<dyn MTLLibrary>>, MetalError> {
let dispatch_data = DispatchData::from_bytes(data);
unsafe { msg_send![self, newLibraryWithData: &*dispatch_data, error: _] }.map_err(MetalError::from_nserror)
}
fn new_library_with_source(
&self,
source: &str,
options: Option<&MTLCompileOptions>,
) -> Result<Retained<ProtocolObject<dyn MTLLibrary>>, MetalError> {
let source = NSString::from_str(source);
unsafe { msg_send![self, newLibraryWithSource: &*source, options: options, error: _] }
.map_err(MetalError::from_nserror)
}
fn new_library_with_stitched_descriptor(
&self,
descriptor: &MTLStitchedLibraryDescriptor,
) -> Result<Retained<ProtocolObject<dyn MTLLibrary>>, MetalError> {
unsafe { msg_send![self, newLibraryWithStitchedDescriptor: descriptor, error: _] }
.map_err(MetalError::from_nserror)
}
fn new_render_pipeline_state_with_descriptor(
&self,
descriptor: &MTLRenderPipelineDescriptor,
) -> Result<Retained<ProtocolObject<dyn MTLRenderPipelineState>>, MetalError> {
unsafe { msg_send![self, newRenderPipelineStateWithDescriptor: descriptor, error: _] }
.map_err(MetalError::from_nserror)
}
fn new_compute_pipeline_state_with_function(
&self,
function: &ProtocolObject<dyn MTLFunction>,
) -> Result<Retained<ProtocolObject<dyn MTLComputePipelineState>>, MetalError> {
unsafe { msg_send![self, newComputePipelineStateWithFunction: function, error: _] }
.map_err(MetalError::from_nserror)
}
fn new_compute_pipeline_state_with_descriptor(
&self,
descriptor: &MTLComputePipelineDescriptor,
options: MTLPipelineOption,
) -> Result<
(Retained<ProtocolObject<dyn MTLComputePipelineState>>, Option<Retained<MTLComputePipelineReflection>>),
MetalError,
> {
let mut reflection: *mut MTLComputePipelineReflection = std::ptr::null_mut();
let mut error: *mut NSError = std::ptr::null_mut();
let result: Option<Retained<ProtocolObject<dyn MTLComputePipelineState>>> = unsafe {
msg_send![
self,
newComputePipelineStateWithDescriptor: descriptor,
options: options,
reflection: &mut reflection,
error: &mut error
]
};
let pipeline = unsafe {
MetalError::result_from_nullable(
result,
error,
"newComputePipelineStateWithDescriptor:options:reflection:error:",
)?
};
Ok((pipeline, unsafe { Retained::retain(reflection) }))
}
fn new_render_pipeline_state_with_mesh_descriptor_options(
&self,
descriptor: &MTLMeshRenderPipelineDescriptor,
options: MTLPipelineOption,
) -> Result<
(Retained<ProtocolObject<dyn MTLRenderPipelineState>>, Option<Retained<MTLRenderPipelineReflection>>),
MetalError,
> {
let mut reflection: *mut MTLRenderPipelineReflection = std::ptr::null_mut();
let mut error: *mut NSError = std::ptr::null_mut();
let result: Option<Retained<ProtocolObject<dyn MTLRenderPipelineState>>> = unsafe {
msg_send![
self,
newRenderPipelineStateWithMeshDescriptor: descriptor,
options: options,
reflection: &mut reflection,
error: &mut error
]
};
let pipeline = unsafe {
MetalError::result_from_nullable(
result,
error,
"newRenderPipelineStateWithMeshDescriptor:options:reflection:error:",
)?
};
Ok((pipeline, unsafe { Retained::retain(reflection) }))
}
fn new_fence(&self) -> Option<Retained<ProtocolObject<dyn MTLFence>>> {
unsafe { msg_send![self, newFence] }
}
#[allow(deprecated)]
fn supports_feature_set(
&self,
feature_set: MTLFeatureSet,
) -> bool {
unsafe { msg_send![self, supportsFeatureSet: feature_set] }
}
fn new_argument_encoder_with_arguments(
&self,
arguments: &[&MTLArgumentDescriptor],
) -> Option<Retained<ProtocolObject<dyn MTLArgumentEncoder>>> {
let arguments = NSArray::from_slice(arguments);
unsafe { msg_send![self, newArgumentEncoderWithArguments: &*arguments] }
}
fn new_event(&self) -> Option<Retained<ProtocolObject<dyn MTLEvent>>> {
unsafe { msg_send![self, newEvent] }
}
fn new_shared_event(&self) -> Option<Retained<ProtocolObject<dyn MTLSharedEvent>>> {
unsafe { msg_send![self, newSharedEvent] }
}
fn new_shared_event_with_handle(
&self,
handle: &MTLSharedEventHandle,
) -> Option<Retained<ProtocolObject<dyn MTLSharedEvent>>> {
unsafe { msg_send![self, newSharedEventWithHandle: handle] }
}
fn new_binary_archive_with_descriptor(
&self,
descriptor: &MTLBinaryArchiveDescriptor,
) -> Result<Retained<ProtocolObject<dyn MTLBinaryArchive>>, MetalError> {
unsafe { msg_send![self, newBinaryArchiveWithDescriptor: descriptor, error: _] }
.map_err(MetalError::from_nserror)
}
fn new_io_command_queue_with_descriptor(
&self,
descriptor: &MTLIOCommandQueueDescriptor,
) -> Result<Retained<ProtocolObject<dyn MTLIOCommandQueue>>, MetalError> {
unsafe { msg_send![self, newIOCommandQueueWithDescriptor: descriptor, error: _] }
.map_err(MetalError::from_nserror)
}
fn new_dynamic_library(
&self,
library: &ProtocolObject<dyn MTLLibrary>,
) -> Result<Retained<ProtocolObject<dyn MTLDynamicLibrary>>, MetalError> {
unsafe { msg_send![self, newDynamicLibrary: library, error: _] }.map_err(MetalError::from_nserror)
}
fn new_dynamic_library_with_path(
&self,
path: &Path,
) -> Result<Retained<ProtocolObject<dyn MTLDynamicLibrary>>, MetalError> {
let url = file_url(path, "newDynamicLibraryWithURL:error:")?;
unsafe { msg_send![self, newDynamicLibraryWithURL: &*url, error: _] }.map_err(MetalError::from_nserror)
}
fn new_acceleration_structure_with_size(
&self,
size: usize,
) -> Option<Retained<ProtocolObject<dyn MTLAccelerationStructure>>> {
unsafe { msg_send![self, newAccelerationStructureWithSize: size] }
}
fn new_acceleration_structure_with_descriptor(
&self,
descriptor: &MTLAccelerationStructureDescriptor,
) -> Option<Retained<ProtocolObject<dyn MTLAccelerationStructure>>> {
unsafe { msg_send![self, newAccelerationStructureWithDescriptor: descriptor] }
}
fn new_residency_set_with_descriptor(
&self,
descriptor: &MTLResidencySetDescriptor,
) -> Result<Retained<ProtocolObject<dyn MTLResidencySet>>, MetalError> {
unsafe { msg_send![self, newResidencySetWithDescriptor: descriptor, error: _] }
.map_err(MetalError::from_nserror)
}
fn tensor_size_and_align_with_descriptor(
&self,
descriptor: &MTLTensorDescriptor,
) -> MTLSizeAndAlign {
unsafe { msg_send![self, tensorSizeAndAlignWithDescriptor: descriptor] }
}
fn new_tensor_with_descriptor(
&self,
descriptor: &MTLTensorDescriptor,
) -> Result<Retained<ProtocolObject<dyn MTLTensor>>, MetalError> {
unsafe { msg_send![self, newTensorWithDescriptor: descriptor, error: _] }.map_err(MetalError::from_nserror)
}
fn new_tensor_with_descriptor_attachments(
&self,
descriptor: &MTLTensorDescriptor,
attachments: &MTLTensorBufferAttachments,
) -> Result<Retained<ProtocolObject<dyn MTLTensor>>, MetalError> {
unsafe { msg_send![self, newTensorWithDescriptor: descriptor, attachments: attachments, error: _] }
.map_err(MetalError::from_nserror)
}
fn function_handle_with_function(
&self,
function: &ProtocolObject<dyn MTLFunction>,
) -> Option<Retained<ProtocolObject<dyn MTLFunctionHandle>>> {
unsafe { msg_send![self, functionHandleWithFunction: function] }
}
fn new_command_allocator(&self) -> Option<Retained<ProtocolObject<dyn crate::MTL4CommandAllocator>>> {
unsafe { msg_send![self, newCommandAllocator] }
}
fn new_command_allocator_with_descriptor(
&self,
descriptor: &MTL4CommandAllocatorDescriptor,
) -> Result<Retained<ProtocolObject<dyn crate::MTL4CommandAllocator>>, MetalError> {
unsafe { msg_send![self, newCommandAllocatorWithDescriptor: descriptor, error: _] }
.map_err(MetalError::from_nserror)
}
fn new_mtl4_command_queue(&self) -> Option<Retained<ProtocolObject<dyn crate::MTL4CommandQueue>>> {
unsafe { msg_send![self, newMTL4CommandQueue] }
}
fn new_mtl4_command_queue_with_descriptor(
&self,
descriptor: &MTL4CommandQueueDescriptor,
) -> Result<Retained<ProtocolObject<dyn crate::MTL4CommandQueue>>, MetalError> {
unsafe { msg_send![self, newMTL4CommandQueueWithDescriptor: descriptor, error: _] }
.map_err(MetalError::from_nserror)
}
fn new_mtl4_command_buffer(&self) -> Option<Retained<ProtocolObject<dyn crate::MTL4CommandBuffer>>> {
unsafe { msg_send![self, newCommandBuffer] }
}
fn new_argument_table_with_descriptor(
&self,
descriptor: &MTL4ArgumentTableDescriptor,
) -> Result<Retained<ProtocolObject<dyn MTL4ArgumentTable>>, MetalError> {
unsafe { msg_send![self, newArgumentTableWithDescriptor: descriptor, error: _] }
.map_err(MetalError::from_nserror)
}
fn new_texture_view_pool_with_descriptor(
&self,
descriptor: &MTLResourceViewPoolDescriptor,
) -> Result<Retained<ProtocolObject<dyn MTLTextureViewPool>>, MetalError> {
unsafe { msg_send![self, newTextureViewPoolWithDescriptor: descriptor, error: _] }
.map_err(MetalError::from_nserror)
}
fn new_compiler_with_descriptor(
&self,
descriptor: &MTL4CompilerDescriptor,
) -> Result<Retained<ProtocolObject<dyn crate::MTL4Compiler>>, MetalError> {
unsafe { msg_send![self, newCompilerWithDescriptor: descriptor, error: _] }.map_err(MetalError::from_nserror)
}
fn new_archive_with_path(
&self,
path: &Path,
) -> Result<Retained<ProtocolObject<dyn MTL4Archive>>, MetalError> {
let url = file_url(path, "newArchiveWithURL:error:")?;
unsafe { msg_send![self, newArchiveWithURL: &*url, error: _] }.map_err(MetalError::from_nserror)
}
fn new_pipeline_data_set_serializer_with_descriptor(
&self,
descriptor: &MTL4PipelineDataSetSerializerDescriptor,
) -> Retained<ProtocolObject<dyn MTL4PipelineDataSetSerializer>> {
unsafe { msg_send![self, newPipelineDataSetSerializerWithDescriptor: descriptor] }
}
fn new_buffer_with_length_options_placement_sparse_page_size(
&self,
length: usize,
options: MTLResourceOptions,
placement_sparse_page_size: MTLSparsePageSize,
) -> Option<Retained<ProtocolObject<dyn MTLBuffer>>> {
unsafe {
msg_send![
self,
newBufferWithLength: length,
options: options,
placementSparsePageSize: placement_sparse_page_size
]
}
}
fn new_counter_heap_with_descriptor(
&self,
descriptor: &MTL4CounterHeapDescriptor,
) -> Result<Retained<ProtocolObject<dyn MTL4CounterHeap>>, MetalError> {
unsafe { msg_send![self, newCounterHeapWithDescriptor: descriptor, error: _] }.map_err(MetalError::from_nserror)
}
fn size_of_counter_heap_entry(
&self,
counter_heap_type: MTL4CounterHeapType,
) -> usize {
unsafe { msg_send![self, sizeOfCounterHeapEntry: counter_heap_type] }
}
fn query_timestamp_frequency(&self) -> u64 {
unsafe { msg_send![self, queryTimestampFrequency] }
}
fn function_handle_with_binary_function(
&self,
function: &ProtocolObject<dyn MTL4BinaryFunction>,
) -> Option<Retained<ProtocolObject<dyn MTLFunctionHandle>>> {
unsafe { msg_send![self, functionHandleWithBinaryFunction: function] }
}
fn default_sample_positions(
&self,
sample_count: usize,
) -> Box<[MTLSamplePosition]> {
let mut positions: Box<[MTLSamplePosition]> = vec![
MTLSamplePosition {
x: 0.0,
y: 0.0
};
sample_count
]
.into_boxed_slice();
unsafe {
let _: () = msg_send![
self,
getDefaultSamplePositions: positions.as_mut_ptr(),
count: sample_count
];
}
positions
}
fn get_default_sample_positions(
&self,
positions: &mut [MTLSamplePosition],
) {
let count = positions.len();
unsafe {
let _: () = msg_send![
self,
getDefaultSamplePositions: positions.as_mut_ptr(),
count: count
];
}
}
fn convert_sparse_pixel_regions_to_tile_regions(
&self,
pixel_regions: &[MTLRegion],
tile_regions: &mut [MTLRegion],
tile_size: MTLSize,
alignment_mode: MTLSparseTextureRegionAlignmentMode,
) {
assert_eq!(pixel_regions.len(), tile_regions.len());
unsafe {
let _: () = msg_send![
self,
convertSparsePixelRegions: pixel_regions.as_ptr(),
toTileRegions: tile_regions.as_mut_ptr(),
withTileSize: tile_size,
alignmentMode: alignment_mode,
numRegions: pixel_regions.len()
];
}
}
fn convert_sparse_tile_regions_to_pixel_regions(
&self,
tile_regions: &[MTLRegion],
pixel_regions: &mut [MTLRegion],
tile_size: MTLSize,
) {
assert_eq!(tile_regions.len(), pixel_regions.len());
unsafe {
let _: () = msg_send![
self,
convertSparseTileRegions: tile_regions.as_ptr(),
toPixelRegions: pixel_regions.as_mut_ptr(),
withTileSize: tile_size,
numRegions: tile_regions.len()
];
}
}
fn new_io_file_handle_with_url(
&self,
path: &Path,
) -> Result<Retained<ProtocolObject<dyn MTLIOFileHandle>>, MetalError> {
let url = file_url(path, "newIOFileHandleWithURL:error:")?;
unsafe { msg_send![self, newIOFileHandleWithURL: &*url, error: _] }.map_err(MetalError::from_nserror)
}
fn new_io_file_handle_with_url_compression_method(
&self,
path: &Path,
compression_method: MTLIOCompressionMethod,
) -> Result<Retained<ProtocolObject<dyn MTLIOFileHandle>>, MetalError> {
let url = file_url(path, "newIOFileHandleWithURL:compressionMethod:error:")?;
unsafe {
msg_send![
self,
newIOFileHandleWithURL: &*url,
compressionMethod: compression_method,
error: _
]
}
.map_err(MetalError::from_nserror)
}
fn new_render_pipeline_state_with_descriptor_options(
&self,
descriptor: &MTLRenderPipelineDescriptor,
options: MTLPipelineOption,
) -> Result<
(Retained<ProtocolObject<dyn MTLRenderPipelineState>>, Option<Retained<MTLRenderPipelineReflection>>),
MetalError,
> {
let mut reflection: *mut MTLRenderPipelineReflection = std::ptr::null_mut();
let mut error: *mut NSError = std::ptr::null_mut();
let result: Option<Retained<ProtocolObject<dyn MTLRenderPipelineState>>> = unsafe {
msg_send![
self,
newRenderPipelineStateWithDescriptor: descriptor,
options: options,
reflection: &mut reflection,
error: &mut error
]
};
let pipeline = unsafe {
MetalError::result_from_nullable(
result,
error,
"newRenderPipelineStateWithDescriptor:options:reflection:error:",
)?
};
Ok((pipeline, unsafe { Retained::retain(reflection) }))
}
fn new_compute_pipeline_state_with_function_options(
&self,
function: &ProtocolObject<dyn MTLFunction>,
options: MTLPipelineOption,
) -> Result<
(Retained<ProtocolObject<dyn MTLComputePipelineState>>, Option<Retained<MTLComputePipelineReflection>>),
MetalError,
> {
let mut reflection: *mut MTLComputePipelineReflection = std::ptr::null_mut();
let mut error: *mut NSError = std::ptr::null_mut();
let result: Option<Retained<ProtocolObject<dyn MTLComputePipelineState>>> = unsafe {
msg_send![
self,
newComputePipelineStateWithFunction: function,
options: options,
reflection: &mut reflection,
error: &mut error
]
};
let pipeline = unsafe {
MetalError::result_from_nullable(
result,
error,
"newComputePipelineStateWithFunction:options:reflection:error:",
)?
};
Ok((pipeline, unsafe { Retained::retain(reflection) }))
}
fn new_render_pipeline_state_with_tile_descriptor(
&self,
descriptor: &MTLTileRenderPipelineDescriptor,
options: MTLPipelineOption,
) -> Result<
(Retained<ProtocolObject<dyn MTLRenderPipelineState>>, Option<Retained<MTLRenderPipelineReflection>>),
MetalError,
> {
let mut reflection: *mut MTLRenderPipelineReflection = std::ptr::null_mut();
let mut error: *mut NSError = std::ptr::null_mut();
let result: Option<Retained<ProtocolObject<dyn MTLRenderPipelineState>>> = unsafe {
msg_send![
self,
newRenderPipelineStateWithTileDescriptor: descriptor,
options: options,
reflection: &mut reflection,
error: &mut error
]
};
let pipeline = unsafe {
MetalError::result_from_nullable(
result,
error,
"newRenderPipelineStateWithTileDescriptor:options:reflection:error:",
)?
};
Ok((pipeline, unsafe { Retained::retain(reflection) }))
}
fn new_render_pipeline_state_with_descriptor_completion_handler(
&self,
descriptor: &MTLRenderPipelineDescriptor,
completion_handler: MTLNewRenderPipelineStateCompletionHandler,
) {
unsafe {
let _: () = msg_send![
self,
newRenderPipelineStateWithDescriptor: descriptor,
completionHandler: completion_handler.as_block()
];
}
}
fn new_render_pipeline_state_with_descriptor_options_completion_handler(
&self,
descriptor: &MTLRenderPipelineDescriptor,
options: MTLPipelineOption,
completion_handler: MTLNewRenderPipelineStateWithReflectionCompletionHandler,
) {
unsafe {
let _: () = msg_send![
self,
newRenderPipelineStateWithDescriptor: descriptor,
options: options,
completionHandler: completion_handler.as_block()
];
}
}
fn new_render_pipeline_state_with_tile_descriptor_options_completion_handler(
&self,
descriptor: &MTLTileRenderPipelineDescriptor,
options: MTLPipelineOption,
completion_handler: MTLNewRenderPipelineStateWithReflectionCompletionHandler,
) {
unsafe {
let _: () = msg_send![
self,
newRenderPipelineStateWithTileDescriptor: descriptor,
options: options,
completionHandler: completion_handler.as_block()
];
}
}
fn new_render_pipeline_state_with_mesh_descriptor_options_completion_handler(
&self,
descriptor: &MTLMeshRenderPipelineDescriptor,
options: MTLPipelineOption,
completion_handler: MTLNewRenderPipelineStateWithReflectionCompletionHandler,
) {
unsafe {
let _: () = msg_send![
self,
newRenderPipelineStateWithMeshDescriptor: descriptor,
options: options,
completionHandler: completion_handler.as_block()
];
}
}
fn new_library_with_source_completion_handler(
&self,
source: &str,
options: Option<&MTLCompileOptions>,
completion_handler: NewLibraryCompletionHandler,
) {
let source = NSString::from_str(source);
unsafe {
let _: () = msg_send![
self,
newLibraryWithSource: &*source,
options: options,
completionHandler: completion_handler.as_block()
];
}
}
fn new_library_with_stitched_descriptor_completion_handler(
&self,
descriptor: &MTLStitchedLibraryDescriptor,
completion_handler: NewLibraryCompletionHandler,
) {
unsafe {
let _: () = msg_send![
self,
newLibraryWithStitchedDescriptor: descriptor,
completionHandler: completion_handler.as_block()
];
}
}
fn new_compute_pipeline_state_with_function_completion_handler(
&self,
function: &ProtocolObject<dyn MTLFunction>,
completion_handler: NewComputePipelineStateCompletionHandler,
) {
unsafe {
let _: () = msg_send![
self,
newComputePipelineStateWithFunction: function,
completionHandler: completion_handler.as_block()
];
}
}
fn new_compute_pipeline_state_with_function_options_completion_handler(
&self,
function: &ProtocolObject<dyn MTLFunction>,
options: MTLPipelineOption,
completion_handler: NewComputePipelineStateWithReflectionCompletionHandler,
) {
unsafe {
let _: () = msg_send![
self,
newComputePipelineStateWithFunction: function,
options: options,
completionHandler: completion_handler.as_block()
];
}
}
fn new_compute_pipeline_state_with_descriptor_options_completion_handler(
&self,
descriptor: &MTLComputePipelineDescriptor,
options: MTLPipelineOption,
completion_handler: NewComputePipelineStateWithReflectionCompletionHandler,
) {
unsafe {
let _: () = msg_send![
self,
newComputePipelineStateWithDescriptor: descriptor,
options: options,
completionHandler: completion_handler.as_block()
];
}
}
}
impl dyn MTLDevice {
pub fn all() -> Box<[Retained<ProtocolObject<dyn MTLDevice>>]> {
unsafe extern "C" {
fn MTLCopyAllDevices() -> *mut NSArray<ProtocolObject<dyn MTLDevice>>;
}
let devices =
unsafe { Retained::from_raw(MTLCopyAllDevices()).expect("MTLCopyAllDevices returned a null array") };
devices.to_vec().into_boxed_slice()
}
#[inline]
pub fn system_default() -> Option<Retained<ProtocolObject<dyn MTLDevice>>> {
unsafe extern "C" {
fn MTLCreateSystemDefaultDevice() -> *mut ProtocolObject<dyn MTLDevice>;
}
let ret = unsafe { MTLCreateSystemDefaultDevice() };
unsafe { Retained::from_raw(ret) }
}
}
#[cfg(test)]
mod tests {
use objc2::runtime::ProtocolObject;
use super::{MTLDevice, MTLTimestamp};
use crate::MTLGPUFamily;
fn assert_send_sync<T: ?Sized + Send + Sync>() {}
#[test]
fn public_device_contract_matches_the_header() {
assert_send_sync::<ProtocolObject<dyn MTLDevice>>();
let _: fn(&ProtocolObject<dyn MTLDevice>, MTLGPUFamily) -> bool =
<ProtocolObject<dyn MTLDevice> as MTLDevice>::supports_family;
let _: fn(&ProtocolObject<dyn MTLDevice>, &mut MTLTimestamp, &mut MTLTimestamp) =
<ProtocolObject<dyn MTLDevice> as MTLDevice>::sample_timestamps_gpu_timestamp;
assert_eq!(size_of::<MTLTimestamp>(), size_of::<u64>());
}
}