mtl_gpu/mtl4/
tile_render_pipeline.rs1use 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 super::{FunctionDescriptor, PipelineOptions, StaticLinkingDescriptor};
12use crate::Size;
13
14#[repr(transparent)]
25pub struct TileRenderPipelineDescriptor(NonNull<c_void>);
26
27impl TileRenderPipelineDescriptor {
28 #[inline]
30 pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
31 NonNull::new(ptr).map(Self)
32 }
33
34 #[inline]
36 pub fn as_raw(&self) -> *mut c_void {
37 self.0.as_ptr()
38 }
39
40 pub fn new() -> Option<Self> {
42 unsafe {
43 let class = mtl_sys::Class::get("MTL4TileRenderPipelineDescriptor")?;
44 let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(alloc));
45 if ptr.is_null() {
46 return None;
47 }
48 let ptr: *mut c_void = msg_send_0(ptr, sel!(init));
49 Self::from_raw(ptr)
50 }
51 }
52
53 pub fn label(&self) -> Option<String> {
57 unsafe {
58 let ns_string: *mut c_void = msg_send_0(self.as_ptr(), sel!(label));
59 if ns_string.is_null() {
60 return None;
61 }
62 let c_str: *const i8 = msg_send_0(ns_string, sel!(UTF8String));
63 if c_str.is_null() {
64 return None;
65 }
66 Some(
67 std::ffi::CStr::from_ptr(c_str)
68 .to_string_lossy()
69 .into_owned(),
70 )
71 }
72 }
73
74 pub fn set_label(&self, label: &str) {
76 if let Some(ns_label) = mtl_foundation::String::from_str(label) {
77 unsafe {
78 let _: () = msg_send_1(self.as_ptr(), sel!(setLabel:), ns_label.as_ptr());
79 }
80 }
81 }
82
83 pub fn options(&self) -> Option<PipelineOptions> {
85 unsafe {
86 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(options));
87 PipelineOptions::from_raw(ptr)
88 }
89 }
90
91 pub fn set_options(&self, options: &PipelineOptions) {
93 unsafe {
94 let _: () = msg_send_1(self.as_ptr(), sel!(setOptions:), options.as_ptr());
95 }
96 }
97
98 pub fn tile_function_descriptor(&self) -> Option<FunctionDescriptor> {
102 unsafe {
103 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(tileFunctionDescriptor));
104 FunctionDescriptor::from_raw(ptr)
105 }
106 }
107
108 pub fn set_tile_function_descriptor(&self, descriptor: &FunctionDescriptor) {
110 unsafe {
111 let _: () = msg_send_1(
112 self.as_ptr(),
113 sel!(setTileFunctionDescriptor:),
114 descriptor.as_ptr(),
115 );
116 }
117 }
118
119 pub fn static_linking_descriptor(&self) -> Option<StaticLinkingDescriptor> {
121 unsafe {
122 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(staticLinkingDescriptor));
123 StaticLinkingDescriptor::from_raw(ptr)
124 }
125 }
126
127 pub fn set_static_linking_descriptor(&self, descriptor: &StaticLinkingDescriptor) {
129 unsafe {
130 let _: () = msg_send_1(
131 self.as_ptr(),
132 sel!(setStaticLinkingDescriptor:),
133 descriptor.as_ptr(),
134 );
135 }
136 }
137
138 pub fn color_attachments_raw(&self) -> *mut c_void {
142 unsafe { msg_send_0(self.as_ptr(), sel!(colorAttachments)) }
143 }
144
145 pub fn max_total_threads_per_threadgroup(&self) -> UInteger {
149 unsafe { msg_send_0(self.as_ptr(), sel!(maxTotalThreadsPerThreadgroup)) }
150 }
151
152 pub fn set_max_total_threads_per_threadgroup(&self, max: UInteger) {
154 unsafe {
155 let _: () = msg_send_1(self.as_ptr(), sel!(setMaxTotalThreadsPerThreadgroup:), max);
156 }
157 }
158
159 pub fn required_threads_per_threadgroup(&self) -> Size {
161 unsafe { msg_send_0(self.as_ptr(), sel!(requiredThreadsPerThreadgroup)) }
162 }
163
164 pub fn set_required_threads_per_threadgroup(&self, size: Size) {
166 unsafe {
167 let _: () = msg_send_1(self.as_ptr(), sel!(setRequiredThreadsPerThreadgroup:), size);
168 }
169 }
170
171 pub fn threadgroup_size_matches_tile_size(&self) -> bool {
173 unsafe { msg_send_0(self.as_ptr(), sel!(threadgroupSizeMatchesTileSize)) }
174 }
175
176 pub fn set_threadgroup_size_matches_tile_size(&self, value: bool) {
178 unsafe {
179 let _: () = msg_send_1(
180 self.as_ptr(),
181 sel!(setThreadgroupSizeMatchesTileSize:),
182 value,
183 );
184 }
185 }
186
187 pub fn raster_sample_count(&self) -> UInteger {
191 unsafe { msg_send_0(self.as_ptr(), sel!(rasterSampleCount)) }
192 }
193
194 pub fn set_raster_sample_count(&self, count: UInteger) {
196 unsafe {
197 let _: () = msg_send_1(self.as_ptr(), sel!(setRasterSampleCount:), count);
198 }
199 }
200
201 pub fn support_binary_linking(&self) -> bool {
205 unsafe { msg_send_0(self.as_ptr(), sel!(supportBinaryLinking)) }
206 }
207
208 pub fn set_support_binary_linking(&self, support: bool) {
210 unsafe {
211 let _: () = msg_send_1(self.as_ptr(), sel!(setSupportBinaryLinking:), support);
212 }
213 }
214
215 pub fn reset(&self) {
217 unsafe {
218 let _: () = msg_send_0(self.as_ptr(), sel!(reset));
219 }
220 }
221}
222
223impl Clone for TileRenderPipelineDescriptor {
224 fn clone(&self) -> Self {
225 unsafe {
226 mtl_sys::msg_send_0::<*mut c_void>(self.as_ptr(), mtl_sys::sel!(retain));
227 }
228 Self(self.0)
229 }
230}
231
232impl Drop for TileRenderPipelineDescriptor {
233 fn drop(&mut self) {
234 unsafe {
235 mtl_sys::msg_send_0::<()>(self.as_ptr(), mtl_sys::sel!(release));
236 }
237 }
238}
239
240impl Referencing for TileRenderPipelineDescriptor {
241 #[inline]
242 fn as_ptr(&self) -> *const c_void {
243 self.0.as_ptr()
244 }
245}
246
247unsafe impl Send for TileRenderPipelineDescriptor {}
248unsafe impl Sync for TileRenderPipelineDescriptor {}
249
250impl std::fmt::Debug for TileRenderPipelineDescriptor {
251 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
252 f.debug_struct("TileRenderPipelineDescriptor")
253 .field("label", &self.label())
254 .field("raster_sample_count", &self.raster_sample_count())
255 .field(
256 "max_total_threads_per_threadgroup",
257 &self.max_total_threads_per_threadgroup(),
258 )
259 .finish()
260 }
261}
262
263#[cfg(test)]
264mod tests {
265 use super::*;
266
267 #[test]
268 fn test_tile_render_pipeline_descriptor_size() {
269 assert_eq!(
270 std::mem::size_of::<TileRenderPipelineDescriptor>(),
271 std::mem::size_of::<*mut c_void>()
272 );
273 }
274}