首页 > 解决方案 > 在 Apple Metal 上的 MPSImageLanczosScale 之后应用着色器的问题

问题描述

在应用MPSImageLanczosScale后在 MTLTexture 上应用着色器时,我得到了奇怪的结果。

即使变换为 scale = 1 和 translationX = 0 和 translationY = 0。

如果我不应用 MPSImageLanczosScale,它运行良好。您可以在下面看到不应用 MPSImageLanczosScale 和应用 MPSImageLanczosScale 的结果。

在此处输入图像描述

我的渲染方法如下所示:

func filter(pixelBuffer: CVPixelBuffer) -> CVPixelBuffer? {

    guard let commandQueue = commandQueue, var commandBuffer = commandQueue.makeCommandBuffer() else {
        print("Failed to create Metal command queue")
        CVMetalTextureCacheFlush(textureCache!, 0)
        return nil
    }

    var newPixelBuffer: CVPixelBuffer?
    CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, outputPixelBufferPool!, &newPixelBuffer)
    guard var outputPixelBuffer = newPixelBuffer else {
        print("Allocation failure: Could not get pixel buffer from pool (\(self.description))")
        return nil
    }

    guard let inputTexture = makeTextureFromCVPixelBuffer(pixelBuffer: pixelBuffer, textureFormat: .bgra8Unorm) else {
        return nil
    }

    guard var intermediateTexture = makeTextureFromCVPixelBuffer(pixelBuffer: outputPixelBuffer, textureFormat: .bgra8Unorm) else {
        return nil
    }

    let imageLanczosScale = MPSImageLanczosScale(device: metalDevice)
    let transform = MPSScaleTransform(scaleX: Double(scale), scaleY: Double(scale), translateX: Double(translationX), translateY: Double(translationY))
    withUnsafePointer(to: &transform) { (transformPtr: UnsafePointer<MPSScaleTransform>) -> () in
        imageLanczosScale.scaleTransform = transformPtr
    }
    imageLanczosScale.encode(commandBuffer: commandBuffer, sourceTexture: inputTexture, destinationTexture: outputTexture)

    guard let commandEncoder = commandBuffer.makeComputeCommandEncoder(),
     let outputTexture = makeTextureFromCVPixelBuffer(pixelBuffer: outputPixelBuffer, textureFormat: .bgra8Unorm) else { return nil }

    commandEncoder.label = "Shader"
    commandEncoder.setComputePipelineState(shaderPipline)
    commandEncoder.setTexture(intermediateTexture, index: 1)
    commandEncoder.setTexture(outputTexture, index: 0)

    let w = shaderPipline.threadExecutionWidth
    let h = shaderPipline.maxTotalThreadsPerThreadgroup / w
    let threadsPerThreadgroup = MTLSizeMake(w, h, 1)
    let threadgroupsPerGrid = MTLSize(width: (intermediateTexture.width + w - 1) / w, height: (intermediateTexture.height + h - 1) / h, depth: 1)
    commandEncoder.dispatchThreadgroups(threadgroupsPerGrid, threadsPerThreadgroup: threadsPerThreadgroup)

    commandEncoder.endEncoding()
    commandBuffer.commit()

    return outputPixelBuffer
}

不知道我做错了什么。有任何想法吗?

标签: iosswiftshadermetalmetal-performance-shaders

解决方案


推荐阅读