05_render_and_explicit_encoders/
05_render_and_explicit_encoders.rs1#![allow(clippy::too_many_lines)]
2
3#[path = "common/mod.rs"]
4mod common;
5
6use apple_metal::{
7 load_action, pixel_format, primitive_type, resource_options, store_action, MetalDevice,
8 TextureDescriptor,
9};
10
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}