【问题标题】:How to pass arguments to Metal CIWarpKernel?如何将参数传递给 Metal CIWarpKernel?
【发布时间】:2021-06-17 16:00:29
【问题描述】:

我有一个简单的 Metal CIWarpKernel:

    float2 MyWarp(destination dest, float offset)
    {
        return float2(dest.coord().x + offset, dest.coord().y);
    }

和:

class MyWarpFilter : CIFilter
{
    var inputImage: CIImage?
    var inputOffset: Float = 100.0

    static var kernel: CIWarpKernel =
    { () -> CIWarpKernel in
        let url = Bundle.main.url(forResource: "MyWarp", withExtension: "ci.metallib")!
        let data = try! Data(contentsOf: url)
        return try! CIWarpKernel(functionName: "MyWarp", fromMetalLibraryData: data) <== ERROR
    }()

    override var outputImage : CIImage?
    {
        get
        {
            guard let input = inputImage else { return nil }

            let roiCallback: CIKernelROICallback =
            { _, rect -> CGRect in
                return CGRect(x: rect.minX, y: rect.minY, width: input.extent.width, height: input.extent.height)
            }

            let arguments: [Any] = [inputOffset]

            return MyWarpFilter.kernel.apply(extent: input.extent,
                                             roiCallback: roiCallback,
                                             image: input, arguments: arguments)
        }
    }
}

当我运行它时,我收到以下运行时错误(在上面用&lt;== ERROR 指示的行):

Thread 1: Fatal error: 'try!' expression unexpectedly raised an error: Foundation._GenericObjCError.nilError

如果我删除第二个MyWarp() 参数,使用arguments: [] 运行过滤器并使用硬编码的偏移量,则不会出现错误(过滤器会按偏移量转换图像)。

将参数传递给CIWarpKernel 我做错了什么?

【问题讨论】:

  • 顺便说一句,您可以更轻松地实现这一切:let offsetImage = input.transformed(by: CGAffineTransform(translationX: inputOffset, y: 0)
  • @FrankSchlegel 是的。这是显示我的问题的最简单的版本。我真正的金属内核使用三角函数和其他东西。 (顺便说一句,要获得相同的结果,应该是translationX: -inputOffset。)

标签: ios swift metal cifilter ciwarpkernel


【解决方案1】:

使用 iOS Simulator 14.4/Xcode 12.4 运行您的代码,我收到以下错误: (不确定我做错了什么或者这只是运行时版本的问题。)

Thread 1: Fatal error: 'try!' expression unexpectedly raised an error: Error Domain=CIKernel Code=4 "(null)" UserInfo={CINonLocalizedDescriptionKey=If specified, destination must be the last parameter of a CIKernel function.}

因此,至少,您可能需要将参数destination dest 移到最后:

    float2 MyWarp(float offset, destination dest)
    {
        return float2(dest.coord().x + offset, dest.coord().y);
    }

Metal Shading Language for Core Image Kernels

destination 允许访问当前正在计算的像素位置的内核参数类型。此参数对于CIWarpKernel 是必需的,对于CIColorKernelCIKernel 是可选的,必须是内核函数的最后一个参数

【讨论】:

  • 我没有得到那个信息量很大的错误。但这确实解决了我的问题。非常感谢。 (我一直在查看 Apple 文档和其他资源,但关于 CI 金属着色器的内容很少。)
猜你喜欢
  • 1970-01-01
  • 2018-10-24
  • 2020-10-09
  • 2012-12-21
  • 2012-01-07
  • 2014-05-03
  • 2015-06-26
  • 2012-01-18
  • 2017-07-14
相关资源
最近更新 更多