Skip to main content

BlitCommandEncoder

Struct BlitCommandEncoder 

Source
pub struct BlitCommandEncoder { /* private fields */ }
Expand description

Re-exports the Metal framework surface for this item. Apple’s id<MTLBlitCommandEncoder> — encodes buffer and texture copy work. Mirrors the Metal framework counterpart for this type.

Implementations§

Source§

impl BlitCommandEncoder

Source

pub const fn as_ptr(&self) -> *mut c_void

Mirrors the Metal framework constant fn.

Source§

impl BlitCommandEncoder

Source

pub fn copy_buffer( &self, src: &MetalBuffer, src_offset: usize, dst: &MetalBuffer, dst_offset: usize, size: usize, ) -> bool

Copy size bytes from src into dst.

Examples found in repository?
examples/05_render_and_explicit_encoders.rs (line 36)
11fn main() {
12    let device = MetalDevice::system_default().expect("Metal device available");
13    println!(
14        "device: {} (registry id {})",
15        device.name(),
16        device.registry_id()
17    );
18
19    let queue = device.new_command_queue().expect("command queue");
20    let status_buffer = queue
21        .new_command_buffer_with_unretained_references()
22        .expect("scratch command buffer");
23    println!("scratch command buffer status={}", status_buffer.status());
24
25    let src = device
26        .new_buffer(64, resource_options::STORAGE_MODE_SHARED)
27        .expect("source buffer");
28    let dst = device
29        .new_buffer(64, resource_options::STORAGE_MODE_SHARED)
30        .expect("destination buffer");
31    let blit_cb = queue.new_command_buffer().expect("blit command buffer");
32    let blit = blit_cb
33        .new_blit_command_encoder()
34        .expect("blit command encoder");
35    assert!(blit.fill_buffer(&src, 0..64, b'Z'));
36    assert!(blit.copy_buffer(&src, 0, &dst, 0, 64));
37    blit.end_encoding();
38    blit_cb.commit();
39    blit_cb.wait_until_completed();
40    let copied = unsafe {
41        core::slice::from_raw_parts(dst.contents().expect("dst contents").cast::<u8>(), 8)
42    };
43    println!("blit copied bytes: {copied:?}");
44
45    let library = device
46        .new_library_with_source(common::COMPUTE_SRC)
47        .expect("compile compute library");
48    let increment = library
49        .new_function("increment")
50        .expect("increment function");
51    let pipeline = device
52        .new_compute_pipeline_state(&increment)
53        .expect("compute pipeline");
54
55    let buffer = device
56        .new_buffer(16, resource_options::STORAGE_MODE_SHARED)
57        .expect("compute buffer");
58    common::write_u32_words(&buffer, &[10, 20, 30, 40]);
59    let compute_cb = queue.new_command_buffer().expect("compute command buffer");
60    let compute = compute_cb
61        .new_compute_command_encoder()
62        .expect("compute command encoder");
63    compute.set_compute_pipeline_state(&pipeline);
64    compute.set_buffer(&buffer, 0, 0);
65    compute.dispatch_threads((4, 1, 1), (1, 1, 1));
66    compute.end_encoding();
67    compute_cb.commit();
68    compute_cb.wait_until_completed();
69    println!("compute output: {:?}", common::read_u32_words(&buffer, 4));
70
71    let render_library = device
72        .new_library_with_source(common::RENDER_SRC)
73        .expect("compile render library");
74    let vertex = render_library
75        .new_function("fullscreen_vertex")
76        .expect("vertex function");
77    let fragment = render_library
78        .new_function("solid_fragment")
79        .expect("fragment function");
80    let render_pipeline = device
81        .new_render_pipeline_state(&vertex, &fragment, pixel_format::BGRA8UNORM, 1)
82        .expect("render pipeline");
83    println!("render pipeline label: {:?}", render_pipeline.label());
84
85    let render_target = device
86        .new_texture(common::shared_render_target(4, 4))
87        .expect("render target");
88    let vertex_buffer = device
89        .new_buffer(16, resource_options::STORAGE_MODE_SHARED)
90        .expect("vertex buffer");
91    let render_cb = queue.new_command_buffer().expect("render command buffer");
92    let render = render_cb
93        .new_render_command_encoder(
94            &render_target,
95            load_action::CLEAR,
96            store_action::STORE,
97            [0.0, 0.0, 0.0, 1.0],
98        )
99        .expect("render command encoder");
100    render.set_render_pipeline_state(&render_pipeline);
101    render.set_vertex_buffer(&vertex_buffer, 0, 0);
102    render.draw_primitives(primitive_type::TRIANGLE, 0, 3);
103    render.end_encoding();
104    render_cb.commit();
105    render_cb.wait_until_completed();
106
107    let mut rendered = vec![0_u8; 4 * 4 * 4];
108    assert!(render_target.read_bytes_2d(&mut rendered, 16, (0, 0), (4, 4), 0));
109    println!("first rendered pixel: {:?}", &rendered[..4]);
110
111    let shared_texture = device
112        .new_texture(TextureDescriptor::new_2d(4, 4, pixel_format::BGRA8UNORM))
113        .expect("shared texture");
114    let upload = vec![0x22_u8; 4 * 4 * 4];
115    assert!(shared_texture.replace_region_2d(&upload, 16, (0, 0), (4, 4), 0));
116    let mut download = vec![0_u8; upload.len()];
117    assert!(shared_texture.read_bytes_2d(&mut download, 16, (0, 0), (4, 4), 0));
118    let view = shared_texture
119        .new_view(pixel_format::BGRA8UNORM)
120        .expect("texture view");
121    println!(
122        "texture {}x{} usage={} storage_mode={} view_width={}",
123        shared_texture.width(),
124        shared_texture.height(),
125        shared_texture.usage(),
126        shared_texture.storage_mode(),
127        view.width(),
128    );
129}
More examples
Hide additional examples
examples/07_advanced_objects.rs (line 79)
11fn main() {
12    let device = MetalDevice::system_default().expect("Metal device available");
13    let queue = device.new_command_queue().expect("command queue");
14    let counter_sets = device.counter_set_names();
15    println!("counter sets: {counter_sets:?}");
16
17    if let Some(event) = device.new_shared_event() {
18        event.set_signaled_value(1);
19        println!("event signaled value={}", event.signaled_value());
20        let signal = queue
21            .new_command_buffer()
22            .expect("event signal command buffer");
23        signal.encode_signal_event(&event, 2);
24        signal.commit();
25        signal.wait_until_completed();
26        println!(
27            "event reached value 2: {}",
28            event.wait_until_signaled_value(2, 1_000),
29        );
30
31        let wait = queue
32            .new_command_buffer()
33            .expect("event wait command buffer");
34        wait.encode_wait_for_event(&event, 2);
35        wait.commit();
36        wait.wait_until_completed();
37    }
38
39    let fence_a = device.new_fence();
40    let fence_b = device.new_fence();
41    let sample_buffer = counter_sets.first().and_then(|name| {
42        if device.supports_counter_sampling(counter_sampling_point::AT_BLIT_BOUNDARY) {
43            device
44                .new_counter_sample_buffer(name, 2, storage_mode::SHARED, Some("example-samples"))
45                .ok()
46        } else {
47            None
48        }
49    });
50
51    let src = device
52        .new_buffer(64, resource_options::STORAGE_MODE_SHARED)
53        .expect("source buffer");
54    let dst = device
55        .new_buffer(64, resource_options::STORAGE_MODE_SHARED)
56        .expect("destination buffer");
57    let blit = queue.new_command_buffer().expect("blit command buffer");
58    let encoder = blit.new_blit_command_encoder().expect("blit encoder");
59    let _ = encoder.fill_buffer(&src, 0..64, b'Q');
60    if let Some(fence) = fence_a.as_ref() {
61        encoder.update_fence(fence);
62    }
63    encoder.end_encoding();
64    blit.commit();
65    blit.wait_until_completed();
66
67    let blit = queue
68        .new_command_buffer()
69        .expect("second blit command buffer");
70    let encoder = blit
71        .new_blit_command_encoder()
72        .expect("second blit encoder");
73    if let Some(fence) = fence_a.as_ref() {
74        encoder.wait_for_fence(fence);
75    }
76    if let Some(sample_buffer) = sample_buffer.as_ref() {
77        let _ = encoder.sample_counters(sample_buffer, 0, false);
78    }
79    let _ = encoder.copy_buffer(&src, 0, &dst, 0, 64);
80    encoder.end_encoding();
81    blit.commit();
82    blit.wait_until_completed();
83    if let Some(sample_buffer) = sample_buffer.as_ref() {
84        println!(
85            "resolved counter bytes={}",
86            sample_buffer
87                .resolve_range(0..1)
88                .map_or(0, |bytes| bytes.len())
89        );
90    }
91
92    let library = device
93        .new_library_with_source(common::COMPUTE_SRC)
94        .expect("compile compute library");
95    let increment = library
96        .new_function("increment")
97        .expect("increment function");
98    let pipeline = device
99        .new_compute_pipeline_state(&increment)
100        .expect("compute pipeline");
101    let visible_table = pipeline.new_visible_function_table(1);
102    let intersection_table = if device.supports_raytracing() {
103        pipeline.new_intersection_function_table(1)
104    } else {
105        None
106    };
107    if let Some(table) = intersection_table.as_ref() {
108        table.set_opaque_triangle_intersection_function(intersection_function_signature::NONE, 0);
109    }
110    let acceleration_structure = if device.supports_raytracing() {
111        device.new_acceleration_structure_with_size(256)
112    } else {
113        None
114    };
115
116    let buffer = device
117        .new_buffer(16, resource_options::STORAGE_MODE_SHARED)
118        .expect("compute buffer");
119    common::write_u32_words(&buffer, &[1, 2, 3, 4]);
120    let texture = device
121        .new_texture(apple_metal::TextureDescriptor::new_2d(
122            4,
123            4,
124            apple_metal::pixel_format::BGRA8UNORM,
125        ))
126        .expect("compute texture");
127    let compute = queue.new_command_buffer().expect("compute command buffer");
128    let encoder = compute
129        .new_compute_command_encoder()
130        .expect("compute command encoder");
131    encoder.set_compute_pipeline_state(&pipeline);
132    encoder.set_buffer(&buffer, 0, 0);
133    encoder.set_texture(&texture, 1);
134    if let Some(fence) = fence_a.as_ref() {
135        encoder.wait_for_fence(fence);
136    }
137    if let Some(table) = visible_table.as_ref() {
138        encoder.set_visible_function_table(table, 2);
139    }
140    if let Some(table) = intersection_table.as_ref() {
141        encoder.set_intersection_function_table(table, 3);
142    }
143    if let Some(acceleration_structure) = acceleration_structure.as_ref() {
144        encoder.set_acceleration_structure(acceleration_structure, 4);
145    }
146    encoder.dispatch_threadgroups((1, 1, 1), (4, 1, 1));
147    if let Some(fence) = fence_b.as_ref() {
148        encoder.update_fence(fence);
149    }
150    encoder.end_encoding();
151    compute.commit();
152    compute.wait_until_completed();
153    println!(
154        "compute buffer after dispatch: {:?}",
155        common::read_u32_words(&buffer, 4)
156    );
157
158    if let Some(indirect) = device.new_indirect_command_buffer(
159        indirect_command_type::CONCURRENT_DISPATCH,
160        1,
161        0,
162        0,
163        4,
164        resource_options::STORAGE_MODE_PRIVATE,
165    ) {
166        indirect.reset_range(0..1);
167        println!("indirect command buffer size={}", indirect.size());
168    }
169
170    if let Some(heap) = device.new_heap(1 << 20, storage_mode::SHARED) {
171        if let Ok(residency_set) = device.new_residency_set(Some("example-residency"), 4) {
172            let heap_buffer = heap
173                .new_buffer(256, resource_options::STORAGE_MODE_SHARED)
174                .expect("heap buffer");
175            residency_set.add_buffer(&heap_buffer);
176            residency_set.add_heap(&heap);
177            residency_set.commit();
178            residency_set.request_residency();
179            queue.add_residency_set(&residency_set);
180            queue.remove_residency_set(&residency_set);
181            residency_set.end_residency();
182            residency_set.remove_all_allocations();
183            residency_set.commit();
184            println!(
185                "residency allocation count={}",
186                residency_set.allocation_count()
187            );
188        } else {
189            println!("residency sets unavailable on this OS");
190        }
191    }
192
193    if let Some(capture_manager) = CaptureManager::shared() {
194        println!(
195            "capture supported for developer tools={} active={}",
196            capture_manager.supports_destination(capture_destination::DEVELOPER_TOOLS),
197            capture_manager.is_capturing(),
198        );
199        if let Some(scope) = capture_manager.new_capture_scope_with_device(&device) {
200            scope.begin();
201            scope.end();
202        }
203        if let Some(scope) = capture_manager.new_capture_scope_with_command_queue(&queue) {
204            scope.begin();
205            scope.end();
206        }
207    }
208}
Source

