在 Metal 中使用自定义计算着色器时发生内存泄漏

Memory leak when I use custom compute shaders in Metal

我正在尝试使用苹果提供的默认 MPSKernal 滤镜和自定义 compute Shaders 滤镜通过金属应用实时相机滤镜。

我使用默认和自定义内核函数的组合在网格中的集合视图上应用自定义过滤器。

在应用程序 Clips 中看起来像。

但我观察到的是,与苹果给出的默认内核函数相比,使用自定义过滤器有很多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)
    }

带有自定义Shader的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] 方法存在泄漏。

截图如下。

我需要帮助找出问题发生的地点和方式。

谢谢。

没有理由显式分配 UnsafeMutablePointer 来存储就地纹理参数。顺便说一下,这就是你泄漏的根源:你分配了指针,然后从不释放它。

改用局部变量传递纹理:

var inPlaceTexture = destinationTexture
blur.encode(commandBuffer: commandBuffer, inPlaceTexture: &inPlaceTexture, fallbackCopyAllocator: nil)

顺便说一句,如果您在不提供后备分配器或检查 return 值的情况下调用就地编码方法,您(最终)将会遇到麻烦。就地编码在某些情况下会失败,因此您应该提供一个闭包,在失败的情况下分配适当的纹理。