Skip to main content

mtl_gpu/pipeline/
tile_pipeline.rs

1//! Tile render pipeline types.
2//!
3//! Corresponds to tile rendering pipeline descriptors and attachments.
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::{PixelFormat, ShaderValidation};
12use crate::types::Size;
13
14use super::PipelineBufferDescriptorArray;
15
16pub struct TileRenderPipelineColorAttachmentDescriptor(pub(crate) NonNull<c_void>);
17
18impl TileRenderPipelineColorAttachmentDescriptor {
19    /// Allocate a new tile render pipeline color attachment descriptor.
20    ///
21    /// C++ equivalent: `static TileRenderPipelineColorAttachmentDescriptor* alloc()`
22    pub fn alloc() -> Option<Self> {
23        unsafe {
24            let cls = mtl_sys::Class::get("MTLTileRenderPipelineColorAttachmentDescriptor")?;
25            let ptr: *mut c_void = msg_send_0(cls.as_ptr(), sel!(alloc));
26            Self::from_raw(ptr)
27        }
28    }
29
30    /// Initialize an allocated descriptor.
31    ///
32    /// C++ equivalent: `TileRenderPipelineColorAttachmentDescriptor* init()`
33    pub fn init(&self) -> Option<Self> {
34        unsafe {
35            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(init));
36            Self::from_raw(ptr)
37        }
38    }
39
40    /// Create a new tile render pipeline color attachment descriptor.
41    pub fn new() -> Option<Self> {
42        Self::alloc()?.init()
43    }
44
45    /// Create from a raw pointer.
46    ///
47    /// # Safety
48    ///
49    /// The pointer must be a valid Metal tile render pipeline color attachment descriptor.
50    #[inline]
51    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
52        NonNull::new(ptr).map(Self)
53    }
54
55    /// Get the raw pointer.
56    #[inline]
57    pub fn as_raw(&self) -> *mut c_void {
58        self.0.as_ptr()
59    }
60
61    /// Get the pixel format.
62    ///
63    /// C++ equivalent: `PixelFormat pixelFormat() const`
64    #[inline]
65    pub fn pixel_format(&self) -> PixelFormat {
66        unsafe { msg_send_0(self.as_ptr(), sel!(pixelFormat)) }
67    }
68
69    /// Set the pixel format.
70    ///
71    /// C++ equivalent: `void setPixelFormat(PixelFormat)`
72    #[inline]
73    pub fn set_pixel_format(&self, format: PixelFormat) {
74        unsafe {
75            msg_send_1::<(), PixelFormat>(self.as_ptr(), sel!(setPixelFormat:), format);
76        }
77    }
78}
79
80impl Default for TileRenderPipelineColorAttachmentDescriptor {
81    fn default() -> Self {
82        Self::new().expect("failed to create TileRenderPipelineColorAttachmentDescriptor")
83    }
84}
85
86impl Clone for TileRenderPipelineColorAttachmentDescriptor {
87    fn clone(&self) -> Self {
88        unsafe {
89            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(copy));
90            Self::from_raw(ptr).expect("copy returned null")
91        }
92    }
93}
94
95impl Drop for TileRenderPipelineColorAttachmentDescriptor {
96    fn drop(&mut self) {
97        unsafe {
98            msg_send_0::<()>(self.as_ptr(), sel!(release));
99        }
100    }
101}
102
103impl Referencing for TileRenderPipelineColorAttachmentDescriptor {
104    #[inline]
105    fn as_ptr(&self) -> *const c_void {
106        self.0.as_ptr()
107    }
108}
109
110unsafe impl Send for TileRenderPipelineColorAttachmentDescriptor {}
111unsafe impl Sync for TileRenderPipelineColorAttachmentDescriptor {}
112
113impl std::fmt::Debug for TileRenderPipelineColorAttachmentDescriptor {
114    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
115        f.debug_struct("TileRenderPipelineColorAttachmentDescriptor")
116            .field("pixel_format", &self.pixel_format())
117            .finish()
118    }
119}
120
121// ============================================================================
122// TileRenderPipelineColorAttachmentDescriptorArray
123// ============================================================================
124
125/// An array of tile render pipeline color attachment descriptors.
126///
127/// C++ equivalent: `MTL::TileRenderPipelineColorAttachmentDescriptorArray`
128#[repr(transparent)]
129pub struct TileRenderPipelineColorAttachmentDescriptorArray(pub(crate) NonNull<c_void>);
130
131impl TileRenderPipelineColorAttachmentDescriptorArray {
132    /// Create from a raw pointer.
133    ///
134    /// # Safety
135    ///
136    /// The pointer must be a valid Metal tile render pipeline color attachment descriptor array.
137    #[inline]
138    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
139        NonNull::new(ptr).map(Self)
140    }
141
142    /// Get the raw pointer.
143    #[inline]
144    pub fn as_raw(&self) -> *mut c_void {
145        self.0.as_ptr()
146    }
147
148    /// Get the descriptor at the specified index.
149    ///
150    /// C++ equivalent: `TileRenderPipelineColorAttachmentDescriptor* object(NS::UInteger attachmentIndex)`
151    pub fn object(&self, index: UInteger) -> Option<TileRenderPipelineColorAttachmentDescriptor> {
152        unsafe {
153            let ptr: *mut c_void =
154                msg_send_1(self.as_ptr(), sel!(objectAtIndexedSubscript:), index);
155            if ptr.is_null() {
156                return None;
157            }
158            msg_send_0::<*mut c_void>(ptr as *const c_void, sel!(retain));
159            TileRenderPipelineColorAttachmentDescriptor::from_raw(ptr)
160        }
161    }
162
163    /// Set the descriptor at the specified index.
164    ///
165    /// C++ equivalent: `void setObject(const TileRenderPipelineColorAttachmentDescriptor*, NS::UInteger)`
166    pub fn set_object(
167        &self,
168        descriptor: Option<&TileRenderPipelineColorAttachmentDescriptor>,
169        index: UInteger,
170    ) {
171        let ptr = descriptor.map(|d| d.as_ptr()).unwrap_or(std::ptr::null());
172        unsafe {
173            let _: () = mtl_sys::msg_send_2(
174                self.as_ptr(),
175                sel!(setObject: atIndexedSubscript:),
176                ptr,
177                index,
178            );
179        }
180    }
181}
182
183impl Clone for TileRenderPipelineColorAttachmentDescriptorArray {
184    fn clone(&self) -> Self {
185        unsafe {
186            msg_send_0::<*mut c_void>(self.as_ptr(), sel!(retain));
187        }
188        Self(self.0)
189    }
190}
191
192impl Drop for TileRenderPipelineColorAttachmentDescriptorArray {
193    fn drop(&mut self) {
194        unsafe {
195            msg_send_0::<()>(self.as_ptr(), sel!(release));
196        }
197    }
198}
199
200impl Referencing for TileRenderPipelineColorAttachmentDescriptorArray {
201    #[inline]
202    fn as_ptr(&self) -> *const c_void {
203        self.0.as_ptr()
204    }
205}
206
207unsafe impl Send for TileRenderPipelineColorAttachmentDescriptorArray {}
208unsafe impl Sync for TileRenderPipelineColorAttachmentDescriptorArray {}
209
210impl std::fmt::Debug for TileRenderPipelineColorAttachmentDescriptorArray {
211    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
212        f.debug_struct("TileRenderPipelineColorAttachmentDescriptorArray")
213            .finish()
214    }
215}
216
217// ============================================================================
218// TileRenderPipelineDescriptor
219// ============================================================================
220
221/// Describes a tile render pipeline configuration.
222///
223/// C++ equivalent: `MTL::TileRenderPipelineDescriptor`
224#[repr(transparent)]
225pub struct TileRenderPipelineDescriptor(pub(crate) NonNull<c_void>);
226
227impl TileRenderPipelineDescriptor {
228    /// Allocate a new tile render pipeline descriptor.
229    ///
230    /// C++ equivalent: `static TileRenderPipelineDescriptor* alloc()`
231    pub fn alloc() -> Option<Self> {
232        unsafe {
233            let cls = mtl_sys::Class::get("MTLTileRenderPipelineDescriptor")?;
234            let ptr: *mut c_void = msg_send_0(cls.as_ptr(), sel!(alloc));
235            Self::from_raw(ptr)
236        }
237    }
238
239    /// Initialize an allocated descriptor.
240    ///
241    /// C++ equivalent: `TileRenderPipelineDescriptor* init()`
242    pub fn init(&self) -> Option<Self> {
243        unsafe {
244            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(init));
245            Self::from_raw(ptr)
246        }
247    }
248
249    /// Create a new tile render pipeline descriptor.
250    pub fn new() -> Option<Self> {
251        Self::alloc()?.init()
252    }
253
254    /// Create from a raw pointer.
255    ///
256    /// # Safety
257    ///
258    /// The pointer must be a valid Metal tile render pipeline descriptor.
259    #[inline]
260    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
261        NonNull::new(ptr).map(Self)
262    }
263
264    /// Get the raw pointer.
265    #[inline]
266    pub fn as_raw(&self) -> *mut c_void {
267        self.0.as_ptr()
268    }
269
270    // =========================================================================
271    // Properties
272    // =========================================================================
273
274    /// Get the label.
275    ///
276    /// C++ equivalent: `NS::String* label() const`
277    pub fn label(&self) -> Option<String> {
278        unsafe {
279            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(label));
280            if ptr.is_null() {
281                return None;
282            }
283            let utf8_ptr: *const std::ffi::c_char =
284                mtl_sys::msg_send_0(ptr as *const c_void, sel!(UTF8String));
285            if utf8_ptr.is_null() {
286                return None;
287            }
288            let c_str = std::ffi::CStr::from_ptr(utf8_ptr);
289            Some(c_str.to_string_lossy().into_owned())
290        }
291    }
292
293    /// Set the label.
294    ///
295    /// C++ equivalent: `void setLabel(const NS::String*)`
296    pub fn set_label(&self, label: &str) {
297        if let Some(ns_label) = mtl_foundation::String::from_str(label) {
298            unsafe {
299                msg_send_1::<(), *const c_void>(self.as_ptr(), sel!(setLabel:), ns_label.as_ptr());
300            }
301        }
302    }
303
304    /// Get the tile function.
305    ///
306    /// C++ equivalent: `Function* tileFunction() const`
307    pub fn tile_function(&self) -> Option<crate::Function> {
308        unsafe {
309            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(tileFunction));
310            if ptr.is_null() {
311                return None;
312            }
313            msg_send_0::<*mut c_void>(ptr as *const c_void, sel!(retain));
314            crate::Function::from_raw(ptr)
315        }
316    }
317
318    /// Set the tile function.
319    ///
320    /// C++ equivalent: `void setTileFunction(const Function*)`
321    pub fn set_tile_function(&self, function: Option<&crate::Function>) {
322        let ptr = function.map(|f| f.as_ptr()).unwrap_or(std::ptr::null());
323        unsafe {
324            msg_send_1::<(), *const c_void>(self.as_ptr(), sel!(setTileFunction:), ptr);
325        }
326    }
327
328    /// Get the raster sample count.
329    ///
330    /// C++ equivalent: `NS::UInteger rasterSampleCount() const`
331    #[inline]
332    pub fn raster_sample_count(&self) -> UInteger {
333        unsafe { msg_send_0(self.as_ptr(), sel!(rasterSampleCount)) }
334    }
335
336    /// Set the raster sample count.
337    ///
338    /// C++ equivalent: `void setRasterSampleCount(NS::UInteger)`
339    #[inline]
340    pub fn set_raster_sample_count(&self, count: UInteger) {
341        unsafe {
342            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setRasterSampleCount:), count);
343        }
344    }
345
346    /// Get the color attachments.
347    ///
348    /// C++ equivalent: `TileRenderPipelineColorAttachmentDescriptorArray* colorAttachments() const`
349    pub fn color_attachments(&self) -> Option<TileRenderPipelineColorAttachmentDescriptorArray> {
350        unsafe {
351            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(colorAttachments));
352            TileRenderPipelineColorAttachmentDescriptorArray::from_raw(ptr)
353        }
354    }
355
356    /// Get whether threadgroup size matches tile size.
357    ///
358    /// C++ equivalent: `bool threadgroupSizeMatchesTileSize() const`
359    #[inline]
360    pub fn threadgroup_size_matches_tile_size(&self) -> bool {
361        unsafe { msg_send_0(self.as_ptr(), sel!(threadgroupSizeMatchesTileSize)) }
362    }
363
364    /// Set whether threadgroup size matches tile size.
365    ///
366    /// C++ equivalent: `void setThreadgroupSizeMatchesTileSize(bool)`
367    #[inline]
368    pub fn set_threadgroup_size_matches_tile_size(&self, matches: bool) {
369        unsafe {
370            msg_send_1::<(), bool>(
371                self.as_ptr(),
372                sel!(setThreadgroupSizeMatchesTileSize:),
373                matches,
374            );
375        }
376    }
377
378    /// Get the tile buffers.
379    ///
380    /// C++ equivalent: `PipelineBufferDescriptorArray* tileBuffers() const`
381    pub fn tile_buffers(&self) -> Option<PipelineBufferDescriptorArray> {
382        unsafe {
383            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(tileBuffers));
384            PipelineBufferDescriptorArray::from_raw(ptr)
385        }
386    }
387
388    /// Get the max total threads per threadgroup.
389    ///
390    /// C++ equivalent: `NS::UInteger maxTotalThreadsPerThreadgroup() const`
391    #[inline]
392    pub fn max_total_threads_per_threadgroup(&self) -> UInteger {
393        unsafe { msg_send_0(self.as_ptr(), sel!(maxTotalThreadsPerThreadgroup)) }
394    }
395
396    /// Set the max total threads per threadgroup.
397    ///
398    /// C++ equivalent: `void setMaxTotalThreadsPerThreadgroup(NS::UInteger)`
399    #[inline]
400    pub fn set_max_total_threads_per_threadgroup(&self, count: UInteger) {
401        unsafe {
402            msg_send_1::<(), UInteger>(
403                self.as_ptr(),
404                sel!(setMaxTotalThreadsPerThreadgroup:),
405                count,
406            );
407        }
408    }
409
410    /// Get the required threads per threadgroup.
411    ///
412    /// C++ equivalent: `Size requiredThreadsPerThreadgroup() const`
413    #[inline]
414    pub fn required_threads_per_threadgroup(&self) -> Size {
415        unsafe { msg_send_0(self.as_ptr(), sel!(requiredThreadsPerThreadgroup)) }
416    }
417
418    /// Set the required threads per threadgroup.
419    ///
420    /// C++ equivalent: `void setRequiredThreadsPerThreadgroup(Size)`
421    #[inline]
422    pub fn set_required_threads_per_threadgroup(&self, size: Size) {
423        unsafe {
424            msg_send_1::<(), Size>(self.as_ptr(), sel!(setRequiredThreadsPerThreadgroup:), size);
425        }
426    }
427
428    /// Get the max call stack depth.
429    ///
430    /// C++ equivalent: `NS::UInteger maxCallStackDepth() const`
431    #[inline]
432    pub fn max_call_stack_depth(&self) -> UInteger {
433        unsafe { msg_send_0(self.as_ptr(), sel!(maxCallStackDepth)) }
434    }
435
436    /// Set the max call stack depth.
437    ///
438    /// C++ equivalent: `void setMaxCallStackDepth(NS::UInteger)`
439    #[inline]
440    pub fn set_max_call_stack_depth(&self, depth: UInteger) {
441        unsafe {
442            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setMaxCallStackDepth:), depth);
443        }
444    }
445
446    /// Get the linked functions.
447    ///
448    /// C++ equivalent: `LinkedFunctions* linkedFunctions() const`
449    pub fn linked_functions(&self) -> Option<crate::LinkedFunctions> {
450        unsafe {
451            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(linkedFunctions));
452            if ptr.is_null() {
453                return None;
454            }
455            msg_send_0::<*mut c_void>(ptr as *const c_void, sel!(retain));
456            crate::LinkedFunctions::from_raw(ptr)
457        }
458    }
459
460    /// Set the linked functions.
461    ///
462    /// C++ equivalent: `void setLinkedFunctions(const LinkedFunctions*)`
463    pub fn set_linked_functions(&self, functions: Option<&crate::LinkedFunctions>) {
464        let ptr = functions.map(|f| f.as_ptr()).unwrap_or(std::ptr::null());
465        unsafe {
466            msg_send_1::<(), *const c_void>(self.as_ptr(), sel!(setLinkedFunctions:), ptr);
467        }
468    }
469
470    /// Get whether adding binary functions is supported.
471    ///
472    /// C++ equivalent: `bool supportAddingBinaryFunctions() const`
473    #[inline]
474    pub fn support_adding_binary_functions(&self) -> bool {
475        unsafe { msg_send_0(self.as_ptr(), sel!(supportAddingBinaryFunctions)) }
476    }
477
478    /// Set whether adding binary functions is supported.
479    ///
480    /// C++ equivalent: `void setSupportAddingBinaryFunctions(bool)`
481    #[inline]
482    pub fn set_support_adding_binary_functions(&self, support: bool) {
483        unsafe {
484            msg_send_1::<(), bool>(
485                self.as_ptr(),
486                sel!(setSupportAddingBinaryFunctions:),
487                support,
488            );
489        }
490    }
491
492    /// Get the shader validation mode.
493    ///
494    /// C++ equivalent: `ShaderValidation shaderValidation() const`
495    #[inline]
496    pub fn shader_validation(&self) -> ShaderValidation {
497        unsafe { msg_send_0(self.as_ptr(), sel!(shaderValidation)) }
498    }
499
500    /// Set the shader validation mode.
501    ///
502    /// C++ equivalent: `void setShaderValidation(ShaderValidation)`
503    #[inline]
504    pub fn set_shader_validation(&self, validation: ShaderValidation) {
505        unsafe {
506            msg_send_1::<(), ShaderValidation>(
507                self.as_ptr(),
508                sel!(setShaderValidation:),
509                validation,
510            );
511        }
512    }
513
514    /// Get the binary archives (raw NSArray pointer).
515    ///
516    /// C++ equivalent: `NS::Array* binaryArchives() const`
517    pub fn binary_archives_raw(&self) -> *mut c_void {
518        unsafe { msg_send_0(self.as_ptr(), sel!(binaryArchives)) }
519    }
520
521    /// Set the binary archives.
522    ///
523    /// C++ equivalent: `void setBinaryArchives(const NS::Array*)`
524    ///
525    /// # Safety
526    ///
527    /// The pointer must be a valid NSArray of BinaryArchive objects.
528    pub unsafe fn set_binary_archives_raw(&self, archives: *const c_void) {
529        unsafe {
530            msg_send_1::<(), *const c_void>(self.as_ptr(), sel!(setBinaryArchives:), archives);
531        }
532    }
533
534    /// Get the preloaded libraries (raw NSArray pointer).
535    ///
536    /// C++ equivalent: `NS::Array* preloadedLibraries() const`
537    pub fn preloaded_libraries_raw(&self) -> *mut c_void {
538        unsafe { msg_send_0(self.as_ptr(), sel!(preloadedLibraries)) }
539    }
540
541    /// Set the preloaded libraries.
542    ///
543    /// C++ equivalent: `void setPreloadedLibraries(const NS::Array*)`
544    ///
545    /// # Safety
546    ///
547    /// The pointer must be a valid NSArray of DynamicLibrary objects.
548    pub unsafe fn set_preloaded_libraries_raw(&self, libraries: *const c_void) {
549        unsafe {
550            msg_send_1::<(), *const c_void>(self.as_ptr(), sel!(setPreloadedLibraries:), libraries);
551        }
552    }
553
554    /// Reset the descriptor to default values.
555    ///
556    /// C++ equivalent: `void reset()`
557    #[inline]
558    pub fn reset(&self) {
559        unsafe {
560            msg_send_0::<()>(self.as_ptr(), sel!(reset));
561        }
562    }
563}
564
565impl Default for TileRenderPipelineDescriptor {
566    fn default() -> Self {
567        Self::new().expect("failed to create TileRenderPipelineDescriptor")
568    }
569}
570
571impl Clone for TileRenderPipelineDescriptor {
572    fn clone(&self) -> Self {
573        unsafe {
574            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(copy));
575            Self::from_raw(ptr).expect("copy returned null")
576        }
577    }
578}
579
580impl Drop for TileRenderPipelineDescriptor {
581    fn drop(&mut self) {
582        unsafe {
583            msg_send_0::<()>(self.as_ptr(), sel!(release));
584        }
585    }
586}
587
588impl Referencing for TileRenderPipelineDescriptor {
589    #[inline]
590    fn as_ptr(&self) -> *const c_void {
591        self.0.as_ptr()
592    }
593}
594
595unsafe impl Send for TileRenderPipelineDescriptor {}
596unsafe impl Sync for TileRenderPipelineDescriptor {}
597
598impl std::fmt::Debug for TileRenderPipelineDescriptor {
599    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
600        f.debug_struct("TileRenderPipelineDescriptor")
601            .field("label", &self.label())
602            .field("raster_sample_count", &self.raster_sample_count())
603            .finish()
604    }
605}