pub fn fill_buffer( &self, buffer: &MetalBuffer, range: Range<usize>, value: u8, ) -> bool

Fill a byte range of buffer with value.

Examples found in repository?
examples/05_render_and_explicit_encoders.rs (line 35)
11fn main() {
12    let device = MetalDevice::system_default().expect("Metal device available");
13    println!(
14        "device: {} (registry id {})",
15        device.name(),
16        device.registry_id()
17    );
18
19    let queue = device.new_command_queue().expect("command queue");
20    let status_buffer = queue
21        .new_command_buffer_with_unretained_references()
22        .expect("scratch command buffer");
23    println!("scratch command buffer status={}", status_buffer.status());
24
25    let src = device
26        .new_buffer(64, resource_options::STORAGE_MODE_SHARED)
27        .expect("source buffer");
28    let dst = device
29        .new_buffer(64, resource_options::STORAGE_MODE_SHARED)
30        .expect("destination buffer");
31    let blit_cb = queue.new_command_buffer().expect("blit command buffer");
32    let blit = blit_cb
33        .new_blit_command_encoder()
34        .expect("blit command encoder");
35    assert!(blit.fill_buffer(&src, 0..64, b'Z'));
36    assert!(blit.copy_buffer(&src, 0, &dst, 0, 64));
37    blit.end_encoding();
38    blit_cb.commit();
39    blit_cb.wait_until_completed();
40    let copied = unsafe {
41        core::slice::from_raw_parts(dst.contents().expect("dst contents").cast::<u8>(), 8)
42    };
43    println!("blit copied bytes: {copied:?}");
44
45    let library = device
46        .new_library_with_source(common::COMPUTE_SRC)
47        .expect("compile compute library");
48    let increment = library
49        .new_function("increment")
50        .expect("increment function");
51    let pipeline = device
52        .new_compute_pipeline_state(&increment)
53        .expect("compute pipeline");
54
55    let buffer = device
56        .new_buffer(16, resource_options::STORAGE_MODE_SHARED)
57        .expect("compute buffer");
58    common::write_u32_words(&buffer, &[10, 20, 30, 40]);
59    let compute_cb = queue.new_command_buffer().expect("compute command buffer");
60    let compute = compute_cb
61        .new_compute_command_encoder()
62        .expect("compute command encoder");
63    compute.set_compute_pipeline_state(&pipeline);
64    compute.set_buffer(&buffer, 0, 0);
65    compute.dispatch_threads((4, 1, 1), (1, 1, 1));
66    compute.end_encoding();
67    compute_cb.commit();
68    compute_cb.wait_until_completed();
69    println!("compute output: {:?}", common::read_u32_words(&buffer, 4));
70
71    let render_library = device
72        .new_library_with_source(common::RENDER_SRC)
73        .expect("compile render library");
74    let vertex = render_library
75        .new_function("fullscreen_vertex")
76        .expect("vertex function");
77    let fragment = render_library
78        .new_function("solid_fragment")
79        .expect("fragment function");
80    let render_pipeline = device
81        .new_render_pipeline_state(&vertex, &fragment, pixel_format::BGRA8UNORM, 1)
82        .expect("render pipeline");
83    println!("render pipeline label: {:?}", render_pipeline.label());
84
85    let render_target = device
86        .new_texture(common::shared_render_target(4, 4))
87        .expect("render target");
88    let vertex_buffer = device
89        .new_buffer(16, resource_options::STORAGE_MODE_SHARED)
90        .expect("vertex buffer");
91    let render_cb = queue.new_command_buffer().expect("render command buffer");
92    let render = render_cb
93        .new_render_command_encoder(
94            &render_target,
95            load_action::CLEAR,
96            store_action::STORE,
97            [0.0, 0.0, 0.0, 1.0],
98        )
99        .expect("render command encoder");
100    render.set_render_pipeline_state(&render_pipeline);
101    render.set_vertex_buffer(&vertex_buffer, 0, 0);
102    render.draw_primitives(primitive_type::TRIANGLE, 0, 3);
103    render.end_encoding();
104    render_cb.commit();
105    render_cb.wait_until_completed();
106
107    let mut rendered = vec![0_u8; 4 * 4 * 4];
108    assert!(render_target.read_bytes_2d(&mut rendered, 16, (0, 0), (4, 4), 0));
109    println!("first rendered pixel: {:?}", &rendered[..4]);
110
111    let shared_texture = device
112        .new_texture(TextureDescriptor::new_2d(4, 4, pixel_format::BGRA8UNORM))
113        .expect("shared texture");
114    let upload = vec![0x22_u8; 4 * 4 * 4];
115    assert!(shared_texture.replace_region_2d(&upload, 16, (0, 0), (4, 4), 0));
116    let mut download = vec![0_u8; upload.len()];
117    assert!(shared_texture.read_bytes_2d(&mut download, 16, (0, 0), (4, 4), 0));
118    let view = shared_texture
119        .new_view(pixel_format::BGRA8UNORM)
120        .expect("texture view");
121    println!(
122        "texture {}x{} usage={} storage_mode={} view_width={}",
123        shared_texture.width(),
124        shared_texture.height(),
125        shared_texture.usage(),
126        shared_texture.storage_mode(),
127        view.width(),
128    );
129}
More examples
Hide additional examples
examples/07_advanced_objects.rs (line 59)
11fn main() {
12    let device = MetalDevice::system_default().expect("Metal device available");
13    let queue = device.new_command_queue().expect("command queue");
14    let counter_sets = device.counter_set_names();
15    println!("counter sets: {counter_sets:?}");
16
17    if let Some(event) = device.new_shared_event() {
18        event.set_signaled_value(1);
19        println!("event signaled value={}", event.signaled_value());
20        let signal = queue
21            .new_command_buffer()
22            .expect("event signal command buffer");
23        signal.encode_signal_event(&event, 2);
24        signal.commit();
25        signal.wait_until_completed();
26        println!(
27            "event reached value 2: {}",
28            event.wait_until_signaled_value(2, 1_000),
29        );
30
31        let wait = queue
32            .new_command_buffer()
33            .expect("event wait command buffer");
34        wait.encode_wait_for_event(&event, 2);
35        wait.commit();
36        wait.wait_until_completed();
37    }
38
39    let fence_a = device.new_fence();
40    let fence_b = device.new_fence();
41    let sample_buffer = counter_sets.first().and_then(|name| {
42        if device.supports_counter_sampling(counter_sampling_point::AT_BLIT_BOUNDARY) {
43            device
44                .new_counter_sample_buffer(name, 2, storage_mode::SHARED, Some("example-samples"))
45                .ok()
46        } else {
47            None
48        }
49    });
50
51    let src = device
52        .new_buffer(64, resource_options::STORAGE_MODE_SHARED)
53        .expect("source buffer");
54    let dst = device
55        .new_buffer(64, resource_options::STORAGE_MODE_SHARED)
56        .expect("destination buffer");
57    let blit = queue.new_command_buffer().expect("blit command buffer");
58    let encoder = blit.new_blit_command_encoder().expect("blit encoder");
59    let _ = encoder.fill_buffer(&src, 0..64, b'Q');
60    if let Some(fence) = fence_a.as_ref() {
61        encoder.update_fence(fence);
62    }
63    encoder.end_encoding();
64    blit.commit();
65    blit.wait_until_completed();
66
67    let blit = queue
68        .new_command_buffer()
69        .expect("second blit command buffer");
70    let encoder = blit
71        .new_blit_command_encoder()
72        .expect("second blit encoder");
73    if let Some(fence) = fence_a.as_ref() {
74        encoder.wait_for_fence(fence);
75    }
76    if let Some(sample_buffer) = sample_buffer.as_ref() {
77        let _ = encoder.sample_counters(sample_buffer, 0, false);
78    }
79    let _ = encoder.copy_buffer(&src, 0, &dst, 0, 64);
80    encoder.end_encoding();
81    blit.commit();
82    blit.wait_until_completed();
83    if let Some(sample_buffer) = sample_buffer.as_ref() {
84        println!(
85            "resolved counter bytes={}",
86            sample_buffer
87                .resolve_range(0..1)
88                .map_or(0, |bytes| bytes.len())
89        );
90    }
91
92    let library = device
93        .new_library_with_source(common::COMPUTE_SRC)
94        .expect("compile compute library");
95    let increment = library
96        .new_function("increment")
97        .expect("increment function");
98    let pipeline = device
99        .new_compute_pipeline_state(&increment)
100        .expect("compute pipeline");
101    let visible_table = pipeline.new_visible_function_table(1);
102    let intersection_table = if device.supports_raytracing() {
103        pipeline.new_intersection_function_table(1)
104    } else {
105        None
106    };
107    if let Some(table) = intersection_table.as_ref() {
108        table.set_opaque_triangle_intersection_function(intersection_function_signature::NONE, 0);
109    }
110    let acceleration_structure = if device.supports_raytracing() {
111        device.new_acceleration_structure_with_size(256)
112    } else {
113        None
114    };
115
116    let buffer = device
117        .new_buffer(16, resource_options::STORAGE_MODE_SHARED)
118        .expect("compute buffer");
119    common::write_u32_words(&buffer, &[1, 2, 3, 4]);
120    let texture = device
121        .new_texture(apple_metal::TextureDescriptor::new_2d(
122            4,
123            4,
124            apple_metal::pixel_format::BGRA8UNORM,
125        ))
126        .expect("compute texture");
127    let compute = queue.new_command_buffer().expect("compute command buffer");
128    let encoder = compute
129        .new_compute_command_encoder()
130        .expect("compute command encoder");
131    encoder.set_compute_pipeline_state(&pipeline);
132    encoder.set_buffer(&buffer, 0, 0);
133    encoder.set_texture(&texture, 1);
134    if let Some(fence) = fence_a.as_ref() {
135        encoder.wait_for_fence(fence);
136    }
137    if let Some(table) = visible_table.as_ref() {
138        encoder.set_visible_function_table(table, 2);
139    }
140    if let Some(table) = intersection_table.as_ref() {
141        encoder.set_intersection_function_table(table, 3);
142    }
143    if let Some(acceleration_structure) = acceleration_structure.as_ref() {
144        encoder.set_acceleration_structure(acceleration_structure, 4);
145    }
146    encoder.dispatch_threadgroups((1, 1, 1), (4, 1, 1));
147    if let Some(fence) = fence_b.as_ref() {
148        encoder.update_fence(fence);
149    }
150    encoder.end_encoding();
151    compute.commit();
152    compute.wait_until_completed();
153    println!(
154        "compute buffer after dispatch: {:?}",
155        common::read_u32_words(&buffer, 4)
156    );
157
158    if let Some(indirect) = device.new_indirect_command_buffer(
159        indirect_command_type::CONCURRENT_DISPATCH,
160        1,
161        0,
162        0,
163        4,
164        resource_options::STORAGE_MODE_PRIVATE,
165    ) {
166        indirect.reset_range(0..1);
167        println!("indirect command buffer size={}", indirect.size());
168    }
169
170    if let Some(heap) = device.new_heap(1 << 20, storage_mode::SHARED) {
171        if let Ok(residency_set) = device.new_residency_set(Some("example-residency"), 4) {
172            let heap_buffer = heap
173                .new_buffer(256, resource_options::STORAGE_MODE_SHARED)
174                .expect("heap buffer");
175            residency_set.add_buffer(&heap_buffer);
176            residency_set.add_heap(&heap);
177            residency_set.commit();
178            residency_set.request_residency();
179            queue.add_residency_set(&residency_set);
180            queue.remove_residency_set(&residency_set);
181            residency_set.end_residency();
182            residency_set.remove_all_allocations();
183            residency_set.commit();
184            println!(
185                "residency allocation count={}",
186                residency_set.allocation_count()
187            );
188        } else {
189            println!("residency sets unavailable on this OS");
190        }
191    }
192
193    if let Some(capture_manager) = CaptureManager::shared() {
194        println!(
195            "capture supported for developer tools={} active={}",
196            capture_manager.supports_destination(capture_destination::DEVELOPER_TOOLS),
197            capture_manager.is_capturing(),
198        );
199        if let Some(scope) = capture_manager.new_capture_scope_with_device(&device) {
200            scope.begin();
201            scope.end();
202        }
203        if let Some(scope) = capture_manager.new_capture_scope_with_command_queue(&queue) {
204            scope.begin();
205            scope.end();
206        }
207    }
208}
Source

