【问题标题】:MTLBuffer allocation + CPU/GPU synchronisationMTLBuffer分配+CPU/GPU同步
【发布时间】:2018-10-17 05:14:13
【问题描述】:

我正在使用金属性能着色器 (MPSImageHistogram) 来计算我抓取的 MTLBuffer 中的某些内容,执行计算,然后通过 MTKView 显示。着色器的MTLBuffer 输出很小(~4K 字节)。所以我为每个渲染通道分配一个新的MTLBuffer 对象,每个视频帧每秒至少有 30 次渲染。

calculation = MPSImageHistogram(device: device, histogramInfo: &histogramInfo)
let bufferLength = calculation.histogramSize(forSourceFormat: MTLPixelFormat.bgra8Unorm)
let buffer = device.makeBuffer(length: bufferLength, options: .storageModeShared)
let commandBuffer = commandQueue?.makeCommandBuffer()

calculation.encode(to: commandBuffer!, sourceTexture: metalTexture!, histogram: buffer!, histogramOffset: 0)
commandBuffer?.commit()

commandBuffer?.addCompletedHandler({ (cmdBuffer) in
    let dataPtr = buffer!.contents().assumingMemoryBound(to: UInt32.self)
    ...
    ...

}

我的问题 -

  1. 是否可以每次使用device.makeBuffer(..)创建一个新缓冲区,还是静态分配更好 几个缓冲区并实现重用这些缓冲区?如果复用更好,我们如何在这些缓冲区上同步 CPU/GPU 数据写入/读取?

  2. 另一个不相关的问题,可以在非主线程上绘制MTKView 的结果吗?或者MTKView draws 只能在主线程中(即使我读过 Metal 是真正的多线程)?

【问题讨论】:

    标签: ios metal metalkit metal-performance-shaders mtlbuffer


    【解决方案1】:
    1. 分配有点贵,所以我推荐一种可重用的缓冲方案。我首选的方法是保留一个可变的缓冲区数组(队列),当使用它的命令缓冲区完成时(或者在你的情况下,在你读回 CPU 上的结果之后)将缓冲区排队,并分配当队列为空并且您需要编码更多工作时,一个新的缓冲区。在稳定状态下,假设您的帧及时完成,您会发现此方案很少会分配超过 2-3 个缓冲区的总数。如果您需要此方案是线程安全的,您可以使用互斥锁(使用dispatch_semaphore 实现)保护对队列的访问。

    2. 只要遵循标准的多线程预防措施,您就可以使用另一个线程对绘制到由MTKView 提供的可绘制对象中绘制的渲染工作进行编码。请记住,虽然命令队列是线程安全的(从某种意义上说,您可以同时从同一个队列创建和编码多个命令缓冲区),但命令缓冲区本身和编码器却不是。我建议您分析单线程情况,仅在绝对必要时才介绍多线程的复杂性。

    【讨论】:

    【解决方案2】:
    1. 如果是少量数据(4K以下)可以使用setBytes():https://developer.apple.com/documentation/metal/mtlcomputecommandencoder/1443159-setbytes

    这可能比每帧分配一个新缓冲区更快/更好。您还可以使用三重缓冲方法,以便连续帧对缓冲区的访问不会干扰。 https://developer.apple.com/library/content/documentation/3DDrawing/Conceptual/MTLBestPracticesGuide/TripleBuffering.html

    本教程展示了如何为渲染设置三重缓冲:https://www.raywenderlich.com/146418/metal-tutorial-swift-3-part-3-adding-texture

    这实际上类似于教程的第三部分,但它是在“重用统一缓冲区”下显示三重缓冲设置的部分。

    【讨论】:

    • setBytes() 不适用于此处,因为MPSImageHistogram 需要写入到缓冲区。
    • 这就是我对三重缓冲的疑问,三重缓冲的成本是否真的适合小缓冲区。
    • 您需要使用动态缓冲区分配和静态三重缓冲来实现它,以确定它是否对您的应用程序至关重要。总的来说,我发现分配步骤是解码循环中最昂贵的事情,但对于非常小的图像可能无关紧要。
    猜你喜欢
    • 2021-03-04
    • 2015-01-23
    • 2017-03-11
    • 1970-01-01
    • 1970-01-01
    • 2017-11-14
    • 2014-05-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多