pub struct TextureDescriptor {
pub pixel_format: usize,
pub width: usize,
pub height: usize,
pub mipmapped: bool,
pub usage: usize,
pub storage_mode: usize,
}Expand description
Configuration for MetalDevice::new_texture.
Fields§
§pixel_format: usizeMirrors the Metal framework property for pixel_format.
width: usizeMirrors the Metal framework property for width.
height: usizeMirrors the Metal framework property for height.
mipmapped: boolMirrors the Metal framework property for mipmapped.
usage: usizeMirrors the Metal framework property for usage.
storage_mode: usizeMirrors the Metal framework property for storage_mode.
Implementations§
Source§impl TextureDescriptor
impl TextureDescriptor
Sourcepub const fn render_target_2d(
width: usize,
height: usize,
pixel_format: usize,
) -> Self
pub const fn render_target_2d( width: usize, height: usize, pixel_format: usize, ) -> Self
Sensible defaults for an offscreen 2D render target texture.
Source§impl TextureDescriptor
impl TextureDescriptor
Sourcepub const fn new_2d(width: usize, height: usize, pixel_format: usize) -> Self
pub const fn new_2d(width: usize, height: usize, pixel_format: usize) -> Self
Sensible defaults for a shader-read+write 2D texture in shared storage.
Examples found in repository?
examples/02_caps_buffer_texture.rs (lines 25-29)
3fn main() {
4 let d = MetalDevice::system_default().expect("no Metal");
5 println!("unified memory: {}", d.has_unified_memory());
6 println!(
7 "recommended max working set: {} MB",
8 d.recommended_max_working_set_size() / (1024 * 1024)
9 );
10 println!("supports Metal3: {}", d.supports_family(gpu_family::METAL3));
11 println!("supports Apple7: {}", d.supports_family(gpu_family::APPLE7));
12
13 let buf = d
14 .new_buffer(4096, resource_options::STORAGE_MODE_SHARED)
15 .expect("buffer create failed");
16 println!(
17 "buffer {} bytes, contents={:?}",
18 buf.length(),
19 buf.contents().is_some()
20 );
21 let n = buf.write_bytes(b"hello metal");
22 println!("wrote {n} bytes");
23
24 let tx = d
25 .new_texture(TextureDescriptor::new_2d(
26 256,
27 256,
28 pixel_format::BGRA8UNORM,
29 ))
30 .expect("texture create failed");
31 println!(
32 "texture {}x{} fmt={}",
33 tx.width(),
34 tx.height(),
35 tx.pixel_format()
36 );
37}More examples
examples/05_render_and_explicit_encoders.rs (line 112)
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}examples/06_resources_and_archives.rs (line 37)
10fn main() {
11 let device = MetalDevice::system_default().expect("Metal device available");
12 println!("device: {}", device.name());
13
14 let queue = device
15 .new_command_queue_with_max_command_buffer_count(4)
16 .expect("bounded command queue");
17 let scratch = queue
18 .new_command_buffer_with_unretained_references()
19 .expect("bounded scratch command buffer");
20 println!("bounded queue scratch status={}", scratch.status());
21
22 let library = device
23 .new_library_with_source(common::COMPUTE_SRC)
24 .expect("compile compute library");
25 let args = library.new_function("use_args").expect("use_args function");
26 let argument_encoder = args.new_argument_encoder(0).expect("argument encoder");
27 let argument_buffer = device
28 .new_buffer(
29 argument_encoder.encoded_length(),
30 resource_options::STORAGE_MODE_SHARED,
31 )
32 .expect("argument buffer");
33 let payload = device
34 .new_buffer(16, resource_options::STORAGE_MODE_SHARED)
35 .expect("payload buffer");
36 let texture = device
37 .new_texture(TextureDescriptor::new_2d(4, 4, pixel_format::BGRA8UNORM))
38 .expect("argument texture");
39 argument_encoder.set_argument_buffer(&argument_buffer, 0);
40 argument_encoder.set_buffer(&payload, 0, 0);
41 argument_encoder.set_texture(&texture, 1);
42 println!(
43 "argument encoder length={} alignment={}",
44 argument_encoder.encoded_length(),
45 argument_encoder.alignment(),
46 );
47
48 let backing = device
49 .new_buffer(256, resource_options::STORAGE_MODE_SHARED)
50 .expect("backing buffer");
51 let buffer_texture = backing
52 .new_texture_view_2d(pixel_format::BGRA8UNORM, 16, 4, 64, 0)
53 .expect("buffer-backed texture");
54 println!(
55 "buffer-backed texture {}x{} fmt={}",
56 buffer_texture.width(),
57 buffer_texture.height(),
58 buffer_texture.pixel_format(),
59 );
60
61 if let Some(heap) = device.new_heap(1 << 20, storage_mode::SHARED) {
62 let heap_buffer = heap
63 .new_buffer(256, resource_options::STORAGE_MODE_SHARED)
64 .expect("heap buffer");
65 let heap_texture = heap
66 .new_texture(TextureDescriptor::new_2d(4, 4, pixel_format::BGRA8UNORM))
67 .expect("heap texture");
68 println!(
69 "heap size={} used={} current={} max_available={}",
70 heap.size(),
71 heap.used_size(),
72 heap.current_allocated_size(),
73 heap.max_available_size(256),
74 );
75 println!(
76 "heap buffer len={} heap texture {}x{} purgeable={}",
77 heap_buffer.length(),
78 heap_texture.width(),
79 heap_texture.height(),
80 heap.set_purgeable_state(apple_metal::purgeable_state::KEEP_CURRENT),
81 );
82 } else {
83 println!("heaps are unavailable on this device");
84 }
85
86 match device.new_log_state(log_level::INFO, 1_024) {
87 Ok(log_state) => {
88 let _ = device
89 .new_command_queue_with_log_state(4, &log_state)
90 .expect("log-state queue");
91 println!("created queue with log state");
92 }
93 Err(error) => println!("log state unavailable on this OS: {error}"),
94 }
95
96 if device.supports_dynamic_libraries() {
97 let dynamic_path = common::artifact_path("example-dylib.metallib");
98 let dynamic_library = device
99 .new_dynamic_library_with_source(
100 common::DYNAMIC_LIB_SRC,
101 dynamic_path.to_string_lossy().as_ref(),
102 )
103 .expect("dynamic library from source");
104 dynamic_library
105 .serialize_to_file(&dynamic_path)
106 .expect("serialize dynamic library");
107 let reloaded = device
108 .load_dynamic_library(&dynamic_path)
109 .expect("reload dynamic library");
110 println!("dynamic library install name: {}", reloaded.install_name());
111
112 let render_library = device
113 .new_library_with_source(common::RENDER_SRC)
114 .expect("compile render library");
115 let vertex = render_library
116 .new_function("fullscreen_vertex")
117 .expect("vertex function");
118 let fragment = render_library
119 .new_function("solid_fragment")
120 .expect("fragment function");
121 let increment = library
122 .new_function("increment")
123 .expect("increment function");
124
125 let archive_path = common::artifact_path("example-archive.metalarc");
126 let archive = device.new_binary_archive(None).expect("binary archive");
127 archive
128 .add_compute_function(&increment)
129 .expect("archive compute pipeline");
130 archive
131 .add_render_functions(&vertex, &fragment, pixel_format::BGRA8UNORM, 1)
132 .expect("archive render pipeline");
133 archive
134 .serialize_to_file(&archive_path)
135 .expect("serialize binary archive");
136 let _ = device
137 .new_binary_archive(Some(&archive_path))
138 .expect("reload binary archive");
139 println!("binary archive written to {}", archive_path.display());
140 } else {
141 println!("dynamic libraries unsupported; skipping archive serialization");
142 }
143}examples/07_advanced_objects.rs (lines 121-125)
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 Clone for TextureDescriptor
impl Clone for TextureDescriptor
Source§fn clone(&self) -> TextureDescriptor
fn clone(&self) -> TextureDescriptor
Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source. Read moreimpl Copy for TextureDescriptor
Auto Trait Implementations§
impl Freeze for TextureDescriptor
impl RefUnwindSafe for TextureDescriptor
impl Send for TextureDescriptor
impl Sync for TextureDescriptor
impl Unpin for TextureDescriptor
impl UnsafeUnpin for TextureDescriptor
impl UnwindSafe for TextureDescriptor
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more