Skip to main content

mtl_gpu/mtl4/
commit_feedback.rs

1//! MTL4 CommitFeedback implementation.
2//!
3//! Corresponds to `Metal/MTL4CommitFeedback.hpp`.
4
5use std::ffi::c_void;
6use std::ptr::NonNull;
7
8use mtl_foundation::Referencing;
9use mtl_sys::{msg_send_0, sel};
10
11/// Time interval type (CFTimeInterval is f64).
12pub type TimeInterval = f64;
13
14// ============================================================
15// CommitFeedback
16// ============================================================
17
18/// Feedback about committed command buffers.
19///
20/// C++ equivalent: `MTL4::CommitFeedback`
21///
22/// CommitFeedback provides information about the execution of committed
23/// command buffers, including GPU timing and error information.
24#[repr(transparent)]
25pub struct CommitFeedback(NonNull<c_void>);
26
27impl CommitFeedback {
28    /// Create a CommitFeedback from a raw pointer.
29    #[inline]
30    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
31        NonNull::new(ptr).map(Self)
32    }
33
34    /// Get the raw pointer.
35    #[inline]
36    pub fn as_raw(&self) -> *mut c_void {
37        self.0.as_ptr()
38    }
39
40    /// Get the GPU start time.
41    ///
42    /// C++ equivalent: `CFTimeInterval GPUStartTime() const`
43    pub fn gpu_start_time(&self) -> TimeInterval {
44        unsafe { msg_send_0(self.as_ptr(), sel!(GPUStartTime)) }
45    }
46
47    /// Get the GPU end time.
48    ///
49    /// C++ equivalent: `CFTimeInterval GPUEndTime() const`
50    pub fn gpu_end_time(&self) -> TimeInterval {
51        unsafe { msg_send_0(self.as_ptr(), sel!(GPUEndTime)) }
52    }
53
54    /// Get the error, if any.
55    ///
56    /// C++ equivalent: `NS::Error* error() const`
57    pub fn error(&self) -> Option<mtl_foundation::Error> {
58        unsafe {
59            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(error));
60            mtl_foundation::Error::from_ptr(ptr)
61        }
62    }
63
64    /// Calculate the GPU execution duration.
65    pub fn gpu_duration(&self) -> TimeInterval {
66        self.gpu_end_time() - self.gpu_start_time()
67    }
68}
69
70impl Clone for CommitFeedback {
71    fn clone(&self) -> Self {
72        unsafe {
73            mtl_sys::msg_send_0::<*mut c_void>(self.as_ptr(), mtl_sys::sel!(retain));
74        }
75        Self(self.0)
76    }
77}
78
79impl Drop for CommitFeedback {
80    fn drop(&mut self) {
81        unsafe {
82            mtl_sys::msg_send_0::<()>(self.as_ptr(), mtl_sys::sel!(release));
83        }
84    }
85}
86
87impl Referencing for CommitFeedback {
88    #[inline]
89    fn as_ptr(&self) -> *const c_void {
90        self.0.as_ptr()
91    }
92}
93
94unsafe impl Send for CommitFeedback {}
95unsafe impl Sync for CommitFeedback {}
96
97impl std::fmt::Debug for CommitFeedback {
98    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
99        f.debug_struct("CommitFeedback")
100            .field("gpu_start_time", &self.gpu_start_time())
101            .field("gpu_end_time", &self.gpu_end_time())
102            .field("has_error", &self.error().is_some())
103            .finish()
104    }
105}
106
107#[cfg(test)]
108mod tests {
109    use super::*;
110
111    #[test]
112    fn test_commit_feedback_size() {
113        assert_eq!(
114            std::mem::size_of::<CommitFeedback>(),
115            std::mem::size_of::<*mut c_void>()
116        );
117    }
118}