1use std::ffi::c_void;
4use std::ptr::NonNull;
5
6use mtl_foundation::Referencing;
7use mtl_sys::{msg_send_0, msg_send_2, msg_send_3, msg_send_4, sel};
8
9use crate::mtl4::{
10 BinaryFunction, BinaryFunctionDescriptor, CompilerTask, ComputePipelineDescriptor,
11 LibraryDescriptor, MachineLearningPipelineDescriptor, MachineLearningPipelineState,
12 PipelineDataSetSerializer, PipelineDescriptor, PipelineStageDynamicLinkingDescriptor,
13 RenderPipelineDynamicLinkingDescriptor,
14};
15use crate::{ComputePipelineState, Device, DynamicLibrary, Library, RenderPipelineState};
16
17use super::CompilerTaskOptions;
18
19fn generic_error() -> mtl_foundation::Error {
21 mtl_foundation::Error::error(std::ptr::null_mut(), -1, std::ptr::null_mut())
22 .expect("failed to create error object")
23}
24
25#[repr(transparent)]
32pub struct Compiler(NonNull<c_void>);
33
34impl Compiler {
35 #[inline]
37 pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
38 NonNull::new(ptr).map(Self)
39 }
40
41 #[inline]
43 pub fn as_raw(&self) -> *mut c_void {
44 self.0.as_ptr()
45 }
46
47 pub fn device(&self) -> Option<Device> {
51 unsafe {
52 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(device));
53 Device::from_raw(ptr)
54 }
55 }
56
57 pub fn label(&self) -> Option<String> {
61 unsafe {
62 let ns_string: *mut c_void = msg_send_0(self.as_ptr(), sel!(label));
63 if ns_string.is_null() {
64 return None;
65 }
66 let c_str: *const i8 = msg_send_0(ns_string, sel!(UTF8String));
67 if c_str.is_null() {
68 return None;
69 }
70 Some(
71 std::ffi::CStr::from_ptr(c_str)
72 .to_string_lossy()
73 .into_owned(),
74 )
75 }
76 }
77
78 pub fn pipeline_data_set_serializer(&self) -> Option<PipelineDataSetSerializer> {
82 unsafe {
83 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(pipelineDataSetSerializer));
84 PipelineDataSetSerializer::from_raw(ptr)
85 }
86 }
87
88 pub fn new_library(
94 &self,
95 descriptor: &LibraryDescriptor,
96 ) -> Result<Library, mtl_foundation::Error> {
97 unsafe {
98 let mut error: *mut c_void = std::ptr::null_mut();
99 let ptr: *mut c_void = msg_send_2(
100 self.as_ptr(),
101 sel!(newLibraryWithDescriptor:error:),
102 descriptor.as_ptr(),
103 &mut error as *mut _,
104 );
105 if !error.is_null() {
106 if let Some(err) = mtl_foundation::Error::from_ptr(error) {
107 return Err(err);
108 }
109 }
110 Library::from_raw(ptr).ok_or_else(|| generic_error())
111 }
112 }
113
114 pub fn new_binary_function(
120 &self,
121 descriptor: &BinaryFunctionDescriptor,
122 options: Option<&CompilerTaskOptions>,
123 ) -> Result<BinaryFunction, mtl_foundation::Error> {
124 unsafe {
125 let mut error: *mut c_void = std::ptr::null_mut();
126 let options_ptr = options.map_or(std::ptr::null(), |o| o.as_ptr());
127 let ptr: *mut c_void = msg_send_3(
128 self.as_ptr(),
129 sel!(newBinaryFunctionWithDescriptor:compilerTaskOptions:error:),
130 descriptor.as_ptr(),
131 options_ptr,
132 &mut error as *mut _,
133 );
134 if !error.is_null() {
135 if let Some(err) = mtl_foundation::Error::from_ptr(error) {
136 return Err(err);
137 }
138 }
139 BinaryFunction::from_raw(ptr).ok_or_else(|| generic_error())
140 }
141 }
142
143 pub fn new_compute_pipeline_state(
149 &self,
150 descriptor: &ComputePipelineDescriptor,
151 options: Option<&CompilerTaskOptions>,
152 ) -> Result<ComputePipelineState, mtl_foundation::Error> {
153 unsafe {
154 let mut error: *mut c_void = std::ptr::null_mut();
155 let options_ptr = options.map_or(std::ptr::null(), |o| o.as_ptr());
156 let ptr: *mut c_void = msg_send_3(
157 self.as_ptr(),
158 sel!(newComputePipelineStateWithDescriptor:compilerTaskOptions:error:),
159 descriptor.as_ptr(),
160 options_ptr,
161 &mut error as *mut _,
162 );
163 if !error.is_null() {
164 if let Some(err) = mtl_foundation::Error::from_ptr(error) {
165 return Err(err);
166 }
167 }
168 ComputePipelineState::from_raw(ptr).ok_or_else(|| generic_error())
169 }
170 }
171
172 pub fn new_compute_pipeline_state_with_dynamic_linking(
176 &self,
177 descriptor: &ComputePipelineDescriptor,
178 dynamic_linking: &PipelineStageDynamicLinkingDescriptor,
179 options: Option<&CompilerTaskOptions>,
180 ) -> Result<ComputePipelineState, mtl_foundation::Error> {
181 unsafe {
182 let mut error: *mut c_void = std::ptr::null_mut();
183 let options_ptr = options.map_or(std::ptr::null(), |o| o.as_ptr());
184 let ptr: *mut c_void = msg_send_4(
185 self.as_ptr(),
186 sel!(newComputePipelineStateWithDescriptor:dynamicLinkingDescriptor:compilerTaskOptions:error:),
187 descriptor.as_ptr(),
188 dynamic_linking.as_ptr(),
189 options_ptr,
190 &mut error as *mut _,
191 );
192 if !error.is_null() {
193 if let Some(err) = mtl_foundation::Error::from_ptr(error) {
194 return Err(err);
195 }
196 }
197 ComputePipelineState::from_raw(ptr).ok_or_else(|| generic_error())
198 }
199 }
200
201 pub fn new_render_pipeline_state(
207 &self,
208 descriptor: &PipelineDescriptor,
209 options: Option<&CompilerTaskOptions>,
210 ) -> Result<RenderPipelineState, mtl_foundation::Error> {
211 unsafe {
212 let mut error: *mut c_void = std::ptr::null_mut();
213 let options_ptr = options.map_or(std::ptr::null(), |o| o.as_ptr());
214 let ptr: *mut c_void = msg_send_3(
215 self.as_ptr(),
216 sel!(newRenderPipelineStateWithDescriptor:compilerTaskOptions:error:),
217 descriptor.as_ptr(),
218 options_ptr,
219 &mut error as *mut _,
220 );
221 if !error.is_null() {
222 if let Some(err) = mtl_foundation::Error::from_ptr(error) {
223 return Err(err);
224 }
225 }
226 RenderPipelineState::from_raw(ptr).ok_or_else(|| generic_error())
227 }
228 }
229
230 pub fn new_render_pipeline_state_with_dynamic_linking(
234 &self,
235 descriptor: &PipelineDescriptor,
236 dynamic_linking: &RenderPipelineDynamicLinkingDescriptor,
237 options: Option<&CompilerTaskOptions>,
238 ) -> Result<RenderPipelineState, mtl_foundation::Error> {
239 unsafe {
240 let mut error: *mut c_void = std::ptr::null_mut();
241 let options_ptr = options.map_or(std::ptr::null(), |o| o.as_ptr());
242 let ptr: *mut c_void = msg_send_4(
243 self.as_ptr(),
244 sel!(newRenderPipelineStateWithDescriptor:dynamicLinkingDescriptor:compilerTaskOptions:error:),
245 descriptor.as_ptr(),
246 dynamic_linking.as_ptr(),
247 options_ptr,
248 &mut error as *mut _,
249 );
250 if !error.is_null() {
251 if let Some(err) = mtl_foundation::Error::from_ptr(error) {
252 return Err(err);
253 }
254 }
255 RenderPipelineState::from_raw(ptr).ok_or_else(|| generic_error())
256 }
257 }
258
259 pub fn new_render_pipeline_state_by_specialization(
263 &self,
264 descriptor: &PipelineDescriptor,
265 pipeline: &RenderPipelineState,
266 ) -> Result<RenderPipelineState, mtl_foundation::Error> {
267 unsafe {
268 let mut error: *mut c_void = std::ptr::null_mut();
269 let ptr: *mut c_void = msg_send_3(
270 self.as_ptr(),
271 sel!(newRenderPipelineStateBySpecializationWithDescriptor:pipeline:error:),
272 descriptor.as_ptr(),
273 pipeline.as_ptr(),
274 &mut error as *mut _,
275 );
276 if !error.is_null() {
277 if let Some(err) = mtl_foundation::Error::from_ptr(error) {
278 return Err(err);
279 }
280 }
281 RenderPipelineState::from_raw(ptr).ok_or_else(|| generic_error())
282 }
283 }
284
285 pub fn new_dynamic_library_from_library(
291 &self,
292 library: &Library,
293 ) -> Result<*mut c_void, mtl_foundation::Error> {
294 unsafe {
295 let mut error: *mut c_void = std::ptr::null_mut();
296 let ptr: *mut c_void = msg_send_2(
297 self.as_ptr(),
298 sel!(newDynamicLibrary:error:),
299 library.as_ptr(),
300 &mut error as *mut _,
301 );
302 if !error.is_null() {
303 if let Some(err) = mtl_foundation::Error::from_ptr(error) {
304 return Err(err);
305 }
306 }
307 if ptr.is_null() {
308 return Err(generic_error());
309 }
310 Ok(ptr)
311 }
312 }
313
314 pub fn new_dynamic_library_from_url(
318 &self,
319 url: *const c_void,
320 ) -> Result<*mut c_void, mtl_foundation::Error> {
321 unsafe {
322 let mut error: *mut c_void = std::ptr::null_mut();
323 let ptr: *mut c_void = msg_send_2(
324 self.as_ptr(),
325 sel!(newDynamicLibraryWithURL:error:),
326 url,
327 &mut error as *mut _,
328 );
329 if !error.is_null() {
330 if let Some(err) = mtl_foundation::Error::from_ptr(error) {
331 return Err(err);
332 }
333 }
334 if ptr.is_null() {
335 return Err(generic_error());
336 }
337 Ok(ptr)
338 }
339 }
340
341 pub fn new_library_async<F>(
347 &self,
348 descriptor: &LibraryDescriptor,
349 completion_handler: F,
350 ) -> Option<CompilerTask>
351 where
352 F: Fn(Option<Library>, Option<mtl_foundation::Error>) + Send + 'static,
353 {
354 let block =
355 mtl_sys::TwoArgBlock::from_fn(move |lib_ptr: *mut c_void, err_ptr: *mut c_void| {
356 let library = if lib_ptr.is_null() {
357 None
358 } else {
359 unsafe { Library::from_raw(lib_ptr) }
360 };
361
362 let error = if err_ptr.is_null() {
363 None
364 } else {
365 unsafe { mtl_foundation::Error::from_ptr(err_ptr) }
366 };
367
368 completion_handler(library, error);
369 });
370
371 unsafe {
372 let ptr: *mut c_void = msg_send_2(
373 self.as_ptr(),
374 sel!(newLibraryWithDescriptor:completionHandler:),
375 descriptor.as_ptr(),
376 block.as_ptr(),
377 );
378
379 std::mem::forget(block);
380 CompilerTask::from_raw(ptr)
381 }
382 }
383
384 pub fn new_binary_function_async<F>(
390 &self,
391 descriptor: &BinaryFunctionDescriptor,
392 options: Option<&CompilerTaskOptions>,
393 completion_handler: F,
394 ) -> Option<CompilerTask>
395 where
396 F: Fn(Option<BinaryFunction>, Option<mtl_foundation::Error>) + Send + 'static,
397 {
398 let block =
399 mtl_sys::TwoArgBlock::from_fn(move |fn_ptr: *mut c_void, err_ptr: *mut c_void| {
400 let function = if fn_ptr.is_null() {
401 None
402 } else {
403 unsafe { BinaryFunction::from_raw(fn_ptr) }
404 };
405
406 let error = if err_ptr.is_null() {
407 None
408 } else {
409 unsafe { mtl_foundation::Error::from_ptr(err_ptr) }
410 };
411
412 completion_handler(function, error);
413 });
414
415 let options_ptr = options.map_or(std::ptr::null(), |o| o.as_ptr());
416
417 unsafe {
418 let ptr: *mut c_void = msg_send_3(
419 self.as_ptr(),
420 sel!(newBinaryFunctionWithDescriptor:compilerTaskOptions:completionHandler:),
421 descriptor.as_ptr(),
422 options_ptr,
423 block.as_ptr(),
424 );
425
426 std::mem::forget(block);
427 CompilerTask::from_raw(ptr)
428 }
429 }
430
431 pub fn new_compute_pipeline_state_async<F>(
437 &self,
438 descriptor: &ComputePipelineDescriptor,
439 options: Option<&CompilerTaskOptions>,
440 completion_handler: F,
441 ) -> Option<CompilerTask>
442 where
443 F: Fn(Option<ComputePipelineState>, Option<mtl_foundation::Error>) + Send + 'static,
444 {
445 let block =
446 mtl_sys::TwoArgBlock::from_fn(move |state_ptr: *mut c_void, err_ptr: *mut c_void| {
447 let state = if state_ptr.is_null() {
448 None
449 } else {
450 unsafe { ComputePipelineState::from_raw(state_ptr) }
451 };
452
453 let error = if err_ptr.is_null() {
454 None
455 } else {
456 unsafe { mtl_foundation::Error::from_ptr(err_ptr) }
457 };
458
459 completion_handler(state, error);
460 });
461
462 let options_ptr = options.map_or(std::ptr::null(), |o| o.as_ptr());
463
464 unsafe {
465 let ptr: *mut c_void = msg_send_3(
466 self.as_ptr(),
467 sel!(newComputePipelineStateWithDescriptor:compilerTaskOptions:completionHandler:),
468 descriptor.as_ptr(),
469 options_ptr,
470 block.as_ptr(),
471 );
472
473 std::mem::forget(block);
474 CompilerTask::from_raw(ptr)
475 }
476 }
477
478 pub fn new_render_pipeline_state_async<F>(
484 &self,
485 descriptor: &PipelineDescriptor,
486 options: Option<&CompilerTaskOptions>,
487 completion_handler: F,
488 ) -> Option<CompilerTask>
489 where
490 F: Fn(Option<RenderPipelineState>, Option<mtl_foundation::Error>) + Send + 'static,
491 {
492 let block =
493 mtl_sys::TwoArgBlock::from_fn(move |state_ptr: *mut c_void, err_ptr: *mut c_void| {
494 let state = if state_ptr.is_null() {
495 None
496 } else {
497 unsafe { RenderPipelineState::from_raw(state_ptr) }
498 };
499
500 let error = if err_ptr.is_null() {
501 None
502 } else {
503 unsafe { mtl_foundation::Error::from_ptr(err_ptr) }
504 };
505
506 completion_handler(state, error);
507 });
508
509 let options_ptr = options.map_or(std::ptr::null(), |o| o.as_ptr());
510
511 unsafe {
512 let ptr: *mut c_void = msg_send_3(
513 self.as_ptr(),
514 sel!(newRenderPipelineStateWithDescriptor:compilerTaskOptions:completionHandler:),
515 descriptor.as_ptr(),
516 options_ptr,
517 block.as_ptr(),
518 );
519
520 std::mem::forget(block);
521 CompilerTask::from_raw(ptr)
522 }
523 }
524
525 pub fn new_render_pipeline_state_by_specialization_async<F>(
529 &self,
530 descriptor: &PipelineDescriptor,
531 pipeline: &RenderPipelineState,
532 completion_handler: F,
533 ) -> Option<CompilerTask>
534 where
535 F: Fn(Option<RenderPipelineState>, Option<mtl_foundation::Error>) + Send + 'static,
536 {
537 let block =
538 mtl_sys::TwoArgBlock::from_fn(move |state_ptr: *mut c_void, err_ptr: *mut c_void| {
539 let state = if state_ptr.is_null() {
540 None
541 } else {
542 unsafe { RenderPipelineState::from_raw(state_ptr) }
543 };
544
545 let error = if err_ptr.is_null() {
546 None
547 } else {
548 unsafe { mtl_foundation::Error::from_ptr(err_ptr) }
549 };
550
551 completion_handler(state, error);
552 });
553
554 unsafe {
555 let ptr: *mut c_void = msg_send_3(
556 self.as_ptr(),
557 sel!(newRenderPipelineStateBySpecializationWithDescriptor:pipeline:completionHandler:),
558 descriptor.as_ptr(),
559 pipeline.as_ptr(),
560 block.as_ptr(),
561 );
562
563 std::mem::forget(block);
564 CompilerTask::from_raw(ptr)
565 }
566 }
567
568 pub fn new_dynamic_library_from_library_async<F>(
574 &self,
575 library: &Library,
576 completion_handler: F,
577 ) -> Option<CompilerTask>
578 where
579 F: Fn(Option<DynamicLibrary>, Option<mtl_foundation::Error>) + Send + 'static,
580 {
581 let block =
582 mtl_sys::TwoArgBlock::from_fn(move |lib_ptr: *mut c_void, err_ptr: *mut c_void| {
583 let dynamic_lib = if lib_ptr.is_null() {
584 None
585 } else {
586 unsafe { DynamicLibrary::from_raw(lib_ptr) }
587 };
588
589 let error = if err_ptr.is_null() {
590 None
591 } else {
592 unsafe { mtl_foundation::Error::from_ptr(err_ptr) }
593 };
594
595 completion_handler(dynamic_lib, error);
596 });
597
598 unsafe {
599 let ptr: *mut c_void = msg_send_2(
600 self.as_ptr(),
601 sel!(newDynamicLibrary:completionHandler:),
602 library.as_ptr(),
603 block.as_ptr(),
604 );
605
606 std::mem::forget(block);
607 CompilerTask::from_raw(ptr)
608 }
609 }
610
611 pub unsafe fn new_dynamic_library_from_url_async<F>(
619 &self,
620 url: *const c_void,
621 completion_handler: F,
622 ) -> Option<CompilerTask>
623 where
624 F: Fn(Option<DynamicLibrary>, Option<mtl_foundation::Error>) + Send + 'static,
625 {
626 let block =
627 mtl_sys::TwoArgBlock::from_fn(move |lib_ptr: *mut c_void, err_ptr: *mut c_void| {
628 let dynamic_lib = if lib_ptr.is_null() {
629 None
630 } else {
631 unsafe { DynamicLibrary::from_raw(lib_ptr) }
632 };
633
634 let error = if err_ptr.is_null() {
635 None
636 } else {
637 unsafe { mtl_foundation::Error::from_ptr(err_ptr) }
638 };
639
640 completion_handler(dynamic_lib, error);
641 });
642
643 unsafe {
644 let ptr: *mut c_void = msg_send_2(
645 self.as_ptr(),
646 sel!(newDynamicLibraryWithURL:completionHandler:),
647 url,
648 block.as_ptr(),
649 );
650
651 std::mem::forget(block);
652 CompilerTask::from_raw(ptr)
653 }
654 }
655
656 pub fn new_compute_pipeline_state_with_dynamic_linking_async<F>(
662 &self,
663 descriptor: &ComputePipelineDescriptor,
664 dynamic_linking: &PipelineStageDynamicLinkingDescriptor,
665 options: Option<&CompilerTaskOptions>,
666 completion_handler: F,
667 ) -> Option<CompilerTask>
668 where
669 F: Fn(Option<ComputePipelineState>, Option<mtl_foundation::Error>) + Send + 'static,
670 {
671 let block =
672 mtl_sys::TwoArgBlock::from_fn(move |state_ptr: *mut c_void, err_ptr: *mut c_void| {
673 let state = if state_ptr.is_null() {
674 None
675 } else {
676 unsafe { ComputePipelineState::from_raw(state_ptr) }
677 };
678
679 let error = if err_ptr.is_null() {
680 None
681 } else {
682 unsafe { mtl_foundation::Error::from_ptr(err_ptr) }
683 };
684
685 completion_handler(state, error);
686 });
687
688 let options_ptr = options.map_or(std::ptr::null(), |o| o.as_ptr());
689
690 unsafe {
691 let ptr: *mut c_void = msg_send_4(
692 self.as_ptr(),
693 sel!(newComputePipelineStateWithDescriptor:dynamicLinkingDescriptor:compilerTaskOptions:completionHandler:),
694 descriptor.as_ptr(),
695 dynamic_linking.as_ptr(),
696 options_ptr,
697 block.as_ptr(),
698 );
699
700 std::mem::forget(block);
701 CompilerTask::from_raw(ptr)
702 }
703 }
704
705 pub fn new_render_pipeline_state_with_dynamic_linking_async<F>(
709 &self,
710 descriptor: &PipelineDescriptor,
711 dynamic_linking: &RenderPipelineDynamicLinkingDescriptor,
712 options: Option<&CompilerTaskOptions>,
713 completion_handler: F,
714 ) -> Option<CompilerTask>
715 where
716 F: Fn(Option<RenderPipelineState>, Option<mtl_foundation::Error>) + Send + 'static,
717 {
718 let block =
719 mtl_sys::TwoArgBlock::from_fn(move |state_ptr: *mut c_void, err_ptr: *mut c_void| {
720 let state = if state_ptr.is_null() {
721 None
722 } else {
723 unsafe { RenderPipelineState::from_raw(state_ptr) }
724 };
725
726 let error = if err_ptr.is_null() {
727 None
728 } else {
729 unsafe { mtl_foundation::Error::from_ptr(err_ptr) }
730 };
731
732 completion_handler(state, error);
733 });
734
735 let options_ptr = options.map_or(std::ptr::null(), |o| o.as_ptr());
736
737 unsafe {
738 let ptr: *mut c_void = msg_send_4(
739 self.as_ptr(),
740 sel!(newRenderPipelineStateWithDescriptor:dynamicLinkingDescriptor:compilerTaskOptions:completionHandler:),
741 descriptor.as_ptr(),
742 dynamic_linking.as_ptr(),
743 options_ptr,
744 block.as_ptr(),
745 );
746
747 std::mem::forget(block);
748 CompilerTask::from_raw(ptr)
749 }
750 }
751
752 pub fn new_machine_learning_pipeline_state(
758 &self,
759 descriptor: &MachineLearningPipelineDescriptor,
760 options: Option<&CompilerTaskOptions>,
761 ) -> Result<MachineLearningPipelineState, mtl_foundation::Error> {
762 unsafe {
763 let mut error: *mut c_void = std::ptr::null_mut();
764 let options_ptr = options.map_or(std::ptr::null(), |o| o.as_ptr());
765 let ptr: *mut c_void = msg_send_3(
766 self.as_ptr(),
767 sel!(newMachineLearningPipelineStateWithDescriptor:compilerTaskOptions:error:),
768 descriptor.as_ptr(),
769 options_ptr,
770 &mut error as *mut _,
771 );
772 if !error.is_null() {
773 if let Some(err) = mtl_foundation::Error::from_ptr(error) {
774 return Err(err);
775 }
776 }
777 MachineLearningPipelineState::from_raw(ptr).ok_or_else(generic_error)
778 }
779 }
780
781 pub fn new_machine_learning_pipeline_state_async<F>(
785 &self,
786 descriptor: &MachineLearningPipelineDescriptor,
787 options: Option<&CompilerTaskOptions>,
788 completion_handler: F,
789 ) -> Option<CompilerTask>
790 where
791 F: Fn(Option<MachineLearningPipelineState>, Option<mtl_foundation::Error>)
792 + Send
793 + 'static,
794 {
795 let block =
796 mtl_sys::TwoArgBlock::from_fn(move |state_ptr: *mut c_void, err_ptr: *mut c_void| {
797 let state = if state_ptr.is_null() {
798 None
799 } else {
800 unsafe { MachineLearningPipelineState::from_raw(state_ptr) }
801 };
802
803 let error = if err_ptr.is_null() {
804 None
805 } else {
806 unsafe { mtl_foundation::Error::from_ptr(err_ptr) }
807 };
808
809 completion_handler(state, error);
810 });
811
812 let options_ptr = options.map_or(std::ptr::null(), |o| o.as_ptr());
813
814 unsafe {
815 let ptr: *mut c_void = msg_send_3(
816 self.as_ptr(),
817 sel!(newMachineLearningPipelineStateWithDescriptor:compilerTaskOptions:completionHandler:),
818 descriptor.as_ptr(),
819 options_ptr,
820 block.as_ptr(),
821 );
822
823 std::mem::forget(block);
824 CompilerTask::from_raw(ptr)
825 }
826 }
827}
828
829impl Clone for Compiler {
830 fn clone(&self) -> Self {
831 unsafe {
832 mtl_sys::msg_send_0::<*mut c_void>(self.as_ptr(), mtl_sys::sel!(retain));
833 }
834 Self(self.0)
835 }
836}
837
838impl Drop for Compiler {
839 fn drop(&mut self) {
840 unsafe {
841 mtl_sys::msg_send_0::<()>(self.as_ptr(), mtl_sys::sel!(release));
842 }
843 }
844}
845
846impl Referencing for Compiler {
847 #[inline]
848 fn as_ptr(&self) -> *const c_void {
849 self.0.as_ptr()
850 }
851}
852
853unsafe impl Send for Compiler {}
854unsafe impl Sync for Compiler {}
855
856impl std::fmt::Debug for Compiler {
857 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
858 f.debug_struct("Compiler")
859 .field("label", &self.label())
860 .finish()
861 }
862}