objc2_metal_performance_shaders/generated/MPSNeuralNetwork/
MPSNNGraph.rs

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