Skip to main content

mtl_gpu/pass/
render_pass.rs

1//! Render pass descriptor.
2
3use std::ffi::c_void;
4use std::ptr::NonNull;
5
6use mtl_foundation::{Referencing, UInteger};
7use mtl_sys::{msg_send_0, msg_send_1, sel};
8
9use crate::enums::VisibilityResultType;
10use crate::types::SamplePosition;
11
12use super::{
13    RenderPassColorAttachmentDescriptorArray, RenderPassDepthAttachmentDescriptor,
14    RenderPassStencilAttachmentDescriptor,
15};
16
17/// A render pass descriptor that configures a render pass.
18///
19/// C++ equivalent: `MTL::RenderPassDescriptor`
20#[repr(transparent)]
21pub struct RenderPassDescriptor(NonNull<c_void>);
22
23impl RenderPassDescriptor {
24    /// Create a RenderPassDescriptor from a raw pointer.
25    ///
26    /// # Safety
27    ///
28    /// The pointer must be a valid Metal render pass descriptor object.
29    #[inline]
30    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
31        NonNull::new(ptr).map(Self)
32    }
33
34    /// Get the raw pointer.
35    #[inline]
36    pub fn as_raw(&self) -> *mut c_void {
37        self.0.as_ptr()
38    }
39
40    /// Create a new render pass descriptor.
41    ///
42    /// C++ equivalent: `RenderPassDescriptor::renderPassDescriptor()`
43    pub fn new() -> Option<Self> {
44        unsafe {
45            let class = mtl_sys::class!(MTLRenderPassDescriptor);
46            let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(renderPassDescriptor));
47            if ptr.is_null() {
48                return None;
49            }
50            let _: *mut c_void = msg_send_0(ptr, sel!(retain));
51            Self::from_raw(ptr)
52        }
53    }
54
55    // =========================================================================
56    // Color Attachments
57    // =========================================================================
58
59    /// Get the array of color attachment descriptors.
60    ///
61    /// C++ equivalent: `RenderPassColorAttachmentDescriptorArray* colorAttachments() const`
62    pub fn color_attachments(&self) -> Option<RenderPassColorAttachmentDescriptorArray> {
63        unsafe {
64            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(colorAttachments));
65            RenderPassColorAttachmentDescriptorArray::from_raw(ptr)
66        }
67    }
68
69    // =========================================================================
70    // Depth Attachment
71    // =========================================================================
72
73    /// Get the depth attachment descriptor.
74    ///
75    /// C++ equivalent: `RenderPassDepthAttachmentDescriptor* depthAttachment() const`
76    pub fn depth_attachment(&self) -> Option<RenderPassDepthAttachmentDescriptor> {
77        unsafe {
78            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(depthAttachment));
79            RenderPassDepthAttachmentDescriptor::from_raw(ptr)
80        }
81    }
82
83    /// Set the depth attachment descriptor.
84    ///
85    /// C++ equivalent: `void setDepthAttachment(const RenderPassDepthAttachmentDescriptor*)`
86    pub fn set_depth_attachment(&self, attachment: Option<&RenderPassDepthAttachmentDescriptor>) {
87        unsafe {
88            let ptr = attachment.map_or(std::ptr::null(), |a| a.as_ptr());
89            msg_send_1::<(), *const c_void>(self.as_ptr(), sel!(setDepthAttachment:), ptr);
90        }
91    }
92
93    // =========================================================================
94    // Stencil Attachment
95    // =========================================================================
96
97    /// Get the stencil attachment descriptor.
98    ///
99    /// C++ equivalent: `RenderPassStencilAttachmentDescriptor* stencilAttachment() const`
100    pub fn stencil_attachment(&self) -> Option<RenderPassStencilAttachmentDescriptor> {
101        unsafe {
102            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(stencilAttachment));
103            RenderPassStencilAttachmentDescriptor::from_raw(ptr)
104        }
105    }
106
107    /// Set the stencil attachment descriptor.
108    ///
109    /// C++ equivalent: `void setStencilAttachment(const RenderPassStencilAttachmentDescriptor*)`
110    pub fn set_stencil_attachment(
111        &self,
112        attachment: Option<&RenderPassStencilAttachmentDescriptor>,
113    ) {
114        unsafe {
115            let ptr = attachment.map_or(std::ptr::null(), |a| a.as_ptr());
116            msg_send_1::<(), *const c_void>(self.as_ptr(), sel!(setStencilAttachment:), ptr);
117        }
118    }
119
120    // =========================================================================
121    // Visibility Result Buffer
122    // =========================================================================
123
124    /// Get the visibility result buffer.
125    ///
126    /// C++ equivalent: `Buffer* visibilityResultBuffer() const`
127    pub fn visibility_result_buffer(&self) -> Option<crate::Buffer> {
128        unsafe {
129            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(visibilityResultBuffer));
130            if ptr.is_null() {
131                return None;
132            }
133            let _: *mut c_void = msg_send_0(ptr, sel!(retain));
134            crate::Buffer::from_raw(ptr)
135        }
136    }
137
138    /// Set the visibility result buffer.
139    ///
140    /// C++ equivalent: `void setVisibilityResultBuffer(const Buffer*)`
141    pub fn set_visibility_result_buffer(&self, buffer: Option<&crate::Buffer>) {
142        unsafe {
143            let ptr = buffer.map_or(std::ptr::null(), |b| b.as_ptr());
144            msg_send_1::<(), *const c_void>(self.as_ptr(), sel!(setVisibilityResultBuffer:), ptr);
145        }
146    }
147
148    /// Get the visibility result type.
149    ///
150    /// C++ equivalent: `VisibilityResultType visibilityResultType() const`
151    #[inline]
152    pub fn visibility_result_type(&self) -> VisibilityResultType {
153        unsafe { msg_send_0(self.as_ptr(), sel!(visibilityResultType)) }
154    }
155
156    /// Set the visibility result type.
157    ///
158    /// C++ equivalent: `void setVisibilityResultType(VisibilityResultType)`
159    #[inline]
160    pub fn set_visibility_result_type(&self, result_type: VisibilityResultType) {
161        unsafe {
162            msg_send_1::<(), VisibilityResultType>(
163                self.as_ptr(),
164                sel!(setVisibilityResultType:),
165                result_type,
166            );
167        }
168    }
169
170    // =========================================================================
171    // Render Target Properties
172    // =========================================================================
173
174    /// Get the render target width.
175    ///
176    /// C++ equivalent: `NS::UInteger renderTargetWidth() const`
177    #[inline]
178    pub fn render_target_width(&self) -> UInteger {
179        unsafe { msg_send_0(self.as_ptr(), sel!(renderTargetWidth)) }
180    }
181
182    /// Set the render target width.
183    ///
184    /// C++ equivalent: `void setRenderTargetWidth(NS::UInteger)`
185    #[inline]
186    pub fn set_render_target_width(&self, width: UInteger) {
187        unsafe {
188            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setRenderTargetWidth:), width);
189        }
190    }
191
192    /// Get the render target height.
193    ///
194    /// C++ equivalent: `NS::UInteger renderTargetHeight() const`
195    #[inline]
196    pub fn render_target_height(&self) -> UInteger {
197        unsafe { msg_send_0(self.as_ptr(), sel!(renderTargetHeight)) }
198    }
199
200    /// Set the render target height.
201    ///
202    /// C++ equivalent: `void setRenderTargetHeight(NS::UInteger)`
203    #[inline]
204    pub fn set_render_target_height(&self, height: UInteger) {
205        unsafe {
206            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setRenderTargetHeight:), height);
207        }
208    }
209
210    /// Get the render target array length.
211    ///
212    /// C++ equivalent: `NS::UInteger renderTargetArrayLength() const`
213    #[inline]
214    pub fn render_target_array_length(&self) -> UInteger {
215        unsafe { msg_send_0(self.as_ptr(), sel!(renderTargetArrayLength)) }
216    }
217
218    /// Set the render target array length.
219    ///
220    /// C++ equivalent: `void setRenderTargetArrayLength(NS::UInteger)`
221    #[inline]
222    pub fn set_render_target_array_length(&self, length: UInteger) {
223        unsafe {
224            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setRenderTargetArrayLength:), length);
225        }
226    }
227
228    // =========================================================================
229    // Sample Count and Positions
230    // =========================================================================
231
232    /// Get the default raster sample count.
233    ///
234    /// C++ equivalent: `NS::UInteger defaultRasterSampleCount() const`
235    #[inline]
236    pub fn default_raster_sample_count(&self) -> UInteger {
237        unsafe { msg_send_0(self.as_ptr(), sel!(defaultRasterSampleCount)) }
238    }
239
240    /// Set the default raster sample count.
241    ///
242    /// C++ equivalent: `void setDefaultRasterSampleCount(NS::UInteger)`
243    #[inline]
244    pub fn set_default_raster_sample_count(&self, count: UInteger) {
245        unsafe {
246            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setDefaultRasterSampleCount:), count);
247        }
248    }
249
250    /// Set the sample positions.
251    ///
252    /// C++ equivalent: `void setSamplePositions(const SamplePosition*, NS::UInteger)`
253    pub fn set_sample_positions(&self, positions: &[SamplePosition]) {
254        unsafe {
255            mtl_sys::msg_send_2::<(), *const SamplePosition, UInteger>(
256                self.as_ptr(),
257                sel!(setSamplePositions: count:),
258                positions.as_ptr(),
259                positions.len() as UInteger,
260            );
261        }
262    }
263
264    /// Get the sample positions.
265    ///
266    /// C++ equivalent: `NS::UInteger getSamplePositions(SamplePosition*, NS::UInteger)`
267    pub fn get_sample_positions(&self, positions: &mut [SamplePosition]) -> UInteger {
268        unsafe {
269            mtl_sys::msg_send_2(
270                self.as_ptr(),
271                sel!(getSamplePositions: count:),
272                positions.as_mut_ptr(),
273                positions.len() as UInteger,
274            )
275        }
276    }
277
278    // =========================================================================
279    // Tile Properties
280    // =========================================================================
281
282    /// Get the tile width.
283    ///
284    /// C++ equivalent: `NS::UInteger tileWidth() const`
285    #[inline]
286    pub fn tile_width(&self) -> UInteger {
287        unsafe { msg_send_0(self.as_ptr(), sel!(tileWidth)) }
288    }
289
290    /// Set the tile width.
291    ///
292    /// C++ equivalent: `void setTileWidth(NS::UInteger)`
293    #[inline]
294    pub fn set_tile_width(&self, width: UInteger) {
295        unsafe {
296            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setTileWidth:), width);
297        }
298    }
299
300    /// Get the tile height.
301    ///
302    /// C++ equivalent: `NS::UInteger tileHeight() const`
303    #[inline]
304    pub fn tile_height(&self) -> UInteger {
305        unsafe { msg_send_0(self.as_ptr(), sel!(tileHeight)) }
306    }
307
308    /// Set the tile height.
309    ///
310    /// C++ equivalent: `void setTileHeight(NS::UInteger)`
311    #[inline]
312    pub fn set_tile_height(&self, height: UInteger) {
313        unsafe {
314            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setTileHeight:), height);
315        }
316    }
317
318    /// Get the threadgroup memory length.
319    ///
320    /// C++ equivalent: `NS::UInteger threadgroupMemoryLength() const`
321    #[inline]
322    pub fn threadgroup_memory_length(&self) -> UInteger {
323        unsafe { msg_send_0(self.as_ptr(), sel!(threadgroupMemoryLength)) }
324    }
325
326    /// Set the threadgroup memory length.
327    ///
328    /// C++ equivalent: `void setThreadgroupMemoryLength(NS::UInteger)`
329    #[inline]
330    pub fn set_threadgroup_memory_length(&self, length: UInteger) {
331        unsafe {
332            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setThreadgroupMemoryLength:), length);
333        }
334    }
335
336    /// Get the imageblock sample length.
337    ///
338    /// C++ equivalent: `NS::UInteger imageblockSampleLength() const`
339    #[inline]
340    pub fn imageblock_sample_length(&self) -> UInteger {
341        unsafe { msg_send_0(self.as_ptr(), sel!(imageblockSampleLength)) }
342    }
343
344    /// Set the imageblock sample length.
345    ///
346    /// C++ equivalent: `void setImageblockSampleLength(NS::UInteger)`
347    #[inline]
348    pub fn set_imageblock_sample_length(&self, length: UInteger) {
349        unsafe {
350            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setImageblockSampleLength:), length);
351        }
352    }
353
354    // =========================================================================
355    // Rasterization Rate Map
356    // =========================================================================
357
358    /// Get the rasterization rate map.
359    ///
360    /// C++ equivalent: `RasterizationRateMap* rasterizationRateMap() const`
361    ///
362    /// Returns a raw pointer to the rasterization rate map.
363    pub fn rasterization_rate_map(&self) -> *mut c_void {
364        unsafe { msg_send_0(self.as_ptr(), sel!(rasterizationRateMap)) }
365    }
366
367    /// Set the rasterization rate map.
368    ///
369    /// C++ equivalent: `void setRasterizationRateMap(const RasterizationRateMap*)`
370    ///
371    /// # Safety
372    ///
373    /// The rate_map pointer must be valid or null.
374    pub unsafe fn set_rasterization_rate_map(&self, rate_map: *const c_void) {
375        unsafe {
376            msg_send_1::<(), *const c_void>(
377                self.as_ptr(),
378                sel!(setRasterizationRateMap:),
379                rate_map,
380            );
381        }
382    }
383
384    // =========================================================================
385    // Color Attachment Mapping
386    // =========================================================================
387
388    /// Check if color attachment mapping is supported.
389    ///
390    /// C++ equivalent: `bool supportColorAttachmentMapping() const`
391    #[inline]
392    pub fn support_color_attachment_mapping(&self) -> bool {
393        unsafe { msg_send_0(self.as_ptr(), sel!(supportColorAttachmentMapping)) }
394    }
395
396    /// Set whether color attachment mapping is supported.
397    ///
398    /// C++ equivalent: `void setSupportColorAttachmentMapping(bool)`
399    #[inline]
400    pub fn set_support_color_attachment_mapping(&self, support: bool) {
401        unsafe {
402            msg_send_1::<(), bool>(
403                self.as_ptr(),
404                sel!(setSupportColorAttachmentMapping:),
405                support,
406            );
407        }
408    }
409}
410
411impl Default for RenderPassDescriptor {
412    fn default() -> Self {
413        Self::new().expect("failed to create RenderPassDescriptor")
414    }
415}
416
417impl Clone for RenderPassDescriptor {
418    fn clone(&self) -> Self {
419        unsafe {
420            msg_send_0::<*mut c_void>(self.as_ptr(), sel!(retain));
421        }
422        Self(self.0)
423    }
424}
425
426impl Drop for RenderPassDescriptor {
427    fn drop(&mut self) {
428        unsafe {
429            msg_send_0::<()>(self.as_ptr(), sel!(release));
430        }
431    }
432}
433
434impl Referencing for RenderPassDescriptor {
435    #[inline]
436    fn as_ptr(&self) -> *const c_void {
437        self.0.as_ptr()
438    }
439}
440
441unsafe impl Send for RenderPassDescriptor {}
442unsafe impl Sync for RenderPassDescriptor {}
443
444impl std::fmt::Debug for RenderPassDescriptor {
445    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
446        f.debug_struct("RenderPassDescriptor")
447            .field("render_target_width", &self.render_target_width())
448            .field("render_target_height", &self.render_target_height())
449            .field(
450                "default_raster_sample_count",
451                &self.default_raster_sample_count(),
452            )
453            .finish()
454    }
455}