Skip to main content

mtl_gpu/pipeline/
render_descriptor.rs

1//! Render pipeline descriptor.
2//!
3//! Corresponds to `MTL::RenderPipelineDescriptor`.
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, sel};
10
11use crate::enums::{
12    PixelFormat, PrimitiveTopologyClass, ShaderValidation, TessellationControlPointIndexType,
13    TessellationFactorFormat, TessellationFactorStepFunction, TessellationPartitionMode, Winding,
14};
15
16use super::{PipelineBufferDescriptorArray, RenderPipelineColorAttachmentDescriptorArray};
17
18pub struct RenderPipelineDescriptor(pub(crate) NonNull<c_void>);
19
20impl RenderPipelineDescriptor {
21    /// Allocate a new render pipeline descriptor.
22    ///
23    /// C++ equivalent: `static RenderPipelineDescriptor* alloc()`
24    pub fn alloc() -> Option<Self> {
25        unsafe {
26            let class = mtl_sys::class!(MTLRenderPipelineDescriptor);
27            let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(alloc));
28            Self::from_raw(ptr)
29        }
30    }
31
32    /// Initialize the descriptor.
33    ///
34    /// C++ equivalent: `RenderPipelineDescriptor* init()`
35    pub fn init(self) -> Option<Self> {
36        unsafe {
37            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(init));
38            // init consumes ownership - we must not release the old pointer
39            // because ObjC init either returns the same pointer (still valid)
40            // or releases the old and returns a new one
41            std::mem::forget(self);
42            Self::from_raw(ptr)
43        }
44    }
45
46    /// Create a new render pipeline descriptor.
47    pub fn new() -> Option<Self> {
48        Self::alloc().and_then(|d| d.init())
49    }
50
51    /// Create from a raw pointer.
52    ///
53    /// # Safety
54    ///
55    /// The pointer must be a valid render pipeline descriptor object.
56    #[inline]
57    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
58        NonNull::new(ptr).map(Self)
59    }
60
61    /// Get the raw pointer.
62    #[inline]
63    pub fn as_raw(&self) -> *mut c_void {
64        self.0.as_ptr()
65    }
66
67    /// Reset the descriptor to default values.
68    ///
69    /// C++ equivalent: `void reset()`
70    #[inline]
71    pub fn reset(&self) {
72        unsafe {
73            msg_send_0::<()>(self.as_ptr(), sel!(reset));
74        }
75    }
76
77    // =========================================================================
78    // Basic Properties
79    // =========================================================================
80
81    /// Get the label.
82    ///
83    /// C++ equivalent: `NS::String* label() const`
84    pub fn label(&self) -> Option<String> {
85        unsafe {
86            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(label));
87            if ptr.is_null() {
88                return None;
89            }
90            let utf8_ptr: *const std::ffi::c_char =
91                mtl_sys::msg_send_0(ptr as *const c_void, sel!(UTF8String));
92            if utf8_ptr.is_null() {
93                return None;
94            }
95            let c_str = std::ffi::CStr::from_ptr(utf8_ptr);
96            Some(c_str.to_string_lossy().into_owned())
97        }
98    }
99
100    /// Set the label.
101    ///
102    /// C++ equivalent: `void setLabel(const NS::String* label)`
103    pub fn set_label(&self, label: &str) {
104        if let Some(ns_label) = mtl_foundation::String::from_str(label) {
105            unsafe {
106                msg_send_1::<(), *const c_void>(self.as_ptr(), sel!(setLabel:), ns_label.as_ptr());
107            }
108        }
109    }
110
111    // =========================================================================
112    // Shader Functions
113    // =========================================================================
114
115    /// Get the vertex function.
116    ///
117    /// C++ equivalent: `Function* vertexFunction() const`
118    pub fn vertex_function(&self) -> Option<crate::Function> {
119        unsafe {
120            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(vertexFunction));
121            if ptr.is_null() {
122                return None;
123            }
124            let _: *mut c_void = msg_send_0(ptr, sel!(retain));
125            crate::Function::from_raw(ptr)
126        }
127    }
128
129    /// Set the vertex function.
130    ///
131    /// C++ equivalent: `void setVertexFunction(const MTL::Function* vertexFunction)`
132    pub fn set_vertex_function(&self, function: Option<&crate::Function>) {
133        unsafe {
134            let ptr = function.map_or(std::ptr::null(), |f| f.as_ptr());
135            msg_send_1::<(), *const c_void>(self.as_ptr(), sel!(setVertexFunction:), ptr);
136        }
137    }
138
139    /// Get the fragment function.
140    ///
141    /// C++ equivalent: `Function* fragmentFunction() const`
142    pub fn fragment_function(&self) -> Option<crate::Function> {
143        unsafe {
144            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(fragmentFunction));
145            if ptr.is_null() {
146                return None;
147            }
148            let _: *mut c_void = msg_send_0(ptr, sel!(retain));
149            crate::Function::from_raw(ptr)
150        }
151    }
152
153    /// Set the fragment function.
154    ///
155    /// C++ equivalent: `void setFragmentFunction(const MTL::Function* fragmentFunction)`
156    pub fn set_fragment_function(&self, function: Option<&crate::Function>) {
157        unsafe {
158            let ptr = function.map_or(std::ptr::null(), |f| f.as_ptr());
159            msg_send_1::<(), *const c_void>(self.as_ptr(), sel!(setFragmentFunction:), ptr);
160        }
161    }
162
163    // =========================================================================
164    // Color Attachments
165    // =========================================================================
166
167    /// Get the color attachments array.
168    ///
169    /// C++ equivalent: `RenderPipelineColorAttachmentDescriptorArray* colorAttachments() const`
170    pub fn color_attachments(&self) -> RenderPipelineColorAttachmentDescriptorArray {
171        unsafe {
172            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(colorAttachments));
173            RenderPipelineColorAttachmentDescriptorArray::from_raw(ptr)
174                .expect("colorAttachments returned null")
175        }
176    }
177
178    // =========================================================================
179    // Depth/Stencil Attachments
180    // =========================================================================
181
182    /// Get the depth attachment pixel format.
183    ///
184    /// C++ equivalent: `PixelFormat depthAttachmentPixelFormat() const`
185    #[inline]
186    pub fn depth_attachment_pixel_format(&self) -> PixelFormat {
187        unsafe { msg_send_0(self.as_ptr(), sel!(depthAttachmentPixelFormat)) }
188    }
189
190    /// Set the depth attachment pixel format.
191    ///
192    /// C++ equivalent: `void setDepthAttachmentPixelFormat(MTL::PixelFormat depthAttachmentPixelFormat)`
193    #[inline]
194    pub fn set_depth_attachment_pixel_format(&self, format: PixelFormat) {
195        unsafe {
196            msg_send_1::<(), PixelFormat>(
197                self.as_ptr(),
198                sel!(setDepthAttachmentPixelFormat:),
199                format,
200            );
201        }
202    }
203
204    /// Get the stencil attachment pixel format.
205    ///
206    /// C++ equivalent: `PixelFormat stencilAttachmentPixelFormat() const`
207    #[inline]
208    pub fn stencil_attachment_pixel_format(&self) -> PixelFormat {
209        unsafe { msg_send_0(self.as_ptr(), sel!(stencilAttachmentPixelFormat)) }
210    }
211
212    /// Set the stencil attachment pixel format.
213    ///
214    /// C++ equivalent: `void setStencilAttachmentPixelFormat(MTL::PixelFormat stencilAttachmentPixelFormat)`
215    #[inline]
216    pub fn set_stencil_attachment_pixel_format(&self, format: PixelFormat) {
217        unsafe {
218            msg_send_1::<(), PixelFormat>(
219                self.as_ptr(),
220                sel!(setStencilAttachmentPixelFormat:),
221                format,
222            );
223        }
224    }
225
226    // =========================================================================
227    // Rasterization
228    // =========================================================================
229
230    /// Get the raster sample count.
231    ///
232    /// C++ equivalent: `NS::UInteger rasterSampleCount() const`
233    #[inline]
234    pub fn raster_sample_count(&self) -> UInteger {
235        unsafe { msg_send_0(self.as_ptr(), sel!(rasterSampleCount)) }
236    }
237
238    /// Set the raster sample count.
239    ///
240    /// C++ equivalent: `void setRasterSampleCount(NS::UInteger rasterSampleCount)`
241    #[inline]
242    pub fn set_raster_sample_count(&self, count: UInteger) {
243        unsafe {
244            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setRasterSampleCount:), count);
245        }
246    }
247
248    /// Check if rasterization is enabled.
249    ///
250    /// C++ equivalent: `bool isRasterizationEnabled() const`
251    #[inline]
252    pub fn is_rasterization_enabled(&self) -> bool {
253        unsafe { msg_send_0(self.as_ptr(), sel!(isRasterizationEnabled)) }
254    }
255
256    /// Set rasterization enabled.
257    ///
258    /// C++ equivalent: `void setRasterizationEnabled(bool rasterizationEnabled)`
259    #[inline]
260    pub fn set_rasterization_enabled(&self, enabled: bool) {
261        unsafe {
262            msg_send_1::<(), bool>(self.as_ptr(), sel!(setRasterizationEnabled:), enabled);
263        }
264    }
265
266    /// Get the input primitive topology.
267    ///
268    /// C++ equivalent: `PrimitiveTopologyClass inputPrimitiveTopology() const`
269    #[inline]
270    pub fn input_primitive_topology(&self) -> PrimitiveTopologyClass {
271        unsafe { msg_send_0(self.as_ptr(), sel!(inputPrimitiveTopology)) }
272    }
273
274    /// Set the input primitive topology.
275    ///
276    /// C++ equivalent: `void setInputPrimitiveTopology(MTL::PrimitiveTopologyClass inputPrimitiveTopology)`
277    #[inline]
278    pub fn set_input_primitive_topology(&self, topology: PrimitiveTopologyClass) {
279        unsafe {
280            msg_send_1::<(), PrimitiveTopologyClass>(
281                self.as_ptr(),
282                sel!(setInputPrimitiveTopology:),
283                topology,
284            );
285        }
286    }
287
288    // =========================================================================
289    // Alpha Coverage
290    // =========================================================================
291
292    /// Check if alpha-to-coverage is enabled.
293    ///
294    /// C++ equivalent: `bool isAlphaToCoverageEnabled() const`
295    #[inline]
296    pub fn is_alpha_to_coverage_enabled(&self) -> bool {
297        unsafe { msg_send_0(self.as_ptr(), sel!(isAlphaToCoverageEnabled)) }
298    }
299
300    /// Set alpha-to-coverage enabled.
301    ///
302    /// C++ equivalent: `void setAlphaToCoverageEnabled(bool alphaToCoverageEnabled)`
303    #[inline]
304    pub fn set_alpha_to_coverage_enabled(&self, enabled: bool) {
305        unsafe {
306            msg_send_1::<(), bool>(self.as_ptr(), sel!(setAlphaToCoverageEnabled:), enabled);
307        }
308    }
309
310    /// Check if alpha-to-one is enabled.
311    ///
312    /// C++ equivalent: `bool isAlphaToOneEnabled() const`
313    #[inline]
314    pub fn is_alpha_to_one_enabled(&self) -> bool {
315        unsafe { msg_send_0(self.as_ptr(), sel!(isAlphaToOneEnabled)) }
316    }
317
318    /// Set alpha-to-one enabled.
319    ///
320    /// C++ equivalent: `void setAlphaToOneEnabled(bool alphaToOneEnabled)`
321    #[inline]
322    pub fn set_alpha_to_one_enabled(&self, enabled: bool) {
323        unsafe {
324            msg_send_1::<(), bool>(self.as_ptr(), sel!(setAlphaToOneEnabled:), enabled);
325        }
326    }
327
328    // =========================================================================
329    // Tessellation
330    // =========================================================================
331
332    /// Get the maximum tessellation factor.
333    ///
334    /// C++ equivalent: `NS::UInteger maxTessellationFactor() const`
335    #[inline]
336    pub fn max_tessellation_factor(&self) -> UInteger {
337        unsafe { msg_send_0(self.as_ptr(), sel!(maxTessellationFactor)) }
338    }
339
340    /// Set the maximum tessellation factor.
341    ///
342    /// C++ equivalent: `void setMaxTessellationFactor(NS::UInteger maxTessellationFactor)`
343    #[inline]
344    pub fn set_max_tessellation_factor(&self, factor: UInteger) {
345        unsafe {
346            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setMaxTessellationFactor:), factor);
347        }
348    }
349
350    /// Check if tessellation factor scale is enabled.
351    ///
352    /// C++ equivalent: `bool isTessellationFactorScaleEnabled() const`
353    #[inline]
354    pub fn is_tessellation_factor_scale_enabled(&self) -> bool {
355        unsafe { msg_send_0(self.as_ptr(), sel!(isTessellationFactorScaleEnabled)) }
356    }
357
358    /// Set tessellation factor scale enabled.
359    ///
360    /// C++ equivalent: `void setTessellationFactorScaleEnabled(bool tessellationFactorScaleEnabled)`
361    #[inline]
362    pub fn set_tessellation_factor_scale_enabled(&self, enabled: bool) {
363        unsafe {
364            msg_send_1::<(), bool>(
365                self.as_ptr(),
366                sel!(setTessellationFactorScaleEnabled:),
367                enabled,
368            );
369        }
370    }
371
372    /// Get the tessellation factor format.
373    ///
374    /// C++ equivalent: `TessellationFactorFormat tessellationFactorFormat() const`
375    #[inline]
376    pub fn tessellation_factor_format(&self) -> TessellationFactorFormat {
377        unsafe { msg_send_0(self.as_ptr(), sel!(tessellationFactorFormat)) }
378    }
379
380    /// Set the tessellation factor format.
381    ///
382    /// C++ equivalent: `void setTessellationFactorFormat(MTL::TessellationFactorFormat tessellationFactorFormat)`
383    #[inline]
384    pub fn set_tessellation_factor_format(&self, format: TessellationFactorFormat) {
385        unsafe {
386            msg_send_1::<(), TessellationFactorFormat>(
387                self.as_ptr(),
388                sel!(setTessellationFactorFormat:),
389                format,
390            );
391        }
392    }
393
394    /// Get the tessellation control point index type.
395    ///
396    /// C++ equivalent: `TessellationControlPointIndexType tessellationControlPointIndexType() const`
397    #[inline]
398    pub fn tessellation_control_point_index_type(&self) -> TessellationControlPointIndexType {
399        unsafe { msg_send_0(self.as_ptr(), sel!(tessellationControlPointIndexType)) }
400    }
401
402    /// Set the tessellation control point index type.
403    ///
404    /// C++ equivalent: `void setTessellationControlPointIndexType(MTL::TessellationControlPointIndexType tessellationControlPointIndexType)`
405    #[inline]
406    pub fn set_tessellation_control_point_index_type(
407        &self,
408        index_type: TessellationControlPointIndexType,
409    ) {
410        unsafe {
411            msg_send_1::<(), TessellationControlPointIndexType>(
412                self.as_ptr(),
413                sel!(setTessellationControlPointIndexType:),
414                index_type,
415            );
416        }
417    }
418
419    /// Get the tessellation factor step function.
420    ///
421    /// C++ equivalent: `TessellationFactorStepFunction tessellationFactorStepFunction() const`
422    #[inline]
423    pub fn tessellation_factor_step_function(&self) -> TessellationFactorStepFunction {
424        unsafe { msg_send_0(self.as_ptr(), sel!(tessellationFactorStepFunction)) }
425    }
426
427    /// Set the tessellation factor step function.
428    ///
429    /// C++ equivalent: `void setTessellationFactorStepFunction(MTL::TessellationFactorStepFunction tessellationFactorStepFunction)`
430    #[inline]
431    pub fn set_tessellation_factor_step_function(&self, func: TessellationFactorStepFunction) {
432        unsafe {
433            msg_send_1::<(), TessellationFactorStepFunction>(
434                self.as_ptr(),
435                sel!(setTessellationFactorStepFunction:),
436                func,
437            );
438        }
439    }
440
441    /// Get the tessellation output winding order.
442    ///
443    /// C++ equivalent: `Winding tessellationOutputWindingOrder() const`
444    #[inline]
445    pub fn tessellation_output_winding_order(&self) -> Winding {
446        unsafe { msg_send_0(self.as_ptr(), sel!(tessellationOutputWindingOrder)) }
447    }
448
449    /// Set the tessellation output winding order.
450    ///
451    /// C++ equivalent: `void setTessellationOutputWindingOrder(MTL::Winding tessellationOutputWindingOrder)`
452    #[inline]
453    pub fn set_tessellation_output_winding_order(&self, winding: Winding) {
454        unsafe {
455            msg_send_1::<(), Winding>(
456                self.as_ptr(),
457                sel!(setTessellationOutputWindingOrder:),
458                winding,
459            );
460        }
461    }
462
463    /// Get the tessellation partition mode.
464    ///
465    /// C++ equivalent: `TessellationPartitionMode tessellationPartitionMode() const`
466    #[inline]
467    pub fn tessellation_partition_mode(&self) -> TessellationPartitionMode {
468        unsafe { msg_send_0(self.as_ptr(), sel!(tessellationPartitionMode)) }
469    }
470
471    /// Set the tessellation partition mode.
472    ///
473    /// C++ equivalent: `void setTessellationPartitionMode(MTL::TessellationPartitionMode tessellationPartitionMode)`
474    #[inline]
475    pub fn set_tessellation_partition_mode(&self, mode: TessellationPartitionMode) {
476        unsafe {
477            msg_send_1::<(), TessellationPartitionMode>(
478                self.as_ptr(),
479                sel!(setTessellationPartitionMode:),
480                mode,
481            );
482        }
483    }
484
485    // =========================================================================
486    // Indirect Command Buffers
487    // =========================================================================
488
489    /// Check if the pipeline supports indirect command buffers.
490    ///
491    /// C++ equivalent: `bool supportIndirectCommandBuffers() const`
492    #[inline]
493    pub fn support_indirect_command_buffers(&self) -> bool {
494        unsafe { msg_send_0(self.as_ptr(), sel!(supportIndirectCommandBuffers)) }
495    }
496
497    /// Set indirect command buffer support.
498    ///
499    /// C++ equivalent: `void setSupportIndirectCommandBuffers(bool supportIndirectCommandBuffers)`
500    #[inline]
501    pub fn set_support_indirect_command_buffers(&self, support: bool) {
502        unsafe {
503            msg_send_1::<(), bool>(
504                self.as_ptr(),
505                sel!(setSupportIndirectCommandBuffers:),
506                support,
507            );
508        }
509    }
510
511    // =========================================================================
512    // Shader Validation
513    // =========================================================================
514
515    /// Get the shader validation mode.
516    ///
517    /// C++ equivalent: `ShaderValidation shaderValidation() const`
518    #[inline]
519    pub fn shader_validation(&self) -> ShaderValidation {
520        unsafe { msg_send_0(self.as_ptr(), sel!(shaderValidation)) }
521    }
522
523    /// Set the shader validation mode.
524    ///
525    /// C++ equivalent: `void setShaderValidation(MTL::ShaderValidation shaderValidation)`
526    #[inline]
527    pub fn set_shader_validation(&self, validation: ShaderValidation) {
528        unsafe {
529            msg_send_1::<(), ShaderValidation>(
530                self.as_ptr(),
531                sel!(setShaderValidation:),
532                validation,
533            );
534        }
535    }
536
537    // =========================================================================
538    // Vertex Amplification
539    // =========================================================================
540
541    /// Get the maximum vertex amplification count.
542    ///
543    /// C++ equivalent: `NS::UInteger maxVertexAmplificationCount() const`
544    #[inline]
545    pub fn max_vertex_amplification_count(&self) -> UInteger {
546        unsafe { msg_send_0(self.as_ptr(), sel!(maxVertexAmplificationCount)) }
547    }
548
549    /// Set the maximum vertex amplification count.
550    ///
551    /// C++ equivalent: `void setMaxVertexAmplificationCount(NS::UInteger maxVertexAmplificationCount)`
552    #[inline]
553    pub fn set_max_vertex_amplification_count(&self, count: UInteger) {
554        unsafe {
555            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setMaxVertexAmplificationCount:), count);
556        }
557    }
558
559    // =========================================================================
560    // Call Stack Depth
561    // =========================================================================
562
563    /// Get the maximum vertex call stack depth.
564    ///
565    /// C++ equivalent: `NS::UInteger maxVertexCallStackDepth() const`
566    #[inline]
567    pub fn max_vertex_call_stack_depth(&self) -> UInteger {
568        unsafe { msg_send_0(self.as_ptr(), sel!(maxVertexCallStackDepth)) }
569    }
570
571    /// Set the maximum vertex call stack depth.
572    ///
573    /// C++ equivalent: `void setMaxVertexCallStackDepth(NS::UInteger maxVertexCallStackDepth)`
574    #[inline]
575    pub fn set_max_vertex_call_stack_depth(&self, depth: UInteger) {
576        unsafe {
577            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setMaxVertexCallStackDepth:), depth);
578        }
579    }
580
581    /// Get the maximum fragment call stack depth.
582    ///
583    /// C++ equivalent: `NS::UInteger maxFragmentCallStackDepth() const`
584    #[inline]
585    pub fn max_fragment_call_stack_depth(&self) -> UInteger {
586        unsafe { msg_send_0(self.as_ptr(), sel!(maxFragmentCallStackDepth)) }
587    }
588
589    /// Set the maximum fragment call stack depth.
590    ///
591    /// C++ equivalent: `void setMaxFragmentCallStackDepth(NS::UInteger maxFragmentCallStackDepth)`
592    #[inline]
593    pub fn set_max_fragment_call_stack_depth(&self, depth: UInteger) {
594        unsafe {
595            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setMaxFragmentCallStackDepth:), depth);
596        }
597    }
598
599    // =========================================================================
600    // Binary Function Support
601    // =========================================================================
602
603    /// Check if support adding vertex binary functions is enabled.
604    ///
605    /// C++ equivalent: `bool supportAddingVertexBinaryFunctions() const`
606    #[inline]
607    pub fn support_adding_vertex_binary_functions(&self) -> bool {
608        unsafe { msg_send_0(self.as_ptr(), sel!(supportAddingVertexBinaryFunctions)) }
609    }
610
611    /// Set support adding vertex binary functions.
612    ///
613    /// C++ equivalent: `void setSupportAddingVertexBinaryFunctions(bool supportAddingVertexBinaryFunctions)`
614    #[inline]
615    pub fn set_support_adding_vertex_binary_functions(&self, support: bool) {
616        unsafe {
617            msg_send_1::<(), bool>(
618                self.as_ptr(),
619                sel!(setSupportAddingVertexBinaryFunctions:),
620                support,
621            );
622        }
623    }
624
625    /// Check if support adding fragment binary functions is enabled.
626    ///
627    /// C++ equivalent: `bool supportAddingFragmentBinaryFunctions() const`
628    #[inline]
629    pub fn support_adding_fragment_binary_functions(&self) -> bool {
630        unsafe { msg_send_0(self.as_ptr(), sel!(supportAddingFragmentBinaryFunctions)) }
631    }
632
633    /// Set support adding fragment binary functions.
634    ///
635    /// C++ equivalent: `void setSupportAddingFragmentBinaryFunctions(bool supportAddingFragmentBinaryFunctions)`
636    #[inline]
637    pub fn set_support_adding_fragment_binary_functions(&self, support: bool) {
638        unsafe {
639            msg_send_1::<(), bool>(
640                self.as_ptr(),
641                sel!(setSupportAddingFragmentBinaryFunctions:),
642                support,
643            );
644        }
645    }
646
647    // =========================================================================
648    // Sample Count (Legacy)
649    // =========================================================================
650
651    /// Get the sample count (deprecated - use rasterSampleCount instead).
652    ///
653    /// C++ equivalent: `NS::UInteger sampleCount() const`
654    #[inline]
655    #[deprecated(note = "use raster_sample_count() instead")]
656    pub fn sample_count(&self) -> UInteger {
657        unsafe { msg_send_0(self.as_ptr(), sel!(sampleCount)) }
658    }
659
660    /// Set the sample count (deprecated - use set_raster_sample_count instead).
661    ///
662    /// C++ equivalent: `void setSampleCount(NS::UInteger sampleCount)`
663    #[inline]
664    #[deprecated(note = "use set_raster_sample_count() instead")]
665    pub fn set_sample_count(&self, count: UInteger) {
666        unsafe {
667            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setSampleCount:), count);
668        }
669    }
670
671    // =========================================================================
672    // Vertex Descriptor
673    // =========================================================================
674
675    /// Get the vertex descriptor.
676    ///
677    /// C++ equivalent: `VertexDescriptor* vertexDescriptor() const`
678    pub fn vertex_descriptor(&self) -> Option<crate::VertexDescriptor> {
679        unsafe {
680            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(vertexDescriptor));
681            if ptr.is_null() {
682                return None;
683            }
684            let _: *mut c_void = msg_send_0(ptr, sel!(retain));
685            crate::VertexDescriptor::from_raw(ptr)
686        }
687    }
688
689    /// Set the vertex descriptor.
690    ///
691    /// C++ equivalent: `void setVertexDescriptor(const MTL::VertexDescriptor* vertexDescriptor)`
692    pub fn set_vertex_descriptor(&self, descriptor: Option<&crate::VertexDescriptor>) {
693        unsafe {
694            let ptr = descriptor.map_or(std::ptr::null(), |d| d.as_ptr());
695            msg_send_1::<(), *const c_void>(self.as_ptr(), sel!(setVertexDescriptor:), ptr);
696        }
697    }
698
699    // =========================================================================
700    // Buffer Descriptors
701    // =========================================================================
702
703    /// Get the vertex buffer descriptors array.
704    ///
705    /// C++ equivalent: `PipelineBufferDescriptorArray* vertexBuffers() const`
706    pub fn vertex_buffers(&self) -> Option<PipelineBufferDescriptorArray> {
707        unsafe {
708            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(vertexBuffers));
709            if ptr.is_null() {
710                return None;
711            }
712            let _: *mut c_void = msg_send_0(ptr, sel!(retain));
713            PipelineBufferDescriptorArray::from_raw(ptr)
714        }
715    }
716
717    /// Get the fragment buffer descriptors array.
718    ///
719    /// C++ equivalent: `PipelineBufferDescriptorArray* fragmentBuffers() const`
720    pub fn fragment_buffers(&self) -> Option<PipelineBufferDescriptorArray> {
721        unsafe {
722            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(fragmentBuffers));
723            if ptr.is_null() {
724                return None;
725            }
726            let _: *mut c_void = msg_send_0(ptr, sel!(retain));
727            PipelineBufferDescriptorArray::from_raw(ptr)
728        }
729    }
730
731    // =========================================================================
732    // Linked Functions
733    // =========================================================================
734
735    /// Get the vertex linked functions.
736    ///
737    /// C++ equivalent: `LinkedFunctions* vertexLinkedFunctions() const`
738    pub fn vertex_linked_functions(&self) -> Option<crate::LinkedFunctions> {
739        unsafe {
740            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(vertexLinkedFunctions));
741            if ptr.is_null() {
742                return None;
743            }
744            let _: *mut c_void = msg_send_0(ptr, sel!(retain));
745            crate::LinkedFunctions::from_raw(ptr)
746        }
747    }
748
749    /// Set the vertex linked functions.
750    ///
751    /// C++ equivalent: `void setVertexLinkedFunctions(const MTL::LinkedFunctions* vertexLinkedFunctions)`
752    pub fn set_vertex_linked_functions(&self, functions: Option<&crate::LinkedFunctions>) {
753        unsafe {
754            let ptr = functions.map_or(std::ptr::null(), |f| f.as_ptr());
755            msg_send_1::<(), *const c_void>(self.as_ptr(), sel!(setVertexLinkedFunctions:), ptr);
756        }
757    }
758
759    /// Get the fragment linked functions.
760    ///
761    /// C++ equivalent: `LinkedFunctions* fragmentLinkedFunctions() const`
762    pub fn fragment_linked_functions(&self) -> Option<crate::LinkedFunctions> {
763        unsafe {
764            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(fragmentLinkedFunctions));
765            if ptr.is_null() {
766                return None;
767            }
768            let _: *mut c_void = msg_send_0(ptr, sel!(retain));
769            crate::LinkedFunctions::from_raw(ptr)
770        }
771    }
772
773    /// Set the fragment linked functions.
774    ///
775    /// C++ equivalent: `void setFragmentLinkedFunctions(const MTL::LinkedFunctions* fragmentLinkedFunctions)`
776    pub fn set_fragment_linked_functions(&self, functions: Option<&crate::LinkedFunctions>) {
777        unsafe {
778            let ptr = functions.map_or(std::ptr::null(), |f| f.as_ptr());
779            msg_send_1::<(), *const c_void>(self.as_ptr(), sel!(setFragmentLinkedFunctions:), ptr);
780        }
781    }
782
783    // =========================================================================
784    // Preloaded Libraries (Raw)
785    // =========================================================================
786
787    /// Get the vertex preloaded libraries array (raw pointer).
788    ///
789    /// C++ equivalent: `NS::Array* vertexPreloadedLibraries() const`
790    pub fn vertex_preloaded_libraries_raw(&self) -> *mut c_void {
791        unsafe { msg_send_0(self.as_ptr(), sel!(vertexPreloadedLibraries)) }
792    }
793
794    /// Set the vertex preloaded libraries array (raw pointer).
795    ///
796    /// C++ equivalent: `void setVertexPreloadedLibraries(const NS::Array* vertexPreloadedLibraries)`
797    ///
798    /// # Safety
799    ///
800    /// The pointer must be a valid NS::Array of Library objects.
801    pub unsafe fn set_vertex_preloaded_libraries_raw(&self, libraries: *const c_void) {
802        unsafe {
803            let _: () = msg_send_1(self.as_ptr(), sel!(setVertexPreloadedLibraries:), libraries);
804        }
805    }
806
807    /// Get the fragment preloaded libraries array (raw pointer).
808    ///
809    /// C++ equivalent: `NS::Array* fragmentPreloadedLibraries() const`
810    pub fn fragment_preloaded_libraries_raw(&self) -> *mut c_void {
811        unsafe { msg_send_0(self.as_ptr(), sel!(fragmentPreloadedLibraries)) }
812    }
813
814    /// Set the fragment preloaded libraries array (raw pointer).
815    ///
816    /// C++ equivalent: `void setFragmentPreloadedLibraries(const NS::Array* fragmentPreloadedLibraries)`
817    ///
818    /// # Safety
819    ///
820    /// The pointer must be a valid NS::Array of Library objects.
821    pub unsafe fn set_fragment_preloaded_libraries_raw(&self, libraries: *const c_void) {
822        unsafe {
823            let _: () = msg_send_1(
824                self.as_ptr(),
825                sel!(setFragmentPreloadedLibraries:),
826                libraries,
827            );
828        }
829    }
830
831    // =========================================================================
832    // Binary Archives (Raw)
833    // =========================================================================
834
835    /// Get the binary archives array (raw pointer).
836    ///
837    /// C++ equivalent: `NS::Array* binaryArchives() const`
838    pub fn binary_archives_raw(&self) -> *mut c_void {
839        unsafe { msg_send_0(self.as_ptr(), sel!(binaryArchives)) }
840    }
841
842    /// Set the binary archives array (raw pointer).
843    ///
844    /// C++ equivalent: `void setBinaryArchives(const NS::Array* binaryArchives)`
845    ///
846    /// # Safety
847    ///
848    /// The pointer must be a valid NS::Array of BinaryArchive objects.
849    pub unsafe fn set_binary_archives_raw(&self, archives: *const c_void) {
850        unsafe {
851            let _: () = msg_send_1(self.as_ptr(), sel!(setBinaryArchives:), archives);
852        }
853    }
854}
855
856impl Clone for RenderPipelineDescriptor {
857    fn clone(&self) -> Self {
858        unsafe {
859            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(copy));
860            Self::from_raw(ptr).expect("copy returned null")
861        }
862    }
863}
864
865impl Drop for RenderPipelineDescriptor {
866    fn drop(&mut self) {
867        unsafe {
868            msg_send_0::<()>(self.as_ptr(), sel!(release));
869        }
870    }
871}
872
873impl Default for RenderPipelineDescriptor {
874    fn default() -> Self {
875        Self::new().expect("failed to create render pipeline descriptor")
876    }
877}
878
879impl Referencing for RenderPipelineDescriptor {
880    #[inline]
881    fn as_ptr(&self) -> *const c_void {
882        self.0.as_ptr()
883    }
884}
885
886unsafe impl Send for RenderPipelineDescriptor {}
887unsafe impl Sync for RenderPipelineDescriptor {}
888
889impl std::fmt::Debug for RenderPipelineDescriptor {
890    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
891        f.debug_struct("RenderPipelineDescriptor")
892            .field("label", &self.label())
893            .field("raster_sample_count", &self.raster_sample_count())
894            .finish()
895    }
896}