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}