Skip to main content

mtl_gpu/mtl4/
render_pipeline.rs

1//! MTL4 RenderPipeline implementation.
2//!
3//! Corresponds to `Metal/MTL4RenderPipeline.hpp`.
4
5use std::ffi::c_void;
6use std::ptr::NonNull;
7
8use mtl_foundation::{Referencing, UInteger};
9use mtl_sys::{msg_send_0, msg_send_1, msg_send_2, sel};
10
11use super::enums::{
12    AlphaToCoverageState, AlphaToOneState, BlendState, IndirectCommandBufferSupportState,
13    LogicalToPhysicalColorAttachmentMappingState,
14};
15use super::{FunctionDescriptor, PipelineOptions, StaticLinkingDescriptor};
16use crate::{BlendFactor, BlendOperation, ColorWriteMask, PixelFormat, PrimitiveTopologyClass};
17
18// ============================================================
19// RenderPipelineColorAttachmentDescriptor
20// ============================================================
21
22/// Descriptor for a render pipeline color attachment.
23///
24/// C++ equivalent: `MTL4::RenderPipelineColorAttachmentDescriptor`
25#[repr(transparent)]
26pub struct RenderPipelineColorAttachmentDescriptor(NonNull<c_void>);
27
28impl RenderPipelineColorAttachmentDescriptor {
29    /// Create a RenderPipelineColorAttachmentDescriptor from a raw pointer.
30    #[inline]
31    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
32        NonNull::new(ptr).map(Self)
33    }
34
35    /// Get the raw pointer.
36    #[inline]
37    pub fn as_raw(&self) -> *mut c_void {
38        self.0.as_ptr()
39    }
40
41    /// Create a new color attachment descriptor.
42    pub fn new() -> Option<Self> {
43        unsafe {
44            let class = mtl_sys::Class::get("MTL4RenderPipelineColorAttachmentDescriptor")?;
45            let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(alloc));
46            if ptr.is_null() {
47                return None;
48            }
49            let ptr: *mut c_void = msg_send_0(ptr, sel!(init));
50            Self::from_raw(ptr)
51        }
52    }
53
54    /// Get the pixel format.
55    ///
56    /// C++ equivalent: `MTL::PixelFormat pixelFormat() const`
57    pub fn pixel_format(&self) -> PixelFormat {
58        unsafe { msg_send_0(self.as_ptr(), sel!(pixelFormat)) }
59    }
60
61    /// Set the pixel format.
62    ///
63    /// C++ equivalent: `void setPixelFormat(MTL::PixelFormat)`
64    pub fn set_pixel_format(&self, format: PixelFormat) {
65        unsafe {
66            let _: () = msg_send_1(self.as_ptr(), sel!(setPixelFormat:), format);
67        }
68    }
69
70    /// Get the blending state.
71    ///
72    /// C++ equivalent: `BlendState blendingState() const`
73    pub fn blending_state(&self) -> BlendState {
74        unsafe { msg_send_0(self.as_ptr(), sel!(blendingState)) }
75    }
76
77    /// Set the blending state.
78    ///
79    /// C++ equivalent: `void setBlendingState(MTL4::BlendState)`
80    pub fn set_blending_state(&self, state: BlendState) {
81        unsafe {
82            let _: () = msg_send_1(self.as_ptr(), sel!(setBlendingState:), state);
83        }
84    }
85
86    /// Get the source RGB blend factor.
87    ///
88    /// C++ equivalent: `MTL::BlendFactor sourceRGBBlendFactor() const`
89    pub fn source_rgb_blend_factor(&self) -> BlendFactor {
90        unsafe { msg_send_0(self.as_ptr(), sel!(sourceRGBBlendFactor)) }
91    }
92
93    /// Set the source RGB blend factor.
94    ///
95    /// C++ equivalent: `void setSourceRGBBlendFactor(MTL::BlendFactor)`
96    pub fn set_source_rgb_blend_factor(&self, factor: BlendFactor) {
97        unsafe {
98            let _: () = msg_send_1(self.as_ptr(), sel!(setSourceRGBBlendFactor:), factor);
99        }
100    }
101
102    /// Get the destination RGB blend factor.
103    ///
104    /// C++ equivalent: `MTL::BlendFactor destinationRGBBlendFactor() const`
105    pub fn destination_rgb_blend_factor(&self) -> BlendFactor {
106        unsafe { msg_send_0(self.as_ptr(), sel!(destinationRGBBlendFactor)) }
107    }
108
109    /// Set the destination RGB blend factor.
110    ///
111    /// C++ equivalent: `void setDestinationRGBBlendFactor(MTL::BlendFactor)`
112    pub fn set_destination_rgb_blend_factor(&self, factor: BlendFactor) {
113        unsafe {
114            let _: () = msg_send_1(self.as_ptr(), sel!(setDestinationRGBBlendFactor:), factor);
115        }
116    }
117
118    /// Get the RGB blend operation.
119    ///
120    /// C++ equivalent: `MTL::BlendOperation rgbBlendOperation() const`
121    pub fn rgb_blend_operation(&self) -> BlendOperation {
122        unsafe { msg_send_0(self.as_ptr(), sel!(rgbBlendOperation)) }
123    }
124
125    /// Set the RGB blend operation.
126    ///
127    /// C++ equivalent: `void setRgbBlendOperation(MTL::BlendOperation)`
128    pub fn set_rgb_blend_operation(&self, operation: BlendOperation) {
129        unsafe {
130            let _: () = msg_send_1(self.as_ptr(), sel!(setRgbBlendOperation:), operation);
131        }
132    }
133
134    /// Get the source alpha blend factor.
135    ///
136    /// C++ equivalent: `MTL::BlendFactor sourceAlphaBlendFactor() const`
137    pub fn source_alpha_blend_factor(&self) -> BlendFactor {
138        unsafe { msg_send_0(self.as_ptr(), sel!(sourceAlphaBlendFactor)) }
139    }
140
141    /// Set the source alpha blend factor.
142    ///
143    /// C++ equivalent: `void setSourceAlphaBlendFactor(MTL::BlendFactor)`
144    pub fn set_source_alpha_blend_factor(&self, factor: BlendFactor) {
145        unsafe {
146            let _: () = msg_send_1(self.as_ptr(), sel!(setSourceAlphaBlendFactor:), factor);
147        }
148    }
149
150    /// Get the destination alpha blend factor.
151    ///
152    /// C++ equivalent: `MTL::BlendFactor destinationAlphaBlendFactor() const`
153    pub fn destination_alpha_blend_factor(&self) -> BlendFactor {
154        unsafe { msg_send_0(self.as_ptr(), sel!(destinationAlphaBlendFactor)) }
155    }
156
157    /// Set the destination alpha blend factor.
158    ///
159    /// C++ equivalent: `void setDestinationAlphaBlendFactor(MTL::BlendFactor)`
160    pub fn set_destination_alpha_blend_factor(&self, factor: BlendFactor) {
161        unsafe {
162            let _: () = msg_send_1(self.as_ptr(), sel!(setDestinationAlphaBlendFactor:), factor);
163        }
164    }
165
166    /// Get the alpha blend operation.
167    ///
168    /// C++ equivalent: `MTL::BlendOperation alphaBlendOperation() const`
169    pub fn alpha_blend_operation(&self) -> BlendOperation {
170        unsafe { msg_send_0(self.as_ptr(), sel!(alphaBlendOperation)) }
171    }
172
173    /// Set the alpha blend operation.
174    ///
175    /// C++ equivalent: `void setAlphaBlendOperation(MTL::BlendOperation)`
176    pub fn set_alpha_blend_operation(&self, operation: BlendOperation) {
177        unsafe {
178            let _: () = msg_send_1(self.as_ptr(), sel!(setAlphaBlendOperation:), operation);
179        }
180    }
181
182    /// Get the write mask.
183    ///
184    /// C++ equivalent: `MTL::ColorWriteMask writeMask() const`
185    pub fn write_mask(&self) -> ColorWriteMask {
186        unsafe { msg_send_0(self.as_ptr(), sel!(writeMask)) }
187    }
188
189    /// Set the write mask.
190    ///
191    /// C++ equivalent: `void setWriteMask(MTL::ColorWriteMask)`
192    pub fn set_write_mask(&self, mask: ColorWriteMask) {
193        unsafe {
194            let _: () = msg_send_1(self.as_ptr(), sel!(setWriteMask:), mask);
195        }
196    }
197
198    /// Reset the descriptor to its default state.
199    ///
200    /// C++ equivalent: `void reset()`
201    pub fn reset(&self) {
202        unsafe {
203            let _: () = msg_send_0(self.as_ptr(), sel!(reset));
204        }
205    }
206}
207
208impl Clone for RenderPipelineColorAttachmentDescriptor {
209    fn clone(&self) -> Self {
210        unsafe {
211            mtl_sys::msg_send_0::<*mut c_void>(self.as_ptr(), mtl_sys::sel!(retain));
212        }
213        Self(self.0)
214    }
215}
216
217impl Drop for RenderPipelineColorAttachmentDescriptor {
218    fn drop(&mut self) {
219        unsafe {
220            mtl_sys::msg_send_0::<()>(self.as_ptr(), mtl_sys::sel!(release));
221        }
222    }
223}
224
225impl Referencing for RenderPipelineColorAttachmentDescriptor {
226    #[inline]
227    fn as_ptr(&self) -> *const c_void {
228        self.0.as_ptr()
229    }
230}
231
232unsafe impl Send for RenderPipelineColorAttachmentDescriptor {}
233unsafe impl Sync for RenderPipelineColorAttachmentDescriptor {}
234
235// ============================================================
236// RenderPipelineColorAttachmentDescriptorArray
237// ============================================================
238
239/// Array of render pipeline color attachment descriptors.
240///
241/// C++ equivalent: `MTL4::RenderPipelineColorAttachmentDescriptorArray`
242#[repr(transparent)]
243pub struct RenderPipelineColorAttachmentDescriptorArray(NonNull<c_void>);
244
245impl RenderPipelineColorAttachmentDescriptorArray {
246    /// Create a RenderPipelineColorAttachmentDescriptorArray from a raw pointer.
247    #[inline]
248    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
249        NonNull::new(ptr).map(Self)
250    }
251
252    /// Get the raw pointer.
253    #[inline]
254    pub fn as_raw(&self) -> *mut c_void {
255        self.0.as_ptr()
256    }
257
258    /// Create a new color attachment descriptor array.
259    pub fn new() -> Option<Self> {
260        unsafe {
261            let class = mtl_sys::Class::get("MTL4RenderPipelineColorAttachmentDescriptorArray")?;
262            let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(alloc));
263            if ptr.is_null() {
264                return None;
265            }
266            let ptr: *mut c_void = msg_send_0(ptr, sel!(init));
267            Self::from_raw(ptr)
268        }
269    }
270
271    /// Get the color attachment descriptor at the given index.
272    ///
273    /// C++ equivalent: `RenderPipelineColorAttachmentDescriptor* object(NS::UInteger)`
274    pub fn object(&self, index: UInteger) -> Option<RenderPipelineColorAttachmentDescriptor> {
275        unsafe {
276            let ptr: *mut c_void =
277                msg_send_1(self.as_ptr(), sel!(objectAtIndexedSubscript:), index);
278            RenderPipelineColorAttachmentDescriptor::from_raw(ptr)
279        }
280    }
281
282    /// Set the color attachment descriptor at the given index.
283    ///
284    /// C++ equivalent: `void setObject(const RenderPipelineColorAttachmentDescriptor*, NS::UInteger)`
285    pub fn set_object(
286        &self,
287        attachment: &RenderPipelineColorAttachmentDescriptor,
288        index: UInteger,
289    ) {
290        unsafe {
291            let _: () = msg_send_2(
292                self.as_ptr(),
293                sel!(setObject:atIndexedSubscript:),
294                attachment.as_ptr(),
295                index,
296            );
297        }
298    }
299
300    /// Reset the array to its default state.
301    ///
302    /// C++ equivalent: `void reset()`
303    pub fn reset(&self) {
304        unsafe {
305            let _: () = msg_send_0(self.as_ptr(), sel!(reset));
306        }
307    }
308}
309
310impl Clone for RenderPipelineColorAttachmentDescriptorArray {
311    fn clone(&self) -> Self {
312        unsafe {
313            mtl_sys::msg_send_0::<*mut c_void>(self.as_ptr(), mtl_sys::sel!(retain));
314        }
315        Self(self.0)
316    }
317}
318
319impl Drop for RenderPipelineColorAttachmentDescriptorArray {
320    fn drop(&mut self) {
321        unsafe {
322            mtl_sys::msg_send_0::<()>(self.as_ptr(), mtl_sys::sel!(release));
323        }
324    }
325}
326
327impl Referencing for RenderPipelineColorAttachmentDescriptorArray {
328    #[inline]
329    fn as_ptr(&self) -> *const c_void {
330        self.0.as_ptr()
331    }
332}
333
334unsafe impl Send for RenderPipelineColorAttachmentDescriptorArray {}
335unsafe impl Sync for RenderPipelineColorAttachmentDescriptorArray {}
336
337// ============================================================
338// RenderPipelineBinaryFunctionsDescriptor
339// ============================================================
340
341/// Descriptor for render pipeline binary functions.
342///
343/// C++ equivalent: `MTL4::RenderPipelineBinaryFunctionsDescriptor`
344#[repr(transparent)]
345pub struct RenderPipelineBinaryFunctionsDescriptor(NonNull<c_void>);
346
347impl RenderPipelineBinaryFunctionsDescriptor {
348    /// Create a RenderPipelineBinaryFunctionsDescriptor from a raw pointer.
349    #[inline]
350    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
351        NonNull::new(ptr).map(Self)
352    }
353
354    /// Get the raw pointer.
355    #[inline]
356    pub fn as_raw(&self) -> *mut c_void {
357        self.0.as_ptr()
358    }
359
360    /// Create a new binary functions descriptor.
361    pub fn new() -> Option<Self> {
362        unsafe {
363            let class = mtl_sys::Class::get("MTL4RenderPipelineBinaryFunctionsDescriptor")?;
364            let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(alloc));
365            if ptr.is_null() {
366                return None;
367            }
368            let ptr: *mut c_void = msg_send_0(ptr, sel!(init));
369            Self::from_raw(ptr)
370        }
371    }
372
373    /// Get the vertex additional binary functions (as raw pointer to NSArray).
374    pub fn vertex_additional_binary_functions_raw(&self) -> *mut c_void {
375        unsafe { msg_send_0(self.as_ptr(), sel!(vertexAdditionalBinaryFunctions)) }
376    }
377
378    /// Set the vertex additional binary functions (from raw pointer to NSArray).
379    pub fn set_vertex_additional_binary_functions_raw(&self, functions: *const c_void) {
380        unsafe {
381            let _: () = msg_send_1(
382                self.as_ptr(),
383                sel!(setVertexAdditionalBinaryFunctions:),
384                functions,
385            );
386        }
387    }
388
389    /// Get the fragment additional binary functions (as raw pointer to NSArray).
390    pub fn fragment_additional_binary_functions_raw(&self) -> *mut c_void {
391        unsafe { msg_send_0(self.as_ptr(), sel!(fragmentAdditionalBinaryFunctions)) }
392    }
393
394    /// Set the fragment additional binary functions (from raw pointer to NSArray).
395    pub fn set_fragment_additional_binary_functions_raw(&self, functions: *const c_void) {
396        unsafe {
397            let _: () = msg_send_1(
398                self.as_ptr(),
399                sel!(setFragmentAdditionalBinaryFunctions:),
400                functions,
401            );
402        }
403    }
404
405    /// Get the tile additional binary functions (as raw pointer to NSArray).
406    pub fn tile_additional_binary_functions_raw(&self) -> *mut c_void {
407        unsafe { msg_send_0(self.as_ptr(), sel!(tileAdditionalBinaryFunctions)) }
408    }
409
410    /// Set the tile additional binary functions (from raw pointer to NSArray).
411    pub fn set_tile_additional_binary_functions_raw(&self, functions: *const c_void) {
412        unsafe {
413            let _: () = msg_send_1(
414                self.as_ptr(),
415                sel!(setTileAdditionalBinaryFunctions:),
416                functions,
417            );
418        }
419    }
420
421    /// Get the object additional binary functions (as raw pointer to NSArray).
422    pub fn object_additional_binary_functions_raw(&self) -> *mut c_void {
423        unsafe { msg_send_0(self.as_ptr(), sel!(objectAdditionalBinaryFunctions)) }
424    }
425
426    /// Set the object additional binary functions (from raw pointer to NSArray).
427    pub fn set_object_additional_binary_functions_raw(&self, functions: *const c_void) {
428        unsafe {
429            let _: () = msg_send_1(
430                self.as_ptr(),
431                sel!(setObjectAdditionalBinaryFunctions:),
432                functions,
433            );
434        }
435    }
436
437    /// Get the mesh additional binary functions (as raw pointer to NSArray).
438    pub fn mesh_additional_binary_functions_raw(&self) -> *mut c_void {
439        unsafe { msg_send_0(self.as_ptr(), sel!(meshAdditionalBinaryFunctions)) }
440    }
441
442    /// Set the mesh additional binary functions (from raw pointer to NSArray).
443    pub fn set_mesh_additional_binary_functions_raw(&self, functions: *const c_void) {
444        unsafe {
445            let _: () = msg_send_1(
446                self.as_ptr(),
447                sel!(setMeshAdditionalBinaryFunctions:),
448                functions,
449            );
450        }
451    }
452
453    /// Reset the descriptor to its default state.
454    pub fn reset(&self) {
455        unsafe {
456            let _: () = msg_send_0(self.as_ptr(), sel!(reset));
457        }
458    }
459}
460
461impl Clone for RenderPipelineBinaryFunctionsDescriptor {
462    fn clone(&self) -> Self {
463        unsafe {
464            mtl_sys::msg_send_0::<*mut c_void>(self.as_ptr(), mtl_sys::sel!(retain));
465        }
466        Self(self.0)
467    }
468}
469
470impl Drop for RenderPipelineBinaryFunctionsDescriptor {
471    fn drop(&mut self) {
472        unsafe {
473            mtl_sys::msg_send_0::<()>(self.as_ptr(), mtl_sys::sel!(release));
474        }
475    }
476}
477
478impl Referencing for RenderPipelineBinaryFunctionsDescriptor {
479    #[inline]
480    fn as_ptr(&self) -> *const c_void {
481        self.0.as_ptr()
482    }
483}
484
485unsafe impl Send for RenderPipelineBinaryFunctionsDescriptor {}
486unsafe impl Sync for RenderPipelineBinaryFunctionsDescriptor {}
487
488// ============================================================
489// RenderPipelineDescriptor
490// ============================================================
491
492/// Descriptor for MTL4 render pipelines.
493///
494/// C++ equivalent: `MTL4::RenderPipelineDescriptor`
495#[repr(transparent)]
496pub struct RenderPipelineDescriptor(NonNull<c_void>);
497
498impl RenderPipelineDescriptor {
499    /// Create a RenderPipelineDescriptor from a raw pointer.
500    #[inline]
501    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
502        NonNull::new(ptr).map(Self)
503    }
504
505    /// Get the raw pointer.
506    #[inline]
507    pub fn as_raw(&self) -> *mut c_void {
508        self.0.as_ptr()
509    }
510
511    /// Create a new render pipeline descriptor.
512    pub fn new() -> Option<Self> {
513        unsafe {
514            let class = mtl_sys::Class::get("MTL4RenderPipelineDescriptor")?;
515            let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(alloc));
516            if ptr.is_null() {
517                return None;
518            }
519            let ptr: *mut c_void = msg_send_0(ptr, sel!(init));
520            Self::from_raw(ptr)
521        }
522    }
523
524    // ========== Base Pipeline Properties ==========
525
526    /// Get the label.
527    pub fn label(&self) -> Option<String> {
528        unsafe {
529            let ns_string: *mut c_void = msg_send_0(self.as_ptr(), sel!(label));
530            if ns_string.is_null() {
531                return None;
532            }
533            let c_str: *const i8 = msg_send_0(ns_string, sel!(UTF8String));
534            if c_str.is_null() {
535                return None;
536            }
537            Some(
538                std::ffi::CStr::from_ptr(c_str)
539                    .to_string_lossy()
540                    .into_owned(),
541            )
542        }
543    }
544
545    /// Set the label.
546    pub fn set_label(&self, label: &str) {
547        if let Some(ns_label) = mtl_foundation::String::from_str(label) {
548            unsafe {
549                let _: () = msg_send_1(self.as_ptr(), sel!(setLabel:), ns_label.as_ptr());
550            }
551        }
552    }
553
554    /// Get the pipeline options.
555    pub fn options(&self) -> Option<PipelineOptions> {
556        unsafe {
557            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(options));
558            PipelineOptions::from_raw(ptr)
559        }
560    }
561
562    /// Set the pipeline options.
563    pub fn set_options(&self, options: &PipelineOptions) {
564        unsafe {
565            let _: () = msg_send_1(self.as_ptr(), sel!(setOptions:), options.as_ptr());
566        }
567    }
568
569    // ========== Vertex Function ==========
570
571    /// Get the vertex function descriptor.
572    pub fn vertex_function_descriptor(&self) -> Option<FunctionDescriptor> {
573        unsafe {
574            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(vertexFunctionDescriptor));
575            FunctionDescriptor::from_raw(ptr)
576        }
577    }
578
579    /// Set the vertex function descriptor.
580    pub fn set_vertex_function_descriptor(&self, descriptor: &FunctionDescriptor) {
581        unsafe {
582            let _: () = msg_send_1(
583                self.as_ptr(),
584                sel!(setVertexFunctionDescriptor:),
585                descriptor.as_ptr(),
586            );
587        }
588    }
589
590    /// Get the vertex static linking descriptor.
591    pub fn vertex_static_linking_descriptor(&self) -> Option<StaticLinkingDescriptor> {
592        unsafe {
593            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(vertexStaticLinkingDescriptor));
594            StaticLinkingDescriptor::from_raw(ptr)
595        }
596    }
597
598    /// Set the vertex static linking descriptor.
599    pub fn set_vertex_static_linking_descriptor(&self, descriptor: &StaticLinkingDescriptor) {
600        unsafe {
601            let _: () = msg_send_1(
602                self.as_ptr(),
603                sel!(setVertexStaticLinkingDescriptor:),
604                descriptor.as_ptr(),
605            );
606        }
607    }
608
609    // ========== Fragment Function ==========
610
611    /// Get the fragment function descriptor.
612    pub fn fragment_function_descriptor(&self) -> Option<FunctionDescriptor> {
613        unsafe {
614            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(fragmentFunctionDescriptor));
615            FunctionDescriptor::from_raw(ptr)
616        }
617    }
618
619    /// Set the fragment function descriptor.
620    pub fn set_fragment_function_descriptor(&self, descriptor: &FunctionDescriptor) {
621        unsafe {
622            let _: () = msg_send_1(
623                self.as_ptr(),
624                sel!(setFragmentFunctionDescriptor:),
625                descriptor.as_ptr(),
626            );
627        }
628    }
629
630    /// Get the fragment static linking descriptor.
631    pub fn fragment_static_linking_descriptor(&self) -> Option<StaticLinkingDescriptor> {
632        unsafe {
633            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(fragmentStaticLinkingDescriptor));
634            StaticLinkingDescriptor::from_raw(ptr)
635        }
636    }
637
638    /// Set the fragment static linking descriptor.
639    pub fn set_fragment_static_linking_descriptor(&self, descriptor: &StaticLinkingDescriptor) {
640        unsafe {
641            let _: () = msg_send_1(
642                self.as_ptr(),
643                sel!(setFragmentStaticLinkingDescriptor:),
644                descriptor.as_ptr(),
645            );
646        }
647    }
648
649    // ========== Color Attachments ==========
650
651    /// Get the color attachments array.
652    pub fn color_attachments(&self) -> Option<RenderPipelineColorAttachmentDescriptorArray> {
653        unsafe {
654            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(colorAttachments));
655            RenderPipelineColorAttachmentDescriptorArray::from_raw(ptr)
656        }
657    }
658
659    /// Get the color attachment mapping state.
660    pub fn color_attachment_mapping_state(&self) -> LogicalToPhysicalColorAttachmentMappingState {
661        unsafe { msg_send_0(self.as_ptr(), sel!(colorAttachmentMappingState)) }
662    }
663
664    /// Set the color attachment mapping state.
665    pub fn set_color_attachment_mapping_state(
666        &self,
667        state: LogicalToPhysicalColorAttachmentMappingState,
668    ) {
669        unsafe {
670            let _: () = msg_send_1(self.as_ptr(), sel!(setColorAttachmentMappingState:), state);
671        }
672    }
673
674    // ========== Rasterization ==========
675
676    /// Get whether rasterization is enabled.
677    pub fn is_rasterization_enabled(&self) -> bool {
678        unsafe { msg_send_0(self.as_ptr(), sel!(isRasterizationEnabled)) }
679    }
680
681    /// Set whether rasterization is enabled.
682    pub fn set_rasterization_enabled(&self, enabled: bool) {
683        unsafe {
684            let _: () = msg_send_1(self.as_ptr(), sel!(setRasterizationEnabled:), enabled);
685        }
686    }
687
688    /// Get the raster sample count.
689    pub fn raster_sample_count(&self) -> UInteger {
690        unsafe { msg_send_0(self.as_ptr(), sel!(rasterSampleCount)) }
691    }
692
693    /// Set the raster sample count.
694    pub fn set_raster_sample_count(&self, count: UInteger) {
695        unsafe {
696            let _: () = msg_send_1(self.as_ptr(), sel!(setRasterSampleCount:), count);
697        }
698    }
699
700    // ========== Alpha ==========
701
702    /// Get the alpha to coverage state.
703    pub fn alpha_to_coverage_state(&self) -> AlphaToCoverageState {
704        unsafe { msg_send_0(self.as_ptr(), sel!(alphaToCoverageState)) }
705    }
706
707    /// Set the alpha to coverage state.
708    pub fn set_alpha_to_coverage_state(&self, state: AlphaToCoverageState) {
709        unsafe {
710            let _: () = msg_send_1(self.as_ptr(), sel!(setAlphaToCoverageState:), state);
711        }
712    }
713
714    /// Get the alpha to one state.
715    pub fn alpha_to_one_state(&self) -> AlphaToOneState {
716        unsafe { msg_send_0(self.as_ptr(), sel!(alphaToOneState)) }
717    }
718
719    /// Set the alpha to one state.
720    pub fn set_alpha_to_one_state(&self, state: AlphaToOneState) {
721        unsafe {
722            let _: () = msg_send_1(self.as_ptr(), sel!(setAlphaToOneState:), state);
723        }
724    }
725
726    // ========== Vertex Descriptor ==========
727
728    /// Get the vertex descriptor (as raw pointer).
729    pub fn vertex_descriptor_raw(&self) -> *mut c_void {
730        unsafe { msg_send_0(self.as_ptr(), sel!(vertexDescriptor)) }
731    }
732
733    /// Set the vertex descriptor (from raw pointer).
734    pub fn set_vertex_descriptor_raw(&self, descriptor: *const c_void) {
735        unsafe {
736            let _: () = msg_send_1(self.as_ptr(), sel!(setVertexDescriptor:), descriptor);
737        }
738    }
739
740    // ========== Primitive Topology ==========
741
742    /// Get the input primitive topology.
743    pub fn input_primitive_topology(&self) -> PrimitiveTopologyClass {
744        unsafe { msg_send_0(self.as_ptr(), sel!(inputPrimitiveTopology)) }
745    }
746
747    /// Set the input primitive topology.
748    pub fn set_input_primitive_topology(&self, topology: PrimitiveTopologyClass) {
749        unsafe {
750            let _: () = msg_send_1(self.as_ptr(), sel!(setInputPrimitiveTopology:), topology);
751        }
752    }
753
754    // ========== Vertex Amplification ==========
755
756    /// Get the maximum vertex amplification count.
757    pub fn max_vertex_amplification_count(&self) -> UInteger {
758        unsafe { msg_send_0(self.as_ptr(), sel!(maxVertexAmplificationCount)) }
759    }
760
761    /// Set the maximum vertex amplification count.
762    pub fn set_max_vertex_amplification_count(&self, count: UInteger) {
763        unsafe {
764            let _: () = msg_send_1(self.as_ptr(), sel!(setMaxVertexAmplificationCount:), count);
765        }
766    }
767
768    // ========== Binary Linking ==========
769
770    /// Get whether vertex binary linking is supported.
771    pub fn support_vertex_binary_linking(&self) -> bool {
772        unsafe { msg_send_0(self.as_ptr(), sel!(supportVertexBinaryLinking)) }
773    }
774
775    /// Set whether vertex binary linking is supported.
776    pub fn set_support_vertex_binary_linking(&self, support: bool) {
777        unsafe {
778            let _: () = msg_send_1(self.as_ptr(), sel!(setSupportVertexBinaryLinking:), support);
779        }
780    }
781
782    /// Get whether fragment binary linking is supported.
783    pub fn support_fragment_binary_linking(&self) -> bool {
784        unsafe { msg_send_0(self.as_ptr(), sel!(supportFragmentBinaryLinking)) }
785    }
786
787    /// Set whether fragment binary linking is supported.
788    pub fn set_support_fragment_binary_linking(&self, support: bool) {
789        unsafe {
790            let _: () = msg_send_1(
791                self.as_ptr(),
792                sel!(setSupportFragmentBinaryLinking:),
793                support,
794            );
795        }
796    }
797
798    // ========== Indirect Command Buffers ==========
799
800    /// Get the indirect command buffer support state.
801    pub fn support_indirect_command_buffers(&self) -> IndirectCommandBufferSupportState {
802        unsafe { msg_send_0(self.as_ptr(), sel!(supportIndirectCommandBuffers)) }
803    }
804
805    /// Set the indirect command buffer support state.
806    pub fn set_support_indirect_command_buffers(&self, state: IndirectCommandBufferSupportState) {
807        unsafe {
808            let _: () = msg_send_1(
809                self.as_ptr(),
810                sel!(setSupportIndirectCommandBuffers:),
811                state,
812            );
813        }
814    }
815
816    /// Reset the descriptor to its default state.
817    pub fn reset(&self) {
818        unsafe {
819            let _: () = msg_send_0(self.as_ptr(), sel!(reset));
820        }
821    }
822}
823
824impl Clone for RenderPipelineDescriptor {
825    fn clone(&self) -> Self {
826        unsafe {
827            mtl_sys::msg_send_0::<*mut c_void>(self.as_ptr(), mtl_sys::sel!(retain));
828        }
829        Self(self.0)
830    }
831}
832
833impl Drop for RenderPipelineDescriptor {
834    fn drop(&mut self) {
835        unsafe {
836            mtl_sys::msg_send_0::<()>(self.as_ptr(), mtl_sys::sel!(release));
837        }
838    }
839}
840
841impl Referencing for RenderPipelineDescriptor {
842    #[inline]
843    fn as_ptr(&self) -> *const c_void {
844        self.0.as_ptr()
845    }
846}
847
848unsafe impl Send for RenderPipelineDescriptor {}
849unsafe impl Sync for RenderPipelineDescriptor {}
850
851impl std::fmt::Debug for RenderPipelineDescriptor {
852    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
853        f.debug_struct("RenderPipelineDescriptor")
854            .field("label", &self.label())
855            .field("raster_sample_count", &self.raster_sample_count())
856            .field("is_rasterization_enabled", &self.is_rasterization_enabled())
857            .finish()
858    }
859}
860
861#[cfg(test)]
862mod tests {
863    use super::*;
864
865    #[test]
866    fn test_render_pipeline_color_attachment_descriptor_size() {
867        assert_eq!(
868            std::mem::size_of::<RenderPipelineColorAttachmentDescriptor>(),
869            std::mem::size_of::<*mut c_void>()
870        );
871    }
872
873    #[test]
874    fn test_render_pipeline_color_attachment_descriptor_array_size() {
875        assert_eq!(
876            std::mem::size_of::<RenderPipelineColorAttachmentDescriptorArray>(),
877            std::mem::size_of::<*mut c_void>()
878        );
879    }
880
881    #[test]
882    fn test_render_pipeline_binary_functions_descriptor_size() {
883        assert_eq!(
884            std::mem::size_of::<RenderPipelineBinaryFunctionsDescriptor>(),
885            std::mem::size_of::<*mut c_void>()
886        );
887    }
888
889    #[test]
890    fn test_render_pipeline_descriptor_size() {
891        assert_eq!(
892            std::mem::size_of::<RenderPipelineDescriptor>(),
893            std::mem::size_of::<*mut c_void>()
894        );
895    }
896}