我尝试使用Apple和自定义MPSKernal
提供的默认compute Shaders
过滤器,通过金属应用实时相机过滤器。
我将自定义过滤器应用于网格中的集合视图,并结合使用默认和自定义内核函数。
它看起来像在应用程序Clips。
但我观察到的是,使用自定义过滤器与apple提供的默认内核函数相比,有很多memory leaks
。
我不知道我犯了哪些错误。
这是我的自定义计算着色器。
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);
}
关于我创建管道和通过线程组调度代码到这里
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)
}
具有自定义着色器的Pipeline状态就是这样创建的。
let defaultLibrary = device.newDefaultLibrary()
let kernelFunction = defaultLibrary!.makeFunction(name: name)
do {
pipelineState = try device.makeComputePipelineState(function: kernelFunction!)
} catch {
fatalError("Unable to create pipeline state")
}
在仪器中,它显示某些Malloc 16 bytes
和[Mtkview draw]
方法存在泄漏。
屏幕截图如下所示。
我希望帮助找到问题的发生地点和方式。
感谢。
答案 0 :(得分:1)
没有理由明确分配UnsafeMutablePointer
来存储就地纹理参数。顺便提一下,这是泄漏的来源:你分配指针然后永远不会解除分配。
使用局部变量代替传递纹理:
var inPlaceTexture = destinationTexture
blur.encode(commandBuffer: commandBuffer, inPlaceTexture: &inPlaceTexture, fallbackCopyAllocator: nil)
顺便说一下,如果你在没有提供回退分配器或检查返回值的情况下调用就地编码方法,那么你(最终)将会遇到不好的时间。在某些情况下,就地编码将失败,因此您应该提供一个闭包,以便在发生故障时分配适当的纹理。