Skip to main content

mtl_gpu/encoder/render_encoder/
advanced.rs

1//! Advanced render encoder features.
2//!
3//! This module contains methods for:
4//! - Memory barriers
5//! - Resource usage declarations
6//! - Fence operations
7//! - Vertex amplification
8//! - Acceleration structure bindings
9//! - Function table bindings
10//! - Indirect command execution
11//! - Counter sampling
12
13use std::ffi::c_void;
14
15use mtl_foundation::{Referencing, UInteger};
16use mtl_sys::{msg_send_0, msg_send_1, sel};
17
18use crate::Buffer;
19use crate::Texture;
20use crate::enums::{BarrierScope, RenderStages, ResourceUsage};
21use crate::types::VertexAmplificationViewMapping;
22
23use super::RenderCommandEncoder;
24
25impl RenderCommandEncoder {
26    // =========================================================================
27    // Memory Barriers
28    // =========================================================================
29
30    /// Insert a memory barrier with scope.
31    ///
32    /// C++ equivalent: `void memoryBarrier(MTL::BarrierScope, MTL::RenderStages, MTL::RenderStages)`
33    #[inline]
34    pub fn memory_barrier_with_scope(
35        &self,
36        scope: BarrierScope,
37        after_stages: RenderStages,
38        before_stages: RenderStages,
39    ) {
40        unsafe {
41            mtl_sys::msg_send_3::<(), BarrierScope, RenderStages, RenderStages>(
42                self.as_ptr(),
43                sel!(memoryBarrierWithScope: afterStages: beforeStages:),
44                scope,
45                after_stages,
46                before_stages,
47            );
48        }
49    }
50
51    /// Insert a texture barrier (deprecated).
52    ///
53    /// C++ equivalent: `void textureBarrier()`
54    #[inline]
55    pub fn texture_barrier(&self) {
56        unsafe {
57            msg_send_0::<()>(self.as_ptr(), sel!(textureBarrier));
58        }
59    }
60
61    /// Insert a memory barrier for specific resources (raw pointer version).
62    ///
63    /// C++ equivalent: `void memoryBarrier(const Resource* const*, NS::UInteger, MTL::RenderStages, MTL::RenderStages)`
64    ///
65    /// # Safety
66    ///
67    /// The resources pointer must be a valid array with the specified count.
68    #[inline]
69    pub unsafe fn memory_barrier_with_resources_ptr(
70        &self,
71        resources: *const *const c_void,
72        count: UInteger,
73        after_stages: RenderStages,
74        before_stages: RenderStages,
75    ) {
76        unsafe {
77            mtl_sys::msg_send_4::<(), *const *const c_void, UInteger, RenderStages, RenderStages>(
78                self.as_ptr(),
79                sel!(memoryBarrierWithResources: count: afterStages: beforeStages:),
80                resources,
81                count,
82                after_stages,
83                before_stages,
84            );
85        }
86    }
87
88    // =========================================================================
89    // Resource Usage
90    // =========================================================================
91
92    /// Declare that a resource will be used (raw pointer version).
93    ///
94    /// C++ equivalent: `void useResource(const Resource*, MTL::ResourceUsage)`
95    ///
96    /// # Safety
97    ///
98    /// The resource pointer must be a valid Metal resource object.
99    #[inline]
100    pub unsafe fn use_resource_ptr(&self, resource: *const c_void, usage: ResourceUsage) {
101        unsafe {
102            mtl_sys::msg_send_2::<(), *const c_void, ResourceUsage>(
103                self.as_ptr(),
104                sel!(useResource: usage:),
105                resource,
106                usage,
107            );
108        }
109    }
110
111    /// Declare that a resource will be used with stages (raw pointer version).
112    ///
113    /// C++ equivalent: `void useResource(const Resource*, MTL::ResourceUsage, MTL::RenderStages)`
114    ///
115    /// # Safety
116    ///
117    /// The resource pointer must be a valid Metal resource object.
118    #[inline]
119    pub unsafe fn use_resource_ptr_with_stages(
120        &self,
121        resource: *const c_void,
122        usage: ResourceUsage,
123        stages: RenderStages,
124    ) {
125        unsafe {
126            mtl_sys::msg_send_3::<(), *const c_void, ResourceUsage, RenderStages>(
127                self.as_ptr(),
128                sel!(useResource: usage: stages:),
129                resource,
130                usage,
131                stages,
132            );
133        }
134    }
135
136    /// Declare that a buffer will be used.
137    ///
138    /// C++ equivalent: `void useResource(const Resource*, MTL::ResourceUsage)`
139    #[inline]
140    pub fn use_buffer(&self, buffer: &Buffer, usage: ResourceUsage) {
141        unsafe { self.use_resource_ptr(buffer.as_ptr(), usage) };
142    }
143
144    /// Declare that a texture will be used.
145    ///
146    /// C++ equivalent: `void useResource(const Resource*, MTL::ResourceUsage)`
147    #[inline]
148    pub fn use_texture(&self, texture: &Texture, usage: ResourceUsage) {
149        unsafe { self.use_resource_ptr(texture.as_ptr(), usage) };
150    }
151
152    /// Declare that a heap will be used (raw pointer version).
153    ///
154    /// C++ equivalent: `void useHeap(const Heap*)`
155    ///
156    /// # Safety
157    ///
158    /// The heap pointer must be a valid Metal heap object.
159    #[inline]
160    pub unsafe fn use_heap_ptr(&self, heap: *const c_void) {
161        unsafe {
162            msg_send_1::<(), *const c_void>(self.as_ptr(), sel!(useHeap:), heap);
163        }
164    }
165
166    /// Declare that a heap will be used.
167    ///
168    /// C++ equivalent: `void useHeap(const Heap*)`
169    #[inline]
170    pub fn use_heap(&self, heap: &crate::Heap) {
171        unsafe { self.use_heap_ptr(heap.as_ptr()) };
172    }
173
174    /// Declare that a heap will be used with stages (raw pointer version).
175    ///
176    /// C++ equivalent: `void useHeap(const Heap*, MTL::RenderStages)`
177    ///
178    /// # Safety
179    ///
180    /// The heap pointer must be a valid Metal heap object.
181    #[inline]
182    pub unsafe fn use_heap_ptr_with_stages(&self, heap: *const c_void, stages: RenderStages) {
183        unsafe {
184            mtl_sys::msg_send_2::<(), *const c_void, RenderStages>(
185                self.as_ptr(),
186                sel!(useHeap: stages:),
187                heap,
188                stages,
189            );
190        }
191    }
192
193    /// Declare that multiple heaps will be used (raw pointer version).
194    ///
195    /// C++ equivalent: `void useHeaps(const Heap* const*, NS::UInteger)`
196    ///
197    /// # Safety
198    ///
199    /// The heaps pointer must be a valid array of heap pointers with the specified count.
200    #[inline]
201    pub unsafe fn use_heaps_ptr(&self, heaps: *const *const c_void, count: UInteger) {
202        unsafe {
203            mtl_sys::msg_send_2::<(), *const *const c_void, UInteger>(
204                self.as_ptr(),
205                sel!(useHeaps: count:),
206                heaps,
207                count,
208            );
209        }
210    }
211
212    /// Declare that multiple heaps will be used with stages (raw pointer version).
213    ///
214    /// C++ equivalent: `void useHeaps(const Heap* const*, NS::UInteger, MTL::RenderStages)`
215    ///
216    /// # Safety
217    ///
218    /// The heaps pointer must be a valid array of heap pointers with the specified count.
219    #[inline]
220    pub unsafe fn use_heaps_with_stages_ptr(
221        &self,
222        heaps: *const *const c_void,
223        count: UInteger,
224        stages: RenderStages,
225    ) {
226        unsafe {
227            mtl_sys::msg_send_3::<(), *const *const c_void, UInteger, RenderStages>(
228                self.as_ptr(),
229                sel!(useHeaps: count: stages:),
230                heaps,
231                count,
232                stages,
233            );
234        }
235    }
236
237    /// Declare that multiple resources will be used (raw pointer version).
238    ///
239    /// C++ equivalent: `void useResources(const Resource* const*, NS::UInteger, MTL::ResourceUsage)`
240    ///
241    /// # Safety
242    ///
243    /// The resources pointer must be a valid array of resource pointers with the specified count.
244    #[inline]
245    pub unsafe fn use_resources_ptr(
246        &self,
247        resources: *const *const c_void,
248        count: UInteger,
249        usage: ResourceUsage,
250    ) {
251        unsafe {
252            mtl_sys::msg_send_3::<(), *const *const c_void, UInteger, ResourceUsage>(
253                self.as_ptr(),
254                sel!(useResources: count: usage:),
255                resources,
256                count,
257                usage,
258            );
259        }
260    }
261
262    /// Declare that multiple resources will be used with stages (raw pointer version).
263    ///
264    /// C++ equivalent: `void useResources(const Resource* const*, NS::UInteger, MTL::ResourceUsage, MTL::RenderStages)`
265    ///
266    /// # Safety
267    ///
268    /// The resources pointer must be a valid array of resource pointers with the specified count.
269    #[inline]
270    pub unsafe fn use_resources_with_stages_ptr(
271        &self,
272        resources: *const *const c_void,
273        count: UInteger,
274        usage: ResourceUsage,
275        stages: RenderStages,
276    ) {
277        unsafe {
278            mtl_sys::msg_send_4::<(), *const *const c_void, UInteger, ResourceUsage, RenderStages>(
279                self.as_ptr(),
280                sel!(useResources: count: usage: stages:),
281                resources,
282                count,
283                usage,
284                stages,
285            );
286        }
287    }
288
289    // =========================================================================
290    // Fence Operations
291    // =========================================================================
292
293    /// Update a fence (raw pointer version).
294    ///
295    /// C++ equivalent: `void updateFence(const Fence*, MTL::RenderStages)`
296    ///
297    /// # Safety
298    ///
299    /// The fence pointer must be a valid Metal fence object.
300    #[inline]
301    pub unsafe fn update_fence_ptr(&self, fence: *const c_void, stages: RenderStages) {
302        unsafe {
303            mtl_sys::msg_send_2::<(), *const c_void, RenderStages>(
304                self.as_ptr(),
305                sel!(updateFence: afterStages:),
306                fence,
307                stages,
308            );
309        }
310    }
311
312    /// Update a fence.
313    ///
314    /// C++ equivalent: `void updateFence(const Fence*, MTL::RenderStages)`
315    #[inline]
316    pub fn update_fence(&self, fence: &crate::Fence, stages: RenderStages) {
317        unsafe { self.update_fence_ptr(fence.as_ptr(), stages) };
318    }
319
320    /// Wait for a fence (raw pointer version).
321    ///
322    /// C++ equivalent: `void waitForFence(const Fence*, MTL::RenderStages)`
323    ///
324    /// # Safety
325    ///
326    /// The fence pointer must be a valid Metal fence object.
327    #[inline]
328    pub unsafe fn wait_for_fence_ptr(&self, fence: *const c_void, stages: RenderStages) {
329        unsafe {
330            mtl_sys::msg_send_2::<(), *const c_void, RenderStages>(
331                self.as_ptr(),
332                sel!(waitForFence: beforeStages:),
333                fence,
334                stages,
335            );
336        }
337    }
338
339    /// Wait for a fence.
340    ///
341    /// C++ equivalent: `void waitForFence(const Fence*, MTL::RenderStages)`
342    #[inline]
343    pub fn wait_for_fence(&self, fence: &crate::Fence, stages: RenderStages) {
344        unsafe { self.wait_for_fence_ptr(fence.as_ptr(), stages) };
345    }
346
347    // =========================================================================
348    // Vertex Amplification
349    // =========================================================================
350
351    /// Set vertex amplification count.
352    ///
353    /// C++ equivalent: `void setVertexAmplificationCount(NS::UInteger, const VertexAmplificationViewMapping*)`
354    #[inline]
355    pub fn set_vertex_amplification_count(
356        &self,
357        count: UInteger,
358        view_mappings: Option<&[VertexAmplificationViewMapping]>,
359    ) {
360        let ptr = view_mappings
361            .map(|m| m.as_ptr())
362            .unwrap_or(std::ptr::null());
363        unsafe {
364            mtl_sys::msg_send_2::<(), UInteger, *const VertexAmplificationViewMapping>(
365                self.as_ptr(),
366                sel!(setVertexAmplificationCount: viewMappings:),
367                count,
368                ptr,
369            );
370        }
371    }
372
373    // =========================================================================
374    // Acceleration Structure Bindings
375    // =========================================================================
376
377    /// Set a vertex acceleration structure (raw pointer version).
378    ///
379    /// C++ equivalent: `void setVertexAccelerationStructure(const AccelerationStructure*, NS::UInteger)`
380    ///
381    /// # Safety
382    ///
383    /// The acceleration structure pointer must be valid.
384    #[inline]
385    pub unsafe fn set_vertex_acceleration_structure_ptr(
386        &self,
387        acceleration_structure: *const c_void,
388        buffer_index: UInteger,
389    ) {
390        unsafe {
391            mtl_sys::msg_send_2::<(), *const c_void, UInteger>(
392                self.as_ptr(),
393                sel!(setVertexAccelerationStructure: atBufferIndex:),
394                acceleration_structure,
395                buffer_index,
396            );
397        }
398    }
399
400    /// Set a vertex acceleration structure.
401    ///
402    /// C++ equivalent: `void setVertexAccelerationStructure(const AccelerationStructure*, NS::UInteger)`
403    #[inline]
404    pub fn set_vertex_acceleration_structure(
405        &self,
406        acceleration_structure: &crate::AccelerationStructure,
407        buffer_index: UInteger,
408    ) {
409        unsafe {
410            self.set_vertex_acceleration_structure_ptr(
411                acceleration_structure.as_ptr(),
412                buffer_index,
413            )
414        };
415    }
416
417    /// Set a fragment acceleration structure (raw pointer version).
418    ///
419    /// C++ equivalent: `void setFragmentAccelerationStructure(const AccelerationStructure*, NS::UInteger)`
420    ///
421    /// # Safety
422    ///
423    /// The acceleration structure pointer must be valid.
424    #[inline]
425    pub unsafe fn set_fragment_acceleration_structure_ptr(
426        &self,
427        acceleration_structure: *const c_void,
428        buffer_index: UInteger,
429    ) {
430        unsafe {
431            mtl_sys::msg_send_2::<(), *const c_void, UInteger>(
432                self.as_ptr(),
433                sel!(setFragmentAccelerationStructure: atBufferIndex:),
434                acceleration_structure,
435                buffer_index,
436            );
437        }
438    }
439
440    /// Set a fragment acceleration structure.
441    ///
442    /// C++ equivalent: `void setFragmentAccelerationStructure(const AccelerationStructure*, NS::UInteger)`
443    #[inline]
444    pub fn set_fragment_acceleration_structure(
445        &self,
446        acceleration_structure: &crate::AccelerationStructure,
447        buffer_index: UInteger,
448    ) {
449        unsafe {
450            self.set_fragment_acceleration_structure_ptr(
451                acceleration_structure.as_ptr(),
452                buffer_index,
453            )
454        };
455    }
456
457    /// Set a tile acceleration structure (raw pointer version).
458    ///
459    /// C++ equivalent: `void setTileAccelerationStructure(const AccelerationStructure*, NS::UInteger)`
460    ///
461    /// # Safety
462    ///
463    /// The acceleration structure pointer must be valid.
464    #[inline]
465    pub unsafe fn set_tile_acceleration_structure_ptr(
466        &self,
467        acceleration_structure: *const c_void,
468        buffer_index: UInteger,
469    ) {
470        unsafe {
471            mtl_sys::msg_send_2::<(), *const c_void, UInteger>(
472                self.as_ptr(),
473                sel!(setTileAccelerationStructure: atBufferIndex:),
474                acceleration_structure,
475                buffer_index,
476            );
477        }
478    }
479
480    /// Set a tile acceleration structure.
481    ///
482    /// C++ equivalent: `void setTileAccelerationStructure(const AccelerationStructure*, NS::UInteger)`
483    #[inline]
484    pub fn set_tile_acceleration_structure(
485        &self,
486        acceleration_structure: &crate::AccelerationStructure,
487        buffer_index: UInteger,
488    ) {
489        unsafe {
490            self.set_tile_acceleration_structure_ptr(acceleration_structure.as_ptr(), buffer_index)
491        };
492    }
493
494    // =========================================================================
495    // Function Table Bindings
496    // =========================================================================
497
498    /// Set a vertex visible function table (raw pointer version).
499    ///
500    /// C++ equivalent: `void setVertexVisibleFunctionTable(const VisibleFunctionTable*, NS::UInteger)`
501    ///
502    /// # Safety
503    ///
504    /// The function table pointer must be valid.
505    #[inline]
506    pub unsafe fn set_vertex_visible_function_table_ptr(
507        &self,
508        function_table: *const c_void,
509        buffer_index: UInteger,
510    ) {
511        unsafe {
512            mtl_sys::msg_send_2::<(), *const c_void, UInteger>(
513                self.as_ptr(),
514                sel!(setVertexVisibleFunctionTable: atBufferIndex:),
515                function_table,
516                buffer_index,
517            );
518        }
519    }
520
521    /// Set multiple vertex visible function tables (raw pointer version).
522    ///
523    /// C++ equivalent: `void setVertexVisibleFunctionTables(const VisibleFunctionTable* const*, NS::Range)`
524    ///
525    /// # Safety
526    ///
527    /// The function tables pointer must be a valid array with at least `range.length` elements.
528    #[inline]
529    pub unsafe fn set_vertex_visible_function_tables_ptr(
530        &self,
531        function_tables: *const *const c_void,
532        range_location: UInteger,
533        range_length: UInteger,
534    ) {
535        let range = mtl_foundation::Range::new(range_location, range_length);
536        unsafe {
537            mtl_sys::msg_send_2::<(), *const *const c_void, mtl_foundation::Range>(
538                self.as_ptr(),
539                sel!(setVertexVisibleFunctionTables: withBufferRange:),
540                function_tables,
541                range,
542            );
543        }
544    }
545
546    /// Set a vertex intersection function table (raw pointer version).
547    ///
548    /// C++ equivalent: `void setVertexIntersectionFunctionTable(const IntersectionFunctionTable*, NS::UInteger)`
549    ///
550    /// # Safety
551    ///
552    /// The function table pointer must be valid.
553    #[inline]
554    pub unsafe fn set_vertex_intersection_function_table_ptr(
555        &self,
556        function_table: *const c_void,
557        buffer_index: UInteger,
558    ) {
559        unsafe {
560            mtl_sys::msg_send_2::<(), *const c_void, UInteger>(
561                self.as_ptr(),
562                sel!(setVertexIntersectionFunctionTable: atBufferIndex:),
563                function_table,
564                buffer_index,
565            );
566        }
567    }
568
569    /// Set multiple vertex intersection function tables (raw pointer version).
570    ///
571    /// C++ equivalent: `void setVertexIntersectionFunctionTables(const IntersectionFunctionTable* const*, NS::Range)`
572    ///
573    /// # Safety
574    ///
575    /// The function tables pointer must be a valid array with at least `range.length` elements.
576    #[inline]
577    pub unsafe fn set_vertex_intersection_function_tables_ptr(
578        &self,
579        function_tables: *const *const c_void,
580        range_location: UInteger,
581        range_length: UInteger,
582    ) {
583        let range = mtl_foundation::Range::new(range_location, range_length);
584        unsafe {
585            mtl_sys::msg_send_2::<(), *const *const c_void, mtl_foundation::Range>(
586                self.as_ptr(),
587                sel!(setVertexIntersectionFunctionTables: withBufferRange:),
588                function_tables,
589                range,
590            );
591        }
592    }
593
594    /// Set a fragment visible function table (raw pointer version).
595    ///
596    /// C++ equivalent: `void setFragmentVisibleFunctionTable(const VisibleFunctionTable*, NS::UInteger)`
597    ///
598    /// # Safety
599    ///
600    /// The function table pointer must be valid.
601    #[inline]
602    pub unsafe fn set_fragment_visible_function_table_ptr(
603        &self,
604        function_table: *const c_void,
605        buffer_index: UInteger,
606    ) {
607        unsafe {
608            mtl_sys::msg_send_2::<(), *const c_void, UInteger>(
609                self.as_ptr(),
610                sel!(setFragmentVisibleFunctionTable: atBufferIndex:),
611                function_table,
612                buffer_index,
613            );
614        }
615    }
616
617    /// Set multiple fragment visible function tables (raw pointer version).
618    ///
619    /// C++ equivalent: `void setFragmentVisibleFunctionTables(const VisibleFunctionTable* const*, NS::Range)`
620    ///
621    /// # Safety
622    ///
623    /// The function tables pointer must be a valid array with at least `range.length` elements.
624    #[inline]
625    pub unsafe fn set_fragment_visible_function_tables_ptr(
626        &self,
627        function_tables: *const *const c_void,
628        range_location: UInteger,
629        range_length: UInteger,
630    ) {
631        let range = mtl_foundation::Range::new(range_location, range_length);
632        unsafe {
633            mtl_sys::msg_send_2::<(), *const *const c_void, mtl_foundation::Range>(
634                self.as_ptr(),
635                sel!(setFragmentVisibleFunctionTables: withBufferRange:),
636                function_tables,
637                range,
638            );
639        }
640    }
641
642    /// Set a fragment intersection function table (raw pointer version).
643    ///
644    /// C++ equivalent: `void setFragmentIntersectionFunctionTable(const IntersectionFunctionTable*, NS::UInteger)`
645    ///
646    /// # Safety
647    ///
648    /// The function table pointer must be valid.
649    #[inline]
650    pub unsafe fn set_fragment_intersection_function_table_ptr(
651        &self,
652        function_table: *const c_void,
653        buffer_index: UInteger,
654    ) {
655        unsafe {
656            mtl_sys::msg_send_2::<(), *const c_void, UInteger>(
657                self.as_ptr(),
658                sel!(setFragmentIntersectionFunctionTable: atBufferIndex:),
659                function_table,
660                buffer_index,
661            );
662        }
663    }
664
665    /// Set multiple fragment intersection function tables (raw pointer version).
666    ///
667    /// C++ equivalent: `void setFragmentIntersectionFunctionTables(const IntersectionFunctionTable* const*, NS::Range)`
668    ///
669    /// # Safety
670    ///
671    /// The function tables pointer must be a valid array with at least `range.length` elements.
672    #[inline]
673    pub unsafe fn set_fragment_intersection_function_tables_ptr(
674        &self,
675        function_tables: *const *const c_void,
676        range_location: UInteger,
677        range_length: UInteger,
678    ) {
679        let range = mtl_foundation::Range::new(range_location, range_length);
680        unsafe {
681            mtl_sys::msg_send_2::<(), *const *const c_void, mtl_foundation::Range>(
682                self.as_ptr(),
683                sel!(setFragmentIntersectionFunctionTables: withBufferRange:),
684                function_tables,
685                range,
686            );
687        }
688    }
689
690    /// Set a tile visible function table (raw pointer version).
691    ///
692    /// C++ equivalent: `void setTileVisibleFunctionTable(const VisibleFunctionTable*, NS::UInteger)`
693    ///
694    /// # Safety
695    ///
696    /// The function table pointer must be valid.
697    #[inline]
698    pub unsafe fn set_tile_visible_function_table_ptr(
699        &self,
700        function_table: *const c_void,
701        buffer_index: UInteger,
702    ) {
703        unsafe {
704            mtl_sys::msg_send_2::<(), *const c_void, UInteger>(
705                self.as_ptr(),
706                sel!(setTileVisibleFunctionTable: atBufferIndex:),
707                function_table,
708                buffer_index,
709            );
710        }
711    }
712
713    /// Set multiple tile visible function tables (raw pointer version).
714    ///
715    /// C++ equivalent: `void setTileVisibleFunctionTables(const VisibleFunctionTable* const*, NS::Range)`
716    ///
717    /// # Safety
718    ///
719    /// The function tables pointer must be a valid array with at least `range.length` elements.
720    #[inline]
721    pub unsafe fn set_tile_visible_function_tables_ptr(
722        &self,
723        function_tables: *const *const c_void,
724        range_location: UInteger,
725        range_length: UInteger,
726    ) {
727        let range = mtl_foundation::Range::new(range_location, range_length);
728        unsafe {
729            mtl_sys::msg_send_2::<(), *const *const c_void, mtl_foundation::Range>(
730                self.as_ptr(),
731                sel!(setTileVisibleFunctionTables: withBufferRange:),
732                function_tables,
733                range,
734            );
735        }
736    }
737
738    /// Set a tile intersection function table (raw pointer version).
739    ///
740    /// C++ equivalent: `void setTileIntersectionFunctionTable(const IntersectionFunctionTable*, NS::UInteger)`
741    ///
742    /// # Safety
743    ///
744    /// The function table pointer must be valid.
745    #[inline]
746    pub unsafe fn set_tile_intersection_function_table_ptr(
747        &self,
748        function_table: *const c_void,
749        buffer_index: UInteger,
750    ) {
751        unsafe {
752            mtl_sys::msg_send_2::<(), *const c_void, UInteger>(
753                self.as_ptr(),
754                sel!(setTileIntersectionFunctionTable: atBufferIndex:),
755                function_table,
756                buffer_index,
757            );
758        }
759    }
760
761    /// Set multiple tile intersection function tables (raw pointer version).
762    ///
763    /// C++ equivalent: `void setTileIntersectionFunctionTables(const IntersectionFunctionTable* const*, NS::Range)`
764    ///
765    /// # Safety
766    ///
767    /// The function tables pointer must be a valid array with at least `range.length` elements.
768    #[inline]
769    pub unsafe fn set_tile_intersection_function_tables_ptr(
770        &self,
771        function_tables: *const *const c_void,
772        range_location: UInteger,
773        range_length: UInteger,
774    ) {
775        let range = mtl_foundation::Range::new(range_location, range_length);
776        unsafe {
777            mtl_sys::msg_send_2::<(), *const *const c_void, mtl_foundation::Range>(
778                self.as_ptr(),
779                sel!(setTileIntersectionFunctionTables: withBufferRange:),
780                function_tables,
781                range,
782            );
783        }
784    }
785
786    // =========================================================================
787    // Indirect Command Execution
788    // =========================================================================
789
790    /// Execute commands from an indirect command buffer (raw pointer version).
791    ///
792    /// C++ equivalent: `void executeCommandsInBuffer(const IndirectCommandBuffer*, NS::Range)`
793    ///
794    /// # Safety
795    ///
796    /// The indirect command buffer pointer must be valid.
797    pub unsafe fn execute_commands_in_buffer_ptr(
798        &self,
799        indirect_command_buffer: *const c_void,
800        offset: UInteger,
801        length: UInteger,
802    ) {
803        let range = mtl_foundation::Range::new(offset, length);
804        unsafe {
805            mtl_sys::msg_send_2::<(), *const c_void, mtl_foundation::Range>(
806                self.as_ptr(),
807                sel!(executeCommandsInBuffer: withRange:),
808                indirect_command_buffer,
809                range,
810            );
811        }
812    }
813
814    /// Execute commands from an indirect command buffer with indirect range (raw pointer version).
815    ///
816    /// C++ equivalent: `void executeCommandsInBuffer(const IndirectCommandBuffer*, const Buffer*, NS::UInteger)`
817    ///
818    /// # Safety
819    ///
820    /// The indirect command buffer and range buffer pointers must be valid.
821    pub unsafe fn execute_commands_in_buffer_with_indirect_range_ptr(
822        &self,
823        indirect_command_buffer: *const c_void,
824        indirect_range_buffer: *const c_void,
825        indirect_buffer_offset: UInteger,
826    ) {
827        unsafe {
828            mtl_sys::msg_send_3::<(), *const c_void, *const c_void, UInteger>(
829                self.as_ptr(),
830                sel!(executeCommandsInBuffer: indirectBuffer: indirectBufferOffset:),
831                indirect_command_buffer,
832                indirect_range_buffer,
833                indirect_buffer_offset,
834            );
835        }
836    }
837
838    // =========================================================================
839    // Counter Sampling
840    // =========================================================================
841
842    /// Sample counters (raw pointer version).
843    ///
844    /// C++ equivalent: `void sampleCountersInBuffer(...)`
845    ///
846    /// # Safety
847    ///
848    /// The sample buffer pointer must be a valid counter sample buffer object.
849    pub unsafe fn sample_counters_in_buffer_ptr(
850        &self,
851        sample_buffer: *const c_void,
852        sample_index: UInteger,
853        barrier: bool,
854    ) {
855        unsafe {
856            mtl_sys::msg_send_3::<(), *const c_void, UInteger, bool>(
857                self.as_ptr(),
858                sel!(sampleCountersInBuffer: atSampleIndex: withBarrier:),
859                sample_buffer,
860                sample_index,
861                barrier,
862            );
863        }
864    }
865
866    // =========================================================================
867    // Color Attachment Map
868    // =========================================================================
869
870    /// Set the color attachment map (raw pointer version).
871    ///
872    /// C++ equivalent: `void setColorAttachmentMap(const LogicalToPhysicalColorAttachmentMap*)`
873    ///
874    /// # Safety
875    ///
876    /// The mapping pointer must be valid.
877    #[inline]
878    pub unsafe fn set_color_attachment_map_ptr(&self, mapping: *const c_void) {
879        unsafe {
880            msg_send_1::<(), *const c_void>(self.as_ptr(), sel!(setColorAttachmentMap:), mapping);
881        }
882    }
883}