Skip to main content

mtl_gpu/argument/
buffer_binding.rs

1//! Buffer binding information.
2
3use std::ffi::c_void;
4use std::ptr::NonNull;
5
6use mtl_foundation::{Referencing, UInteger};
7use mtl_sys::{msg_send_0, sel};
8
9use crate::enums::{BindingAccess, BindingType, DataType};
10
11use super::{PointerType, StructType};
12
13/// Buffer binding information.
14///
15/// C++ equivalent: `MTL::BufferBinding`
16#[repr(transparent)]
17pub struct BufferBinding(pub(crate) NonNull<c_void>);
18
19impl BufferBinding {
20    /// Create from a raw pointer.
21    ///
22    /// # Safety
23    ///
24    /// The pointer must be a valid Metal BufferBinding.
25    #[inline]
26    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
27        NonNull::new(ptr).map(Self)
28    }
29
30    /// Get the raw pointer.
31    #[inline]
32    pub fn as_raw(&self) -> *mut c_void {
33        self.0.as_ptr()
34    }
35
36    // Inherited from Binding
37
38    /// Get the access mode.
39    #[inline]
40    pub fn access(&self) -> BindingAccess {
41        unsafe { msg_send_0(self.as_ptr(), sel!(access)) }
42    }
43
44    /// Get the index.
45    #[inline]
46    pub fn index(&self) -> UInteger {
47        unsafe { msg_send_0(self.as_ptr(), sel!(index)) }
48    }
49
50    /// Check if this is an argument.
51    #[inline]
52    pub fn is_argument(&self) -> bool {
53        unsafe { msg_send_0(self.as_ptr(), sel!(isArgument)) }
54    }
55
56    /// Check if this binding is used.
57    #[inline]
58    pub fn is_used(&self) -> bool {
59        unsafe { msg_send_0(self.as_ptr(), sel!(isUsed)) }
60    }
61
62    /// Get the name.
63    pub fn name(&self) -> Option<String> {
64        unsafe {
65            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(name));
66            if ptr.is_null() {
67                return None;
68            }
69            let utf8_ptr: *const std::ffi::c_char =
70                mtl_sys::msg_send_0(ptr as *const c_void, sel!(UTF8String));
71            if utf8_ptr.is_null() {
72                return None;
73            }
74            let c_str = std::ffi::CStr::from_ptr(utf8_ptr);
75            Some(c_str.to_string_lossy().into_owned())
76        }
77    }
78
79    /// Get the binding type.
80    #[inline]
81    pub fn binding_type(&self) -> BindingType {
82        unsafe { msg_send_0(self.as_ptr(), sel!(type)) }
83    }
84
85    // BufferBinding-specific
86
87    /// Get the buffer alignment.
88    ///
89    /// C++ equivalent: `NS::UInteger bufferAlignment() const`
90    #[inline]
91    pub fn buffer_alignment(&self) -> UInteger {
92        unsafe { msg_send_0(self.as_ptr(), sel!(bufferAlignment)) }
93    }
94
95    /// Get the buffer data size.
96    ///
97    /// C++ equivalent: `NS::UInteger bufferDataSize() const`
98    #[inline]
99    pub fn buffer_data_size(&self) -> UInteger {
100        unsafe { msg_send_0(self.as_ptr(), sel!(bufferDataSize)) }
101    }
102
103    /// Get the buffer data type.
104    ///
105    /// C++ equivalent: `DataType bufferDataType() const`
106    #[inline]
107    pub fn buffer_data_type(&self) -> DataType {
108        unsafe { msg_send_0(self.as_ptr(), sel!(bufferDataType)) }
109    }
110
111    /// Get the buffer pointer type.
112    ///
113    /// C++ equivalent: `PointerType* bufferPointerType() const`
114    pub fn buffer_pointer_type(&self) -> Option<PointerType> {
115        unsafe {
116            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(bufferPointerType));
117            PointerType::from_raw(ptr)
118        }
119    }
120
121    /// Get the buffer struct type.
122    ///
123    /// C++ equivalent: `StructType* bufferStructType() const`
124    pub fn buffer_struct_type(&self) -> Option<StructType> {
125        unsafe {
126            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(bufferStructType));
127            StructType::from_raw(ptr)
128        }
129    }
130}
131
132impl Clone for BufferBinding {
133    fn clone(&self) -> Self {
134        unsafe {
135            msg_send_0::<*mut c_void>(self.as_ptr(), sel!(retain));
136        }
137        Self(self.0)
138    }
139}
140
141impl Drop for BufferBinding {
142    fn drop(&mut self) {
143        unsafe {
144            msg_send_0::<()>(self.as_ptr(), sel!(release));
145        }
146    }
147}
148
149impl Referencing for BufferBinding {
150    #[inline]
151    fn as_ptr(&self) -> *const c_void {
152        self.0.as_ptr()
153    }
154}
155
156unsafe impl Send for BufferBinding {}
157unsafe impl Sync for BufferBinding {}