iOS Metal - 在写入纹理时读取旧值

时间:2016-06-28 14:37:22

标签: ios shader texture2d metal

我有一个内核函数(计算着色器),它从纹理中读取像素的附近像素,并根据旧的附近像素值更新当前像素的值(它不是简单的卷积)。

我尝试使用BlitCommandEncoder创建纹理的副本,并为内核函数提供2个纹理 - 一个只读,另一个只写。不幸的是,这种方法耗费了GPU时间。

在更新内容时,从纹理中读取旧值的最有效(GPU和内存方式)是什么?

2 个答案:

答案 0 :(得分:3)

(迟到但很好)

你无法让它只用一个纹理,因为GPU是一个高度并行的处理器:你为一个像素写的内核在所有像素上并行调用,你无法分辨出哪一个先走了。

所以你肯定需要2个纹理。您可能应该这样做的方法是使用2个纹理,其中一个是“旧”纹理,另一个是“新”纹理。在传递之间,你切换纹理的角色,现在旧的是新的,新的是旧的。这是一些伪转换:

var currentText = MTLTexture()
var nextText = MTLTexture()

let semaphore = dispatch_semaphore_create(1)

func update() {
    dispatch_semaphore_wait(semaphore) // Wait for updating done signal

    let commands = commandQueue.commandBuffer()
    let encoder = commands.computeCommandEncoder()

    encoder.setTexture(currentText, atIndex: 0)
    encoder.setTexture(nextText, atIndex: 1)

    encoder.dispatchThreadgroups(...)
    encoder.endEncoding()

    // When updating done, swap the textures and signal that it's done updating
    commands.addCompletionHandler { 
        swap(&currentText, &nextText)
        dispatch_semaphore_signal(semaphore)
    }
    commands.commit()
}

答案 1 :(得分:0)

我已经编写了大量的iOS Metal代码,可以从它渲染的相同纹理中采样(或读取)。我正在使用渲染管道,将我的纹理设置为渲染目标附件,并将其加载为源纹理。它运作得很好。

要明确一点,更有效的方法是在片段着色器中使用color()属性,但这只适用于您需要的只是当前片段的值,没有任何其他附近的位置。如果你需要从渲染目标中的其他位置读取,我只需将渲染目标作为源纹理加载到片段着色器中。