Skip to main content

mtl_gpu/device/
heap.rs

1//! Device heap creation methods.
2//!
3//! Corresponds to heap creation methods in `Metal/MTLDevice.hpp`.
4
5use std::ffi::c_void;
6
7use mtl_foundation::Referencing;
8use mtl_sys::{msg_send_1, sel};
9
10use super::Device;
11use crate::error::ValidationError;
12use crate::heap::{Heap, HeapDescriptor};
13
14impl Device {
15    // =========================================================================
16    // Heap Creation
17    // =========================================================================
18
19    /// Create a new heap with the specified descriptor.
20    ///
21    /// C++ equivalent: `Heap* newHeap(const HeapDescriptor*)`
22    pub fn new_heap(&self, descriptor: &HeapDescriptor) -> Option<Heap> {
23        unsafe {
24            let ptr: *mut c_void = msg_send_1(
25                self.as_ptr(),
26                sel!(newHeapWithDescriptor:),
27                descriptor.as_ptr(),
28            );
29            Heap::from_raw(ptr)
30        }
31    }
32
33    /// Create a heap with validation.
34    ///
35    /// This safe method validates the descriptor before calling Metal APIs:
36    /// - Ensures heap size is > 0
37    ///
38    /// # Example
39    ///
40    /// ```ignore
41    /// let desc = HeapDescriptor::new().unwrap();
42    /// desc.set_size(1024 * 1024); // 1 MB
43    /// desc.set_storage_mode(StorageMode::PRIVATE);
44    ///
45    /// match device.new_heap_validated(&desc) {
46    ///     Ok(heap) => { /* use heap */ }
47    ///     Err(ValidationError::InvalidHeapSize) => { /* handle error */ }
48    ///     Err(e) => { /* handle other errors */ }
49    /// }
50    /// ```
51    pub fn new_heap_validated(&self, descriptor: &HeapDescriptor) -> Result<Heap, ValidationError> {
52        // Validate size
53        if descriptor.size() == 0 {
54            return Err(ValidationError::InvalidHeapSize);
55        }
56
57        // Call existing safe implementation
58        self.new_heap(descriptor)
59            .ok_or(ValidationError::CreationFailed(None))
60    }
61
62    /// Create a new heap with a raw descriptor pointer.
63    ///
64    /// C++ equivalent: `Heap* newHeap(const HeapDescriptor*)`
65    ///
66    /// # Safety
67    ///
68    /// The descriptor pointer must be valid.
69    pub unsafe fn new_heap_with_ptr(&self, descriptor: *const c_void) -> Option<Heap> {
70        unsafe {
71            let ptr: *mut c_void =
72                msg_send_1(self.as_ptr(), sel!(newHeapWithDescriptor:), descriptor);
73            Heap::from_raw(ptr)
74        }
75    }
76}
77
78#[cfg(test)]
79mod tests {
80    use super::*;
81    use crate::device::system_default;
82    use crate::enums::StorageMode;
83
84    #[test]
85    fn test_new_heap() {
86        let device = system_default().expect("no Metal device");
87        let descriptor = HeapDescriptor::new().expect("failed to create descriptor");
88
89        descriptor.set_size(1024 * 1024); // 1 MB
90        descriptor.set_storage_mode(StorageMode::PRIVATE);
91
92        let heap = device.new_heap(&descriptor);
93        assert!(heap.is_some());
94
95        let heap = heap.unwrap();
96        assert!(heap.size() >= 1024 * 1024);
97    }
98}