pub fn sample_counters( &self, sample_buffer: &CounterSampleBuffer, sample_index: usize, barrier: bool, ) -> bool

Sample hardware counters into sample_buffer.

Examples found in repository?
examples/07_advanced_objects.rs (line 77)
11fn main() {
12    let device = MetalDevice::system_default().expect("Metal device available");
13    let queue = device.new_command_queue().expect("command queue");
14    let counter_sets = device.counter_set_names();
15    println!("counter sets: {counter_sets:?}");
16
17    if let Some(event) = device.new_shared_event() {
18        event.set_signaled_value(1);
19        println!("event signaled value={}", event.signaled_value());
20        let signal = queue
21            .new_command_buffer()
22            .expect("event signal command buffer");
23        signal.encode_signal_event(&event, 2);
24        signal.commit();
25        signal.wait_until_completed();
26        println!(
27            "event reached value 2: {}",
28            event.wait_until_signaled_value(2, 1_000),
29        );
30
31        let wait = queue
32            .new_command_buffer()
33            .expect("event wait command buffer");
34        wait.encode_wait_for_event(&event, 2);
35        wait.commit();
36        wait.wait_until_completed();
37    }
38
39    let fence_a = device.new_fence();
40    let fence_b = device.new_fence();
41    let sample_buffer = counter_sets.first().and_then(|name| {
42        if device.supports_counter_sampling(counter_sampling_point::AT_BLIT_BOUNDARY) {
43            device
44                .new_counter_sample_buffer(name, 2, storage_mode::SHARED, Some("example-samples"))
45                .ok()
46        } else {
47            None
48        }
49    });
50
51    let src = device
52        .new_buffer(64, resource_options::STORAGE_MODE_SHARED)
53        .expect("source buffer");
54    let dst = device
55        .new_buffer(64, resource_options::STORAGE_MODE_SHARED)
56        .expect("destination buffer");
57    let blit = queue.new_command_buffer().expect("blit command buffer");
58    let encoder = blit.new_blit_command_encoder().expect("blit encoder");
59    let _ = encoder.fill_buffer(&src, 0..64, b'Q');
60    if let Some(fence) = fence_a.as_ref() {
61        encoder.update_fence(fence);
62    }
63    encoder.end_encoding();
64    blit.commit();
65    blit.wait_until_completed();
66
67    let blit = queue
68        .new_command_buffer()
69        .expect("second blit command buffer");
70    let encoder = blit
71        .new_blit_command_encoder()
72        .expect("second blit encoder");
73    if let Some(fence) = fence_a.as_ref() {
74        encoder.wait_for_fence(fence);
75    }
76    if let Some(sample_buffer) = sample_buffer.as_ref() {
77        let _ = encoder.sample_counters(sample_buffer, 0, false);
78    }
79    let _ = encoder.copy_buffer(&src, 0, &dst, 0, 64);
80    encoder.end_encoding();
81    blit.commit();
82    blit.wait_until_completed();
83    if let Some(sample_buffer) = sample_buffer.as_ref() {
84        println!(
85            "resolved counter bytes={}",
86            sample_buffer
87                .resolve_range(0..1)
88                .map_or(0, |bytes| bytes.len())
89        );
90    }
91
92    let library = device
93        .new_library_with_source(common::COMPUTE_SRC)
94        .expect("compile compute library");
95    let increment = library
96        .new_function("increment")
97        .expect("increment function");
98    let pipeline = device
99        .new_compute_pipeline_state(&increment)
100        .expect("compute pipeline");
101    let visible_table = pipeline.new_visible_function_table(1);
102    let intersection_table = if device.supports_raytracing() {
103        pipeline.new_intersection_function_table(1)
104    } else {
105        None
106    };
107    if let Some(table) = intersection_table.as_ref() {
108        table.set_opaque_triangle_intersection_function(intersection_function_signature::NONE, 0);
109    }
110    let acceleration_structure = if device.supports_raytracing() {
111        device.new_acceleration_structure_with_size(256)
112    } else {
113        None
114    };
115
116    let buffer = device
117        .new_buffer(16, resource_options::STORAGE_MODE_SHARED)
118        .expect("compute buffer");
119    common::write_u32_words(&buffer, &[1, 2, 3, 4]);
120    let texture = device
121        .new_texture(apple_metal::TextureDescriptor::new_2d(
122            4,
123            4,
124            apple_metal::pixel_format::BGRA8UNORM,
125        ))
126        .expect("compute texture");
127    let compute = queue.new_command_buffer().expect("compute command buffer");
128    let encoder = compute
129        .new_compute_command_encoder()
130        .expect("compute command encoder");
131    encoder.set_compute_pipeline_state(&pipeline);
132    encoder.set_buffer(&buffer, 0, 0);
133    encoder.set_texture(&texture, 1);
134    if let Some(fence) = fence_a.as_ref() {
135        encoder.wait_for_fence(fence);
136    }
137    if let Some(table) = visible_table.as_ref() {
138        encoder.set_visible_function_table(table, 2);
139    }
140    if let Some(table) = intersection_table.as_ref() {
141        encoder.set_intersection_function_table(table, 3);
142    }
143    if let Some(acceleration_structure) = acceleration_structure.as_ref() {
144        encoder.set_acceleration_structure(acceleration_structure, 4);
145    }
146    encoder.dispatch_threadgroups((1, 1, 1), (4, 1, 1));
147    if let Some(fence) = fence_b.as_ref() {
148        encoder.update_fence(fence);
149    }
150    encoder.end_encoding();
151    compute.commit();
152    compute.wait_until_completed();
153    println!(
154        "compute buffer after dispatch: {:?}",
155        common::read_u32_words(&buffer, 4)
156    );
157
158    if let Some(indirect) = device.new_indirect_command_buffer(
159        indirect_command_type::CONCURRENT_DISPATCH,
160        1,
161        0,
162        0,
163        4,
164        resource_options::STORAGE_MODE_PRIVATE,
165    ) {
166        indirect.reset_range(0..1);
167        println!("indirect command buffer size={}", indirect.size());
168    }
169
170    if let Some(heap) = device.new_heap(1 << 20, storage_mode::SHARED) {
171        if let Ok(residency_set) = device.new_residency_set(Some("example-residency"), 4) {
172            let heap_buffer = heap
173                .new_buffer(256, resource_options::STORAGE_MODE_SHARED)
174                .expect("heap buffer");
175            residency_set.add_buffer(&heap_buffer);
176            residency_set.add_heap(&heap);
177            residency_set.commit();
178            residency_set.request_residency();
179            queue.add_residency_set(&residency_set);
180            queue.remove_residency_set(&residency_set);
181            residency_set.end_residency();
182            residency_set.remove_all_allocations();
183            residency_set.commit();
184            println!(
185                "residency allocation count={}",
186                residency_set.allocation_count()
187            );
188        } else {
189            println!("residency sets unavailable on this OS");
190        }
191    }
192
193    if let Some(capture_manager) = CaptureManager::shared() {
194        println!(
195            "capture supported for developer tools={} active={}",
196            capture_manager.supports_destination(capture_destination::DEVELOPER_TOOLS),
197            capture_manager.is_capturing(),
198        );
199        if let Some(scope) = capture_manager.new_capture_scope_with_device(&device) {
200            scope.begin();
201            scope.end();
202        }
203        if let Some(scope) = capture_manager.new_capture_scope_with_command_queue(&queue) {
204            scope.begin();
205            scope.end();
206        }
207    }
208}
Source

