Reputation: 350
Im trying to apply the live camera filters through metal using the default MPSKernal
filters given by apple and custom compute Shaders
.
Im applying the custom filters on a collection view in a grid with the combination of default and the custom kernel functions.
It looks like in the app Clips.
But what I observed is that using the custom filters there is a lot of memory leaks
compared to the default kernel functions given by apple.
I don't know what mistakes I made though if any.
Here is my custom compute shader.
kernel void customFunction1(
texture2d<float, access::read> inTexture [[texture(0)]],
texture2d<float, access::write> outTexture [[texture(1)]],
uint2 gid [[thread_position_in_grid]]){
const float4 colorAtPixel = inTexture.read(gid);
const float4 outputColor = float4(colorAtPixel.r, colorAtPixel.g, colorAtPixel.b, 1);
outTexture.write(outputColor, gid);
}
Regarding to my creating my pipeline and the dispatching through thread groups the code goes here
let blur = MPSImageGaussianBlur(device: device, sigma: 0)
let threadsPerThreadgroup = MTLSizeMake(4, 4, 1)
let threadgroupsPerGrid = MTLSizeMake(destinationTexture.width / threadsPerThreadgroup.width, destinationTexture.height / threadsPerThreadgroup.height, 1)
let commandEncoder = commandBuffer.makeComputeCommandEncoder()
commandEncoder.setComputePipelineState(pipelineState!)
commandEncoder.setTexture(sourceTexture, at: 0)
commandEncoder.setTexture(destinationTexture, at: 1)
commandEncoder.dispatchThreadgroups(threadgroupsPerGrid, threadsPerThreadgroup: threadsPerThreadgroup)
commandEncoder.endEncoding()
autoreleasepool {
let inPlaceTexture = UnsafeMutablePointer<MTLTexture>.allocate(capacity: 1)
inPlaceTexture.initialize(to: destinationTexture)
blur.encode(commandBuffer: commandBuffer, inPlaceTexture: inPlaceTexture, fallbackCopyAllocator: nil)
}
The Pipeline state with the custom Shader is created like this.
let defaultLibrary = device.newDefaultLibrary()
let kernelFunction = defaultLibrary!.makeFunction(name: name)
do {
pipelineState = try device.makeComputePipelineState(function: kernelFunction!)
} catch {
fatalError("Unable to create pipeline state")
}
And in instrumentation it shows there is a leak in some Malloc 16 bytes
and in [Mtkview draw]
method.
The screenshot is shown below.
I want help in finding where and how the issue is occurring from.
Thanks.
Upvotes: 0
Views: 1159
Reputation: 31782
There's no reason to explicitly allocate an UnsafeMutablePointer
to store the in-place texture parameter. Incidentally, that's the source of your leak: you allocate the pointer and then never deallocate it.
Use a local variable to pass the texture instead:
var inPlaceTexture = destinationTexture
blur.encode(commandBuffer: commandBuffer, inPlaceTexture: &inPlaceTexture, fallbackCopyAllocator: nil)
By the way, you're (eventually) going to have a bad time if you call the in-place encode method without providing a fallback allocator or checking the return value. In-place encoding will fail in certain situations, so you should provide a closure that allocates an appropriate texture in the event of failure.
Upvotes: 2