pub struct Image { /* private fields */ }Expand description
Safe owner for an Objective-C MPSImage.
Implementations§
Source§impl Image
impl Image
Sourcepub fn new(device: &MetalDevice, descriptor: ImageDescriptor) -> Option<Self>
pub fn new(device: &MetalDevice, descriptor: ImageDescriptor) -> Option<Self>
Allocate a lazily backed MPSImage on device.
Examples found in repository?
examples/08_cnn_convolution.rs (line 23)
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 14)
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 11)
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 40)
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}Sourcepub fn from_texture(
texture: &MetalTexture,
feature_channels: usize,
) -> Option<Self>
pub fn from_texture( texture: &MetalTexture, feature_channels: usize, ) -> Option<Self>
Wrap an existing Metal texture in an MPSImage.
Sourcepub fn width(&self) -> usize
pub fn width(&self) -> usize
Image width in pixels.
Examples found in repository?
examples/09_rnn_image_inference.rs (line 34)
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}Sourcepub fn height(&self) -> usize
pub fn height(&self) -> usize
Image height in pixels.
Examples found in repository?
examples/09_rnn_image_inference.rs (line 35)
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}Sourcepub fn feature_channels(&self) -> usize
pub fn feature_channels(&self) -> usize
Number of feature channels per pixel.
Examples found in repository?
examples/09_rnn_image_inference.rs (line 36)
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}Sourcepub fn number_of_images(&self) -> usize
pub fn number_of_images(&self) -> usize
Number of images stored in the backing texture array.
Sourcepub fn pixel_size(&self) -> usize
pub fn pixel_size(&self) -> usize
Bytes between neighboring pixels in storage order.
Sourcepub fn pixel_format(&self) -> usize
pub fn pixel_format(&self) -> usize
Underlying MTLPixelFormat raw value.
Sourcepub fn whole_region(&self) -> ImageRegion
pub fn whole_region(&self) -> ImageRegion
Convenience region covering the full first image.
Sourcepub fn read_bytes(
&self,
dst: &mut [u8],
data_layout: usize,
bytes_per_row: usize,
region: ImageRegion,
params: ImageReadWriteParams,
image_index: usize,
) -> Result<()>
pub fn read_bytes( &self, dst: &mut [u8], data_layout: usize, bytes_per_row: usize, region: ImageRegion, params: ImageReadWriteParams, image_index: usize, ) -> Result<()>
Read bytes out of the image into a caller-provided buffer.
Sourcepub fn write_bytes(
&self,
src: &[u8],
data_layout: usize,
bytes_per_row: usize,
region: ImageRegion,
params: ImageReadWriteParams,
image_index: usize,
) -> Result<()>
pub fn write_bytes( &self, src: &[u8], data_layout: usize, bytes_per_row: usize, region: ImageRegion, params: ImageReadWriteParams, image_index: usize, ) -> Result<()>
Write bytes into the image from a caller-provided buffer.
Sourcepub fn read_f32(&self) -> Result<Vec<f32>>
pub fn read_f32(&self) -> Result<Vec<f32>>
Read the first image slice as tightly packed float32 HWC data.
Examples found in repository?
examples/08_cnn_convolution.rs (line 32)
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 33)
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 28)
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 52)
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}Sourcepub fn write_f32(&self, data: &[f32]) -> Result<()>
pub fn write_f32(&self, data: &[f32]) -> Result<()>
Write tightly packed float32 HWC data into the first image slice.
Examples found in repository?
examples/08_cnn_convolution.rs (line 25)
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 18)
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 17)
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 42)
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§
Auto Trait Implementations§
impl Freeze for Image
impl RefUnwindSafe for Image
impl Unpin for Image
impl UnsafeUnpin for Image
impl UnwindSafe for Image
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