Skip to main content

mtl_gpu/pipeline/
buffer_descriptor.rs

1//! Pipeline buffer descriptors.
2//!
3//! Corresponds to `MTL::PipelineBufferDescriptor` and `MTL::PipelineBufferDescriptorArray`.
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
11pub struct PipelineBufferDescriptor(pub(crate) NonNull<c_void>);
12
13impl PipelineBufferDescriptor {
14    /// Create a new pipeline buffer descriptor.
15    ///
16    /// C++ equivalent: `static PipelineBufferDescriptor* alloc()->init()`
17    pub fn new() -> Option<Self> {
18        unsafe {
19            let class = mtl_sys::Class::get("MTLPipelineBufferDescriptor")?;
20            let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(alloc));
21            if ptr.is_null() {
22                return None;
23            }
24            let ptr: *mut c_void = msg_send_0(ptr, sel!(init));
25            Self::from_raw(ptr)
26        }
27    }
28
29    /// Create a PipelineBufferDescriptor from a raw pointer.
30    ///
31    /// # Safety
32    ///
33    /// The pointer must be a valid Metal pipeline buffer descriptor object.
34    #[inline]
35    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
36        NonNull::new(ptr).map(Self)
37    }
38
39    /// Get the raw pointer to the descriptor.
40    #[inline]
41    pub fn as_raw(&self) -> *mut c_void {
42        self.0.as_ptr()
43    }
44
45    // =========================================================================
46    // Properties
47    // =========================================================================
48
49    /// Get the mutability of the buffer.
50    ///
51    /// C++ equivalent: `Mutability mutability() const`
52    #[inline]
53    pub fn mutability(&self) -> crate::enums::Mutability {
54        unsafe { msg_send_0(self.as_ptr(), sel!(mutability)) }
55    }
56
57    /// Set the mutability of the buffer.
58    ///
59    /// C++ equivalent: `void setMutability(MTL::Mutability mutability)`
60    #[inline]
61    pub fn set_mutability(&self, mutability: crate::enums::Mutability) {
62        unsafe {
63            let _: () = msg_send_1(self.as_ptr(), sel!(setMutability:), mutability);
64        }
65    }
66}
67
68impl Clone for PipelineBufferDescriptor {
69    fn clone(&self) -> Self {
70        unsafe {
71            msg_send_0::<*mut c_void>(self.as_ptr(), sel!(retain));
72        }
73        Self(self.0)
74    }
75}
76
77impl Drop for PipelineBufferDescriptor {
78    fn drop(&mut self) {
79        unsafe {
80            msg_send_0::<()>(self.as_ptr(), sel!(release));
81        }
82    }
83}
84
85impl Referencing for PipelineBufferDescriptor {
86    #[inline]
87    fn as_ptr(&self) -> *const c_void {
88        self.0.as_ptr()
89    }
90}
91
92unsafe impl Send for PipelineBufferDescriptor {}
93unsafe impl Sync for PipelineBufferDescriptor {}
94
95impl std::fmt::Debug for PipelineBufferDescriptor {
96    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
97        f.debug_struct("PipelineBufferDescriptor")
98            .field("mutability", &self.mutability())
99            .finish()
100    }
101}
102
103// ============================================================================
104// PipelineBufferDescriptorArray
105// ============================================================================
106
107/// An array of pipeline buffer descriptors.
108///
109/// C++ equivalent: `MTL::PipelineBufferDescriptorArray`
110#[repr(transparent)]
111pub struct PipelineBufferDescriptorArray(pub(crate) NonNull<c_void>);
112
113impl PipelineBufferDescriptorArray {
114    /// Create a new pipeline buffer descriptor array.
115    ///
116    /// C++ equivalent: `static PipelineBufferDescriptorArray* alloc()->init()`
117    pub fn new() -> Option<Self> {
118        unsafe {
119            let class = mtl_sys::Class::get("MTLPipelineBufferDescriptorArray")?;
120            let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(alloc));
121            if ptr.is_null() {
122                return None;
123            }
124            let ptr: *mut c_void = msg_send_0(ptr, sel!(init));
125            Self::from_raw(ptr)
126        }
127    }
128
129    /// Create a PipelineBufferDescriptorArray from a raw pointer.
130    ///
131    /// # Safety
132    ///
133    /// The pointer must be a valid Metal pipeline buffer descriptor array object.
134    #[inline]
135    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
136        NonNull::new(ptr).map(Self)
137    }
138
139    /// Get the raw pointer to the array.
140    #[inline]
141    pub fn as_raw(&self) -> *mut c_void {
142        self.0.as_ptr()
143    }
144
145    // =========================================================================
146    // Array Access
147    // =========================================================================
148
149    /// Get the descriptor at the specified buffer index.
150    ///
151    /// C++ equivalent: `PipelineBufferDescriptor* object(NS::UInteger bufferIndex)`
152    pub fn object(&self, buffer_index: UInteger) -> Option<PipelineBufferDescriptor> {
153        unsafe {
154            let ptr: *mut c_void =
155                msg_send_1(self.as_ptr(), sel!(objectAtIndexedSubscript:), buffer_index);
156            if ptr.is_null() {
157                return None;
158            }
159            // Retain since we're returning an owned reference
160            msg_send_0::<*mut c_void>(ptr, sel!(retain));
161            PipelineBufferDescriptor::from_raw(ptr)
162        }
163    }
164
165    /// Set the descriptor at the specified buffer index.
166    ///
167    /// C++ equivalent: `void setObject(const MTL::PipelineBufferDescriptor* buffer, NS::UInteger bufferIndex)`
168    pub fn set_object(&self, buffer: &PipelineBufferDescriptor, buffer_index: UInteger) {
169        unsafe {
170            let _: () = mtl_sys::msg_send_2(
171                self.as_ptr(),
172                sel!(setObject:atIndexedSubscript:),
173                buffer.as_ptr(),
174                buffer_index,
175            );
176        }
177    }
178}
179
180impl Clone for PipelineBufferDescriptorArray {
181    fn clone(&self) -> Self {
182        unsafe {
183            msg_send_0::<*mut c_void>(self.as_ptr(), sel!(retain));
184        }
185        Self(self.0)
186    }
187}
188
189impl Drop for PipelineBufferDescriptorArray {
190    fn drop(&mut self) {
191        unsafe {
192            msg_send_0::<()>(self.as_ptr(), sel!(release));
193        }
194    }
195}
196
197impl Referencing for PipelineBufferDescriptorArray {
198    #[inline]
199    fn as_ptr(&self) -> *const c_void {
200        self.0.as_ptr()
201    }
202}
203
204unsafe impl Send for PipelineBufferDescriptorArray {}
205unsafe impl Sync for PipelineBufferDescriptorArray {}
206
207impl std::fmt::Debug for PipelineBufferDescriptorArray {
208    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
209        f.debug_struct("PipelineBufferDescriptorArray").finish()
210    }
211}