如何使用MTLBlitCommandEncoder将隔行视频字段复制到MTLBuffer

时间:2017-03-28 12:12:51

标签: swift macos metal

我们正在使用隔行扫描高清视频。我用于渲染的金属颜色附件具有一个场的尺寸(1920 * 540 RGBA)。 当我尝试将两个渲染字段复制到大小为1920 * 1080 * 4 = 8294400字节的相同MTL缓冲区时,仅当目标偏移量为零时才有效。

let commandBuffer = commandQueue.makeCommandBuffer()
let blitEncoder = commandBuffer.makeBlitCommandEncoder()
blitEncoder.copy(from: attachmentTexture,
                 sourceSlice: 0,
                 sourceLevel: 0,
                 sourceOrigin: MTLOriginMake(0, 0, 0),
                 sourceSize: MTLSizeMake(attachmentTexture.width, attachmentTexture.height, 1),
                 to: destinationBuffer,
                 destinationOffset: 1920*4,
                 destinationBytesPerRow: 1920*4*2,
                 destinationBytesPerImage: destinationBuffer.length)
blitEncoder.endEncoding()
commandBuffer.commit()

对于目标偏移量为零的第一个字段,该功能运行良好。每隔一行填充目标缓冲区。

但是当我想用相同的代码将第二个字段写入相同的MTLBuffer对象时,只将destinationOffset设置为1920 * 4,就像你在上面的代码中看到的那样(从缓冲区的第二行开始)然后我得到这样的断言:

  

- [MTLDebugBlitCommandEncoder validateCopyFromTexture:sourceSlice:sourceLevel:sourceOrigin:sourceSize:toBuffer:destinationOffset:destinationBytesPerRow:destinationBytesPerImage:options:]:677:   断言失败`totalBytesUsed(8302080)必须是< =   destinationBuffer length。'

totalBytesUsed正是目标缓冲区长度(以字节为单位)加上偏移量。因此,我在此函数中使用的每个偏移都将导致此断言错误。

有人可以解释一下如何正确使用这个功能,因为另外一种方法就是为输入的视频帧创建两个MTLTexture对象(奇数和偶数场),并且使用类似的参数。

1 个答案:

答案 0 :(得分:1)

我最近也碰到了这样的事情。

您已将destinationBuffer.length传递给destinationBytesPerImage:参数。正如您所注意到的,Metal正在将偏移量和每个图像的字节数值相加,并将其与to:目标缓冲区(destinationBuffer)的长度进行比较。它注意到偏移量加上每个图像的字节数不符合缓冲区并且拒绝接受它。

您可以简单地为destinationBytesPerImage:传递0,因为您不使用3D或2D数组纹理。如果这不起作用,请传递destinationBuffer.length - 1920*4