pub fn update_fence(&self, fence: &Fence)

Update fence with work encoded so far.

Examples found in repository?
examples/07_advanced_objects.rs (line 61)
11fn main() {
12    let device = MetalDevice::system_default().expect("Metal device available");
13    let queue = device.new_command_queue().expect("command queue");
14    let counter_sets = device.counter_set_names();
15    println!("counter sets: {counter_sets:?}");
16
17    if let Some(event) = device.new_shared_event() {
18        event.set_signaled_value(1);
19        println!("event signaled value={}", event.signaled_value());
20        let signal = queue
21            .new_command_buffer()
22            .expect("event signal command buffer");
23        signal.encode_signal_event(&event, 2);
24        signal.commit();
25        signal.wait_until_completed();
26        println!(
27            "event reached value 2: {}",
28            event.wait_until_signaled_value(2, 1_000),
29        );
30
31        let wait = queue
32            .new_command_buffer()
33            .expect("event wait command buffer");
34        wait.encode_wait_for_event(&event, 2);
35        wait.commit();
36        wait.wait_until_completed();
37    }
38
39    let fence_a = device.new_fence();
40    let fence_b = device.new_fence();
41    let sample_buffer = counter_sets.first().and_then(|name| {
42        if device.supports_counter_sampling(counter_sampling_point::AT_BLIT_BOUNDARY) {
43            device
44                .new_counter_sample_buffer(name, 2, storage_mode::SHARED, Some("example-samples"))
45                .ok()
46        } else {
47            None
48        }
49    });
50
51    let src = device
52        .new_buffer(64, resource_options::STORAGE_MODE_SHARED)
53        .expect("source buffer");
54    let dst = device
55        .new_buffer(64, resource_options::STORAGE_MODE_SHARED)
56        .expect("destination buffer");
57    let blit = queue.new_command_buffer().expect("blit command buffer");
58    let encoder = blit.new_blit_command_encoder().expect("blit encoder");
59    let _ = encoder.fill_buffer(&src, 0..64, b'Q');
60    if let Some(fence) = fence_a.as_ref() {
61        encoder.update_fence(fence);
62    }
63    encoder.end_encoding();
64    blit.commit();
65    blit.wait_until_completed();
66
67    let blit = queue
68        .new_command_buffer()
69        .expect("second blit command buffer");
70    let encoder = blit
71        .new_blit_command_encoder()
72        .expect("second blit encoder");
73    if let Some(fence) = fence_a.as_ref() {
74        encoder.wait_for_fence(fence);
75    }
76    if let Some(sample_buffer) = sample_buffer.as_ref() {
77        let _ = encoder.sample_counters(sample_buffer, 0, false);
78    }
79    let _ = encoder.copy_buffer(&src, 0, &dst, 0, 64);
80    encoder.end_encoding();
81    blit.commit();
82    blit.wait_until_completed();
83    if let Some(sample_buffer) = sample_buffer.as_ref() {
84        println!(
85            "resolved counter bytes={}",
86            sample_buffer
87                .resolve_range(0..1)
88                .map_or(0, |bytes| bytes.len())
89        );
90    }
91
92    let library = device
93        .new_library_with_source(common::COMPUTE_SRC)
94        .expect("compile compute library");
95    let increment = library
96        .new_function("increment")
97        .expect("increment function");
98    let pipeline = device
99        .new_compute_pipeline_state(&increment)
100        .expect("compute pipeline");
101    let visible_table = pipeline.new_visible_function_table(1);
102    let intersection_table = if device.supports_raytracing() {
103        pipeline.new_intersection_function_table(1)
104    } else {
105        None
106    };
107    if let Some(table) = intersection_table.as_ref() {
108        table.set_opaque_triangle_intersection_function(intersection_function_signature::NONE, 0);
109    }
110    let acceleration_structure = if device.supports_raytracing() {
111        device.new_acceleration_structure_with_size(256)
112    } else {
113        None
114    };
115
116    let buffer = device
117        .new_buffer(16, resource_options::STORAGE_MODE_SHARED)
118        .expect("compute buffer");
119    common::write_u32_words(&buffer, &[1, 2, 3, 4]);
120    let texture = device
121        .new_texture(apple_metal::TextureDescriptor::new_2d(
122            4,
123            4,
124            apple_metal::pixel_format::BGRA8UNORM,
125        ))
126        .expect("compute texture");
127    let compute = queue.new_command_buffer().expect("compute command buffer");
128    let encoder = compute
129        .new_compute_command_encoder()
130        .expect("compute command encoder");
131    encoder.set_compute_pipeline_state(&pipeline);
132    encoder.set_buffer(&buffer, 0, 0);
133    encoder.set_texture(&texture, 1);
134    if let Some(fence) = fence_a.as_ref() {
135        encoder.wait_for_fence(fence);
136    }
137    if let Some(table) = visible_table.as_ref() {
138        encoder.set_visible_function_table(table, 2);
139    }
140    if let Some(table) = intersection_table.as_ref() {
141        encoder.set_intersection_function_table(table, 3);
142    }
143    if let Some(acceleration_structure) = acceleration_structure.as_ref() {
144        encoder.set_acceleration_structure(acceleration_structure, 4);
145    }
146    encoder.dispatch_threadgroups((1, 1, 1), (4, 1, 1));
147    if let Some(fence) = fence_b.as_ref() {
148        encoder.update_fence(fence);
149    }
150    encoder.end_encoding();
151    compute.commit();
152    compute.wait_until_completed();
153    println!(
154        "compute buffer after dispatch: {:?}",
155        common::read_u32_words(&buffer, 4)
156    );
157
158    if let Some(indirect) = device.new_indirect_command_buffer(
159        indirect_command_type::CONCURRENT_DISPATCH,
160        1,
161        0,
162        0,
163        4,
164        resource_options::STORAGE_MODE_PRIVATE,
165    ) {
166        indirect.reset_range(0..1);
167        println!("indirect command buffer size={}", indirect.size());
168    }
169
170    if let Some(heap) = device.new_heap(1 << 20, storage_mode::SHARED) {
171        if let Ok(residency_set) = device.new_residency_set(Some("example-residency"), 4) {
172            let heap_buffer = heap
173                .new_buffer(256, resource_options::STORAGE_MODE_SHARED)
174                .expect("heap buffer");
175            residency_set.add_buffer(&heap_buffer);
176            residency_set.add_heap(&heap);
177            residency_set.commit();
178            residency_set.request_residency();
179            queue.add_residency_set(&residency_set);
180            queue.remove_residency_set(&residency_set);
181            residency_set.end_residency();
182            residency_set.remove_all_allocations();
183            residency_set.commit();
184            println!(
185                "residency allocation count={}",
186                residency_set.allocation_count()
187            );
188        } else {
189            println!("residency sets unavailable on this OS");
190        }
191    }
192
193    if let Some(capture_manager) = CaptureManager::shared() {
194        println!(
195            "capture supported for developer tools={} active={}",
196            capture_manager.supports_destination(capture_destination::DEVELOPER_TOOLS),
197            capture_manager.is_capturing(),
198        );
199        if let Some(scope) = capture_manager.new_capture_scope_with_device(&device) {
200            scope.begin();
201            scope.end();
202        }
203        if let Some(scope) = capture_manager.new_capture_scope_with_command_queue(&queue) {
204            scope.begin();
205            scope.end();
206        }
207    }
208}
Source

