MPSTemporaryImage(3) | MetalPerformanceShaders.framework | MPSTemporaryImage(3) |
MPSTemporaryImage
#import <MPSImage.h>
Inherits MPSImage.
(nonnull instancetype) - initWithTexture:featureChannels:
(nonnull instancetype) - initWithDevice:imageDescriptor:
(nonnull id< MPSImageAllocator >) + defaultAllocator
(nonnull instancetype) +
temporaryImageWithCommandBuffer:imageDescriptor:
(nonnull instancetype) +
temporaryImageWithCommandBuffer:textureDescriptor:
(nonnull instancetype) +
temporaryImageWithCommandBuffer:textureDescriptor:featureChannels:
(void) + prefetchStorageWithCommandBuffer:imageDescriptorList:
NSUInteger readCount
MPSImage MPSTemporaryImages are for MPSImages with short lifetimes.
What is temporary memory? It is memory, plain and simple. Analogy: If we use an app as an analogy for a command buffer, then 'Regular memory' (such as what backs a MPSImage or the typical MTLTexture) would be memory that you allocate at launch and never free. Temporary memory would be memory that you free when you are done with it so it can be used for something else as needed later in your app. You /could/ write your app to allocate everything you will ever need up front, but this is very inefficient and quite frankly a pain to plan out in advance. You don't do it for your app, so why would you do it for your command buffers?
Welcome to the 1970's! We have added a heap.
Unsurprisingly, MPSTemporaryImages can provide for profound reduction in the the amount of memory used by your application. Like malloc, MPS maintains a heap of memory usable in a command buffer. Over the lifetime of a command buffer, the same piece of memory may be reused many times. This means that each time the same memory is reused, it aliases with previous uses. If we aren't careful, we might find that needed data is overwritten by successive allocations. However, this is no different than accessing freed memory only to discover it doesn't contain what you thought it did anymore, so you should be able to keep out of trouble by following a few simple rules, like with malloc.
To this end, we added some restrictions to help you out and get a bit more performance. Some comments are appended in parentheses below to extend the analogy of command buffer = program:
Since MPSTemporaryImages can only be used with a single MTLCommandBuffer, and can not be used off the GPU, they generally should not be kept around past the completion of the MTLCommandBuffer. The lifetime of MPSTemporaryImages is expected to be typically extremely short, perhaps only a few lines of code. Like malloc, it is intended to be fairly cheap to make MPSTemporaryImages and throw them away. Please do so.
To keep the lifetime of the underlying texture allocation as short as possible, the underlying texture is not allocated until the first time the MPSTemporaryImage is used by a MPSCNNKernel or the .texture property is read. The readCount property serves to limit the lifetime on the other end.
You may use the MPSTemporaryImage.texture with MPSUnaryImageKernel -encode... methods, iff featureChannels <= 4 and the MTLTexture conforms to requirements of that MPSKernel. There is no locking mechanism provided to prevent a MTLTexture returned from the .texture property from becoming invalid when the readCount reaches 0.
Finally, MPSTemporaryImages are complicated to use with blit encoders. Your application should assume that the MPSTemporaryImage is backed by a MTLHeap, and consequently needs a MTLFence to ensure that compute command encoders and other encoders do not trip over one another with heap based memory. MPS will almost never use a blit encoder for this reason. If you do need one, then you will need to make a new compute encoder to block on whatever previous compute encoder last used the heap block. (MPS will not tell you who previously used the heap block. That encoder is almost certainly long dead anyway.) If concurrent encoders are involved, then a barrier might be needed. Within that compute encoder, you will call -updateFence. End the compute encoder, make a blit encoder wait for the fence, do the blit, update a new fence, then make a new compute encoder, wait for the second fence, then you can continue. Possibly the second do-nothing compute encoder needs to be ended so MPS can be called. Frankly, we don't bother with blit encoders and just write a compute operation for copy / clear as needed, or better yet find a way to eliminate the clear / copy pass so we don't have to pay for it. Note: the most common use of a blit encoder, -synchronizeResource: can not encounter this problem because MPSTemporaryImages live in GPU private memory and can not be read by the CPU.
MPSTemporaryImages can otherwise be used wherever MPSImages are used.
Get a well known MPSImageAllocator that makes MPSTemporaryImages
Reimplemented from MPSImage.
Unavailable. Use itemporaryImageForCommandBuffer:textureDescriptor: instead.
Reimplemented from MPSImage.
Unavailable. Use temporaryImageForCommandBuffer:textureDescriptor: or -temporaryImageForCommandBuffer:imageDescriptor: instead.
Reimplemented from MPSImage.
Help MPS decide which allocations to make ahead of time The texture cache that underlies the MPSTemporaryImage can automatically allocate new storage as needed as you create new temporary images. However, sometimes a more global view of what you plan to make is useful for maximizing memory reuse to get the most efficient operation. This class method hints to the cache what the list of images will be.
It is never necessary to call this method. It is purely a performance and memory optimization.
This method makes a conservative estimate of memory required and may not fully cover temporary memory needs, resulting in additional allocations later that could encounter pathological behavior, if they are too small. If the full extent and timing of the workload is known in advance, it is recommended that MPSHintTemporaryMemoryHighWaterMark() be used instead.
Parameters:
Initialize a MPSTemporaryImage for use on a MTLCommandBuffer
Parameters:
Returns:
Low level interface for creating a MPSTemporaryImage using a MTLTextureDescriptor This function provides access to MTLPixelFormats not typically covered by -initForCommandBuffer:imageDescriptor: The feature channels will be inferred from the MTLPixelFormat without changing the width. The following restrictions apply:
MTLTextureType must be MTLTextureType2D or MTLTextureType2DArray MTLTextureUsage must contain at least one of MTLTextureUsageShaderRead, MTLTextureUsageShaderWrite MTLStorageMode must be MTLStorageModePrivate depth must be 1
Parameters:
Returns:
Low level interface for creating a MPSTemporaryImage using a MTLTextureDescriptor This function provides access to MTLPixelFormats not typically covered by -initForCommandBuffer:imageDescriptor: The number of images will be inferred from number of slices in the descriptor.arrayLength and the number of feature channels.
The following restrictions apply:
MTLTextureType must be MTLTextureType2D or MTLTextureType2DArray MTLTextureUsage must contain at least one of MTLTextureUsageShaderRead, MTLTextureUsageShaderWrite MTLStorageMode must be MTLStorageModePrivate
Parameters:
Returns:
Generated automatically by Doxygen for MetalPerformanceShaders.framework from the source code.
Mon Jul 9 2018 | Version MetalPerformanceShaders-119.3 |