iOS Metal – 在写入纹理时读取旧值
iOS Metal – reading old values while writing into texture
我有一个内核函数(计算着色器),它从纹理中读取像素的附近像素,并根据旧的附近像素值更新当前像素的值(这不是一个简单的卷积).
我已经尝试使用 BlitCommandEncoder
创建纹理的副本并为内核函数提供 2 个纹理 - 一个只读和另一个只写。不幸的是,这种方法在 GPU 方面非常耗时。
在更新纹理内容的同时从纹理读取旧值的最有效(GPU 和内存)方式是什么?
(有点晚但是哦好吧)
你不可能让它只使用一个纹理,因为 GPU 是一个高度并行的处理器:你为单个像素编写的内核会在所有像素上并行调用,你无法分辨哪个先走
所以你肯定需要2个纹理。您可能应该这样做的方法是使用 2 个纹理,其中一个是 "old" 一个,另一个是 "new" 一个。在通道之间,您可以切换纹理的角色,现在旧的是新的,新的是旧的。这是一些 pseudoswift:
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(¤tText, &nextText)
dispatch_semaphore_signal(semaphore)
}
commands.commit()
}
我写了很多 iOS 金属代码,这些代码从渲染到的相同纹理中采样(或读取)。我正在使用渲染管道,将我的纹理设置为渲染目标附件,并将其加载为源纹理。它工作得很好。
需要说明的是,更有效的方法是在片段着色器中使用 color()
属性,但这仅适用于您只需要 current 片段,而不是附近的任何其他位置。如果您需要从渲染目标中的其他位置读取,我只会将渲染目标作为源纹理加载到片段着色器中。
我有一个内核函数(计算着色器),它从纹理中读取像素的附近像素,并根据旧的附近像素值更新当前像素的值(这不是一个简单的卷积).
我已经尝试使用 BlitCommandEncoder
创建纹理的副本并为内核函数提供 2 个纹理 - 一个只读和另一个只写。不幸的是,这种方法在 GPU 方面非常耗时。
在更新纹理内容的同时从纹理读取旧值的最有效(GPU 和内存)方式是什么?
(有点晚但是哦好吧)
你不可能让它只使用一个纹理,因为 GPU 是一个高度并行的处理器:你为单个像素编写的内核会在所有像素上并行调用,你无法分辨哪个先走
所以你肯定需要2个纹理。您可能应该这样做的方法是使用 2 个纹理,其中一个是 "old" 一个,另一个是 "new" 一个。在通道之间,您可以切换纹理的角色,现在旧的是新的,新的是旧的。这是一些 pseudoswift:
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(¤tText, &nextText)
dispatch_semaphore_signal(semaphore)
}
commands.commit()
}
我写了很多 iOS 金属代码,这些代码从渲染到的相同纹理中采样(或读取)。我正在使用渲染管道,将我的纹理设置为渲染目标附件,并将其加载为源纹理。它工作得很好。
需要说明的是,更有效的方法是在片段着色器中使用 color()
属性,但这仅适用于您只需要 current 片段,而不是附近的任何其他位置。如果您需要从渲染目标中的其他位置读取,我只会将渲染目标作为源纹理加载到片段着色器中。