pub struct ImageDescriptor {
pub channel_format: usize,
pub width: usize,
pub height: usize,
pub feature_channels: usize,
pub number_of_images: usize,
pub usage: usize,
pub storage_mode: usize,
}Expand description
Plain-Rust configuration for building a MPSImageDescriptor on the Swift side.
Fields§
§channel_format: usize§width: usize§height: usize§feature_channels: usize§number_of_images: usize§usage: usize§storage_mode: usizeImplementations§
Source§impl ImageDescriptor
impl ImageDescriptor
Sourcepub const fn new(
width: usize,
height: usize,
feature_channels: usize,
channel_format: usize,
) -> Self
pub const fn new( width: usize, height: usize, feature_channels: usize, channel_format: usize, ) -> Self
Create a single-image descriptor with sensible defaults for read/write image processing.
Examples found in repository?
examples/08_cnn_convolution.rs (line 22)
7fn main() {
8 let device = MetalDevice::system_default().expect("no Metal device available");
9 let queue = device.new_command_queue().expect("command queue");
10
11 let descriptor = CnnConvolutionDescriptor::new(1, 1, 1, 1).expect("descriptor");
12 let convolution = CnnConvolution::new(
13 &device,
14 &descriptor,
15 &[2.0],
16 Some(&[0.5]),
17 cnn_convolution_flags::NONE,
18 )
19 .expect("convolution");
20 convolution.set_accumulator_precision_option(cnn_accumulator_precision_option::FLOAT);
21
22 let image_descriptor = ImageDescriptor::new(2, 2, 1, feature_channel_format::FLOAT32);
23 let source = Image::new(&device, image_descriptor).expect("source image");
24 let destination = Image::new(&device, image_descriptor).expect("destination image");
25 source.write_f32(&[1.0, 2.0, 3.0, 4.0]).expect("write source");
26
27 let command_buffer = queue.new_command_buffer().expect("command buffer");
28 convolution.encode_image(&command_buffer, &source, &destination);
29 command_buffer.commit();
30 command_buffer.wait_until_completed();
31
32 let output = destination.read_f32().expect("output");
33 println!("{output:?}");
34}More examples
examples/09_rnn_image_inference.rs (line 13)
4fn main() {
5 let device = MetalDevice::system_default().expect("no Metal device available");
6 let queue = device.new_command_queue().expect("command queue");
7
8 let single_gate = RnnSingleGateDescriptor::new(1, 1).expect("single gate descriptor");
9 single_gate.set_use_layer_input_unit_transform_mode(true);
10 let descriptor = single_gate.as_descriptor().expect("base descriptor");
11 let layer = RnnImageInferenceLayer::new(&device, &descriptor).expect("rnn layer");
12
13 let image_descriptor = ImageDescriptor::new(1, 1, 1, feature_channel_format::FLOAT32);
14 let src0 = Image::new(&device, image_descriptor).expect("src0");
15 let src1 = Image::new(&device, image_descriptor).expect("src1");
16 let dst0 = Image::new(&device, image_descriptor).expect("dst0");
17 let dst1 = Image::new(&device, image_descriptor).expect("dst1");
18 src0.write_f32(&[0.25]).expect("write src0");
19 src1.write_f32(&[0.75]).expect("write src1");
20
21 let command_buffer = queue.new_command_buffer().expect("command buffer");
22 let recurrent_state = layer
23 .encode_sequence(&command_buffer, &[&src0, &src1], &[&dst0, &dst1], None)
24 .expect("recurrent state");
25 command_buffer.commit();
26 command_buffer.wait_until_completed();
27
28 let recurrent_output = recurrent_state
29 .recurrent_output_image_for_layer_index(0)
30 .expect("recurrent output image");
31 println!(
32 "{:?} {}x{}x{}",
33 dst1.read_f32().expect("dst1 output"),
34 recurrent_output.width(),
35 recurrent_output.height(),
36 recurrent_output.feature_channels()
37 );
38}examples/01_blur_image.rs (line 10)
4fn main() {
5 let device = MetalDevice::system_default().expect("no Metal device available");
6 let queue = device
7 .new_command_queue()
8 .expect("failed to create command queue");
9
10 let descriptor = ImageDescriptor::new(256, 256, 1, feature_channel_format::FLOAT32);
11 let src = Image::new(&device, descriptor).expect("failed to allocate source image");
12 let dst = Image::new(&device, descriptor).expect("failed to allocate destination image");
13
14 let mut impulse = vec![0.0_f32; 256 * 256];
15 let center_index = (256 / 2) * 256 + (256 / 2);
16 impulse[center_index] = 1.0;
17 src.write_f32(&impulse)
18 .expect("failed to upload source image");
19
20 let blur = ImageGaussianBlur::new(&device, 2.0).expect("failed to create gaussian blur");
21 let command_buffer = queue
22 .new_command_buffer()
23 .expect("failed to allocate command buffer");
24 blur.encode_image(&command_buffer, &src, &dst);
25 command_buffer.commit();
26 command_buffer.wait_until_completed();
27
28 let output = dst.read_f32().expect("failed to download blurred image");
29 let center_value = output[center_index];
30 let neighbor_value = output[center_index + 1];
31 let corner_value = output[0];
32 let total_energy: f32 = output.iter().sum();
33
34 assert!(
35 center_value < 1.0,
36 "center should have blurred away from impulse"
37 );
38 assert!(
39 neighbor_value > 0.0,
40 "neighbor should receive energy after blur"
41 );
42 assert!(
43 center_value > neighbor_value,
44 "center should remain strongest sample"
45 );
46 assert!(corner_value.abs() < 1.0e-6, "corners should stay at zero");
47 assert!(
48 (total_energy - 1.0).abs() < 1.0e-2,
49 "gaussian blur should preserve energy, got {total_energy}"
50 );
51
52 println!(
53 "blur smoke passed: center={center_value:.6} neighbor={neighbor_value:.6} sum={total_energy:.6}"
54 );
55}examples/05_nn_graph_relu.rs (line 39)
8fn main() {
9 let device = MetalDevice::system_default().expect("no Metal device available");
10 let queue = device.new_command_queue().expect("command queue");
11
12 let input_node = NNImageNode::new().expect("input node");
13 input_node.set_format(feature_channel_format::FLOAT32);
14 let relu = CnnNeuronReluNode::new(&input_node, 0.0).expect("relu node");
15 let relu_result = relu.result_image().expect("relu result image");
16 relu_result.set_format(feature_channel_format::FLOAT32);
17 relu_result.set_synchronize_resource(true);
18 relu_result.use_default_allocator();
19 let pooling = CnnPoolingMaxNode::new(&relu_result, 2, 2).expect("pooling node");
20 assert!(
21 pooling.result_image().is_some(),
22 "pooling result image should exist"
23 );
24 let softmax = CnnSoftMaxNode::new(&relu_result).expect("softmax node");
25 assert!(
26 softmax.result_image().is_some(),
27 "softmax result image should exist"
28 );
29 let upsampling = CnnUpsamplingNearestNode::new(&relu_result, 2, 2).expect("upsampling node");
30 assert!(
31 upsampling.result_image().is_some(),
32 "upsampling result image should exist"
33 );
34
35 let graph = NNGraph::new(&device, &relu_result, true).expect("graph");
36 graph.set_format(feature_channel_format::FLOAT32);
37 graph.use_default_destination_image_allocator();
38
39 let descriptor = ImageDescriptor::new(2, 2, 1, feature_channel_format::FLOAT32);
40 let source = Image::new(&device, descriptor).expect("source image");
41 source
42 .write_f32(&[-1.0, 0.5, 2.0, -0.25])
43 .expect("write source image");
44
45 let command_buffer = queue.new_command_buffer().expect("command buffer");
46 let result = graph
47 .encode(&command_buffer, &[&source])
48 .expect("graph encode");
49 command_buffer.commit();
50 command_buffer.wait_until_completed();
51
52 let output = result.read_f32().expect("read graph output");
53 let expected = [0.0_f32, 0.5, 2.0, 0.0];
54 for (actual, expected_value) in output.iter().zip(expected) {
55 assert!(
56 (actual - expected_value).abs() < 1.0e-4,
57 "unexpected relu graph output: {output:?}"
58 );
59 }
60
61 let convolution = CnnConvolutionDescriptor::new(3, 3, 1, 4).expect("convolution descriptor");
62 convolution.set_stride_in_pixels_x(2);
63 convolution.set_stride_in_pixels_y(1);
64 convolution.set_groups(1);
65 convolution.set_dilation_rate_x(1);
66 convolution.set_dilation_rate_y(2);
67 assert_eq!(convolution.kernel_width(), 3);
68 assert_eq!(convolution.kernel_height(), 3);
69 assert_eq!(convolution.stride_in_pixels_x(), 2);
70 assert_eq!(convolution.stride_in_pixels_y(), 1);
71 assert_eq!(convolution.groups(), 1);
72 assert_eq!(convolution.dilation_rate_x(), 1);
73 assert_eq!(convolution.dilation_rate_y(), 2);
74
75 let rnn = RnnSingleGateDescriptor::new(3, 5).expect("rnn descriptor");
76 rnn.set_use_layer_input_unit_transform_mode(true);
77 rnn.set_use_float32_weights(true);
78 rnn.set_layer_sequence_direction(rnn_sequence_direction::BACKWARD);
79 assert_eq!(rnn.input_feature_channels(), 3);
80 assert_eq!(rnn.output_feature_channels(), 5);
81 assert!(rnn.use_layer_input_unit_transform_mode());
82 assert!(rnn.use_float32_weights());
83 assert_eq!(
84 rnn.layer_sequence_direction(),
85 rnn_sequence_direction::BACKWARD,
86 "expected backward RNN sequence direction"
87 );
88
89 println!(
90 "nn smoke passed: relu={output:?} source_images={}",
91 graph.source_image_count()
92 );
93}Trait Implementations§
Source§impl Clone for ImageDescriptor
impl Clone for ImageDescriptor
Source§fn clone(&self) -> ImageDescriptor
fn clone(&self) -> ImageDescriptor
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 moreSource§impl Debug for ImageDescriptor
impl Debug for ImageDescriptor
impl Copy for ImageDescriptor
Auto Trait Implementations§
impl Freeze for ImageDescriptor
impl RefUnwindSafe for ImageDescriptor
impl Send for ImageDescriptor
impl Sync for ImageDescriptor
impl Unpin for ImageDescriptor
impl UnsafeUnpin for ImageDescriptor
impl UnwindSafe for ImageDescriptor
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