Skip to main content

mtl_gpu/indirect/
buffer_descriptor.rs

1//! Descriptor for creating an indirect command buffer.
2
3use std::ffi::c_void;
4use std::ptr::NonNull;
5
6use mtl_foundation::{Referencing, UInteger};
7use mtl_sys::{msg_send_0, msg_send_1, sel};
8
9use crate::enums::IndirectCommandType;
10
11/// Descriptor for creating an indirect command buffer.
12///
13/// C++ equivalent: `MTL::IndirectCommandBufferDescriptor`
14#[repr(transparent)]
15pub struct IndirectCommandBufferDescriptor(NonNull<c_void>);
16
17impl IndirectCommandBufferDescriptor {
18    /// Allocate a new indirect command buffer descriptor.
19    ///
20    /// C++ equivalent: `static IndirectCommandBufferDescriptor* alloc()`
21    pub fn alloc() -> Option<Self> {
22        unsafe {
23            let cls = mtl_sys::Class::get("MTLIndirectCommandBufferDescriptor")?;
24            let ptr: *mut c_void = msg_send_0(cls.as_ptr(), sel!(alloc));
25            Self::from_raw(ptr)
26        }
27    }
28
29    /// Initialize an allocated descriptor.
30    ///
31    /// C++ equivalent: `IndirectCommandBufferDescriptor* init()`
32    pub fn init(&self) -> Option<Self> {
33        unsafe {
34            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(init));
35            Self::from_raw(ptr)
36        }
37    }
38
39    /// Create a new indirect command buffer descriptor.
40    pub fn new() -> Option<Self> {
41        Self::alloc()?.init()
42    }
43
44    /// Create from a raw pointer.
45    ///
46    /// # Safety
47    ///
48    /// The pointer must be a valid Metal indirect command buffer descriptor.
49    #[inline]
50    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
51        NonNull::new(ptr).map(Self)
52    }
53
54    /// Get the raw pointer.
55    #[inline]
56    pub fn as_raw(&self) -> *mut c_void {
57        self.0.as_ptr()
58    }
59
60    // =========================================================================
61    // Command Types
62    // =========================================================================
63
64    /// Get the command types that can be encoded.
65    ///
66    /// C++ equivalent: `IndirectCommandType commandTypes() const`
67    #[inline]
68    pub fn command_types(&self) -> IndirectCommandType {
69        unsafe { msg_send_0(self.as_ptr(), sel!(commandTypes)) }
70    }
71
72    /// Set the command types that can be encoded.
73    ///
74    /// C++ equivalent: `void setCommandTypes(IndirectCommandType)`
75    #[inline]
76    pub fn set_command_types(&self, types: IndirectCommandType) {
77        unsafe {
78            msg_send_1::<(), IndirectCommandType>(self.as_ptr(), sel!(setCommandTypes:), types);
79        }
80    }
81
82    // =========================================================================
83    // Inherit Properties
84    // =========================================================================
85
86    /// Get whether commands inherit buffers from the encoder.
87    ///
88    /// C++ equivalent: `bool inheritBuffers() const`
89    #[inline]
90    pub fn inherit_buffers(&self) -> bool {
91        unsafe { msg_send_0(self.as_ptr(), sel!(inheritBuffers)) }
92    }
93
94    /// Set whether commands inherit buffers from the encoder.
95    ///
96    /// C++ equivalent: `void setInheritBuffers(bool)`
97    #[inline]
98    pub fn set_inherit_buffers(&self, inherit: bool) {
99        unsafe {
100            msg_send_1::<(), bool>(self.as_ptr(), sel!(setInheritBuffers:), inherit);
101        }
102    }
103
104    /// Get whether commands inherit cull mode from the encoder.
105    ///
106    /// C++ equivalent: `bool inheritCullMode() const`
107    #[inline]
108    pub fn inherit_cull_mode(&self) -> bool {
109        unsafe { msg_send_0(self.as_ptr(), sel!(inheritCullMode)) }
110    }
111
112    /// Set whether commands inherit cull mode from the encoder.
113    ///
114    /// C++ equivalent: `void setInheritCullMode(bool)`
115    #[inline]
116    pub fn set_inherit_cull_mode(&self, inherit: bool) {
117        unsafe {
118            msg_send_1::<(), bool>(self.as_ptr(), sel!(setInheritCullMode:), inherit);
119        }
120    }
121
122    /// Get whether commands inherit depth bias from the encoder.
123    ///
124    /// C++ equivalent: `bool inheritDepthBias() const`
125    #[inline]
126    pub fn inherit_depth_bias(&self) -> bool {
127        unsafe { msg_send_0(self.as_ptr(), sel!(inheritDepthBias)) }
128    }
129
130    /// Set whether commands inherit depth bias from the encoder.
131    ///
132    /// C++ equivalent: `void setInheritDepthBias(bool)`
133    #[inline]
134    pub fn set_inherit_depth_bias(&self, inherit: bool) {
135        unsafe {
136            msg_send_1::<(), bool>(self.as_ptr(), sel!(setInheritDepthBias:), inherit);
137        }
138    }
139
140    /// Get whether commands inherit depth clip mode from the encoder.
141    ///
142    /// C++ equivalent: `bool inheritDepthClipMode() const`
143    #[inline]
144    pub fn inherit_depth_clip_mode(&self) -> bool {
145        unsafe { msg_send_0(self.as_ptr(), sel!(inheritDepthClipMode)) }
146    }
147
148    /// Set whether commands inherit depth clip mode from the encoder.
149    ///
150    /// C++ equivalent: `void setInheritDepthClipMode(bool)`
151    #[inline]
152    pub fn set_inherit_depth_clip_mode(&self, inherit: bool) {
153        unsafe {
154            msg_send_1::<(), bool>(self.as_ptr(), sel!(setInheritDepthClipMode:), inherit);
155        }
156    }
157
158    /// Get whether commands inherit depth stencil state from the encoder.
159    ///
160    /// C++ equivalent: `bool inheritDepthStencilState() const`
161    #[inline]
162    pub fn inherit_depth_stencil_state(&self) -> bool {
163        unsafe { msg_send_0(self.as_ptr(), sel!(inheritDepthStencilState)) }
164    }
165
166    /// Set whether commands inherit depth stencil state from the encoder.
167    ///
168    /// C++ equivalent: `void setInheritDepthStencilState(bool)`
169    #[inline]
170    pub fn set_inherit_depth_stencil_state(&self, inherit: bool) {
171        unsafe {
172            msg_send_1::<(), bool>(self.as_ptr(), sel!(setInheritDepthStencilState:), inherit);
173        }
174    }
175
176    /// Get whether commands inherit front facing winding from the encoder.
177    ///
178    /// C++ equivalent: `bool inheritFrontFacingWinding() const`
179    #[inline]
180    pub fn inherit_front_facing_winding(&self) -> bool {
181        unsafe { msg_send_0(self.as_ptr(), sel!(inheritFrontFacingWinding)) }
182    }
183
184    /// Set whether commands inherit front facing winding from the encoder.
185    ///
186    /// C++ equivalent: `void setInheritFrontFacingWinding(bool)`
187    #[inline]
188    pub fn set_inherit_front_facing_winding(&self, inherit: bool) {
189        unsafe {
190            msg_send_1::<(), bool>(self.as_ptr(), sel!(setInheritFrontFacingWinding:), inherit);
191        }
192    }
193
194    /// Get whether commands inherit pipeline state from the encoder.
195    ///
196    /// C++ equivalent: `bool inheritPipelineState() const`
197    #[inline]
198    pub fn inherit_pipeline_state(&self) -> bool {
199        unsafe { msg_send_0(self.as_ptr(), sel!(inheritPipelineState)) }
200    }
201
202    /// Set whether commands inherit pipeline state from the encoder.
203    ///
204    /// C++ equivalent: `void setInheritPipelineState(bool)`
205    #[inline]
206    pub fn set_inherit_pipeline_state(&self, inherit: bool) {
207        unsafe {
208            msg_send_1::<(), bool>(self.as_ptr(), sel!(setInheritPipelineState:), inherit);
209        }
210    }
211
212    /// Get whether commands inherit triangle fill mode from the encoder.
213    ///
214    /// C++ equivalent: `bool inheritTriangleFillMode() const`
215    #[inline]
216    pub fn inherit_triangle_fill_mode(&self) -> bool {
217        unsafe { msg_send_0(self.as_ptr(), sel!(inheritTriangleFillMode)) }
218    }
219
220    /// Set whether commands inherit triangle fill mode from the encoder.
221    ///
222    /// C++ equivalent: `void setInheritTriangleFillMode(bool)`
223    #[inline]
224    pub fn set_inherit_triangle_fill_mode(&self, inherit: bool) {
225        unsafe {
226            msg_send_1::<(), bool>(self.as_ptr(), sel!(setInheritTriangleFillMode:), inherit);
227        }
228    }
229
230    // =========================================================================
231    // Buffer Bind Counts
232    // =========================================================================
233
234    /// Get the maximum number of vertex buffer bindings.
235    ///
236    /// C++ equivalent: `NS::UInteger maxVertexBufferBindCount() const`
237    #[inline]
238    pub fn max_vertex_buffer_bind_count(&self) -> UInteger {
239        unsafe { msg_send_0(self.as_ptr(), sel!(maxVertexBufferBindCount)) }
240    }
241
242    /// Set the maximum number of vertex buffer bindings.
243    ///
244    /// C++ equivalent: `void setMaxVertexBufferBindCount(NS::UInteger)`
245    #[inline]
246    pub fn set_max_vertex_buffer_bind_count(&self, count: UInteger) {
247        unsafe {
248            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setMaxVertexBufferBindCount:), count);
249        }
250    }
251
252    /// Get the maximum number of fragment buffer bindings.
253    ///
254    /// C++ equivalent: `NS::UInteger maxFragmentBufferBindCount() const`
255    #[inline]
256    pub fn max_fragment_buffer_bind_count(&self) -> UInteger {
257        unsafe { msg_send_0(self.as_ptr(), sel!(maxFragmentBufferBindCount)) }
258    }
259
260    /// Set the maximum number of fragment buffer bindings.
261    ///
262    /// C++ equivalent: `void setMaxFragmentBufferBindCount(NS::UInteger)`
263    #[inline]
264    pub fn set_max_fragment_buffer_bind_count(&self, count: UInteger) {
265        unsafe {
266            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setMaxFragmentBufferBindCount:), count);
267        }
268    }
269
270    /// Get the maximum number of kernel buffer bindings.
271    ///
272    /// C++ equivalent: `NS::UInteger maxKernelBufferBindCount() const`
273    #[inline]
274    pub fn max_kernel_buffer_bind_count(&self) -> UInteger {
275        unsafe { msg_send_0(self.as_ptr(), sel!(maxKernelBufferBindCount)) }
276    }
277
278    /// Set the maximum number of kernel buffer bindings.
279    ///
280    /// C++ equivalent: `void setMaxKernelBufferBindCount(NS::UInteger)`
281    #[inline]
282    pub fn set_max_kernel_buffer_bind_count(&self, count: UInteger) {
283        unsafe {
284            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setMaxKernelBufferBindCount:), count);
285        }
286    }
287
288    /// Get the maximum number of kernel threadgroup memory bindings.
289    ///
290    /// C++ equivalent: `NS::UInteger maxKernelThreadgroupMemoryBindCount() const`
291    #[inline]
292    pub fn max_kernel_threadgroup_memory_bind_count(&self) -> UInteger {
293        unsafe { msg_send_0(self.as_ptr(), sel!(maxKernelThreadgroupMemoryBindCount)) }
294    }
295
296    /// Set the maximum number of kernel threadgroup memory bindings.
297    ///
298    /// C++ equivalent: `void setMaxKernelThreadgroupMemoryBindCount(NS::UInteger)`
299    #[inline]
300    pub fn set_max_kernel_threadgroup_memory_bind_count(&self, count: UInteger) {
301        unsafe {
302            msg_send_1::<(), UInteger>(
303                self.as_ptr(),
304                sel!(setMaxKernelThreadgroupMemoryBindCount:),
305                count,
306            );
307        }
308    }
309
310    /// Get the maximum number of mesh buffer bindings.
311    ///
312    /// C++ equivalent: `NS::UInteger maxMeshBufferBindCount() const`
313    #[inline]
314    pub fn max_mesh_buffer_bind_count(&self) -> UInteger {
315        unsafe { msg_send_0(self.as_ptr(), sel!(maxMeshBufferBindCount)) }
316    }
317
318    /// Set the maximum number of mesh buffer bindings.
319    ///
320    /// C++ equivalent: `void setMaxMeshBufferBindCount(NS::UInteger)`
321    #[inline]
322    pub fn set_max_mesh_buffer_bind_count(&self, count: UInteger) {
323        unsafe {
324            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setMaxMeshBufferBindCount:), count);
325        }
326    }
327
328    /// Get the maximum number of object buffer bindings.
329    ///
330    /// C++ equivalent: `NS::UInteger maxObjectBufferBindCount() const`
331    #[inline]
332    pub fn max_object_buffer_bind_count(&self) -> UInteger {
333        unsafe { msg_send_0(self.as_ptr(), sel!(maxObjectBufferBindCount)) }
334    }
335
336    /// Set the maximum number of object buffer bindings.
337    ///
338    /// C++ equivalent: `void setMaxObjectBufferBindCount(NS::UInteger)`
339    #[inline]
340    pub fn set_max_object_buffer_bind_count(&self, count: UInteger) {
341        unsafe {
342            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setMaxObjectBufferBindCount:), count);
343        }
344    }
345
346    /// Get the maximum number of object threadgroup memory bindings.
347    ///
348    /// C++ equivalent: `NS::UInteger maxObjectThreadgroupMemoryBindCount() const`
349    #[inline]
350    pub fn max_object_threadgroup_memory_bind_count(&self) -> UInteger {
351        unsafe { msg_send_0(self.as_ptr(), sel!(maxObjectThreadgroupMemoryBindCount)) }
352    }
353
354    /// Set the maximum number of object threadgroup memory bindings.
355    ///
356    /// C++ equivalent: `void setMaxObjectThreadgroupMemoryBindCount(NS::UInteger)`
357    #[inline]
358    pub fn set_max_object_threadgroup_memory_bind_count(&self, count: UInteger) {
359        unsafe {
360            msg_send_1::<(), UInteger>(
361                self.as_ptr(),
362                sel!(setMaxObjectThreadgroupMemoryBindCount:),
363                count,
364            );
365        }
366    }
367
368    // =========================================================================
369    // Support Flags
370    // =========================================================================
371
372    /// Get whether color attachment mapping is supported.
373    ///
374    /// C++ equivalent: `bool supportColorAttachmentMapping() const`
375    #[inline]
376    pub fn support_color_attachment_mapping(&self) -> bool {
377        unsafe { msg_send_0(self.as_ptr(), sel!(supportColorAttachmentMapping)) }
378    }
379
380    /// Set whether color attachment mapping is supported.
381    ///
382    /// C++ equivalent: `void setSupportColorAttachmentMapping(bool)`
383    #[inline]
384    pub fn set_support_color_attachment_mapping(&self, support: bool) {
385        unsafe {
386            msg_send_1::<(), bool>(
387                self.as_ptr(),
388                sel!(setSupportColorAttachmentMapping:),
389                support,
390            );
391        }
392    }
393
394    /// Get whether dynamic attribute stride is supported.
395    ///
396    /// C++ equivalent: `bool supportDynamicAttributeStride() const`
397    #[inline]
398    pub fn support_dynamic_attribute_stride(&self) -> bool {
399        unsafe { msg_send_0(self.as_ptr(), sel!(supportDynamicAttributeStride)) }
400    }
401
402    /// Set whether dynamic attribute stride is supported.
403    ///
404    /// C++ equivalent: `void setSupportDynamicAttributeStride(bool)`
405    #[inline]
406    pub fn set_support_dynamic_attribute_stride(&self, support: bool) {
407        unsafe {
408            msg_send_1::<(), bool>(
409                self.as_ptr(),
410                sel!(setSupportDynamicAttributeStride:),
411                support,
412            );
413        }
414    }
415
416    /// Get whether ray tracing is supported.
417    ///
418    /// C++ equivalent: `bool supportRayTracing() const`
419    #[inline]
420    pub fn support_ray_tracing(&self) -> bool {
421        unsafe { msg_send_0(self.as_ptr(), sel!(supportRayTracing)) }
422    }
423
424    /// Set whether ray tracing is supported.
425    ///
426    /// C++ equivalent: `void setSupportRayTracing(bool)`
427    #[inline]
428    pub fn set_support_ray_tracing(&self, support: bool) {
429        unsafe {
430            msg_send_1::<(), bool>(self.as_ptr(), sel!(setSupportRayTracing:), support);
431        }
432    }
433}
434
435impl Default for IndirectCommandBufferDescriptor {
436    fn default() -> Self {
437        Self::new().expect("failed to create IndirectCommandBufferDescriptor")
438    }
439}
440
441impl Clone for IndirectCommandBufferDescriptor {
442    fn clone(&self) -> Self {
443        unsafe {
444            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(copy));
445            Self::from_raw(ptr).expect("failed to copy IndirectCommandBufferDescriptor")
446        }
447    }
448}
449
450impl Drop for IndirectCommandBufferDescriptor {
451    fn drop(&mut self) {
452        unsafe {
453            msg_send_0::<()>(self.as_ptr(), sel!(release));
454        }
455    }
456}
457
458impl Referencing for IndirectCommandBufferDescriptor {
459    #[inline]
460    fn as_ptr(&self) -> *const c_void {
461        self.0.as_ptr()
462    }
463}
464
465unsafe impl Send for IndirectCommandBufferDescriptor {}
466unsafe impl Sync for IndirectCommandBufferDescriptor {}
467
468impl std::fmt::Debug for IndirectCommandBufferDescriptor {
469    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
470        f.debug_struct("IndirectCommandBufferDescriptor")
471            .field("command_types", &self.command_types())
472            .field(
473                "max_vertex_buffer_bind_count",
474                &self.max_vertex_buffer_bind_count(),
475            )
476            .finish()
477    }
478}