pub fn wait_for_fence(&self, fence: &Fence)

Wait for fence before executing subsequent work.

Examples found in repository?
examples/07_advanced_objects.rs (line 74)
11fn main() {
12    let device = MetalDevice::system_default().expect("Metal device available");
13    let queue = device.new_command_queue().expect("command queue");
14    let counter_sets = device.counter_set_names();
15    println!("counter sets: {counter_sets:?}");
16
17    if let Some(event) = device.new_shared_event() {
18        event.set_signaled_value(1);
19        println!("event signaled value={}", event.signaled_value());
20        let signal = queue
21            .new_command_buffer()
22            .expect("event signal command buffer");
23        signal.encode_signal_event(&event, 2);
24        signal.commit();
25        signal.wait_until_completed();
26        println!(
27            "event reached value 2: {}",
28            event.wait_until_signaled_value(2, 1_000),
29        );
30
31        let wait = queue
32            .new_command_buffer()
33            .expect("event wait command buffer");
34        wait.encode_wait_for_event(&event, 2);
35        wait.commit();
36        wait.wait_until_completed();
37    }
38
39    let fence_a = device.new_fence();
40    let fence_b = device.new_fence();
41    let sample_buffer = counter_sets.first().and_then(|name| {
42        if device.supports_counter_sampling(counter_sampling_point::AT_BLIT_BOUNDARY) {
43            device
44                .new_counter_sample_buffer(name, 2, storage_mode::SHARED, Some("example-samples"))
45                .ok()
46        } else {
47            None
48        }
49    });
50
51    let src = device
52        .new_buffer(64, resource_options::STORAGE_MODE_SHARED)
53        .expect("source buffer");
54    let dst = device
55        .new_buffer(64, resource_options::STORAGE_MODE_SHARED)
56        .expect("destination buffer");
57    let blit = queue.new_command_buffer().expect("blit command buffer");
58    let encoder = blit.new_blit_command_encoder().expect("blit encoder");
59    let _ = encoder.fill_buffer(&src, 0..64, b'Q');
60    if let Some(fence) = fence_a.as_ref() {
61        encoder.update_fence(fence);
62    }
63    encoder.end_encoding();
64    blit.commit();
65    blit.wait_until_completed();
66
67    let blit = queue
68        .new_command_buffer()
69        .expect("second blit command buffer");
70    let encoder = blit
71        .new_blit_command_encoder()
72        .expect("second blit encoder");
73    if let Some(fence) = fence_a.as_ref() {
74        encoder.wait_for_fence(fence);
75    }
76    if let Some(sample_buffer) = sample_buffer.as_ref() {
77        let _ = encoder.sample_counters(sample_buffer, 0, false);
78    }
79    let _ = encoder.copy_buffer(&src, 0, &dst, 0, 64);
80    encoder.end_encoding();
81    blit.commit();
82    blit.wait_until_completed();
83    if let Some(sample_buffer) = sample_buffer.as_ref() {
84        println!(
85            "resolved counter bytes={}",
86            sample_buffer
87                .resolve_range(0..1)
88                .map_or(0, |bytes| bytes.len())
89        );
90    }
91
92    let library = device
93        .new_library_with_source(common::COMPUTE_SRC)
94        .expect("compile compute library");
95    let increment = library
96        .new_function("increment")
97        .expect("increment function");
98    let pipeline = device
99        .new_compute_pipeline_state(&increment)
100        .expect("compute pipeline");
101    let visible_table = pipeline.new_visible_function_table(1);
102    let intersection_table = if device.supports_raytracing() {
103        pipeline.new_intersection_function_table(1)
104    } else {
105        None
106    };
107    if let Some(table) = intersection_table.as_ref() {
108        table.set_opaque_triangle_intersection_function(intersection_function_signature::NONE, 0);
109    }
110    let acceleration_structure = if device.supports_raytracing() {
111        device.new_acceleration_structure_with_size(256)
112    } else {
113        None
114    };
115
116    let buffer = device
117        .new_buffer(16, resource_options::STORAGE_MODE_SHARED)
118        .expect("compute buffer");
119    common::write_u32_words(&buffer, &[1, 2, 3, 4]);
120    let texture = device
121        .new_texture(apple_metal::TextureDescriptor::new_2d(
122            4,
123            4,
124            apple_metal::pixel_format::BGRA8UNORM,
125        ))
126        .expect("compute texture");
127    let compute = queue.new_command_buffer().expect("compute command buffer");
128    let encoder = compute
129        .new_compute_command_encoder()
130        .expect("compute command encoder");
131    encoder.set_compute_pipeline_state(&pipeline);
132    encoder.set_buffer(&buffer, 0, 0);
133    encoder.set_texture(&texture, 1);
134    if let Some(fence) = fence_a.as_ref() {
135        encoder.wait_for_fence(fence);
136    }
137    if let Some(table) = visible_table.as_ref() {
138        encoder.set_visible_function_table(table, 2);
139    }
140    if let Some(table) = intersection_table.as_ref() {
141        encoder.set_intersection_function_table(table, 3);
142    }
143    if let Some(acceleration_structure) = acceleration_structure.as_ref() {
144        encoder.set_acceleration_structure(acceleration_structure, 4);
145    }
146    encoder.dispatch_threadgroups((1, 1, 1), (4, 1, 1));
147    if let Some(fence) = fence_b.as_ref() {
148        encoder.update_fence(fence);
149    }
150    encoder.end_encoding();
151    compute.commit();
152    compute.wait_until_completed();
153    println!(
154        "compute buffer after dispatch: {:?}",
155        common::read_u32_words(&buffer, 4)
156    );
157
158    if let Some(indirect) = device.new_indirect_command_buffer(
159        indirect_command_type::CONCURRENT_DISPATCH,
160        1,
161        0,
162        0,
163        4,
164        resource_options::STORAGE_MODE_PRIVATE,
165    ) {
166        indirect.reset_range(0..1);
167        println!("indirect command buffer size={}", indirect.size());
168    }
169
170    if let Some(heap) = device.new_heap(1 << 20, storage_mode::SHARED) {
171        if let Ok(residency_set) = device.new_residency_set(Some("example-residency"), 4) {
172            let heap_buffer = heap
173                .new_buffer(256, resource_options::STORAGE_MODE_SHARED)
174                .expect("heap buffer");
175            residency_set.add_buffer(&heap_buffer);
176            residency_set.add_heap(&heap);
177            residency_set.commit();
178            residency_set.request_residency();
179            queue.add_residency_set(&residency_set);
180            queue.remove_residency_set(&residency_set);
181            residency_set.end_residency();
182            residency_set.remove_all_allocations();
183            residency_set.commit();
184            println!(
185                "residency allocation count={}",
186                residency_set.allocation_count()
187            );
188        } else {
189            println!("residency sets unavailable on this OS");
190        }
191    }
192
193    if let Some(capture_manager) = CaptureManager::shared() {
194        println!(
195            "capture supported for developer tools={} active={}",
196            capture_manager.supports_destination(capture_destination::DEVELOPER_TOOLS),
197            capture_manager.is_capturing(),
198        );
199        if let Some(scope) = capture_manager.new_capture_scope_with_device(&device) {
200            scope.begin();
201            scope.end();
202        }
203        if let Some(scope) = capture_manager.new_capture_scope_with_command_queue(&queue) {
204            scope.begin();
205            scope.end();
206        }
207    }
208}
Source

