1use std::ffi::c_void;
6use std::ptr::NonNull;
7
8use mtl_foundation::{Referencing, UInteger};
9use mtl_sys::{msg_send_0, msg_send_1, msg_send_2, sel};
10
11use crate::{
12 Buffer, RenderPassColorAttachmentDescriptorArray, RenderPassDepthAttachmentDescriptor,
13 RenderPassStencilAttachmentDescriptor, SamplePosition, VisibilityResultType,
14};
15
16#[repr(transparent)]
27pub struct RenderPassDescriptor(NonNull<c_void>);
28
29impl RenderPassDescriptor {
30 #[inline]
32 pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
33 NonNull::new(ptr).map(Self)
34 }
35
36 #[inline]
38 pub fn as_raw(&self) -> *mut c_void {
39 self.0.as_ptr()
40 }
41
42 pub fn new() -> Option<Self> {
44 unsafe {
45 let class = mtl_sys::Class::get("MTL4RenderPassDescriptor")?;
46 let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(alloc));
47 if ptr.is_null() {
48 return None;
49 }
50 let ptr: *mut c_void = msg_send_0(ptr, sel!(init));
51 Self::from_raw(ptr)
52 }
53 }
54
55 pub fn color_attachments(&self) -> Option<RenderPassColorAttachmentDescriptorArray> {
61 unsafe {
62 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(colorAttachments));
63 RenderPassColorAttachmentDescriptorArray::from_raw(ptr)
64 }
65 }
66
67 pub fn depth_attachment(&self) -> Option<RenderPassDepthAttachmentDescriptor> {
73 unsafe {
74 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(depthAttachment));
75 RenderPassDepthAttachmentDescriptor::from_raw(ptr)
76 }
77 }
78
79 pub fn set_depth_attachment(&self, attachment: &RenderPassDepthAttachmentDescriptor) {
83 unsafe {
84 let _: () = msg_send_1(
85 self.as_ptr(),
86 sel!(setDepthAttachment:),
87 attachment.as_ptr(),
88 );
89 }
90 }
91
92 pub fn stencil_attachment(&self) -> Option<RenderPassStencilAttachmentDescriptor> {
98 unsafe {
99 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(stencilAttachment));
100 RenderPassStencilAttachmentDescriptor::from_raw(ptr)
101 }
102 }
103
104 pub fn set_stencil_attachment(&self, attachment: &RenderPassStencilAttachmentDescriptor) {
108 unsafe {
109 let _: () = msg_send_1(
110 self.as_ptr(),
111 sel!(setStencilAttachment:),
112 attachment.as_ptr(),
113 );
114 }
115 }
116
117 pub fn render_target_width(&self) -> UInteger {
123 unsafe { msg_send_0(self.as_ptr(), sel!(renderTargetWidth)) }
124 }
125
126 pub fn set_render_target_width(&self, width: UInteger) {
130 unsafe {
131 let _: () = msg_send_1(self.as_ptr(), sel!(setRenderTargetWidth:), width);
132 }
133 }
134
135 pub fn render_target_height(&self) -> UInteger {
139 unsafe { msg_send_0(self.as_ptr(), sel!(renderTargetHeight)) }
140 }
141
142 pub fn set_render_target_height(&self, height: UInteger) {
146 unsafe {
147 let _: () = msg_send_1(self.as_ptr(), sel!(setRenderTargetHeight:), height);
148 }
149 }
150
151 pub fn render_target_array_length(&self) -> UInteger {
155 unsafe { msg_send_0(self.as_ptr(), sel!(renderTargetArrayLength)) }
156 }
157
158 pub fn set_render_target_array_length(&self, length: UInteger) {
162 unsafe {
163 let _: () = msg_send_1(self.as_ptr(), sel!(setRenderTargetArrayLength:), length);
164 }
165 }
166
167 pub fn default_raster_sample_count(&self) -> UInteger {
173 unsafe { msg_send_0(self.as_ptr(), sel!(defaultRasterSampleCount)) }
174 }
175
176 pub fn set_default_raster_sample_count(&self, count: UInteger) {
180 unsafe {
181 let _: () = msg_send_1(self.as_ptr(), sel!(setDefaultRasterSampleCount:), count);
182 }
183 }
184
185 pub fn get_sample_positions(&self, positions: &mut [SamplePosition]) -> UInteger {
191 unsafe {
192 msg_send_2(
193 self.as_ptr(),
194 sel!(getSamplePositions:count:),
195 positions.as_mut_ptr(),
196 positions.len() as UInteger,
197 )
198 }
199 }
200
201 pub fn set_sample_positions(&self, positions: &[SamplePosition]) {
205 unsafe {
206 let _: () = msg_send_2(
207 self.as_ptr(),
208 sel!(setSamplePositions:count:),
209 positions.as_ptr(),
210 positions.len() as UInteger,
211 );
212 }
213 }
214
215 pub fn tile_width(&self) -> UInteger {
221 unsafe { msg_send_0(self.as_ptr(), sel!(tileWidth)) }
222 }
223
224 pub fn set_tile_width(&self, width: UInteger) {
228 unsafe {
229 let _: () = msg_send_1(self.as_ptr(), sel!(setTileWidth:), width);
230 }
231 }
232
233 pub fn tile_height(&self) -> UInteger {
237 unsafe { msg_send_0(self.as_ptr(), sel!(tileHeight)) }
238 }
239
240 pub fn set_tile_height(&self, height: UInteger) {
244 unsafe {
245 let _: () = msg_send_1(self.as_ptr(), sel!(setTileHeight:), height);
246 }
247 }
248
249 pub fn threadgroup_memory_length(&self) -> UInteger {
255 unsafe { msg_send_0(self.as_ptr(), sel!(threadgroupMemoryLength)) }
256 }
257
258 pub fn set_threadgroup_memory_length(&self, length: UInteger) {
262 unsafe {
263 let _: () = msg_send_1(self.as_ptr(), sel!(setThreadgroupMemoryLength:), length);
264 }
265 }
266
267 pub fn imageblock_sample_length(&self) -> UInteger {
273 unsafe { msg_send_0(self.as_ptr(), sel!(imageblockSampleLength)) }
274 }
275
276 pub fn set_imageblock_sample_length(&self, length: UInteger) {
280 unsafe {
281 let _: () = msg_send_1(self.as_ptr(), sel!(setImageblockSampleLength:), length);
282 }
283 }
284
285 pub fn rasterization_rate_map_raw(&self) -> *mut c_void {
291 unsafe { msg_send_0(self.as_ptr(), sel!(rasterizationRateMap)) }
292 }
293
294 pub fn set_rasterization_rate_map_raw(&self, map: *const c_void) {
298 unsafe {
299 let _: () = msg_send_1(self.as_ptr(), sel!(setRasterizationRateMap:), map);
300 }
301 }
302
303 pub fn visibility_result_buffer(&self) -> Option<Buffer> {
309 unsafe {
310 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(visibilityResultBuffer));
311 Buffer::from_raw(ptr)
312 }
313 }
314
315 pub fn set_visibility_result_buffer(&self, buffer: &Buffer) {
319 unsafe {
320 let _: () = msg_send_1(
321 self.as_ptr(),
322 sel!(setVisibilityResultBuffer:),
323 buffer.as_ptr(),
324 );
325 }
326 }
327
328 pub fn visibility_result_type(&self) -> VisibilityResultType {
332 unsafe { msg_send_0(self.as_ptr(), sel!(visibilityResultType)) }
333 }
334
335 pub fn set_visibility_result_type(&self, result_type: VisibilityResultType) {
339 unsafe {
340 let _: () = msg_send_1(self.as_ptr(), sel!(setVisibilityResultType:), result_type);
341 }
342 }
343
344 pub fn support_color_attachment_mapping(&self) -> bool {
350 unsafe { msg_send_0(self.as_ptr(), sel!(supportColorAttachmentMapping)) }
351 }
352
353 pub fn set_support_color_attachment_mapping(&self, support: bool) {
357 unsafe {
358 let _: () = msg_send_1(
359 self.as_ptr(),
360 sel!(setSupportColorAttachmentMapping:),
361 support,
362 );
363 }
364 }
365}
366
367impl Default for RenderPassDescriptor {
368 fn default() -> Self {
369 Self::new().expect("Failed to create MTL4RenderPassDescriptor")
370 }
371}
372
373impl Clone for RenderPassDescriptor {
374 fn clone(&self) -> Self {
375 unsafe {
376 mtl_sys::msg_send_0::<*mut c_void>(self.as_ptr(), mtl_sys::sel!(retain));
377 }
378 Self(self.0)
379 }
380}
381
382impl Drop for RenderPassDescriptor {
383 fn drop(&mut self) {
384 unsafe {
385 mtl_sys::msg_send_0::<()>(self.as_ptr(), mtl_sys::sel!(release));
386 }
387 }
388}
389
390impl Referencing for RenderPassDescriptor {
391 #[inline]
392 fn as_ptr(&self) -> *const c_void {
393 self.0.as_ptr()
394 }
395}
396
397unsafe impl Send for RenderPassDescriptor {}
398unsafe impl Sync for RenderPassDescriptor {}
399
400impl std::fmt::Debug for RenderPassDescriptor {
401 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
402 f.debug_struct("RenderPassDescriptor")
403 .field("render_target_width", &self.render_target_width())
404 .field("render_target_height", &self.render_target_height())
405 .field("tile_width", &self.tile_width())
406 .field("tile_height", &self.tile_height())
407 .finish()
408 }
409}
410
411#[cfg(test)]
412mod tests {
413 use super::*;
414
415 #[test]
416 fn test_render_pass_descriptor_size() {
417 assert_eq!(
418 std::mem::size_of::<RenderPassDescriptor>(),
419 std::mem::size_of::<*mut c_void>()
420 );
421 }
422}