Skip to main content

mtl_gpu/mtl4/
linking_descriptor.rs

1//! MTL4 LinkingDescriptor implementation.
2//!
3//! Corresponds to `Metal/MTL4LinkingDescriptor.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, sel};
10
11// ============================================================
12// StaticLinkingDescriptor
13// ============================================================
14
15/// Descriptor for static shader linking.
16///
17/// C++ equivalent: `MTL4::StaticLinkingDescriptor`
18///
19/// StaticLinkingDescriptor specifies functions to be statically linked
20/// with a pipeline.
21#[repr(transparent)]
22pub struct StaticLinkingDescriptor(NonNull<c_void>);
23
24impl StaticLinkingDescriptor {
25    /// Create a StaticLinkingDescriptor from a raw pointer.
26    #[inline]
27    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
28        NonNull::new(ptr).map(Self)
29    }
30
31    /// Get the raw pointer.
32    #[inline]
33    pub fn as_raw(&self) -> *mut c_void {
34        self.0.as_ptr()
35    }
36
37    /// Create a new static linking descriptor.
38    pub fn new() -> Option<Self> {
39        unsafe {
40            let class = mtl_sys::Class::get("MTL4StaticLinkingDescriptor")?;
41            let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(alloc));
42            if ptr.is_null() {
43                return None;
44            }
45            let ptr: *mut c_void = msg_send_0(ptr, sel!(init));
46            Self::from_raw(ptr)
47        }
48    }
49
50    /// Get the function descriptors (as raw pointer to NSArray).
51    ///
52    /// C++ equivalent: `NS::Array* functionDescriptors() const`
53    pub fn function_descriptors_raw(&self) -> *mut c_void {
54        unsafe { msg_send_0(self.as_ptr(), sel!(functionDescriptors)) }
55    }
56
57    /// Set the function descriptors (from raw pointer to NSArray).
58    ///
59    /// C++ equivalent: `void setFunctionDescriptors(const NS::Array*)`
60    pub fn set_function_descriptors_raw(&self, descriptors: *const c_void) {
61        unsafe {
62            let _: () = msg_send_1(self.as_ptr(), sel!(setFunctionDescriptors:), descriptors);
63        }
64    }
65
66    /// Get the groups dictionary (as raw pointer to NSDictionary).
67    ///
68    /// C++ equivalent: `NS::Dictionary* groups() const`
69    pub fn groups_raw(&self) -> *mut c_void {
70        unsafe { msg_send_0(self.as_ptr(), sel!(groups)) }
71    }
72
73    /// Set the groups dictionary (from raw pointer to NSDictionary).
74    ///
75    /// C++ equivalent: `void setGroups(const NS::Dictionary*)`
76    pub fn set_groups_raw(&self, groups: *const c_void) {
77        unsafe {
78            let _: () = msg_send_1(self.as_ptr(), sel!(setGroups:), groups);
79        }
80    }
81
82    /// Get the private function descriptors (as raw pointer to NSArray).
83    ///
84    /// C++ equivalent: `NS::Array* privateFunctionDescriptors() const`
85    pub fn private_function_descriptors_raw(&self) -> *mut c_void {
86        unsafe { msg_send_0(self.as_ptr(), sel!(privateFunctionDescriptors)) }
87    }
88
89    /// Set the private function descriptors (from raw pointer to NSArray).
90    ///
91    /// C++ equivalent: `void setPrivateFunctionDescriptors(const NS::Array*)`
92    pub fn set_private_function_descriptors_raw(&self, descriptors: *const c_void) {
93        unsafe {
94            let _: () = msg_send_1(
95                self.as_ptr(),
96                sel!(setPrivateFunctionDescriptors:),
97                descriptors,
98            );
99        }
100    }
101}
102
103impl Clone for StaticLinkingDescriptor {
104    fn clone(&self) -> Self {
105        unsafe {
106            mtl_sys::msg_send_0::<*mut c_void>(self.as_ptr(), mtl_sys::sel!(retain));
107        }
108        Self(self.0)
109    }
110}
111
112impl Drop for StaticLinkingDescriptor {
113    fn drop(&mut self) {
114        unsafe {
115            mtl_sys::msg_send_0::<()>(self.as_ptr(), mtl_sys::sel!(release));
116        }
117    }
118}
119
120impl Referencing for StaticLinkingDescriptor {
121    #[inline]
122    fn as_ptr(&self) -> *const c_void {
123        self.0.as_ptr()
124    }
125}
126
127unsafe impl Send for StaticLinkingDescriptor {}
128unsafe impl Sync for StaticLinkingDescriptor {}
129
130impl std::fmt::Debug for StaticLinkingDescriptor {
131    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
132        f.debug_struct("StaticLinkingDescriptor").finish()
133    }
134}
135
136// ============================================================
137// PipelineStageDynamicLinkingDescriptor
138// ============================================================
139
140/// Descriptor for pipeline stage dynamic linking.
141///
142/// C++ equivalent: `MTL4::PipelineStageDynamicLinkingDescriptor`
143///
144/// PipelineStageDynamicLinkingDescriptor specifies dynamic linking
145/// configuration for a single pipeline stage.
146#[repr(transparent)]
147pub struct PipelineStageDynamicLinkingDescriptor(NonNull<c_void>);
148
149impl PipelineStageDynamicLinkingDescriptor {
150    /// Create a PipelineStageDynamicLinkingDescriptor from a raw pointer.
151    #[inline]
152    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
153        NonNull::new(ptr).map(Self)
154    }
155
156    /// Get the raw pointer.
157    #[inline]
158    pub fn as_raw(&self) -> *mut c_void {
159        self.0.as_ptr()
160    }
161
162    /// Create a new pipeline stage dynamic linking descriptor.
163    pub fn new() -> Option<Self> {
164        unsafe {
165            let class = mtl_sys::Class::get("MTL4PipelineStageDynamicLinkingDescriptor")?;
166            let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(alloc));
167            if ptr.is_null() {
168                return None;
169            }
170            let ptr: *mut c_void = msg_send_0(ptr, sel!(init));
171            Self::from_raw(ptr)
172        }
173    }
174
175    /// Get the binary linked functions (as raw pointer to NSArray).
176    ///
177    /// C++ equivalent: `NS::Array* binaryLinkedFunctions() const`
178    pub fn binary_linked_functions_raw(&self) -> *mut c_void {
179        unsafe { msg_send_0(self.as_ptr(), sel!(binaryLinkedFunctions)) }
180    }
181
182    /// Set the binary linked functions (from raw pointer to NSArray).
183    ///
184    /// C++ equivalent: `void setBinaryLinkedFunctions(const NS::Array*)`
185    pub fn set_binary_linked_functions_raw(&self, functions: *const c_void) {
186        unsafe {
187            let _: () = msg_send_1(self.as_ptr(), sel!(setBinaryLinkedFunctions:), functions);
188        }
189    }
190
191    /// Get the maximum call stack depth.
192    ///
193    /// C++ equivalent: `NS::UInteger maxCallStackDepth() const`
194    pub fn max_call_stack_depth(&self) -> UInteger {
195        unsafe { msg_send_0(self.as_ptr(), sel!(maxCallStackDepth)) }
196    }
197
198    /// Set the maximum call stack depth.
199    ///
200    /// C++ equivalent: `void setMaxCallStackDepth(NS::UInteger)`
201    pub fn set_max_call_stack_depth(&self, depth: UInteger) {
202        unsafe {
203            let _: () = msg_send_1(self.as_ptr(), sel!(setMaxCallStackDepth:), depth);
204        }
205    }
206
207    /// Get the preloaded libraries (as raw pointer to NSArray).
208    ///
209    /// C++ equivalent: `NS::Array* preloadedLibraries() const`
210    pub fn preloaded_libraries_raw(&self) -> *mut c_void {
211        unsafe { msg_send_0(self.as_ptr(), sel!(preloadedLibraries)) }
212    }
213
214    /// Set the preloaded libraries (from raw pointer to NSArray).
215    ///
216    /// C++ equivalent: `void setPreloadedLibraries(const NS::Array*)`
217    pub fn set_preloaded_libraries_raw(&self, libraries: *const c_void) {
218        unsafe {
219            let _: () = msg_send_1(self.as_ptr(), sel!(setPreloadedLibraries:), libraries);
220        }
221    }
222}
223
224impl Clone for PipelineStageDynamicLinkingDescriptor {
225    fn clone(&self) -> Self {
226        unsafe {
227            mtl_sys::msg_send_0::<*mut c_void>(self.as_ptr(), mtl_sys::sel!(retain));
228        }
229        Self(self.0)
230    }
231}
232
233impl Drop for PipelineStageDynamicLinkingDescriptor {
234    fn drop(&mut self) {
235        unsafe {
236            mtl_sys::msg_send_0::<()>(self.as_ptr(), mtl_sys::sel!(release));
237        }
238    }
239}
240
241impl Referencing for PipelineStageDynamicLinkingDescriptor {
242    #[inline]
243    fn as_ptr(&self) -> *const c_void {
244        self.0.as_ptr()
245    }
246}
247
248unsafe impl Send for PipelineStageDynamicLinkingDescriptor {}
249unsafe impl Sync for PipelineStageDynamicLinkingDescriptor {}
250
251impl std::fmt::Debug for PipelineStageDynamicLinkingDescriptor {
252    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
253        f.debug_struct("PipelineStageDynamicLinkingDescriptor")
254            .field("max_call_stack_depth", &self.max_call_stack_depth())
255            .finish()
256    }
257}
258
259// ============================================================
260// RenderPipelineDynamicLinkingDescriptor
261// ============================================================
262
263/// Descriptor for render pipeline dynamic linking.
264///
265/// C++ equivalent: `MTL4::RenderPipelineDynamicLinkingDescriptor`
266///
267/// RenderPipelineDynamicLinkingDescriptor provides access to dynamic
268/// linking descriptors for each render pipeline stage.
269#[repr(transparent)]
270pub struct RenderPipelineDynamicLinkingDescriptor(NonNull<c_void>);
271
272impl RenderPipelineDynamicLinkingDescriptor {
273    /// Create a RenderPipelineDynamicLinkingDescriptor from a raw pointer.
274    #[inline]
275    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
276        NonNull::new(ptr).map(Self)
277    }
278
279    /// Get the raw pointer.
280    #[inline]
281    pub fn as_raw(&self) -> *mut c_void {
282        self.0.as_ptr()
283    }
284
285    /// Create a new render pipeline dynamic linking descriptor.
286    pub fn new() -> Option<Self> {
287        unsafe {
288            let class = mtl_sys::Class::get("MTL4RenderPipelineDynamicLinkingDescriptor")?;
289            let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(alloc));
290            if ptr.is_null() {
291                return None;
292            }
293            let ptr: *mut c_void = msg_send_0(ptr, sel!(init));
294            Self::from_raw(ptr)
295        }
296    }
297
298    /// Get the fragment linking descriptor.
299    ///
300    /// C++ equivalent: `PipelineStageDynamicLinkingDescriptor* fragmentLinkingDescriptor() const`
301    pub fn fragment_linking_descriptor(&self) -> Option<PipelineStageDynamicLinkingDescriptor> {
302        unsafe {
303            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(fragmentLinkingDescriptor));
304            PipelineStageDynamicLinkingDescriptor::from_raw(ptr)
305        }
306    }
307
308    /// Get the mesh linking descriptor.
309    ///
310    /// C++ equivalent: `PipelineStageDynamicLinkingDescriptor* meshLinkingDescriptor() const`
311    pub fn mesh_linking_descriptor(&self) -> Option<PipelineStageDynamicLinkingDescriptor> {
312        unsafe {
313            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(meshLinkingDescriptor));
314            PipelineStageDynamicLinkingDescriptor::from_raw(ptr)
315        }
316    }
317
318    /// Get the object linking descriptor.
319    ///
320    /// C++ equivalent: `PipelineStageDynamicLinkingDescriptor* objectLinkingDescriptor() const`
321    pub fn object_linking_descriptor(&self) -> Option<PipelineStageDynamicLinkingDescriptor> {
322        unsafe {
323            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(objectLinkingDescriptor));
324            PipelineStageDynamicLinkingDescriptor::from_raw(ptr)
325        }
326    }
327
328    /// Get the tile linking descriptor.
329    ///
330    /// C++ equivalent: `PipelineStageDynamicLinkingDescriptor* tileLinkingDescriptor() const`
331    pub fn tile_linking_descriptor(&self) -> Option<PipelineStageDynamicLinkingDescriptor> {
332        unsafe {
333            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(tileLinkingDescriptor));
334            PipelineStageDynamicLinkingDescriptor::from_raw(ptr)
335        }
336    }
337
338    /// Get the vertex linking descriptor.
339    ///
340    /// C++ equivalent: `PipelineStageDynamicLinkingDescriptor* vertexLinkingDescriptor() const`
341    pub fn vertex_linking_descriptor(&self) -> Option<PipelineStageDynamicLinkingDescriptor> {
342        unsafe {
343            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(vertexLinkingDescriptor));
344            PipelineStageDynamicLinkingDescriptor::from_raw(ptr)
345        }
346    }
347}
348
349impl Clone for RenderPipelineDynamicLinkingDescriptor {
350    fn clone(&self) -> Self {
351        unsafe {
352            mtl_sys::msg_send_0::<*mut c_void>(self.as_ptr(), mtl_sys::sel!(retain));
353        }
354        Self(self.0)
355    }
356}
357
358impl Drop for RenderPipelineDynamicLinkingDescriptor {
359    fn drop(&mut self) {
360        unsafe {
361            mtl_sys::msg_send_0::<()>(self.as_ptr(), mtl_sys::sel!(release));
362        }
363    }
364}
365
366impl Referencing for RenderPipelineDynamicLinkingDescriptor {
367    #[inline]
368    fn as_ptr(&self) -> *const c_void {
369        self.0.as_ptr()
370    }
371}
372
373unsafe impl Send for RenderPipelineDynamicLinkingDescriptor {}
374unsafe impl Sync for RenderPipelineDynamicLinkingDescriptor {}
375
376impl std::fmt::Debug for RenderPipelineDynamicLinkingDescriptor {
377    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
378        f.debug_struct("RenderPipelineDynamicLinkingDescriptor")
379            .finish()
380    }
381}
382
383#[cfg(test)]
384mod tests {
385    use super::*;
386
387    #[test]
388    fn test_static_linking_descriptor_size() {
389        assert_eq!(
390            std::mem::size_of::<StaticLinkingDescriptor>(),
391            std::mem::size_of::<*mut c_void>()
392        );
393    }
394
395    #[test]
396    fn test_pipeline_stage_dynamic_linking_descriptor_size() {
397        assert_eq!(
398            std::mem::size_of::<PipelineStageDynamicLinkingDescriptor>(),
399            std::mem::size_of::<*mut c_void>()
400        );
401    }
402
403    #[test]
404    fn test_render_pipeline_dynamic_linking_descriptor_size() {
405        assert_eq!(
406            std::mem::size_of::<RenderPipelineDynamicLinkingDescriptor>(),
407            std::mem::size_of::<*mut c_void>()
408        );
409    }
410}