pub fn end_encoding(&self)

Finish encoding commands.

Examples found in repository?
examples/05_render_and_explicit_encoders.rs (line 37)
11fn main() {
12    let device = MetalDevice::system_default().expect("Metal device available");
13    println!(
14        "device: {} (registry id {})",
15        device.name(),
16        device.registry_id()
17    );
18
19    let queue = device.new_command_queue().expect("command queue");
20    let status_buffer = queue
21        .new_command_buffer_with_unretained_references()
22        .expect("scratch command buffer");
23    println!("scratch command buffer status={}", status_buffer.status());
24
25    let src = device
26        .new_buffer(64, resource_options::STORAGE_MODE_SHARED)
27        .expect("source buffer");
28    let dst = device
29        .new_buffer(64, resource_options::STORAGE_MODE_SHARED)
30        .expect("destination buffer");
31    let blit_cb = queue.new_command_buffer().expect("blit command buffer");
32    let blit = blit_cb
33        .new_blit_command_encoder()
34        .expect("blit command encoder");
35    assert!(blit.fill_buffer(&src, 0..64, b'Z'));
36    assert!(blit.copy_buffer(&src, 0, &dst, 0, 64));
37    blit.end_encoding();
38    blit_cb.commit();
39    blit_cb.wait_until_completed();
40    let copied = unsafe {
41        core::slice::from_raw_parts(dst.contents().expect("dst contents").cast::<u8>(), 8)
42    };
43    println!("blit copied bytes: {copied:?}");
44
45    let library = device
46        .new_library_with_source(common::COMPUTE_SRC)
47        .expect("compile compute library");
48    let increment = library
49        .new_function("increment")
50        .expect("increment function");
51    let pipeline = device
52        .new_compute_pipeline_state(&increment)
53        .expect("compute pipeline");
54
55    let buffer = device
56        .new_buffer(16, resource_options::STORAGE_MODE_SHARED)
57        .expect("compute buffer");
58    common::write_u32_words(&buffer, &[10, 20, 30, 40]);
59    let compute_cb = queue.new_command_buffer().expect("compute command buffer");
60    let compute = compute_cb
61        .new_compute_command_encoder()
62        .expect("compute command encoder");
63    compute.set_compute_pipeline_state(&pipeline);
64    compute.set_buffer(&buffer, 0, 0);
65    compute.dispatch_threads((4, 1, 1), (1, 1, 1));
66    compute.end_encoding();
67    compute_cb.commit();
68    compute_cb.wait_until_completed();
69    println!("compute output: {:?}", common::read_u32_words(&buffer, 4));
70
71    let render_library = device
72        .new_library_with_source(common::RENDER_SRC)
73        .expect("compile render library");
74    let vertex = render_library
75        .new_function("fullscreen_vertex")
76        .expect("vertex function");
77    let fragment = render_library
78        .new_function("solid_fragment")
79        .expect("fragment function");
80    let render_pipeline = device
81        .new_render_pipeline_state(&vertex, &fragment, pixel_format::BGRA8UNORM, 1)
82        .expect("render pipeline");
83    println!("render pipeline label: {:?}", render_pipeline.label());
84
85    let render_target = device
86        .new_texture(common::shared_render_target(4, 4))
87        .expect("render target");
88    let vertex_buffer = device
89        .new_buffer(16, resource_options::STORAGE_MODE_SHARED)
90        .expect("vertex buffer");
91    let render_cb = queue.new_command_buffer().expect("render command buffer");
92    let render = render_cb
93        .new_render_command_encoder(
94            &render_target,
95            load_action::CLEAR,
96            store_action::STORE,
97            [0.0, 0.0, 0.0, 1.0],
98        )
99        .expect("render command encoder");
100    render.set_render_pipeline_state(&render_pipeline);
101    render.set_vertex_buffer(&vertex_buffer, 0, 0);
102    render.draw_primitives(primitive_type::TRIANGLE, 0, 3);
103    render.end_encoding();
104    render_cb.commit();
105    render_cb.wait_until_completed();
106
107    let mut rendered = vec![0_u8; 4 * 4 * 4];
108    assert!(render_target.read_bytes_2d(&mut rendered, 16, (0, 0), (4, 4), 0));
109    println!("first rendered pixel: {:?}", &rendered[..4]);
110
111    let shared_texture = device
112        .new_texture(TextureDescriptor::new_2d(4, 4, pixel_format::BGRA8UNORM))
113        .expect("shared texture");
114    let upload = vec![0x22_u8; 4 * 4 * 4];
115    assert!(shared_texture.replace_region_2d(&upload, 16, (0, 0), (4, 4), 0));
116    let mut download = vec![0_u8; upload.len()];
117    assert!(shared_texture.read_bytes_2d(&mut download, 16, (0, 0), (4, 4), 0));
118    let view = shared_texture
119        .new_view(pixel_format::BGRA8UNORM)
120        .expect("texture view");
121    println!(
122        "texture {}x{} usage={} storage_mode={} view_width={}",
123        shared_texture.width(),
124        shared_texture.height(),
125        shared_texture.usage(),
126        shared_texture.storage_mode(),
127        view.width(),
128    );
129}
More examples
Hide additional examples
examples/07_advanced_objects.rs (line 63)
11fn main() {
12    let device = MetalDevice::system_default().expect("Metal device available");
13    let queue = device.new_command_queue().expect("command queue");
14    let counter_sets = device.counter_set_names();
15    println!("counter sets: {counter_sets:?}");
16
17    if let Some(event) = device.new_shared_event() {
18        event.set_signaled_value(1);
19        println!("event signaled value={}", event.signaled_value());
20        let signal = queue
21            .new_command_buffer()
22            .expect("event signal command buffer");
23        signal.encode_signal_event(&event, 2);
24        signal.commit();
25        signal.wait_until_completed();
26        println!(
27            "event reached value 2: {}",
28            event.wait_until_signaled_value(2, 1_000),
29        );
30
31        let wait = queue
32            .new_command_buffer()
33            .expect("event wait command buffer");
34        wait.encode_wait_for_event(&event, 2);
35        wait.commit();
36        wait.wait_until_completed();
37    }
38
39    let fence_a = device.new_fence();
40    let fence_b = device.new_fence();
41    let sample_buffer = counter_sets.first().and_then(|name| {
42        if device.supports_counter_sampling(counter_sampling_point::AT_BLIT_BOUNDARY) {
43            device
44                .new_counter_sample_buffer(name, 2, storage_mode::SHARED, Some("example-samples"))
45                .ok()
46        } else {
47            None
48        }
49    });
50
51    let src = device
52        .new_buffer(64, resource_options::STORAGE_MODE_SHARED)
53        .expect("source buffer");
54    let dst = device
55        .new_buffer(64, resource_options::STORAGE_MODE_SHARED)
56        .expect("destination buffer");
57    let blit = queue.new_command_buffer().expect("blit command buffer");
58    let encoder = blit.new_blit_command_encoder().expect("blit encoder");
59    let _ = encoder.fill_buffer(&src, 0..64, b'Q');
60    if let Some(fence) = fence_a.as_ref() {
61        encoder.update_fence(fence);
62    }
63    encoder.end_encoding();
64    blit.commit();
65    blit.wait_until_completed();
66
67    let blit = queue
68        .new_command_buffer()
69        .expect("second blit command buffer");
70    let encoder = blit
71        .new_blit_command_encoder()
72        .expect("second blit encoder");
73    if let Some(fence) = fence_a.as_ref() {
74        encoder.wait_for_fence(fence);
75    }
76    if let Some(sample_buffer) = sample_buffer.as_ref() {
77        let _ = encoder.sample_counters(sample_buffer, 0, false);
78    }
79    let _ = encoder.copy_buffer(&src, 0, &dst, 0, 64);
80    encoder.end_encoding();
81    blit.commit();
82    blit.wait_until_completed();
83    if let Some(sample_buffer) = sample_buffer.as_ref() {
84        println!(
85            "resolved counter bytes={}",
86            sample_buffer
87                .resolve_range(0..1)
88                .map_or(0, |bytes| bytes.len())
89        );
90    }
91
92    let library = device
93        .new_library_with_source(common::COMPUTE_SRC)
94        .expect("compile compute library");
95    let increment = library
96        .new_function("increment")
97        .expect("increment function");
98    let pipeline = device
99        .new_compute_pipeline_state(&increment)
100        .expect("compute pipeline");
101    let visible_table = pipeline.new_visible_function_table(1);
102    let intersection_table = if device.supports_raytracing() {
103        pipeline.new_intersection_function_table(1)
104    } else {
105        None
106    };
107    if let Some(table) = intersection_table.as_ref() {
108        table.set_opaque_triangle_intersection_function(intersection_function_signature::NONE, 0);
109    }
110    let acceleration_structure = if device.supports_raytracing() {
111        device.new_acceleration_structure_with_size(256)
112    } else {
113        None
114    };
115
116    let buffer = device
117        .new_buffer(16, resource_options::STORAGE_MODE_SHARED)
118        .expect("compute buffer");
119    common::write_u32_words(&buffer, &[1, 2, 3, 4]);
120    let texture = device
121        .new_texture(apple_metal::TextureDescriptor::new_2d(
122            4,
123            4,
124            apple_metal::pixel_format::BGRA8UNORM,
125        ))
126        .expect("compute texture");
127    let compute = queue.new_command_buffer().expect("compute command buffer");
128    let encoder = compute
129        .new_compute_command_encoder()
130        .expect("compute command encoder");
131    encoder.set_compute_pipeline_state(&pipeline);
132    encoder.set_buffer(&buffer, 0, 0);
133    encoder.set_texture(&texture, 1);
134    if let Some(fence) = fence_a.as_ref() {
135        encoder.wait_for_fence(fence);
136    }
137    if let Some(table) = visible_table.as_ref() {
138        encoder.set_visible_function_table(table, 2);
139    }
140    if let Some(table) = intersection_table.as_ref() {
141        encoder.set_intersection_function_table(table, 3);
142    }
143    if let Some(acceleration_structure) = acceleration_structure.as_ref() {
144        encoder.set_acceleration_structure(acceleration_structure, 4);
145    }
146    encoder.dispatch_threadgroups((1, 1, 1), (4, 1, 1));
147    if let Some(fence) = fence_b.as_ref() {
148        encoder.update_fence(fence);
149    }
150    encoder.end_encoding();
151    compute.commit();
152    compute.wait_until_completed();
153    println!(
154        "compute buffer after dispatch: {:?}",
155        common::read_u32_words(&buffer, 4)
156    );
157
158    if let Some(indirect) = device.new_indirect_command_buffer(
159        indirect_command_type::CONCURRENT_DISPATCH,
160        1,
161        0,
162        0,
163        4,
164        resource_options::STORAGE_MODE_PRIVATE,
165    ) {
166        indirect.reset_range(0..1);
167        println!("indirect command buffer size={}", indirect.size());
168    }
169
170    if let Some(heap) = device.new_heap(1 << 20, storage_mode::SHARED) {
171        if let Ok(residency_set) = device.new_residency_set(Some("example-residency"), 4) {
172            let heap_buffer = heap
173                .new_buffer(256, resource_options::STORAGE_MODE_SHARED)
174                .expect("heap buffer");
175            residency_set.add_buffer(&heap_buffer);
176            residency_set.add_heap(&heap);
177            residency_set.commit();
178            residency_set.request_residency();
179            queue.add_residency_set(&residency_set);
180            queue.remove_residency_set(&residency_set);
181            residency_set.end_residency();
182            residency_set.remove_all_allocations();
183            residency_set.commit();
184            println!(
185                "residency allocation count={}",
186                residency_set.allocation_count()
187            );
188        } else {
189            println!("residency sets unavailable on this OS");
190        }
191    }
192
193    if let Some(capture_manager) = CaptureManager::shared() {
194        println!(
195            "capture supported for developer tools={} active={}",
196            capture_manager.supports_destination(capture_destination::DEVELOPER_TOOLS),
197            capture_manager.is_capturing(),
198        );
199        if let Some(scope) = capture_manager.new_capture_scope_with_device(&device) {
200            scope.begin();
201            scope.end();
202        }
203        if let Some(scope) = capture_manager.new_capture_scope_with_command_queue(&queue) {
204            scope.begin();
205            scope.end();
206        }
207    }
208}

Trait Implementations§

Source§

impl Drop for BlitCommandEncoder

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.