1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
//! This file has been automatically generated by `objc2`'s `header-translator`.
//! DO NOT EDIT
use core::ffi::*;
use core::ptr::NonNull;
use objc2::__framework_prelude::*;
use objc2_foundation::*;
use objc2_metal::*;
use crate::*;
/// A notification when computeAsyncWithSourceImages:completionHandler: has finished
///
/// Parameter `result`: If no error, the image produced by the graph operation.
///
/// Parameter `error`: If an error occurs, more information might be found here.
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/metalperformanceshaders/mpsnngraphcompletionhandler?language=objc)
#[cfg(all(feature = "MPSCore", feature = "MPSImage", feature = "block2"))]
pub type MPSNNGraphCompletionHandler = *mut block2::DynBlock<dyn Fn(*mut MPSImage, *mut NSError)>;
extern_class!(
/// Optimized representation of a graph of MPSNNImageNodes and MPSNNFilterNodes
///
/// Once you have prepared a graph of MPSNNImageNodes and MPSNNFilterNodes
/// (and if needed MPSNNStateNodes), you may initialize a MPSNNGraph using
/// the MPSNNImageNode that you wish to appear as the result. The MPSNNGraph
/// object will introspect the graph representation and determine which nodes
/// are needed for inputs, and which nodes are produced as output state (if any).
/// Nodes which are not needed to calculate the result image node are ignored.
/// Some nodes may be internally concatenated with other nodes for better
/// performance.
///
/// Note: the MPSNNImageNode that you choose as the result node may be interior
/// to a graph. This feature is provided as a means to examine intermediate
/// computations in the full graph for debugging purposes.
///
/// During MPSNNGraph construction, the graph attached to the result node will
/// be parsed and reduced to an optimized representation. This representation may
/// be saved using the NSSecureCoding protocol for later recall.
///
/// When decoding a MPSNNGraph using a NSCoder, it will be created against
/// the system default MTLDevice. If you would like to set the MTLDevice,
/// your NSCoder should conform to the
/// <MPSDeviceProvider
/// > protocol.
///
/// You may find it helpful to set MPSKernelOptionsVerbose on the graph when
/// debugging. To turn this on during MPSKernel initialization (including
/// MPSNNGraph initialization) set the MPS_LOG_INFO environment variable.
/// There is a lot of information about what optimizations are done to your
/// graph, including some information on why certain optimizations were not
/// made.
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/metalperformanceshaders/mpsnngraph?language=objc)
#[unsafe(super(MPSKernel, NSObject))]
#[derive(Debug, PartialEq, Eq, Hash)]
#[cfg(all(feature = "MPSCore", feature = "MPSKernel"))]
pub struct MPSNNGraph;
);
#[cfg(all(feature = "MPSCore", feature = "MPSKernel"))]
extern_conformance!(
unsafe impl NSCoding for MPSNNGraph {}
);
#[cfg(all(feature = "MPSCore", feature = "MPSKernel"))]
extern_conformance!(
unsafe impl NSCopying for MPSNNGraph {}
);
#[cfg(all(feature = "MPSCore", feature = "MPSKernel"))]
unsafe impl CopyingHelper for MPSNNGraph {
type Result = Self;
}
#[cfg(all(feature = "MPSCore", feature = "MPSKernel"))]
extern_conformance!(
unsafe impl NSObjectProtocol for MPSNNGraph {}
);
#[cfg(all(feature = "MPSCore", feature = "MPSKernel"))]
extern_conformance!(
unsafe impl NSSecureCoding for MPSNNGraph {}
);
#[cfg(all(feature = "MPSCore", feature = "MPSKernel"))]
impl MPSNNGraph {
extern_methods!(
#[cfg(feature = "MPSNNGraphNodes")]
/// Initialize a MPSNNGraph object on a device starting with resultImage working backward
///
/// The MPSNNGraph constructor will start with the indicated result image, and look
/// to see what MPSNNFilterNode produced it, then look to its dependencies and so
/// forth to reveal the subsection of the graph necessary to compute the image.
///
/// Parameter `device`: The MTLDevice on which to run the graph
///
/// Parameter `resultImage`: The MPSNNImageNode corresponding to the last image in the graph.
/// This is the image that will be returned. Note: the imageAllocator
/// for this node is ignored and the MPSNNGraph.destinationImageAllocator
/// is used for this node instead.
///
/// Parameter `resultIsNeeded`: Commonly, when training a graph, the last MPSImage out of the
/// graph is not used. The final gradient filter is run solely to update
/// some weights. If resultIsNeeded is set to NO, nil will
/// be returned from the left hand side of the -encode call instead,
/// and computation to produce the last image may be pruned away.
///
/// Returns: A new MPSNNGraph.
#[unsafe(method(initWithDevice:resultImage:resultImageIsNeeded:))]
#[unsafe(method_family = init)]
pub unsafe fn initWithDevice_resultImage_resultImageIsNeeded(
this: Allocated<Self>,
device: &ProtocolObject<dyn MTLDevice>,
result_image: &MPSNNImageNode,
result_is_needed: bool,
) -> Option<Retained<Self>>;
#[cfg(feature = "MPSNNGraphNodes")]
#[unsafe(method(graphWithDevice:resultImage:resultImageIsNeeded:))]
#[unsafe(method_family = none)]
pub unsafe fn graphWithDevice_resultImage_resultImageIsNeeded(
device: &ProtocolObject<dyn MTLDevice>,
result_image: &MPSNNImageNode,
result_is_needed: bool,
) -> Option<Retained<Self>>;
#[cfg(feature = "MPSNNGraphNodes")]
/// Initialize a MPSNNGraph object on a device starting with resultImage working backward
///
/// The MPSNNGraph constructor will start with the indicated result images, and look
/// to see what MPSNNFilterNode produced them, then look to its dependencies and so
/// forth to reveal the subsection of the graph necessary to compute the image. This variant
/// is provided to support graphs and subgraphs with multiple image outputs.
///
/// Parameter `device`: The MTLDevice on which to run the graph
///
/// Parameter `resultImages`: The MPSNNImageNodes corresponding to the last images in the graph.
/// The first image in the array will be returned from the -encode method
/// LHS. The rest will be included in the list of intermediate images.
///
/// Parameter `areResultsNeeded`: An array of BOOL values with count equal to resultImages.count.
/// If NO is passed for a given image, the image itself is marked unneeded
/// and might be skipped. The graph will prune this branch back to the
/// first requred filter. A filter is required if it generates a needed
/// result image, or is needed to update training parameters.
///
/// Returns: A new MPSNNGraph.
///
/// # Safety
///
/// `are_results_needed` must be a valid pointer or null.
#[unsafe(method(initWithDevice:resultImages:resultsAreNeeded:))]
#[unsafe(method_family = init)]
pub unsafe fn initWithDevice_resultImages_resultsAreNeeded(
this: Allocated<Self>,
device: &ProtocolObject<dyn MTLDevice>,
result_images: &NSArray<MPSNNImageNode>,
are_results_needed: *mut Bool,
) -> Option<Retained<Self>>;
#[cfg(feature = "MPSNNGraphNodes")]
/// # Safety
///
/// `are_results_needed` must be a valid pointer or null.
#[unsafe(method(graphWithDevice:resultImages:resultsAreNeeded:))]
#[unsafe(method_family = none)]
pub unsafe fn graphWithDevice_resultImages_resultsAreNeeded(
device: &ProtocolObject<dyn MTLDevice>,
result_images: &NSArray<MPSNNImageNode>,
are_results_needed: *mut Bool,
) -> Option<Retained<Self>>;
#[cfg(feature = "MPSNNGraphNodes")]
#[deprecated]
#[unsafe(method(initWithDevice:resultImage:))]
#[unsafe(method_family = init)]
pub unsafe fn initWithDevice_resultImage(
this: Allocated<Self>,
device: &ProtocolObject<dyn MTLDevice>,
result_image: &MPSNNImageNode,
) -> Option<Retained<Self>>;
#[cfg(feature = "MPSNNGraphNodes")]
#[deprecated]
#[unsafe(method(graphWithDevice:resultImage:))]
#[unsafe(method_family = none)]
pub unsafe fn graphWithDevice_resultImage(
device: &ProtocolObject<dyn MTLDevice>,
result_image: &MPSNNImageNode,
) -> Option<Retained<Self>>;
/// NSSecureCoding compatability
///
/// While the standard NSSecureCoding/NSCoding method
/// -initWithCoder: should work, since the file can't
/// know which device your data is allocated on, we
/// have to guess and may guess incorrectly. To avoid
/// that problem, use initWithCoder:device instead.
///
/// Parameter `aDecoder`: The NSCoder subclass with your serialized MPSKernel
///
/// Parameter `device`: The MTLDevice on which to make the MPSKernel
///
/// Returns: A new MPSKernel object, or nil if failure.
///
/// # Safety
///
/// `a_decoder` possibly has further requirements.
#[unsafe(method(initWithCoder:device:))]
#[unsafe(method_family = init)]
pub unsafe fn initWithCoder_device(
this: Allocated<Self>,
a_decoder: &NSCoder,
device: &ProtocolObject<dyn MTLDevice>,
) -> Option<Retained<Self>>;
/// Use initWithDevice:resultImage: instead
#[unsafe(method(initWithDevice:))]
#[unsafe(method_family = init)]
pub unsafe fn initWithDevice(
this: Allocated<Self>,
device: &ProtocolObject<dyn MTLDevice>,
) -> Retained<Self>;
#[cfg(feature = "MPSNNGraphNodes")]
/// Get a list of identifiers for source images needed to calculate the result image
#[unsafe(method(sourceImageHandles))]
#[unsafe(method_family = none)]
pub unsafe fn sourceImageHandles(&self)
-> Retained<NSArray<ProtocolObject<dyn MPSHandle>>>;
#[cfg(feature = "MPSNNGraphNodes")]
/// Get a list of identifiers for source state objects needed to calculate the result image
///
/// Not guaranteed to be in the same order as resultStateHandles
#[unsafe(method(sourceStateHandles))]
#[unsafe(method_family = none)]
pub unsafe fn sourceStateHandles(
&self,
) -> Option<Retained<NSArray<ProtocolObject<dyn MPSHandle>>>>;
#[cfg(feature = "MPSNNGraphNodes")]
/// Get a list of identifiers for intermediate images objects produced by the graph
#[unsafe(method(intermediateImageHandles))]
#[unsafe(method_family = none)]
pub unsafe fn intermediateImageHandles(
&self,
) -> Option<Retained<NSArray<ProtocolObject<dyn MPSHandle>>>>;
#[cfg(feature = "MPSNNGraphNodes")]
/// Get a list of identifiers for result state objects produced by the graph
///
/// Not guaranteed to be in the same order as sourceStateHandles
#[unsafe(method(resultStateHandles))]
#[unsafe(method_family = none)]
pub unsafe fn resultStateHandles(
&self,
) -> Option<Retained<NSArray<ProtocolObject<dyn MPSHandle>>>>;
#[cfg(feature = "MPSNNGraphNodes")]
/// Get a handle for the graph result image
#[unsafe(method(resultHandle))]
#[unsafe(method_family = none)]
pub unsafe fn resultHandle(&self) -> Option<Retained<ProtocolObject<dyn MPSHandle>>>;
/// Should MPSState objects produced by -encodeToCommandBuffer... be temporary objects.
///
/// See MPSState description. Default: NO
#[unsafe(method(outputStateIsTemporary))]
#[unsafe(method_family = none)]
pub unsafe fn outputStateIsTemporary(&self) -> bool;
/// Setter for [`outputStateIsTemporary`][Self::outputStateIsTemporary].
#[unsafe(method(setOutputStateIsTemporary:))]
#[unsafe(method_family = none)]
pub unsafe fn setOutputStateIsTemporary(&self, output_state_is_temporary: bool);
#[cfg(feature = "MPSImage")]
/// Method to allocate the result image from -encodeToCommandBuffer...
///
/// This property overrides the allocator for the final result image in
/// the graph. Default: MPSImage.defaultAllocator
#[unsafe(method(destinationImageAllocator))]
#[unsafe(method_family = none)]
pub unsafe fn destinationImageAllocator(
&self,
) -> Retained<ProtocolObject<dyn MPSImageAllocator>>;
#[cfg(feature = "MPSImage")]
/// Setter for [`destinationImageAllocator`][Self::destinationImageAllocator].
#[unsafe(method(setDestinationImageAllocator:))]
#[unsafe(method_family = none)]
pub unsafe fn setDestinationImageAllocator(
&self,
destination_image_allocator: &ProtocolObject<dyn MPSImageAllocator>,
);
#[cfg(feature = "MPSCoreTypes")]
/// The default storage format used for graph intermediate images
///
/// This doesn't affect how data is stored in buffers in states.
/// Nor does it affect the storage format for weights
/// such as convolution weights stored by individual filters.
/// Default: MPSImageFeatureChannelFormatFloat16
#[unsafe(method(format))]
#[unsafe(method_family = none)]
pub unsafe fn format(&self) -> MPSImageFeatureChannelFormat;
#[cfg(feature = "MPSCoreTypes")]
/// Setter for [`format`][Self::format].
#[unsafe(method(setFormat:))]
#[unsafe(method_family = none)]
pub unsafe fn setFormat(&self, format: MPSImageFeatureChannelFormat);
/// Set at -init time.
///
/// If NO, nil will be returned from -encode calls and some computation
/// may be omitted.
#[unsafe(method(resultImageIsNeeded))]
#[unsafe(method_family = none)]
pub unsafe fn resultImageIsNeeded(&self) -> bool;
/// Reinitialize all graph nodes from data sources
///
/// A number of the nodes that make up a graph have a data source
/// associated with them, for example a MPSCNNConvolutionDataSource
/// or a MPSCNNBatchNormalizationDataSource. Generally, the data
/// is read from these once at graph initialization time and then
/// not looked at again, except during the weight / parameter update
/// phase of the corresponding gradient nodes and then only if CPU
/// updates are requested. Otherwise, update occurs on the GPU,
/// and the data in the data source is thereafter ignored.
///
/// It can happen, though, that your application has determined the
/// graph should load a new set of weights from the data source.
/// When this method is called, the graph will find all nodes that
/// support reloading and direct them to reinitialize themselves
/// based on their data source.
///
/// This process occurs immediately. Your application will
/// need to make sure any GPU work being done by the graph is complete
/// to ensure data coherency. Most nodes do not have a data source
/// and will not be modified. Nodes that are not used by the graph
/// will not be updated.
#[unsafe(method(reloadFromDataSources))]
#[unsafe(method_family = none)]
pub unsafe fn reloadFromDataSources(&self);
#[cfg(all(feature = "MPSImage", feature = "MPSState"))]
/// Encode the graph to a MTLCommandBuffer
///
/// Parameter `commandBuffer`: The command buffer. If the command buffer is a MPSCommandBuffer,
/// the work will be committed to Metal in small pieces so that
/// the CPU-side latency is much reduced.
///
/// Parameter `sourceImages`: A list of MPSImages to use as the source images for the graph.
/// These should be in the same order as the list returned from MPSNNGraph.sourceImageHandles.
/// The images may be image arrays. Typically, this is only one or two images
/// such as a .JPG decoded into a MPSImage*. If the sourceImages are MPSTemporaryImages,
/// the graph will decrement the readCount by 1, even if the graph actually
/// reads an image multiple times.
///
/// Parameter `sourceStates`: A list of MPSState objects to use as state for a graph.
/// These should be in the same order as the list returned from MPSNNGraph.sourceStateHandles.
/// May be nil, if there is no source state. If the sourceStates are temporary,
/// the graph will decrement the readCount by 1, even if the graph actually
/// reads the state multiple times.
///
/// Parameter `intermediateImages`: An optional NSMutableArray to receive any MPSImage objects exported as part of its operation.
/// These are only the images that were tagged with MPSNNImageNode.exportFromGraph = YES. The
/// identity of the states is given by -resultStateHandles. If temporary, each intermediateImage
/// will have a readCount of 1. If the result was tagged exportFromGraph = YES, it will be here
/// too, with a readCount of 2. To be able to access the images from outside the graph on the CPU,
/// your application must also set MPSNNImageNode.synchronizeResource = YES,
/// and MPSNNImageNode.imageAllocator = [MPSImage defaultAllocator]; The defaultAllocator creates
/// a permanent image that can be read with readBytes.
///
/// Parameter `destinationStates`: An optional NSMutableArray to receive any MPSState objects created as part of its operation.
/// The identity of the states is given by -resultStateHandles.
///
/// Returns: A MPSImage or MPSTemporaryImage allocated per the destinationImageAllocator containing the output of the graph.
/// It will be automatically released when commandBuffer completes.
#[unsafe(method(encodeToCommandBuffer:sourceImages:sourceStates:intermediateImages:destinationStates:))]
#[unsafe(method_family = none)]
pub unsafe fn encodeToCommandBuffer_sourceImages_sourceStates_intermediateImages_destinationStates(
&self,
command_buffer: &ProtocolObject<dyn MTLCommandBuffer>,
source_images: &NSArray<MPSImage>,
source_states: Option<&NSArray<MPSState>>,
intermediate_images: Option<&NSMutableArray<MPSImage>>,
destination_states: Option<&NSMutableArray<MPSState>>,
) -> Option<Retained<MPSImage>>;
#[cfg(all(feature = "MPSImage", feature = "MPSNDArray", feature = "MPSState"))]
/// Encode the graph to a MTLCommandBuffer
///
/// This interface is like the other except that it operates on a batch of images all
/// at once. In addition, you may specify whether the result is needed.
///
/// Parameter `commandBuffer`: The command buffer. If the command buffer is a MPSCommandBuffer,
/// the work will be committed to Metal in small pieces so that
/// the CPU-side latency is much reduced.
///
/// Parameter `sourceImages`: A list of MPSImages to use as the source images for the graph.
/// These should be in the same order as the list returned from MPSNNGraph.sourceImageHandles.
/// The images may be image arrays. Typically, this is only one or two images
/// such as a .JPG decoded into a MPSImage*. If the sourceImages are MPSTemporaryImages,
/// the graph will decrement the readCount by 1, even if the graph actually
/// reads an image multiple times.
///
/// Parameter `sourceStates`: A list of MPSState objects to use as state for a graph.
/// These should be in the same order as the list returned from MPSNNGraph.sourceStateHandles.
/// May be nil, if there is no source state. If the sourceStates are temporary,
/// the graph will decrement the readCount by 1, even if the graph actually
/// reads the state multiple times.
///
/// Parameter `intermediateImages`: An optional NSMutableArray to receive any MPSImage objects exported as part of its operation.
/// These are only the images that were tagged with MPSNNImageNode.exportFromGraph = YES. The
/// identity of the states is given by -resultStateHandles. If temporary, each intermediateImage
/// will have a readCount of 1. If the result was tagged exportFromGraph = YES, it will be here
/// too, with a readCount of 2. To be able to access the images from outside the graph on the CPU,
/// your application must also set MPSNNImageNode.synchronizeResource = YES,
/// and MPSNNImageNode.imageAllocator = [MPSImage defaultAllocator]; The defaultAllocator creates
/// a permanent image that can be read with readBytes.
///
/// Parameter `destinationStates`: An optional NSMutableArray to receive any MPSState objects created as part of its operation.
/// The identity of the states is given by -resultStateHandles.
///
/// Returns: A MPSImageBatch or MPSTemporaryImageBatch allocated per the destinationImageAllocator containing the output of the graph.
/// It will be automatically released when commandBuffer completes. If resultIsNeeded == NO, then this
/// will return nil.
#[unsafe(method(encodeBatchToCommandBuffer:sourceImages:sourceStates:intermediateImages:destinationStates:))]
#[unsafe(method_family = none)]
pub unsafe fn encodeBatchToCommandBuffer_sourceImages_sourceStates_intermediateImages_destinationStates(
&self,
command_buffer: &ProtocolObject<dyn MTLCommandBuffer>,
source_images: &NSArray<MPSImageBatch>,
source_states: Option<&NSArray<MPSStateBatch>>,
intermediate_images: Option<&NSMutableArray<MPSImageBatch>>,
destination_states: Option<&NSMutableArray<MPSStateBatch>>,
) -> Option<Retained<MPSImageBatch>>;
#[cfg(feature = "MPSImage")]
/// Encode the graph to a MTLCommandBuffer
///
///
/// IMPORTANT: Please use [MTLCommandBuffer addCompletedHandler:] to determine when this work is
/// done. Use CPU time that would have been spent waiting for the GPU to encode the next command
/// buffer and commit it too. That way, the work for the next command buffer is ready to go the
/// moment the GPU is done. This will keep the GPU busy and running at top speed.
///
/// Those who ignore this advice and use [MTLCommandBuffer waitUntilCompleted] instead will likely
/// cause their code to slow down by a factor of two or more. The CPU clock spins down while it
/// waits for the GPU. When the GPU completes, the CPU runs slowly for a while until it spins up.
/// The GPU has to wait for the CPU to encode more work (at low clock), giving it plenty of time to
/// spin its own clock down. In typical CNN graph usage, neither may ever reach maximum clock
/// frequency, causing slow down far beyond what otherwise would be expected from simple failure
/// to schedule CPU and GPU work concurrently. Regrattably, it is probable that every performance
/// benchmark you see on the net will be based on [MTLCommandBuffer waitUntilCompleted].
///
///
/// Parameter `commandBuffer`: The command buffer. If the command buffer is a MPSCommandBuffer,
/// the work will be committed to Metal in small pieces so that
/// the CPU-side latency is much reduced.
///
/// Parameter `sourceImages`: A list of MPSImages to use as the source images for the graph.
/// These should be in the same order as the list returned from MPSNNGraph.sourceImageHandles.
///
/// Returns: A MPSImage or MPSTemporaryImage allocated per the destinationImageAllocator containing the output of the graph.
/// It will be automatically released when commandBuffer completes. It can be nil if resultImageIsNeeded == NO
#[unsafe(method(encodeToCommandBuffer:sourceImages:))]
#[unsafe(method_family = none)]
pub unsafe fn encodeToCommandBuffer_sourceImages(
&self,
command_buffer: &ProtocolObject<dyn MTLCommandBuffer>,
source_images: &NSArray<MPSImage>,
) -> Option<Retained<MPSImage>>;
#[cfg(all(feature = "MPSImage", feature = "MPSNDArray", feature = "MPSState"))]
/// Convenience method to encode a batch of images
#[unsafe(method(encodeBatchToCommandBuffer:sourceImages:sourceStates:))]
#[unsafe(method_family = none)]
pub unsafe fn encodeBatchToCommandBuffer_sourceImages_sourceStates(
&self,
command_buffer: &ProtocolObject<dyn MTLCommandBuffer>,
source_images: &NSArray<MPSImageBatch>,
source_states: Option<&NSArray<MPSStateBatch>>,
) -> Option<Retained<MPSImageBatch>>;
#[cfg(all(feature = "MPSImage", feature = "block2"))]
/// Convenience method to execute a graph without having to manage many Metal details
///
/// This function will synchronously encode the graph on a private command buffer,
/// commit it to a MPS internal command queue and return. The GPU will start working.
/// When the GPU is done, the completion handler will be called. You should use
/// the intervening time to encode other work for execution on the GPU, so that
/// the GPU stays busy and doesn't clock down.
///
/// The work will be performed on the MTLDevice that hosts the source images.
///
/// This is a convenience API. There are a few situations it does not handle optimally.
/// These may be better handled using [encodeToCommandBuffer:sourceImages:].
/// Specifically:
///
/// ```text
/// o If the graph needs to be run multiple times for different images,
/// it would be better to encode the graph multiple times on the same
/// command buffer using [encodeToCommandBuffer:sourceImages:] This
/// will allow the multiple graphs to share memory for intermediate
/// storage, dramatically reducing memory usage.
///
/// o If preprocessing or post-processing of the MPSImage is required,
/// such as resizing or normalization outside of a convolution, it would
/// be better to encode those things on the same command buffer.
/// Memory may be saved here too for intermediate storage. (MPSTemporaryImage
/// lifetime does not span multiple command buffers.)
/// ```
///
///
/// Parameter `sourceImages`: A list of MPSImages to use as the source images for the graph.
/// These should be in the same order as the list returned from
/// MPSNNGraph.sourceImageHandles. They should be allocated against
/// the same MTLDevice. There must be at least one source image.
/// Note: this array is intended to handle the case where multiple
/// input images are required to generate a single graph result.
/// That is, the graph itself has multiple inputs. If you need to
/// execute the graph multiple times, then call this API multiple
/// times, or (faster) make use of MPSImageBatches using
/// -executeBatchToCommandBuffer:sourceImages:sourceStates:...
/// (See discussion)
///
///
/// Parameter `handler`: A block to receive any errors generated. This block may run
/// on any thread and may be called before this method returns.
/// The image, if any, passed to this callback is the same image
/// as that returned from the left hand side.
///
///
/// Returns: A MPSImage to receive the result. The data in the image will not be valid until
/// the completionHandler is called.
///
/// # Safety
///
/// `handler` must be a valid pointer.
#[unsafe(method(executeAsyncWithSourceImages:completionHandler:))]
#[unsafe(method_family = none)]
pub unsafe fn executeAsyncWithSourceImages_completionHandler(
&self,
source_images: &NSArray<MPSImage>,
handler: MPSNNGraphCompletionHandler,
) -> Retained<MPSImage>;
/// Find the number of times a image will be read by the graph *
///
/// From the set of images (or image batches) passed in to the graph, find
/// the number of times the graph will read an image. This may be needed
/// by your application to correctly set the MPSImage.readCount property.
///
/// Parameter `index`: The index of the image. The index of the image matches the index of the image in the array returned
/// by the sourceImageHandles property.
///
/// Returns: The read count of the image(s) at the index will be reduced by the value returned
/// when the graph is finished encoding. The readcount of the image(s) must be at least
/// this value when it is passed into the -encode... method.
#[unsafe(method(readCountForSourceImageAtIndex:))]
#[unsafe(method_family = none)]
pub unsafe fn readCountForSourceImageAtIndex(&self, index: NSUInteger) -> NSUInteger;
/// Find the number of times a state will be read by the graph *
///
/// From the set of state (or state batches) passed in to the graph, find
/// the number of times the graph will read a state. This may be needed
/// by your application to correctly set the MPSState.readCount property.
///
/// Parameter `index`: The index of the state. The index of the state matches the index of the state in the array returned
/// by the sourceStateHandles property.
///
/// Returns: The read count of the state(s) at the index will be reduced by the value returned
/// when the graph is finished encoding. The read count of the state(s) must be at least
/// this value when it is passed into the -encode... method.
#[unsafe(method(readCountForSourceStateAtIndex:))]
#[unsafe(method_family = none)]
pub unsafe fn readCountForSourceStateAtIndex(&self, index: NSUInteger) -> NSUInteger;
);
}
/// Methods declared on superclass `MPSKernel`.
#[cfg(all(feature = "MPSCore", feature = "MPSKernel"))]
impl MPSNNGraph {
extern_methods!(
/// Called by NSCoder to decode MPSKernels
///
/// This isn't the right interface to decode a MPSKernel, but
/// it is the one that NSCoder uses. To enable your NSCoder
/// (e.g. NSKeyedUnarchiver) to set which device to use
/// extend the object to adopt the MPSDeviceProvider
/// protocol. Otherwise, the Metal system default device
/// will be used.
///
/// # Safety
///
/// `a_decoder` possibly has further requirements.
#[unsafe(method(initWithCoder:))]
#[unsafe(method_family = init)]
pub unsafe fn initWithCoder(
this: Allocated<Self>,
a_decoder: &NSCoder,
) -> Option<Retained<Self>>;
);
}
/// Methods declared on superclass `NSObject`.
#[cfg(all(feature = "MPSCore", feature = "MPSKernel"))]
impl MPSNNGraph {
extern_methods!(
#[unsafe(method(init))]
#[unsafe(method_family = init)]
pub unsafe fn init(this: Allocated<Self>) -> Retained<Self>;
#[unsafe(method(new))]
#[unsafe(method_family = new)]
pub unsafe fn new() -> Retained<Self>;
);
}