检测MTLTexture是否为空

时间:2018-03-20 03:00:16

标签: ios swift metal

我试图通过计算每个像素的所有R G B和A分量的总和来确定MTLTexture(以bgra8Unorm格式)是否为空。

此函数旨在通过在将纹理复制到指针后在内存中添加相邻浮点数来实现此目的。但是我已经确定这个函数最终会返回给出MTLTexture的虚假数字。

这个功能出了什么问题?

func anythingHere(_ texture: MTLTexture) -> Bool {
        let width = texture.width
        let height = texture.height
        let bytesPerRow = width * 4

        let data = UnsafeMutableRawPointer.allocate(bytes: bytesPerRow * height, alignedTo: 4)
        defer {
            data.deallocate(bytes: bytesPerRow * height, alignedTo: 4)
        }

        let region = MTLRegionMake2D(0, 0, width, height)
        texture.getBytes(data, bytesPerRow: bytesPerRow, from: region, mipmapLevel: 0)
        var bind = data.assumingMemoryBound(to: UInt8.self)

        var sum:UInt8 = 0;
        for i in 0..<width*height {
            sum += bind.pointee
            bind.advanced(by: 1)
        }
        return sum != 0
}

2 个答案:

答案 0 :(得分:4)

Matthijs&#39;改变是必要的,但是这个方法的正确性还有其他一些问题。

您实际上只迭代了超过1/4的像素,因为您按字节顺序步进,并且循环的上限是width * height而不是bytesPerRow * height

此外,计算像素的总和并不像你想要的那样。一旦遇到非零值(if bind.pointee != 0),您可以通过返回true来保存一些工作。

(顺便提一下,如果你将一个大于255的值累加到UInt8中,Swift的整数溢出保护实际上会引发一个异常。我想你可以使用一个更大的整数,或用{来禁用溢出检查{1}},但同样,打破第一个非清晰像素上的循环将节省一些时间并防止误累,当累加器&#34;翻转到#34;正好为0。)

这是您的功能版本,对我有用:

sum = sum &+ bind.pointee

请注意,在macOS上,纹理的默认func anythingHere(_ texture: MTLTexture) -> Bool { let width = texture.width let height = texture.height let bytesPerRow = width * 4 let data = UnsafeMutableRawPointer.allocate(byteCount: bytesPerRow * height, alignment: 4) defer { data.deallocate() } let region = MTLRegionMake2D(0, 0, width, height) texture.getBytes(data, bytesPerRow: bytesPerRow, from: region, mipmapLevel: 0) var bind = data.assumingMemoryBound(to: UInt8.self) for _ in 0..<bytesPerRow * height { if bind.pointee != 0 { return true } bind = bind.advanced(by: 1) } return false } storageMode,这意味着当它们的内容被修改后,它们的内容不会自动同步回主内存。 GPU。您必须明确使用blit命令编码器来自己同步内容:

managed

答案 1 :(得分:1)

没有仔细查看其余代码,但我认为这是

bind.advanced(by: 1)

应该是:

bind = bind.advanced(by: 1)