在不同形状的金属纹理之间复制数据

时间:2018-07-09 16:33:55

标签: swift keras metal metal-performance-shaders

我正在将两个训练有素的Keras模型转换为Metal Performance Shaders。我必须重塑第一张图的输出并将其用作第二张图的输入。第一个图形的输出是具有“形状”(1,1,8192)的MPSImage,第二个图形的输入是具有“形状”(4,4,512)的MPSImage。

我将graph1的输出image.texture转换为float16数组,并将其传递给以下函数,以将数据复制到4x4x512 MPSImage“ midImage”中:

func reshapeTexture(imageArray:[Float16]) -> MPSImage{

    let image = imageArray
    image.withUnsafeBufferPointer { ptr in
        let width = midImage.texture.width
        let height = midImage.texture.height
        for slice in 0..<128{
            for w in 0..<width{
                for h in 0..<height{
                    let region = MTLRegion(origin: MTLOriginMake(w, h, 0),
                                           size: MTLSizeMake(1, 1, 1))
                    midImage.texture.replace(region: region, mipmapLevel: 0, slice: slice, withBytes: ptr.baseAddress!.advanced(by: ((slice * 4 * width * height) + ((w + h) * 4)), bytesPerRow: MemoryLayout<Float16>.stride * 4, bytesPerImage: 0)
                }
            }
        }
    }
    return midImage
}

当我将midImage传递给graph2时,图形的输出是一个正方形,其杂乱的噪声为3/4,右下角为1/4黑色。我想我不了解有关MPSImage slice属性用于存储额外通道的信息。谢谢!

1 个答案:

答案 0 :(得分:0)

金属2d纹理阵列几乎总是以某种Morton或“ Z”顺序存储。当然,MPS总是以这种方式分配它们,尽管我认为在MacOS上可能有一种方法可以制作线性2D纹理数组并将MPSImage包裹在其周围。因此,如果没有适当的照顾,直接访问2d纹理阵列后备存储将导致悲伤和困惑。

正确的方法是编写一个简单的Metal复制内核。这样可以使存储顺序独立,并且您无需等待命令缓冲区完成就可以执行操作。

也可能需要Radar中的功能请求。还请查看最新的macOS / iOS种子,以了解Apple最近是否为您添加了变形过滤器。